Scippy

SCIP

Solving Constraint Integer Programs

solve.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 solve.c
17  * @brief main solving loop and node processing
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Marc Pfetsch
21  * @author Gerald Gamrath
22  */
23 
24 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
25 #include <assert.h>
26 
27 #include "scip/def.h"
28 #include "scip/set.h"
29 #include "scip/stat.h"
30 #include "scip/clock.h"
31 #include "scip/visual.h"
32 #include "scip/interrupt.h"
33 #include "scip/event.h"
34 #include "scip/lp.h"
35 #include "scip/mem.h"
36 #include "scip/var.h"
37 #include "scip/prob.h"
38 #include "scip/sol.h"
39 #include "scip/primal.h"
40 #include "scip/tree.h"
41 #include "scip/reopt.h"
42 #include "scip/pricestore.h"
43 #include "scip/sepastore.h"
44 #include "scip/cutpool.h"
45 #include "scip/solve.h"
46 #include "scip/scip.h"
47 #include "scip/branch.h"
48 #include "scip/conflict.h"
49 #include "scip/cons.h"
50 #include "scip/disp.h"
51 #include "scip/heur.h"
52 #include "scip/nodesel.h"
53 #include "scip/pricer.h"
54 #include "scip/relax.h"
55 #include "scip/sepa.h"
56 #include "scip/prop.h"
57 #include "scip/pub_misc.h"
58 #include "scip/debug.h"
59 #include "scip/concurrent.h"
60 #include "scip/syncstore.h"
61 
62 
63 #define MAXNLPERRORS 10 /**< maximal number of LP error loops in a single node */
64 #define MAXNCLOCKSKIPS 64 /**< maximum number of SCIPsolveIsStopped() calls without checking the clock */
65 #define NINITCALLS 1000L /**< minimum number of calls to SCIPsolveIsStopped() prior to dynamic clock skips */
66 #define SAFETYFACTOR 1e-2 /**< the probability that SCIP skips the clock call after the time limit has already been reached */
67 
68 /** returns whether the solving process will be / was stopped before proving optimality;
69  * if the solving process was stopped, stores the reason as status in stat
70  */
72  SCIP_SET* set, /**< global SCIP settings */
73  SCIP_STAT* stat, /**< dynamic problem statistics */
74  SCIP_Bool checknodelimits /**< should the node limits be involved in the check? */
75  )
76 {
77  assert(set != NULL);
78  assert(stat != NULL);
79 
80  /* increase the number of calls to this method */
81  SCIPstatIncrement(stat, set, nisstoppedcalls);
82 
83  /* in case lowerbound >= upperbound, we do not want to terminate with SCIP_STATUS_GAPLIMIT but with the ordinary
84  * SCIP_STATUS_OPTIMAL/INFEASIBLE/...
85  */
86  if( set->stage >= SCIP_STAGE_SOLVING && SCIPsetIsLE(set, SCIPgetUpperbound(set->scip), SCIPgetLowerbound(set->scip)) )
87  return TRUE;
88 
89  /* if some limit has been changed since the last call, we reset the status */
90  if( set->limitchanged )
91  {
93  set->limitchanged = FALSE;
94  }
95 
96  if( SCIPinterrupted() || stat->userinterrupt )
97  {
99  stat->userinterrupt = FALSE;
100 
101  /* only reset the interrupted counter if this is the main SCIP catching CTRL-C */
102  if( set->misc_catchctrlc )
103  {
105  }
106  }
107  /* only measure the clock if a time limit is set */
108  else if( set->istimelimitfinite )
109  {
110  /* check if we have already called this function sufficiently often for a valid estimation of its average call interval */
111  if( stat->nclockskipsleft <= 0 || stat->nisstoppedcalls < NINITCALLS )
112  {
113  SCIP_Real currtime = SCIPclockGetTime(stat->solvingtime);
114 
115  /* use the measured time to update the average time interval between two calls to this method */
116  if( set->time_rareclockcheck && stat->nisstoppedcalls >= NINITCALLS )
117  {
118  SCIP_Real avgisstoppedfreq;
119  int nclockskips = MAXNCLOCKSKIPS;
120 
121  avgisstoppedfreq = currtime / stat->nisstoppedcalls;
122 
123  /* if we are approaching the time limit, reset the number of clock skips to 0 */
124  if( (SAFETYFACTOR * (set->limit_time - currtime) / (avgisstoppedfreq + 1e-6)) < nclockskips )
125  nclockskips = 0;
126 
127  stat->nclockskipsleft = nclockskips;
128  }
129  else
130  stat->nclockskipsleft = 0;
131 
132  /* set the status if the time limit was hit */
133  if( currtime >= set->limit_time )
134  {
136  return TRUE;
137  }
138  }
139  else if( SCIPclockGetLastTime(stat->solvingtime) >= set->limit_time )
140  {
141  /* use information if clock has been updated more recently */
143  return TRUE;
144  }
145  else
146  --stat->nclockskipsleft;
147  }
148  if( SCIPgetConcurrentMemTotal(set->scip) >= set->limit_memory*1048576.0 - stat->externmemestim * (1.0 + SCIPgetNConcurrentSolvers(set->scip)) )
150  else if( SCIPgetNLimSolsFound(set->scip) > 0
151  && (SCIPsetIsLT(set, SCIPgetGap(set->scip), set->limit_gap)
152  || SCIPsetIsLT(set, SCIPgetUpperbound(set->scip) - SCIPgetLowerbound(set->scip), set->limit_absgap)) )
154  else if( set->limit_solutions >= 0 && set->stage >= SCIP_STAGE_PRESOLVED
155  && SCIPgetNLimSolsFound(set->scip) >= set->limit_solutions )
157  else if( set->limit_bestsol >= 0 && set->stage >= SCIP_STAGE_PRESOLVED
158  && SCIPgetNBestSolsFound(set->scip) >= set->limit_bestsol )
160  else if( checknodelimits && set->limit_nodes >= 0 && stat->nnodes >= set->limit_nodes )
162  else if( checknodelimits && set->limit_totalnodes >= 0 && stat->ntotalnodes >= set->limit_totalnodes )
164  else if( checknodelimits && set->limit_stallnodes >= 0 && stat->nnodes >= stat->bestsolnode + set->limit_stallnodes )
166 
167  /* If stat->status was initialized to SCIP_STATUS_NODELIMIT or SCIP_STATUS_STALLNODELIMIT due to a previous call to SCIPsolveIsStopped(,,TRUE),
168  * in the case of checknodelimits == FALSE, we do not want to report here that the solve will be stopped due to a nodelimit.
169  */
170  if( !checknodelimits )
172  else
174 }
175 
176 /** calls primal heuristics */
178  SCIP_SET* set, /**< global SCIP settings */
179  SCIP_STAT* stat, /**< dynamic problem statistics */
180  SCIP_PROB* prob, /**< transformed problem after presolve */
181  SCIP_PRIMAL* primal, /**< primal data */
182  SCIP_TREE* tree, /**< branch and bound tree, or NULL if called during presolving */
183  SCIP_LP* lp, /**< LP data, or NULL if called during presolving or propagation */
184  SCIP_NODE* nextnode, /**< next node that will be processed, or NULL if no more nodes left
185  * (only needed when calling after node heuristics) */
186  SCIP_HEURTIMING heurtiming, /**< current point in the node solving process */
187  SCIP_Bool nodeinfeasible, /**< was the current node already detected to be infeasible? */
188  SCIP_Bool* foundsol, /**< pointer to store whether a solution has been found */
189  SCIP_Bool* unbounded /**< pointer to store whether an unbounded ray was found in the LP */
190  )
191 { /*lint --e{715}*/
192 
193  SCIP_RESULT result;
194  SCIP_Longint oldnbestsolsfound;
195  SCIP_Real lowerbound;
196  int ndelayedheurs;
197  int depth;
198  int lpstateforkdepth;
199  int h;
200 #ifndef NDEBUG
201  SCIP_Bool inprobing;
202  SCIP_Bool indiving;
203 #endif
204 
205  assert(set != NULL);
206  assert(primal != NULL);
207  assert(tree != NULL || heurtiming == SCIP_HEURTIMING_BEFOREPRESOL || heurtiming == SCIP_HEURTIMING_DURINGPRESOLLOOP);
208  assert(lp != NULL || heurtiming == SCIP_HEURTIMING_BEFOREPRESOL || heurtiming == SCIP_HEURTIMING_DURINGPRESOLLOOP
209  || heurtiming == SCIP_HEURTIMING_AFTERPROPLOOP);
210  assert(heurtiming == SCIP_HEURTIMING_BEFORENODE || heurtiming == SCIP_HEURTIMING_DURINGLPLOOP
211  || heurtiming == SCIP_HEURTIMING_AFTERLPLOOP || heurtiming == SCIP_HEURTIMING_AFTERNODE
212  || heurtiming == SCIP_HEURTIMING_DURINGPRICINGLOOP || heurtiming == SCIP_HEURTIMING_BEFOREPRESOL
213  || heurtiming == SCIP_HEURTIMING_DURINGPRESOLLOOP || heurtiming == SCIP_HEURTIMING_AFTERPROPLOOP
215  assert(heurtiming != SCIP_HEURTIMING_AFTERNODE || (nextnode == NULL) == (SCIPtreeGetNNodes(tree) == 0));
216  assert(foundsol != NULL);
217 
218  *foundsol = FALSE;
219 
220  /* nothing to do, if no heuristics are available, or if the branch-and-bound process is finished */
221  if( set->nheurs == 0 || (heurtiming == SCIP_HEURTIMING_AFTERNODE && nextnode == NULL) )
222  return SCIP_OKAY;
223 
224  /* do not continue if we reached a time limit */
225  if( SCIPsolveIsStopped(set, stat, FALSE) )
226  return SCIP_OKAY;
227 
228  /* sort heuristics by priority, but move the delayed heuristics to the front */
229  SCIPsetSortHeurs(set);
230 
231  /* specialize the AFTERNODE timing flag */
232  if( (heurtiming & SCIP_HEURTIMING_AFTERNODE) == SCIP_HEURTIMING_AFTERNODE )
233  {
234  SCIP_Bool plunging;
235  SCIP_Bool pseudonode;
236 
237  /* clear the AFTERNODE flags and replace them by the right ones */
238  heurtiming &= ~SCIP_HEURTIMING_AFTERNODE;
239 
240  /* we are in plunging mode iff the next node is a sibling or a child, and no leaf */
241  assert(nextnode == NULL
242  || SCIPnodeGetType(nextnode) == SCIP_NODETYPE_SIBLING
243  || SCIPnodeGetType(nextnode) == SCIP_NODETYPE_CHILD
244  || SCIPnodeGetType(nextnode) == SCIP_NODETYPE_LEAF);
245  plunging = (nextnode != NULL && SCIPnodeGetType(nextnode) != SCIP_NODETYPE_LEAF);
246  pseudonode = !SCIPtreeHasFocusNodeLP(tree);
247  if( plunging && SCIPtreeGetCurrentDepth(tree) > 0 ) /* call plunging heuristics also at root node */
248  {
249  if( !pseudonode )
250  heurtiming |= SCIP_HEURTIMING_AFTERLPNODE;
251  else
252  heurtiming |= SCIP_HEURTIMING_AFTERPSEUDONODE;
253  }
254  else
255  {
256  if( !pseudonode )
258  else
260  }
261  }
262 
263  /* initialize the tree related data, if we are not in presolving */
264  if( heurtiming == SCIP_HEURTIMING_BEFOREPRESOL || heurtiming == SCIP_HEURTIMING_DURINGPRESOLLOOP )
265  {
266  depth = -1;
267  lpstateforkdepth = -1;
268 
269  SCIPsetDebugMsg(set, "calling primal heuristics %s presolving\n",
270  heurtiming == SCIP_HEURTIMING_BEFOREPRESOL ? "before" : "during");
271  }
272  else
273  {
274  assert(tree != NULL); /* for lint */
275  depth = SCIPtreeGetFocusDepth(tree);
276  lpstateforkdepth = (tree->focuslpstatefork != NULL ? SCIPnodeGetDepth(tree->focuslpstatefork) : -1);
277 
278  SCIPsetDebugMsg(set, "calling primal heuristics in depth %d (timing: %u)\n", depth, heurtiming);
279  }
280 
281  /* call heuristics */
282  ndelayedheurs = 0;
283  oldnbestsolsfound = primal->nbestsolsfound;
284 
285 #ifndef NDEBUG
286  /* remember old probing and diving status */
287  inprobing = tree != NULL && SCIPtreeProbing(tree);
288  indiving = lp != NULL && SCIPlpDiving(lp);
289 
290  /* heuristics should currently not be called in diving mode */
291  assert(!indiving);
292 #endif
293 
294  /* collect lower bound of current node */
295  if( tree != NULL )
296  {
297  assert(SCIPtreeGetFocusNode(tree) != NULL);
298  lowerbound = SCIPnodeGetLowerbound(SCIPtreeGetFocusNode(tree));
299  }
300  else if( lp != NULL )
301  lowerbound = SCIPlpGetPseudoObjval(lp, set, prob);
302  else
303  lowerbound = -SCIPsetInfinity(set);
304 
305  for( h = 0; h < set->nheurs; ++h )
306  {
307 #ifndef NDEBUG
308  size_t nusedbuffer = BMSgetNUsedBufferMemory(SCIPbuffer(set->scip));
309 #endif
310  /* it might happen that a diving heuristic renders the previously solved node LP invalid
311  * such that additional calls to LP heuristics will fail; better abort the loop in this case
312  */
313  if( lp != NULL && lp->resolvelperror)
314  break;
315 
316 #ifdef SCIP_DEBUG
317  {
318  SCIP_Bool delayed;
319  if( SCIPheurShouldBeExecuted(set->heurs[h], depth, lpstateforkdepth, heurtiming, &delayed) )
320  {
321  SCIPsetDebugMsg(set, " -> executing heuristic <%s> with priority %d\n",
322  SCIPheurGetName(set->heurs[h]), SCIPheurGetPriority(set->heurs[h]));
323  }
324  }
325 #endif
326 
327  SCIP_CALL( SCIPheurExec(set->heurs[h], set, primal, depth, lpstateforkdepth, heurtiming, nodeinfeasible,
328  &ndelayedheurs, &result) );
329 
330 #ifndef NDEBUG
331  if( BMSgetNUsedBufferMemory(SCIPbuffer(set->scip)) > nusedbuffer )
332  {
333  SCIPerrorMessage("Buffer not completely freed after executing heuristic <%s>\n", SCIPheurGetName(set->heurs[h]));
334  SCIPABORT();
335  }
336 #endif
337 
338  /* if the new solution cuts off the current node due to a new primal solution (via the cutoff bound) interrupt
339  * calling the remaining heuristics
340  */
341  if( (result == SCIP_FOUNDSOL && lowerbound > primal->cutoffbound) || SCIPsolveIsStopped(set, stat, FALSE) )
342  break;
343 
344  /* check if the problem is proven to be unbounded, currently this happens only in reoptimization */
345  if( result == SCIP_UNBOUNDED )
346  {
347  *unbounded = TRUE;
348  break;
349  }
350 
351  /* make sure that heuristic did not change probing or diving status */
352  assert(tree == NULL || inprobing == SCIPtreeProbing(tree));
353  assert(lp == NULL || indiving == SCIPlpDiving(lp));
354  }
355  assert(0 <= ndelayedheurs && ndelayedheurs <= set->nheurs);
356 
357  *foundsol = (primal->nbestsolsfound > oldnbestsolsfound);
358 
359  return SCIP_OKAY;
360 }
361 
362 /** applies one round of propagation */
363 static
365  BMS_BLKMEM* blkmem, /**< block memory buffers */
366  SCIP_SET* set, /**< global SCIP settings */
367  SCIP_STAT* stat, /**< dynamic problem statistics */
368  SCIP_PRIMAL* primal, /**< primal data */
369  SCIP_TREE* tree, /**< branch and bound tree */
370  int depth, /**< depth level to use for propagator frequency checks */
371  SCIP_Bool fullpropagation, /**< should all constraints be propagated (or only new ones)? */
372  SCIP_Bool onlydelayed, /**< should only delayed propagators be called? */
373  SCIP_Bool* delayed, /**< pointer to store whether a propagator was delayed */
374  SCIP_Bool* propagain, /**< pointer to store whether propagation should be applied again */
375  SCIP_PROPTIMING timingmask, /**< timing mask to decide which propagators are executed */
376  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
377  SCIP_Bool* postpone /**< pointer to store whether the node should be postponed */
378  )
379 { /*lint --e{715}*/
380  SCIP_RESULT result;
381  SCIP_Bool abortoncutoff;
382  int i;
383 
384  assert(set != NULL);
385  assert(delayed != NULL);
386  assert(propagain != NULL);
387  assert(cutoff != NULL);
388  assert(postpone != NULL);
389 
390  *delayed = FALSE;
391  *propagain = FALSE;
392 
393  /* sort propagators */
394  SCIPsetSortProps(set);
395 
396  /* check if we want to abort on a cutoff; if we are not in the solving stage (e.g., in presolving), we want to abort
397  * anyway
398  */
399  abortoncutoff = set->prop_abortoncutoff || (set->stage != SCIP_STAGE_SOLVING);
400 
401  /* call additional propagators with nonnegative priority */
402  for( i = 0; i < set->nprops && !(*postpone) && (!(*cutoff) || !abortoncutoff); ++i )
403  {
404 #ifndef NDEBUG
405  size_t nusedbuffer = BMSgetNUsedBufferMemory(SCIPbuffer(set->scip));
406 #endif
407  /* timing needs to fit */
408  if( (SCIPpropGetTimingmask(set->props[i]) & timingmask) == 0 )
409  continue;
410 
411  if( SCIPpropGetPriority(set->props[i]) < 0 )
412  continue;
413 
414  if( onlydelayed && !SCIPpropWasDelayed(set->props[i]) )
415  continue;
416 
417  SCIPsetDebugMsg(set, "calling propagator <%s>\n", SCIPpropGetName(set->props[i]));
418 
419  SCIP_CALL( SCIPpropExec(set->props[i], set, stat, depth, onlydelayed, tree->sbprobing, timingmask, &result) );
420 
421 #ifndef NDEBUG
422  if( BMSgetNUsedBufferMemory(SCIPbuffer(set->scip)) > nusedbuffer )
423  {
424  SCIPerrorMessage("Buffer not completely freed after executing propagator <%s>\n", SCIPpropGetName(set->props[i]));
425  SCIPABORT();
426  }
427 #endif
428 
429  *delayed = *delayed || (result == SCIP_DELAYED);
430  *propagain = *propagain || (result == SCIP_REDUCEDDOM);
431 
432  /* beside the result pointer of the propagator we have to check if an internal cutoff was detected; this can
433  * happen when a global bound change was applied which is globally valid and leads locally (for the current node
434  * and others) to an infeasible problem;
435  */
436  *cutoff = *cutoff || (result == SCIP_CUTOFF) || (tree->cutoffdepth <= SCIPtreeGetCurrentDepth(tree));
437  *postpone = (result == SCIP_DELAYNODE) && !(*cutoff);
438 
439  if( result == SCIP_CUTOFF )
440  {
441  SCIPsetDebugMsg(set, " -> propagator <%s> detected cutoff\n", SCIPpropGetName(set->props[i]));
442  }
443 
444  /* if we work off the delayed propagators, we stop immediately if a reduction was found */
445  if( onlydelayed && result == SCIP_REDUCEDDOM )
446  {
447  *delayed = TRUE;
448  return SCIP_OKAY;
449  }
450  }
451 
452  /* propagate constraints */
453  for( i = 0; i < set->nconshdlrs && !(*postpone) && (!(*cutoff) || !abortoncutoff); ++i )
454  {
455  /* timing needs to fit */
456  if( (SCIPconshdlrGetPropTiming(set->conshdlrs[i]) & timingmask) == 0 )
457  continue;
458 
459  if( onlydelayed && !SCIPconshdlrWasPropagationDelayed(set->conshdlrs[i]) )
460  continue;
461 
462  SCIPsetDebugMsg(set, "calling propagation method of constraint handler <%s>\n", SCIPconshdlrGetName(set->conshdlrs[i]));
463 
464  SCIP_CALL( SCIPconshdlrPropagate(set->conshdlrs[i], blkmem, set, stat, depth, fullpropagation, onlydelayed,
465  tree->sbprobing, timingmask, &result) );
466  *delayed = *delayed || (result == SCIP_DELAYED);
467  *propagain = *propagain || (result == SCIP_REDUCEDDOM);
468 
469  /* beside the result pointer of the propagator we have to check if an internal cutoff was detected; this can
470  * happen when a global bound change was applied which is globally valid and leads locally (for the current node
471  * and others) to an infeasible problem;
472  */
473  *cutoff = *cutoff || (result == SCIP_CUTOFF) || (tree->cutoffdepth <= SCIPtreeGetCurrentDepth(tree));
474  *postpone = (result == SCIP_DELAYNODE) && !(*cutoff);
475 
476  if( result == SCIP_CUTOFF )
477  {
478  SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in propagation\n",
479  SCIPconshdlrGetName(set->conshdlrs[i]));
480  }
481 
482  /* if we work off the delayed propagators, we stop immediately if a reduction was found */
483  if( onlydelayed && result == SCIP_REDUCEDDOM )
484  {
485  *delayed = TRUE;
486  return SCIP_OKAY;
487  }
488  }
489 
490  /* call additional propagators with negative priority */
491  for( i = 0; i < set->nprops && !(*postpone) && (!(*cutoff) || !abortoncutoff); ++i )
492  {
493  /* timing needs to fit */
494  if( (SCIPpropGetTimingmask(set->props[i]) & timingmask) == 0 )
495  continue;
496 
497  if( SCIPpropGetPriority(set->props[i]) >= 0 )
498  continue;
499 
500  if( onlydelayed && !SCIPpropWasDelayed(set->props[i]) )
501  continue;
502 
503  SCIPsetDebugMsg(set, "calling propagator <%s>\n", SCIPpropGetName(set->props[i]));
504 
505  SCIP_CALL( SCIPpropExec(set->props[i], set, stat, depth, onlydelayed, tree->sbprobing, timingmask, &result) );
506  *delayed = *delayed || (result == SCIP_DELAYED);
507  *propagain = *propagain || (result == SCIP_REDUCEDDOM);
508 
509  /* beside the result pointer of the propagator we have to check if an internal cutoff was detected; this can
510  * happen when a global bound change was applied which is globally valid and leads locally (for the current node
511  * and others) to an infeasible problem;
512  */
513  *cutoff = *cutoff || (result == SCIP_CUTOFF) || (tree->cutoffdepth <= SCIPtreeGetCurrentDepth(tree));
514  *postpone = (result == SCIP_DELAYNODE) && !(*cutoff);
515 
516  if( result == SCIP_CUTOFF )
517  {
518  SCIPsetDebugMsg(set, " -> propagator <%s> detected cutoff\n", SCIPpropGetName(set->props[i]));
519  }
520 
521  /* if we work off the delayed propagators, we stop immediately if a reduction was found */
522  if( onlydelayed && result == SCIP_REDUCEDDOM )
523  {
524  *delayed = TRUE;
525  return SCIP_OKAY;
526  }
527  }
528 
529  return SCIP_OKAY;
530 }
531 
532 /** applies domain propagation on current node */
533 static
535  BMS_BLKMEM* blkmem, /**< block memory buffers */
536  SCIP_SET* set, /**< global SCIP settings */
537  SCIP_STAT* stat, /**< dynamic problem statistics */
538  SCIP_PRIMAL* primal, /**< primal data */
539  SCIP_TREE* tree, /**< branch and bound tree */
540  int depth, /**< depth level to use for propagator frequency checks */
541  int maxproprounds, /**< maximal number of propagation rounds (-1: no limit, 0: parameter settings) */
542  SCIP_Bool fullpropagation, /**< should all constraints be propagated (or only new ones)? */
543  SCIP_PROPTIMING timingmask, /**< timing mask to decide which propagators are executed */
544  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
545  SCIP_Bool* postpone /**< pointer to store whether the node should be postponed */
546  )
547 {
548  SCIP_NODE* node;
549  SCIP_Bool delayed;
550  SCIP_Bool propagain;
551  int propround;
552 
553  assert(set != NULL);
554  assert(tree != NULL);
555  assert(depth >= 0);
556  assert(cutoff != NULL);
557 
558  node = SCIPtreeGetCurrentNode(tree);
559  assert(node != NULL && SCIPnodeIsActive(node));
563 
564  /* adjust maximal number of propagation rounds */
565  if( maxproprounds == 0 )
566  maxproprounds = (depth == 0 ? set->prop_maxroundsroot : set->prop_maxrounds);
567  if( maxproprounds == -1 )
568  maxproprounds = INT_MAX;
569 
570  SCIPsetDebugMsg(set, "domain propagation of node %p in depth %d (using depth %d, maxrounds %d, proptiming %u)\n",
571  (void*)node, SCIPnodeGetDepth(node), depth, maxproprounds, timingmask);
572 
573  /* propagate as long new bound changes were found and the maximal number of propagation rounds is not exceeded */
574  *cutoff = FALSE;
575  *postpone = FALSE;
576  propround = 0;
577  propagain = TRUE;
578  while( propagain && !(*cutoff) && !(*postpone) && propround < maxproprounds && !SCIPsolveIsStopped(set, stat, FALSE) )
579  {
580  propround++;
581 
582  /* perform the propagation round by calling the propagators and constraint handlers */
583  SCIP_CALL( propagationRound(blkmem, set, stat, primal, tree, depth, fullpropagation, FALSE, &delayed, &propagain, timingmask, cutoff, postpone) );
584 
585  /* if the propagation will be terminated, call the delayed propagators */
586  while( delayed && (!propagain || propround >= maxproprounds) && !(*cutoff) )
587  {
588  /* call the delayed propagators and constraint handlers */
589  SCIP_CALL( propagationRound(blkmem, set, stat, primal, tree, depth, fullpropagation, TRUE, &delayed, &propagain, timingmask, cutoff, postpone) );
590  }
591 
592  /* if a reduction was found, we want to do another full propagation round (even if the propagator only claimed
593  * to have done a domain reduction without applying a domain change)
594  */
595  fullpropagation = TRUE;
596  }
597 
598  /* mark the node to be completely propagated in the current repropagation subtree level */
599  SCIPnodeMarkPropagated(node, tree);
600 
601  if( *cutoff )
602  {
603  SCIPsetDebugMsg(set, " --> domain propagation of node %p finished: cutoff!\n", (void*)node);
604  }
605 
606  return SCIP_OKAY;
607 }
608 
609 /** applies domain propagation on current node and flushes the conflict store afterwards */
611  BMS_BLKMEM* blkmem, /**< block memory buffers */
612  SCIP_SET* set, /**< global SCIP settings */
613  SCIP_STAT* stat, /**< dynamic problem statistics */
614  SCIP_PROB* transprob, /**< transformed problem */
615  SCIP_PROB* origprob, /**< original problem */
616  SCIP_PRIMAL* primal, /**< primal data */
617  SCIP_TREE* tree, /**< branch and bound tree */
618  SCIP_REOPT* reopt, /**< reoptimization data structure */
619  SCIP_LP* lp, /**< LP data */
620  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
621  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
622  SCIP_CONFLICT* conflict, /**< conflict analysis data */
623  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
624  int depth, /**< depth level to use for propagator frequency checks */
625  int maxproprounds, /**< maximal number of propagation rounds (-1: no limit, 0: parameter settings) */
626  SCIP_PROPTIMING timingmask, /**< timing mask to decide which propagators are executed */
627  SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
628  )
629 {
630  SCIP_Bool postpone;
631 
632  /* apply domain propagation */
633  SCIP_CALL( propagateDomains(blkmem, set, stat, primal, tree, depth, maxproprounds, TRUE, timingmask, cutoff, &postpone) );
634 
635  /* flush the conflict set storage */
636  SCIP_CALL( SCIPconflictFlushConss(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cliquetable) );
637 
638  return SCIP_OKAY;
639 }
640 
641 /** returns whether the given variable with the old LP solution value should lead to an update of the pseudo cost entry */
642 static
644  SCIP_VAR* var, /**< problem variable */
645  SCIP_SET* set, /**< global SCIP settings */
646  SCIP_Real oldlpsolval, /**< solution value of variable in old LP */
647  SCIP_Bool updateintegers, /**< whether to update pseudo costs for integer variables */
648  SCIP_Bool updatecontinuous /**< whether to update pseudo costs for continuous variables */
649  )
650 {
651  SCIP_Real newlpsolval;
652 
653  assert(var != NULL);
654 
655  if( !updatecontinuous && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
656  return FALSE;
657 
658  if( !updateintegers && SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS )
659  return FALSE;
660 
661  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS && set->branch_lpgainnorm != 'l' )
662  {
663  /* if the variable is fixed at +/- infinity or it has an unbounded domain, then the domain-based update strategies will not work */
665  return FALSE;
666 
667  /* @todo if set->branch_lpgainnorm == 's', then we would need to know then domain before branching
668  * since this is difficult to get, we don't check for unboundedness here and let the pscost update fail later
669  * however, this makes the weights used to spread a pseudo cost update over all domain changes inaccurate
670  */
671 
672  return TRUE;
673  }
674 
675  /* if the old LP solution value is unknown, the pseudo cost update cannot be performed */
676  if( oldlpsolval >= SCIP_INVALID )
677  return FALSE;
678 
679  /* the bound change on the given variable was responsible for the gain in the dual bound, if the variable's
680  * old solution value is outside the current bounds, and the new solution value is equal to the bound
681  * closest to the old solution value
682  */
683 
684  /* find out, which of the current bounds is violated by the old LP solution value */
685  if( SCIPsetIsLT(set, oldlpsolval, SCIPvarGetLbLocal(var)) )
686  {
687  newlpsolval = SCIPvarGetLPSol(var);
688  return SCIPsetIsEQ(set, newlpsolval, SCIPvarGetLbLocal(var));
689  }
690  else if( SCIPsetIsGT(set, oldlpsolval, SCIPvarGetUbLocal(var)) )
691  {
692  newlpsolval = SCIPvarGetLPSol(var);
693  return SCIPsetIsEQ(set, newlpsolval, SCIPvarGetUbLocal(var));
694  }
695  else
696  return FALSE;
697 }
698 
699 /** pseudo cost flag stored in the variables to mark them for the pseudo cost update */
701 {
702  PSEUDOCOST_NONE = 0, /**< variable's bounds were not changed */
703  PSEUDOCOST_IGNORE = 1, /**< bound changes on variable should be ignored for pseudo cost updates */
704  PSEUDOCOST_UPDATE = 2 /**< pseudo cost value of variable should be updated */
705 };
707 
708 /** updates the variable's pseudo cost values after the node's initial LP was solved */
709 static
711  SCIP_SET* set, /**< global SCIP settings */
712  SCIP_STAT* stat, /**< dynamic problem statistics */
713  SCIP_PROB* prob, /**< transformed problem after presolve */
714  SCIP_TREE* tree, /**< branch and bound tree */
715  SCIP_LP* lp, /**< LP data */
716  SCIP_Bool updateintegers, /**< whether to update pseudo costs for integer variables */
717  SCIP_Bool updatecontinuous /**< whether to update pseudo costs for continuous variables */
718  )
719 {
720  SCIP_NODE* focusnode;
721  int actdepth;
722 
723  assert(lp != NULL);
724  assert(tree != NULL);
725  assert(tree->path != NULL);
726 
727  focusnode = SCIPtreeGetFocusNode(tree);
728  assert(SCIPnodeIsActive(focusnode));
729  assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
730  actdepth = SCIPnodeGetDepth(focusnode);
731  assert(tree->path[actdepth] == focusnode);
732 
733  if( (updateintegers || updatecontinuous) && lp->solved && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && tree->focuslpstatefork != NULL )
734  {
735  SCIP_BOUNDCHG** updates;
736  SCIP_NODE* node;
737  SCIP_VAR* var;
738  SCIP_Real weight;
739  SCIP_Real lpgain;
740  int nupdates;
741  int nvalidupdates;
742  int d;
743  int i;
744 
745  assert(SCIPnodeIsActive(tree->focuslpstatefork));
746  assert(tree->path[tree->focuslpstatefork->depth] == tree->focuslpstatefork);
747 
748  /* get a buffer for the collected bound changes; start with a size twice as large as the number of nodes between
749  * current node and LP fork
750  */
751  SCIP_CALL( SCIPsetAllocBufferArray(set, &updates, (int)(2*(actdepth - tree->focuslpstatefork->depth))) );
752  nupdates = 0;
753  nvalidupdates = 0;
754 
755  /* search the nodes from LP fork down to current node for bound changes in between; move in this direction,
756  * because the bound changes closer to the LP fork are more likely to have a valid LP solution information
757  * attached; collect the bound changes for pseudo cost value updates and mark the corresponding variables such
758  * that they are not updated twice in case of more than one bound change on the same variable
759  */
760  for( d = tree->focuslpstatefork->depth+1; d <= actdepth; ++d )
761  {
762  node = tree->path[d];
763 
764  if( node->domchg != NULL )
765  {
766  SCIP_BOUNDCHG* boundchgs;
767  int nboundchgs;
768 
769  boundchgs = node->domchg->domchgbound.boundchgs;
770  nboundchgs = node->domchg->domchgbound.nboundchgs;
771  for( i = 0; i < nboundchgs; ++i )
772  {
773  var = boundchgs[i].var;
774  assert(var != NULL);
775 
776  /* we even collect redundant bound changes, since they were not redundant in the LP branching decision
777  * and therefore should be regarded in the pseudocost updates
778  *
779  * however, if the variable is continuous and we normalize the pseudo costs by the domain reduction,
780  * then getting the variable bound before the branching is not possible by looking at the variables branching information (since redundant branchings are not applied)
781  * thus, in this case we ignore the boundchange
782  */
783  if( (SCIP_BOUNDCHGTYPE)boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING &&
785  )
786  {
787  /* remember the bound change and mark the variable */
788  SCIP_CALL( SCIPsetReallocBufferArray(set, &updates, nupdates+1) );
789  updates[nupdates] = &boundchgs[i];
790  nupdates++;
791 
792  /* check, if the bound change would lead to a valid pseudo cost update
793  * and see comment above (however, ...) */
794  if( isPseudocostUpdateValid(var, set, boundchgs[i].data.branchingdata.lpsolval, updateintegers, updatecontinuous) &&
795  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS || !boundchgs[i].redundant || set->branch_lpgainnorm != 'd')
796  )
797  {
798  var->pseudocostflag = PSEUDOCOST_UPDATE; /*lint !e641*/
799  nvalidupdates++;
800  }
801  else
802  var->pseudocostflag = PSEUDOCOST_IGNORE; /*lint !e641*/
803  }
804  }
805  }
806  }
807 
808  /* update the pseudo cost values and reset the variables' flags; assume, that the responsibility for the dual gain
809  * is equally spread on all bound changes that lead to valid pseudo cost updates
810  */
812  weight = (nvalidupdates > 0 ? 1.0 / (SCIP_Real)nvalidupdates : 1.0);
813  lpgain = (SCIPlpGetObjval(lp, set, prob) - tree->focuslpstatefork->data.fork->lpobjval) * weight;
814  lpgain = MAX(lpgain, 0.0);
815 
816  for( i = 0; i < nupdates; ++i )
817  {
818  assert((SCIP_BOUNDCHGTYPE)updates[i]->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING);
819 
820  var = updates[i]->var;
821  assert(var != NULL);
823 
825  {
826  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS || set->branch_lpgainnorm == 'l' )
827  {
828  SCIPsetDebugMsg(set, "updating pseudocosts of <%s>: sol: %g -> %g, LP: %e -> %e => solvaldelta = %g, gain=%g, weight: %g\n",
829  SCIPvarGetName(var), updates[i]->data.branchingdata.lpsolval, SCIPvarGetLPSol(var),
830  tree->focuslpstatefork->data.fork->lpobjval, SCIPlpGetObjval(lp, set, prob),
831  SCIPvarGetLPSol(var) - updates[i]->data.branchingdata.lpsolval, lpgain, weight);
832  SCIP_CALL( SCIPvarUpdatePseudocost(var, set, stat,
833  SCIPvarGetLPSol(var) - updates[i]->data.branchingdata.lpsolval, lpgain, weight) );
834  }
835  else
836  {
837  /* set->branch_lpgainnorm == 'd':
838  * For continuous variables, we want to pseudocosts to be the average of the gain in the LP value
839  * if the domain is reduced from x% of its original width to y% of its original (e.g., global) width, i.e.,
840  * to be the average of LPgain / (oldwidth/origwidth - newwidth/origwidth) = LPgain * origwidth / (oldwidth - newwidth).
841  * Then an expected improvement in the LP value by a reduction of the domain width
842  * from x% to y% of its original width can be computed by pseudocost * (oldwidth - newwidth) / origwidth.
843  * Since the original width cancels out, we can also define the pseudocosts as average of LPgain / (oldwidth - newwidth)
844  * and compute the expected improvement as pseudocost * (oldwidth - newwidth).
845  *
846  * Let var have bounds [a,c] before the branching and assume we branched on some value b.
847  * b is given by updates[i]->newbound.
848  *
849  * If updates[i]->boundtype = upper, then node corresponds to the child [a,b].
850  * Thus, we have oldwidth = c-a, newwidth = b-a, and oldwidth - newwidth = c-b.
851  * To get c (the previous upper bound), we look into the var->ubchginfos array.
852  *
853  * If updates[i]->boundtype = lower, then node corresponds to the child [b,c].
854  * Thus, we have oldwidth = c-a, newwidth = c-b, and oldwidth - newwidth = b-a.
855  * To get c (the previous lower bound), we look into the var->lbchginfos array.
856  */
857  SCIP_BDCHGINFO* bdchginfo;
858  SCIP_Real oldbound;
859  SCIP_Real delta;
860  int j;
861  int nbdchginfos;
862 
863  assert(set->branch_lpgainnorm == 'd' || set->branch_lpgainnorm == 's');
864 
865  oldbound = SCIP_INVALID;
866 
867  if( set->branch_lpgainnorm == 'd' )
868  {
869  assert(!updates[i]->redundant);
870 
871  if( (SCIP_BOUNDTYPE)updates[i]->boundtype == SCIP_BOUNDTYPE_UPPER )
872  {
873  nbdchginfos = SCIPvarGetNBdchgInfosUb(var);
874 
875  /* walk backwards through bound change information array to find the bound change corresponding to branching in updates[i]
876  * usually it will be the first one we look at */
877  for( j = nbdchginfos-1; j >= 0; --j )
878  {
879  bdchginfo = SCIPvarGetBdchgInfoUb(var, j);
880 
881  if( bdchginfo->oldbound > updates[i]->newbound )
882  {
883  /* first boundchange which upper bound is above the upper bound set by the branching in updates[i]
884  * if bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING, then this should be exactly the bound change that we are looking for
885  * if bdchginfo->boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING, then this should be because the branching domain change has not been applied to the variable due to redundancy
886  * in this case, i.e., if there was another boundchange coming from somewhere else, I am not sure whether oldbound is an accurate value to compute the old domain size, so we skip the pseudocosts update
887  */
889  {
890  assert(bdchginfo->newbound == updates[i]->newbound); /*lint !e777*/
891  oldbound = bdchginfo->oldbound;
892  }
893  else
894  assert(updates[i]->redundant);
895 
896  break;
897  }
898  }
899  /* if the bound change was redundant (e.g., due to a change in the global bound), then it was not applied, so there exists no corresponding bound change info
900  * if it is not redundant, then we should have found at least one corresponding boundchange */
901  assert(j >= 0 || updates[i]->redundant);
902  if( oldbound != SCIP_INVALID ) /*lint !e777*/
903  {
904  assert(!SCIPsetIsInfinity(set, -oldbound)); /* branching on a variable fixed to -infinity does not make sense */
905  assert(!SCIPsetIsInfinity(set, updates[i]->newbound)); /* branching to infinity does not make sense */
906 
907  /* if the old upper bound is at infinity or the new upper bound is at -infinity, then we say the delta (c-b) is infinity */
908  if( SCIPsetIsInfinity(set, oldbound) || SCIPsetIsInfinity(set, -updates[i]->newbound) )
909  delta = SCIP_INVALID;
910  else
911  delta = updates[i]->newbound - oldbound;
912  }
913  else
914  delta = SCIP_INVALID;
915 
916  }
917  else
918  {
919  assert((SCIP_BOUNDTYPE)updates[i]->boundtype == SCIP_BOUNDTYPE_LOWER);
920  nbdchginfos = SCIPvarGetNBdchgInfosLb(var);
921 
922  /* walk backwards through bound change information array to find the bound change corresponding to branching in updates[i]
923  * usually it will be the first one we look at */
924  for( j = nbdchginfos-1; j >= 0; --j )
925  {
926  bdchginfo = SCIPvarGetBdchgInfoLb(var, j);
927 
928  if( bdchginfo->oldbound < updates[i]->newbound )
929  {
930  /* first boundchange which lower bound is below the lower bound set by the branching in updates[i]
931  * if bdchginfo->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING, then this should be exactly the bound change that we are looking for
932  * if bdchginfo->boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING, then this should be because the branching domain change has not been applied to the variable due to redundancy
933  * in this case, i.e., if there was another boundchange coming from somewhere else, I am not sure whether oldbound is an accurate value to compute the old domain size, so we skip the pseudocosts update
934  */
936  {
937  assert(bdchginfo->newbound == updates[i]->newbound); /*lint !e777*/
938  oldbound = bdchginfo->oldbound;
939  }
940  else
941  assert(updates[i]->redundant);
942 
943  break;
944  }
945  }
946  /* if the bound change was redundant (e.g., due to a change in the global bound), then it was not applied, so there exists no corresponding bound change info
947  * if it is not redundant, then we should have found at least one corresponding boundchange */
948  assert(j >= 0 || updates[i]->redundant);
949  if( oldbound != SCIP_INVALID ) /*lint !e777*/
950  {
951  assert(!SCIPsetIsInfinity(set, oldbound)); /* branching on a variable fixed to +infinity does not make sense */
952  assert(!SCIPsetIsInfinity(set, -updates[i]->newbound)); /* branching to infinity does not make sense */
953 
954  /* if the old lower bound is at -infinity or the new lower bound is at +infinity, then we say the delta (b-a) is infinity */
955  if( SCIPsetIsInfinity(set, -oldbound) || SCIPsetIsInfinity(set, updates[i]->newbound) )
956  delta = SCIP_INVALID;
957  else
958  delta = updates[i]->newbound - oldbound;
959  }
960  else
961  delta = SCIP_INVALID;
962  }
963  }
964  else
965  {
966  /* set->branch_lpgainnorm == 's':
967  * Here, we divide the LPgain by the reduction in the sibling node.
968  *
969  * If updates[i]->boundtype = upper, then node corresponds to the child [a,b].
970  * Thus, we have oldwidth = c-a, newwidth = c-b, and oldwidth - newwidth = b-a.
971  * Conveniently, we just use the current lower bound for a (it may have been tightened, though).
972  *
973  * If updates[i]->boundtype = lower, then node corresponds to the child [b,a].
974  * Thus, we have oldwidth = c-a, newwidth = b-a, and oldwidth - newwidth = c-b.
975  * Conveniently, we just use the current upper bound for c (it may have been tightened, though).
976  */
977  if( (SCIP_BOUNDTYPE)updates[i]->boundtype == SCIP_BOUNDTYPE_UPPER )
978  {
979  assert(!SCIPsetIsInfinity(set, updates[i]->newbound)); /* branching on a variable fixed to +infinity does not make sense */
980  assert(!SCIPsetIsInfinity(set, SCIPvarGetLbLocal(var))); /* branching to infinity does not make sense */
981  if( SCIPsetIsInfinity(set, -updates[i]->newbound) || SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)) )
982  delta = SCIP_INVALID;
983  else
984  delta = updates[i]->newbound - SCIPvarGetLbLocal(var);
985  }
986  else
987  {
988  assert((SCIP_BOUNDTYPE)updates[i]->boundtype == SCIP_BOUNDTYPE_LOWER);
989  assert(!SCIPsetIsInfinity(set, -updates[i]->newbound)); /* branching on a variable fixed to -infinity does not make sense */
990  assert(!SCIPsetIsInfinity(set, -SCIPvarGetUbLocal(var))); /* branching to -infinity does not make sense */
991  if( SCIPsetIsInfinity(set, updates[i]->newbound) || SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)) )
992  delta = SCIP_INVALID;
993  else
994  delta = -(SCIPvarGetUbLocal(var) - updates[i]->newbound);
995  }
996  }
997 
998  if( delta != SCIP_INVALID ) /*lint !e777*/
999  {
1000  SCIPsetDebugMsg(set, "updating pseudocosts of <%s> with strategy %c: domain: [%g,%g] -> [%g,%g], LP: %e -> %e => "
1001  "delta = %g, gain=%g, weight: %g\n",
1002  SCIPvarGetName(var), set->branch_lpgainnorm,
1003  (SCIP_BOUNDTYPE)updates[i]->boundtype == SCIP_BOUNDTYPE_UPPER ? SCIPvarGetLbLocal(var) : oldbound,
1004  (SCIP_BOUNDTYPE)updates[i]->boundtype == SCIP_BOUNDTYPE_UPPER ? oldbound : SCIPvarGetUbLocal(var),
1005  (SCIP_BOUNDTYPE)updates[i]->boundtype == SCIP_BOUNDTYPE_UPPER ? SCIPvarGetLbLocal(var) : updates[i]->newbound,
1006  (SCIP_BOUNDTYPE)updates[i]->boundtype == SCIP_BOUNDTYPE_UPPER ? updates[i]->newbound : SCIPvarGetUbLocal(var),
1007  tree->focuslpstatefork->lowerbound, SCIPlpGetObjval(lp, set, prob),
1008  delta, lpgain, weight);
1009 
1010  SCIP_CALL( SCIPvarUpdatePseudocost(var, set, stat, delta, lpgain, weight) );
1011  }
1012  }
1013  }
1014  var->pseudocostflag = PSEUDOCOST_NONE; /*lint !e641*/
1015  }
1016 
1017  /* free the buffer for the collected bound changes */
1018  SCIPsetFreeBufferArray(set, &updates);
1019  }
1020 
1021  return SCIP_OKAY;
1022 }
1023 
1024 /** updates the estimated value of a primal feasible solution for the focus node after the LP was solved */
1025 static
1027  SCIP_SET* set, /**< global SCIP settings */
1028  SCIP_STAT* stat, /**< problem statistics */
1029  SCIP_TREE* tree, /**< branch and bound tree */
1030  SCIP_LP* lp, /**< current LP data */
1031  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
1032  )
1033 {
1034  SCIP_NODE* focusnode;
1035  SCIP_VAR** lpcands;
1036  SCIP_Real* lpcandsfrac;
1037  SCIP_Real estimate;
1038  int nlpcands;
1039  int i;
1040 
1041  /* estimate is only available if LP was solved to optimality */
1043  return SCIP_OKAY;
1044 
1045  focusnode = SCIPtreeGetFocusNode(tree);
1046  assert(focusnode != NULL);
1047 
1048  /* get the fractional variables */
1049  SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, &lpcands, NULL, &lpcandsfrac, &nlpcands, NULL, NULL) );
1050 
1051  /* calculate the estimate: lowerbound + sum(min{f_j * pscdown_j, (1-f_j) * pscup_j}) */
1052  estimate = SCIPnodeGetLowerbound(focusnode);
1053 
1054  /* an infinite lower bound implies an infinite estimate */
1055  if( SCIPsetIsInfinity(set, estimate) )
1056  {
1057  SCIPnodeSetEstimate(focusnode, set, estimate);
1058  return SCIP_OKAY;
1059  }
1060 
1061  for( i = 0; i < nlpcands; ++i )
1062  {
1063  SCIP_Real pscdown;
1064  SCIP_Real pscup;
1065 
1066  pscdown = SCIPvarGetPseudocost(lpcands[i], stat, 0.0-lpcandsfrac[i]);
1067  pscup = SCIPvarGetPseudocost(lpcands[i], stat, 1.0-lpcandsfrac[i]);
1068  estimate += MIN(pscdown, pscup);
1069  }
1070  SCIPnodeSetEstimate(focusnode, set, estimate);
1071 
1072  return SCIP_OKAY;
1073 }
1074 
1075 /** puts all constraints with initial flag TRUE into the LP */
1077  BMS_BLKMEM* blkmem, /**< block memory buffers */
1078  SCIP_SET* set, /**< global SCIP settings */
1079  SCIP_SEPASTORE* sepastore, /**< separation storage */
1080  SCIP_CUTPOOL* cutpool, /**< global cutpool */
1081  SCIP_STAT* stat, /**< dynamic problem statistics */
1082  SCIP_PROB* transprob, /**< transformed problem */
1083  SCIP_PROB* origprob, /**< original problem */
1084  SCIP_TREE* tree, /**< branch and bound tree */
1085  SCIP_REOPT* reopt, /**< reoptimization data structure */
1086  SCIP_LP* lp, /**< LP data */
1087  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1088  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1089  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1090  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1091  SCIP_Bool root, /**< is this the initial root LP? */
1092  SCIP_Bool firstsubtreeinit, /**< is this the first call in the current subtree after jumping through the tree? */
1093  SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
1094  )
1095 {
1096  int h;
1097 
1098  assert(set != NULL);
1099  assert(lp != NULL);
1100  assert(cutoff != NULL);
1101 
1102  *cutoff = FALSE;
1103 
1104  /* inform separation storage, that LP is now filled with initial data */
1105  SCIPsepastoreStartInitialLP(sepastore);
1106 
1107  /* add LP relaxations of all initial constraints to LP */
1108  SCIPsetDebugMsg(set, "init LP: initial rows\n");
1109  for( h = 0; h < set->nconshdlrs && !(*cutoff); ++h )
1110  {
1111  SCIP_CALL( SCIPconshdlrInitLP(set->conshdlrs[h], blkmem, set, stat, tree, firstsubtreeinit, cutoff) );
1112  }
1113 
1114  if( set->reopt_enable && set->reopt_usecuts && firstsubtreeinit && !(*cutoff) )
1115  {
1116  /* add stored cuts from last reoptimization run */
1117  SCIP_CALL( SCIPreoptApplyCuts(reopt, tree->focusnode, sepastore, cutpool, blkmem, set, stat, eventqueue,
1118  eventfilter, lp, root) );
1119  }
1120 
1121  if( !(*cutoff) )
1122  {
1123  /* apply cuts */
1124  SCIP_CALL( SCIPsepastoreApplyCuts(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
1125  eventqueue, eventfilter, cliquetable, root, SCIP_EFFICIACYCHOICE_LP, cutoff) );
1126  }
1127  else
1128  {
1129  /* the current node will be cut off; we clear the sepastore */
1130  SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
1131  }
1132 
1133 
1134  /* inform separation storage, that initial LP setup is now finished */
1135  SCIPsepastoreEndInitialLP(sepastore);
1136 
1137  return SCIP_OKAY;
1138 }
1139 
1140 /** constructs the initial LP of the current node */
1141 static
1143  BMS_BLKMEM* blkmem, /**< block memory buffers */
1144  SCIP_SET* set, /**< global SCIP settings */
1145  SCIP_STAT* stat, /**< dynamic problem statistics */
1146  SCIP_PROB* transprob, /**< transformed problem */
1147  SCIP_PROB* origprob, /**< original problem */
1148  SCIP_TREE* tree, /**< branch and bound tree */
1149  SCIP_REOPT* reopt, /**< reoptimization data structure */
1150  SCIP_LP* lp, /**< LP data */
1151  SCIP_PRICESTORE* pricestore, /**< pricing storage */
1152  SCIP_SEPASTORE* sepastore, /**< separation storage */
1153  SCIP_CUTPOOL* cutpool, /**< global cut pool */
1154  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1155  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1156  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1157  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1158  SCIP_Bool root, /**< is this the initial root LP? */
1159  SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
1160  )
1161 {
1162  SCIP_VAR* var;
1163  int v;
1164 
1165  assert(set != NULL);
1166  assert(transprob != NULL);
1167  assert(lp != NULL);
1168  assert(cutoff != NULL);
1169 
1170  *cutoff = FALSE;
1171 
1172  /* at the root node, we have to add the initial variables as columns */
1173  if( root )
1174  {
1175  assert(SCIPlpGetNCols(lp) == 0);
1176  assert(SCIPlpGetNRows(lp) == 0);
1177  assert(lp->nremovablecols == 0);
1178  assert(lp->nremovablerows == 0);
1179 
1180  /* inform pricing storage, that LP is now filled with initial data */
1181  SCIPpricestoreStartInitialLP(pricestore);
1182 
1183  /* add all initial variables to LP */
1184  SCIPsetDebugMsg(set, "init LP: initial columns\n");
1185  for( v = 0; v < transprob->nvars && !(*cutoff); ++v )
1186  {
1187  var = transprob->vars[v];
1188  assert(SCIPvarGetProbindex(var) >= 0);
1189 
1190  if( SCIPvarIsInitial(var) )
1191  {
1192  SCIP_CALL( SCIPpricestoreAddVar(pricestore, blkmem, set, eventqueue, lp, var, 0.0, TRUE) );
1193  }
1194 
1195  /* check for empty domains (necessary if no presolving was performed) */
1196  if( SCIPsetIsGT(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) )
1197  *cutoff = TRUE;
1198  }
1199  assert(lp->nremovablecols == 0);
1200  SCIP_CALL( SCIPpricestoreApplyVars(pricestore, blkmem, set, stat, eventqueue, transprob, tree, lp) );
1201 
1202  /* inform pricing storage, that initial LP setup is now finished */
1203  SCIPpricestoreEndInitialLP(pricestore);
1204  }
1205 
1206  if( *cutoff )
1207  return SCIP_OKAY;
1208 
1209  /* put all initial constraints into the LP */
1210  /* @todo check whether we jumped through the tree */
1211  SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
1212  eventfilter, cliquetable, root, TRUE, cutoff) );
1213 
1214  return SCIP_OKAY;
1215 }
1216 
1217 /** constructs the LP of the current node, but does not load the LP state and warmstart information */
1219  BMS_BLKMEM* blkmem, /**< block memory buffers */
1220  SCIP_SET* set, /**< global SCIP settings */
1221  SCIP_STAT* stat, /**< dynamic problem statistics */
1222  SCIP_PROB* transprob, /**< transformed problem */
1223  SCIP_PROB* origprob, /**< original problem */
1224  SCIP_TREE* tree, /**< branch and bound tree */
1225  SCIP_REOPT* reopt, /**< reoptimization data structure */
1226  SCIP_LP* lp, /**< LP data */
1227  SCIP_PRICESTORE* pricestore, /**< pricing storage */
1228  SCIP_SEPASTORE* sepastore, /**< separation storage */
1229  SCIP_CUTPOOL* cutpool, /**< global cutpool */
1230  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1231  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1232  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1233  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1234  SCIP_Bool newinitconss, /**< do we have to add new initial constraints? */
1235  SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
1236  )
1237 {
1238  SCIP_Bool initroot;
1239 
1240  assert(tree != NULL);
1241  assert(cutoff != NULL);
1242 
1243  *cutoff = FALSE;
1244 
1246  {
1247  /* load the LP into the solver and load the LP state */
1248  SCIPsetDebugMsg(set, "loading LP\n");
1249  SCIP_CALL( SCIPtreeLoadLP(tree, blkmem, set, eventqueue, eventfilter, lp, &initroot) );
1250  assert(initroot || SCIPnodeGetDepth(SCIPtreeGetFocusNode(tree)) > 0);
1251  assert(SCIPtreeIsFocusNodeLPConstructed(tree));
1252 
1253  /* setup initial LP relaxation of node */
1254  SCIP_CALL( initLP(blkmem, set, stat, transprob, origprob, tree, reopt, lp, pricestore, sepastore, cutpool, branchcand,
1255  eventqueue, eventfilter, cliquetable, initroot, cutoff) );
1256  }
1257  else if( newinitconss )
1258  {
1259  SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob,
1260  origprob, tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE,
1261  cutoff) );
1262  }
1263 
1264  return SCIP_OKAY;
1265 }
1266 
1267 /** updates the primal ray stored in primal data
1268  * clears previously stored primal ray, if existing and there was no LP error
1269  * stores current primal ray, if LP is unbounded and there has been no error
1270  */
1271 static
1273  BMS_BLKMEM* blkmem, /**< block memory buffers */
1274  SCIP_SET* set, /**< global SCIP settings */
1275  SCIP_STAT* stat, /**< dynamic problem statistics */
1276  SCIP_PROB* prob, /**< transformed problem after presolve */
1277  SCIP_PRIMAL* primal, /**< primal data */
1278  SCIP_TREE* tree, /**< branch and bound tree */
1279  SCIP_LP* lp, /**< LP data */
1280  SCIP_Bool lperror /**< has there been an LP error? */
1281  )
1282 {
1283  assert(blkmem != NULL);
1284  assert(set != NULL);
1285  assert(stat != NULL);
1286  assert(prob != NULL);
1287  assert(primal != NULL);
1288  assert(tree != NULL);
1289  assert(lp != NULL);
1290 
1291  if( lperror )
1292  return SCIP_OKAY;
1293 
1294  /* clear previously stored primal ray, if any */
1295  if( primal->primalray != NULL )
1296  {
1297  SCIP_CALL( SCIPsolFree(&primal->primalray, blkmem, primal) );
1298  }
1299 
1300  /* store unbounded ray, if LP is unbounded */
1302  {
1303  SCIP_VAR** vars;
1304  SCIP_Real* ray;
1305  int nvars;
1306  int i;
1307 
1308  SCIPsetDebugMsg(set, "LP is unbounded, store primal ray\n");
1309 
1310  vars = prob->vars;
1311  nvars = prob->nvars;
1312 
1313  /* get buffer memory for storing the ray and load the ray values into it */
1314  SCIP_CALL( SCIPsetAllocBufferArray(set, &ray, nvars) );
1315  BMSclearMemoryArray(ray, nvars);
1316  SCIP_CALL( SCIPlpGetPrimalRay(lp, set, ray) );
1317 
1318  /* create solution to store the primal ray in */
1319  assert(primal->primalray == NULL);
1320  SCIP_CALL( SCIPsolCreate(&primal->primalray, blkmem, set, stat, primal, tree, NULL) );
1321 
1322  /* set values of all active variable in the solution that represents the primal ray */
1323  for( i = 0; i < nvars; i++ )
1324  {
1325  SCIP_CALL( SCIPsolSetVal(primal->primalray, set, stat, tree, vars[i], ray[i]) );
1326  }
1327 
1328  SCIPdebug( SCIP_CALL( SCIPprintRay(set->scip, primal->primalray, NULL, FALSE) ) );
1329 
1330  /* free memory for buffering the ray values */
1331  SCIPsetFreeBufferArray(set, &ray);
1332  }
1333 
1334  return SCIP_OKAY;
1335 }
1336 
1337 /** load and solve the initial LP of a node */
1338 static
1340  BMS_BLKMEM* blkmem, /**< block memory buffers */
1341  SCIP_SET* set, /**< global SCIP settings */
1342  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1343  SCIP_STAT* stat, /**< dynamic problem statistics */
1344  SCIP_PROB* transprob, /**< transformed problem after presolve */
1345  SCIP_PROB* origprob, /**< original problem */
1346  SCIP_PRIMAL* primal, /**< primal data */
1347  SCIP_TREE* tree, /**< branch and bound tree */
1348  SCIP_REOPT* reopt, /**< reoptimization data structure */
1349  SCIP_LP* lp, /**< LP data */
1350  SCIP_PRICESTORE* pricestore, /**< pricing storage */
1351  SCIP_SEPASTORE* sepastore, /**< separation storage */
1352  SCIP_CUTPOOL* cutpool, /**< global cutpool */
1353  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1354  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1355  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1356  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1357  SCIP_Bool newinitconss, /**< do we have to add new initial constraints? */
1358  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
1359  SCIP_Bool* lperror /**< pointer to store whether an unresolved error in LP solving occured */
1360  )
1361 {
1362  /* initializing variables for compiler warnings, which are not correct */
1363  SCIP_Real starttime = 0.0;
1364  SCIP_Longint nlpiterations = 0;
1365  SCIP_NODE* focusnode;
1366 
1367  assert(stat != NULL);
1368  assert(tree != NULL);
1369  assert(lp != NULL);
1370  assert(cutoff != NULL);
1371  assert(lperror != NULL);
1372  assert(SCIPtreeGetFocusNode(tree) != NULL);
1374 
1375  *cutoff = FALSE;
1376  *lperror = FALSE;
1377 
1378  /* load the LP into the solver */
1379  SCIP_CALL( SCIPconstructCurrentLP(blkmem, set, stat, transprob, origprob, tree, reopt, lp, pricestore, sepastore, cutpool,
1380  branchcand, eventqueue, eventfilter, cliquetable, newinitconss, cutoff) );
1381 
1382  if( *cutoff )
1383  return SCIP_OKAY;
1384 
1385  /* load the LP state */
1386  SCIP_CALL( SCIPtreeLoadLPState(tree, blkmem, set, stat, eventqueue, lp) );
1387 
1388  focusnode = SCIPtreeGetFocusNode(tree);
1389 
1390  /* store current LP iteration count and solving time if we are at the root node */
1391  if( focusnode->depth == 0 )
1392  {
1393  nlpiterations = stat->nlpiterations;
1394  starttime = SCIPclockGetTime(stat->solvingtime);
1395  }
1396 
1397  /* solve initial LP */
1398  SCIPsetDebugMsg(set, "node: solve initial LP\n");
1399  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
1400  SCIPnodeGetDepth(SCIPtreeGetFocusNode(tree)) == 0 ? set->lp_rootiterlim : set->lp_iterlim, TRUE, TRUE, FALSE, lperror) );
1401  assert(lp->flushed);
1402  assert(lp->solved || *lperror);
1403 
1404  /* save time for very first LP in root node */
1405  if ( stat->nnodelps == 0 && focusnode->depth == 0 )
1406  {
1407  stat->firstlptime = SCIPclockGetTime(stat->solvingtime) - starttime;
1408  }
1409 
1410  /* remove previous primal ray, store new one if LP is unbounded */
1411  SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
1412 
1413  if( !(*lperror) )
1414  {
1415  /* cppcheck-suppress unassignedVariable */
1416  SCIP_EVENT event;
1417 
1419  {
1420  /* issue FIRSTLPSOLVED event */
1423  SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
1424  }
1425 
1426  /* update pseudo cost values for integer variables (always) and for continuous variables (if not delayed) */
1427  SCIP_CALL( updatePseudocost(set, stat, transprob, tree, lp, TRUE, !set->branch_delaypscost) );
1428 
1429  /* update lower bound of current node w.r.t. initial lp */
1430  assert(!(*cutoff));
1433  && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
1434  {
1435  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
1436 
1437  /* if this is the first LP solved at the root, store its iteration count and solution value */
1438  if( stat->nnodelps == 0 && focusnode->depth == 0 )
1439  {
1440  SCIP_Real lowerbound;
1441 
1442  assert(stat->nrootfirstlpiterations == 0);
1443  stat->nrootfirstlpiterations = stat->nlpiterations - nlpiterations;
1444 
1445  if( set->misc_exactsolve )
1446  {
1447  SCIP_CALL( SCIPlpGetProvedLowerbound(lp, set, &lowerbound) );
1448  }
1449  else
1450  lowerbound = SCIPlpGetObjval(lp, set, transprob);
1451 
1452  stat->firstlpdualbound = SCIPprobExternObjval(transprob, origprob, set, lowerbound);
1453  }
1454  }
1455  }
1456 
1457  return SCIP_OKAY;
1458 }
1459 
1460 /** makes sure the LP is flushed and solved */
1461 static
1463  BMS_BLKMEM* blkmem, /**< block memory buffers */
1464  SCIP_SET* set, /**< global SCIP settings */
1465  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1466  SCIP_STAT* stat, /**< dynamic problem statistics */
1467  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1468  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1469  SCIP_PROB* prob, /**< transformed problem after presolve */
1470  SCIP_PRIMAL* primal, /**< primal data */
1471  SCIP_TREE* tree, /**< branch and bound tree */
1472  SCIP_LP* lp, /**< LP data */
1473  SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
1474  SCIP_Bool* mustsepa, /**< pointer to store TRUE if additional separation rounds should be performed */
1475  SCIP_Bool* mustprice /**< pointer to store TRUE if additional pricing rounds should be performed */
1476  )
1477 {
1478  assert(lp != NULL);
1479  assert(lperror != NULL);
1480  assert(mustsepa != NULL);
1481  assert(mustprice != NULL);
1482 
1483  /* if bound changes were applied in the separation round, we have to resolve the LP */
1484  if( !lp->flushed )
1485  {
1486  /* solve LP (with dual simplex) */
1487  SCIPsetDebugMsg(set, "separation: resolve LP\n");
1488  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, prob, set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
1489  assert(lp->flushed);
1490  assert(lp->solved || *lperror);
1491  *mustsepa = TRUE;
1492  *mustprice = TRUE;
1493 
1494  /* remove previous primal ray, store new one if LP is unbounded */
1495  SCIP_CALL( updatePrimalRay(blkmem, set, stat, prob, primal, tree, lp, *lperror) );
1496  }
1497 
1498  return SCIP_OKAY;
1499 }
1500 
1501 /** applies one round of LP separation */
1502 static
1504  BMS_BLKMEM* blkmem, /**< block memory buffers */
1505  SCIP_SET* set, /**< global SCIP settings */
1506  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1507  SCIP_STAT* stat, /**< dynamic problem statistics */
1508  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1509  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1510  SCIP_PROB* prob, /**< transformed problem after presolve */
1511  SCIP_PRIMAL* primal, /**< primal data */
1512  SCIP_TREE* tree, /**< branch and bound tree */
1513  SCIP_LP* lp, /**< LP data */
1514  SCIP_SEPASTORE* sepastore, /**< separation storage */
1515  int actdepth, /**< current depth in the tree */
1516  SCIP_Real bounddist, /**< current relative distance of local dual bound to global dual bound */
1517  SCIP_Bool onlydelayed, /**< should only delayed separators be called? */
1518  SCIP_Bool* delayed, /**< pointer to store whether a separator was delayed */
1519  SCIP_Bool* enoughcuts, /**< pointer to store whether enough cuts have been found this round */
1520  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
1521  SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
1522  SCIP_Bool* mustsepa, /**< pointer to store TRUE if additional separation rounds should be performed */
1523  SCIP_Bool* mustprice /**< pointer to store TRUE if additional pricing rounds should be performed */
1524  )
1525 {
1526  SCIP_RESULT result;
1527  int i;
1528  SCIP_Bool consadded;
1529  SCIP_Bool root;
1530 
1531  assert(set != NULL);
1532  assert(lp != NULL);
1533  assert(set->conshdlrs_sepa != NULL);
1534  assert(delayed != NULL);
1535  assert(enoughcuts != NULL);
1536  assert(cutoff != NULL);
1537  assert(lperror != NULL);
1538 
1539  root = (actdepth == 0);
1540  *delayed = FALSE;
1541  *enoughcuts = (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root));
1542  *lperror = FALSE;
1543  consadded = FALSE;
1544 
1545  SCIPsetDebugMsg(set, "calling separators on LP solution in depth %d (onlydelayed: %u)\n", actdepth, onlydelayed);
1546 
1547  /* sort separators by priority */
1548  SCIPsetSortSepas(set);
1549 
1550  /* call LP separators with nonnegative priority */
1551  for( i = 0; i < set->nsepas && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1553  ++i )
1554  {
1555 #ifndef NDEBUG
1556  size_t nusedbuffer = BMSgetNUsedBufferMemory(SCIPbuffer(set->scip));
1557 #endif
1558 
1559  if( SCIPsepaGetPriority(set->sepas[i]) < 0 )
1560  continue;
1561 
1562  if( onlydelayed && !SCIPsepaWasLPDelayed(set->sepas[i]) )
1563  continue;
1564 
1565  SCIPsetDebugMsg(set, " -> executing separator <%s> with priority %d\n",
1566  SCIPsepaGetName(set->sepas[i]), SCIPsepaGetPriority(set->sepas[i]));
1567  SCIP_CALL( SCIPsepaExecLP(set->sepas[i], set, stat, sepastore, actdepth, bounddist, onlydelayed, &result) );
1568 #ifndef NDEBUG
1569  if( BMSgetNUsedBufferMemory(SCIPbuffer(set->scip)) > nusedbuffer )
1570  {
1571  SCIPerrorMessage("Buffer not completely freed after executing separator <%s>\n", SCIPsepaGetName(set->sepas[i]));
1572  SCIPABORT();
1573  }
1574 #endif
1575  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1576  consadded = consadded || (result == SCIP_CONSADDED);
1577  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1578  *delayed = *delayed || (result == SCIP_DELAYED);
1579 
1580  if( !(*cutoff) )
1581  {
1582  /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1583  SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1584  }
1585  else
1586  {
1587  SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1588  }
1589 
1590  /* if we work off the delayed separators, we stop immediately if a cut was found */
1591  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1592  {
1593  SCIPsetDebugMsg(set, " -> delayed separator <%s> found a cut\n", SCIPsepaGetName(set->sepas[i]));
1594  *delayed = TRUE;
1595  return SCIP_OKAY;
1596  }
1597  }
1598 
1599  /* try separating constraints of the constraint handlers */
1600  for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1602  ++i )
1603  {
1604  if( onlydelayed && !SCIPconshdlrWasLPSeparationDelayed(set->conshdlrs_sepa[i]) )
1605  continue;
1606 
1607  SCIPsetDebugMsg(set, " -> executing separation of constraint handler <%s> with priority %d\n",
1608  SCIPconshdlrGetName(set->conshdlrs_sepa[i]), SCIPconshdlrGetSepaPriority(set->conshdlrs_sepa[i]));
1609  SCIP_CALL( SCIPconshdlrSeparateLP(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, actdepth, onlydelayed,
1610  &result) );
1611 
1612  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1613  consadded = consadded || (result == SCIP_CONSADDED);
1614  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1615  *delayed = *delayed || (result == SCIP_DELAYED);
1616 
1617  if( !(*cutoff) )
1618  {
1619  /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1620  SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1621  }
1622  else
1623  {
1624  SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n", SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1625  }
1626 
1627  /* if we work off the delayed separators, we stop immediately if a cut was found */
1628  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1629  {
1630  SCIPsetDebugMsg(set, " -> delayed constraint handler <%s> found a cut\n",
1631  SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1632  *delayed = TRUE;
1633  return SCIP_OKAY;
1634  }
1635  }
1636 
1637  /* call LP separators with negative priority */
1638  for( i = 0; i < set->nsepas && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1640  ++i )
1641  {
1642  if( SCIPsepaGetPriority(set->sepas[i]) >= 0 )
1643  continue;
1644 
1645  if( onlydelayed && !SCIPsepaWasLPDelayed(set->sepas[i]) )
1646  continue;
1647 
1648  SCIPsetDebugMsg(set, " -> executing separator <%s> with priority %d\n",
1649  SCIPsepaGetName(set->sepas[i]), SCIPsepaGetPriority(set->sepas[i]));
1650  SCIP_CALL( SCIPsepaExecLP(set->sepas[i], set, stat, sepastore, actdepth, bounddist, onlydelayed, &result) );
1651 
1652  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1653  consadded = consadded || (result == SCIP_CONSADDED);
1654  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1655  *delayed = *delayed || (result == SCIP_DELAYED);
1656 
1657  if( !(*cutoff) )
1658  {
1659  /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1660  SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1661  }
1662  else
1663  {
1664  SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1665  }
1666 
1667  /* if we work off the delayed separators, we stop immediately if a cut was found */
1668  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1669  {
1670  SCIPsetDebugMsg(set, " -> delayed separator <%s> found a cut\n", SCIPsepaGetName(set->sepas[i]));
1671  *delayed = TRUE;
1672  return SCIP_OKAY;
1673  }
1674  }
1675 
1676  /* process the constraints that were added during this separation round */
1677  while( consadded )
1678  {
1679  assert(!onlydelayed);
1680  consadded = FALSE;
1681 
1682  for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1684  ++i )
1685  {
1686  SCIPsetDebugMsg(set, " -> executing separation of constraint handler <%s> with priority %d\n",
1687  SCIPconshdlrGetName(set->conshdlrs_sepa[i]), SCIPconshdlrGetSepaPriority(set->conshdlrs_sepa[i]));
1688  SCIP_CALL( SCIPconshdlrSeparateLP(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, actdepth, onlydelayed,
1689  &result) );
1690 
1691  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1692  consadded = consadded || (result == SCIP_CONSADDED);
1693  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1694  *delayed = *delayed || (result == SCIP_DELAYED);
1695 
1696  if( !(*cutoff) )
1697  {
1698  /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1699  SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1700  }
1701  else
1702  {
1703  SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n", SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1704  }
1705  }
1706  }
1707 
1708  SCIPsetDebugMsg(set, " -> separation round finished: delayed=%u, enoughcuts=%u, lpflushed=%u, cutoff=%u\n",
1709  *delayed, *enoughcuts, lp->flushed, *cutoff);
1710 
1711  return SCIP_OKAY;
1712 }
1713 
1714 /** applies one round of separation on the given primal solution */
1715 static
1717  BMS_BLKMEM* blkmem, /**< block memory buffers */
1718  SCIP_SET* set, /**< global SCIP settings */
1719  SCIP_STAT* stat, /**< dynamic problem statistics */
1720  SCIP_SEPASTORE* sepastore, /**< separation storage */
1721  SCIP_SOL* sol, /**< primal solution that should be separated, or NULL for LP solution */
1722  int actdepth, /**< current depth in the tree */
1723  SCIP_Bool onlydelayed, /**< should only delayed separators be called? */
1724  SCIP_Bool* delayed, /**< pointer to store whether a separator was delayed */
1725  SCIP_Bool* enoughcuts, /**< pointer to store whether enough cuts have been found this round */
1726  SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
1727  )
1728 {
1729  SCIP_RESULT result;
1730  int i;
1731  SCIP_Bool consadded;
1732  SCIP_Bool root;
1733 
1734  assert(set != NULL);
1735  assert(set->conshdlrs_sepa != NULL);
1736  assert(delayed != NULL);
1737  assert(enoughcuts != NULL);
1738  assert(cutoff != NULL);
1739 
1740  *delayed = FALSE;
1741  *enoughcuts = FALSE;
1742  consadded = FALSE;
1743  root = (actdepth == 0);
1744 
1745  SCIPsetDebugMsg(set, "calling separators on primal solution in depth %d (onlydelayed: %u)\n", actdepth, onlydelayed);
1746 
1747  /* sort separators by priority */
1748  SCIPsetSortSepas(set);
1749 
1750  /* call separators with nonnegative priority */
1751  for( i = 0; i < set->nsepas && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
1752  {
1753  if( SCIPsepaGetPriority(set->sepas[i]) < 0 )
1754  continue;
1755 
1756  if( onlydelayed && !SCIPsepaWasSolDelayed(set->sepas[i]) )
1757  continue;
1758 
1759  SCIP_CALL( SCIPsepaExecSol(set->sepas[i], set, stat, sepastore, sol, actdepth, onlydelayed, &result) );
1760  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1761  consadded = consadded || (result == SCIP_CONSADDED);
1762  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1763  *delayed = *delayed || (result == SCIP_DELAYED);
1764  if( *cutoff )
1765  {
1766  SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1767  }
1768 
1769  /* if we work off the delayed separators, we stop immediately if a cut was found */
1770  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1771  {
1772  *delayed = TRUE;
1773  return SCIP_OKAY;
1774  }
1775  }
1776 
1777  /* try separating constraints of the constraint handlers */
1778  for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
1779  {
1780  if( onlydelayed && !SCIPconshdlrWasSolSeparationDelayed(set->conshdlrs_sepa[i]) )
1781  continue;
1782 
1783  SCIP_CALL( SCIPconshdlrSeparateSol(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, sol, actdepth, onlydelayed,
1784  &result) );
1785  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1786  consadded = consadded || (result == SCIP_CONSADDED);
1787  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1788  *delayed = *delayed || (result == SCIP_DELAYED);
1789  if( *cutoff )
1790  {
1791  SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n",
1792  SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1793  }
1794 
1795  /* if we work off the delayed separators, we stop immediately if a cut was found */
1796  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1797  {
1798  *delayed = TRUE;
1799  return SCIP_OKAY;
1800  }
1801  }
1802 
1803  /* call separators with negative priority */
1804  for( i = 0; i < set->nsepas && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
1805  {
1806  if( SCIPsepaGetPriority(set->sepas[i]) >= 0 )
1807  continue;
1808 
1809  if( onlydelayed && !SCIPsepaWasSolDelayed(set->sepas[i]) )
1810  continue;
1811 
1812  SCIP_CALL( SCIPsepaExecSol(set->sepas[i], set, stat, sepastore, sol, actdepth, onlydelayed, &result) );
1813  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1814  consadded = consadded || (result == SCIP_CONSADDED);
1815  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1816  *delayed = *delayed || (result == SCIP_DELAYED);
1817  if( *cutoff )
1818  {
1819  SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1820  }
1821 
1822  /* if we work off the delayed separators, we stop immediately if a cut was found */
1823  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1824  {
1825  *delayed = TRUE;
1826  return SCIP_OKAY;
1827  }
1828  }
1829 
1830  /* process the constraints that were added during this separation round */
1831  while( consadded )
1832  {
1833  assert(!onlydelayed);
1834  consadded = FALSE;
1835 
1836  for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
1837  {
1838  SCIP_CALL( SCIPconshdlrSeparateSol(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, sol, actdepth, onlydelayed, &result) );
1839  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1840  consadded = consadded || (result == SCIP_CONSADDED);
1841  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1842  *delayed = *delayed || (result == SCIP_DELAYED);
1843  if( *cutoff )
1844  {
1845  SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n",
1846  SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1847  }
1848  }
1849  }
1850 
1851  SCIPsetDebugMsg(set, " -> separation round finished: delayed=%u, enoughcuts=%u, cutoff=%u\n",
1852  *delayed, *enoughcuts, *cutoff);
1853 
1854  return SCIP_OKAY;
1855 }
1856 
1857 /** applies one round of separation on the given primal solution or on the LP solution */
1859  BMS_BLKMEM* blkmem, /**< block memory buffers */
1860  SCIP_SET* set, /**< global SCIP settings */
1861  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1862  SCIP_STAT* stat, /**< dynamic problem statistics */
1863  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1864  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1865  SCIP_PROB* prob, /**< transformed problem after presolve */
1866  SCIP_PRIMAL* primal, /**< primal data */
1867  SCIP_TREE* tree, /**< branch and bound tree */
1868  SCIP_LP* lp, /**< LP data */
1869  SCIP_SEPASTORE* sepastore, /**< separation storage */
1870  SCIP_SOL* sol, /**< primal solution that should be separated, or NULL for LP solution */
1871  int actdepth, /**< current depth in the tree */
1872  SCIP_Bool onlydelayed, /**< should only delayed separators be called? */
1873  SCIP_Bool* delayed, /**< pointer to store whether a separator was delayed */
1874  SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
1875  )
1876 {
1877  SCIP_Bool enoughcuts;
1878 
1879  assert(delayed != NULL);
1880  assert(cutoff != NULL);
1881 
1882  *delayed = FALSE;
1883  *cutoff = FALSE;
1884  enoughcuts = FALSE;
1885 
1886  if( sol == NULL )
1887  {
1888  SCIP_Bool lperror;
1889  SCIP_Bool mustsepa;
1890  SCIP_Bool mustprice;
1891 
1892  /* apply a separation round on the LP solution */
1893  lperror = FALSE;
1894  mustsepa = FALSE;
1895  mustprice = FALSE;
1896  SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, sepastore, actdepth, 0.0, onlydelayed, delayed, &enoughcuts,
1897  cutoff, &lperror, &mustsepa, &mustprice) );
1898  }
1899  else
1900  {
1901  /* apply a separation round on the given primal solution */
1902  SCIP_CALL( separationRoundSol(blkmem, set, stat, sepastore, sol, actdepth, onlydelayed, delayed, &enoughcuts, cutoff) );
1903  }
1904 
1905  return SCIP_OKAY;
1906 }
1907 
1908 /** solves the current LP completely with pricing in new variables */
1910  BMS_BLKMEM* blkmem, /**< block memory buffers */
1911  SCIP_SET* set, /**< global SCIP settings */
1912  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1913  SCIP_STAT* stat, /**< dynamic problem statistics */
1914  SCIP_PROB* transprob, /**< transformed problem */
1915  SCIP_PROB* origprob, /**< original problem */
1916  SCIP_PRIMAL* primal, /**< primal data */
1917  SCIP_TREE* tree, /**< branch and bound tree */
1918  SCIP_REOPT* reopt, /**< reoptimization data structure */
1919  SCIP_LP* lp, /**< LP data */
1920  SCIP_PRICESTORE* pricestore, /**< pricing storage */
1921  SCIP_SEPASTORE* sepastore, /**< separation storage */
1922  SCIP_CUTPOOL* cutpool, /**< global cutpool */
1923  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1924  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1925  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1926  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1927  SCIP_Bool pretendroot, /**< should the pricers be called as if we are at the root node? */
1928  SCIP_Bool displayinfo, /**< should info lines be displayed after each pricing round? */
1929  int maxpricerounds, /**< maximal number of pricing rounds (-1: no limit);
1930  * a finite limit means that the LP might not be solved to optimality! */
1931  int* npricedcolvars, /**< pointer to store number of column variables after problem vars were priced */
1932  SCIP_Bool* mustsepa, /**< pointer to store TRUE if a separation round should follow */
1933  SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
1934  SCIP_Bool* aborted /**< pointer to store whether the pricing was aborted and the lower bound must
1935  * not be used */
1936  )
1937 {
1938  SCIP_NODE* currentnode;
1939  int npricerounds;
1940  SCIP_Bool mustprice;
1941  SCIP_Bool cutoff;
1942  SCIP_Bool unbounded;
1943 
1944  assert(transprob != NULL);
1945  assert(lp != NULL);
1946  assert(lp->flushed);
1947  assert(lp->solved);
1948  assert(npricedcolvars != NULL);
1949  assert(mustsepa != NULL);
1950  assert(lperror != NULL);
1951  assert(aborted != NULL);
1952 
1953  currentnode = SCIPtreeGetCurrentNode(tree);
1954  assert(currentnode == SCIPtreeGetFocusNode(tree) || SCIPtreeProbing(tree));
1955  *npricedcolvars = transprob->ncolvars;
1956  *lperror = FALSE;
1957  *aborted = FALSE;
1958 
1959  /* if the LP is unbounded, we don't need to price */
1960  mustprice = (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL
1963 
1964  /* if all the variables are already in the LP, we don't need to price */
1965  mustprice = mustprice && !SCIPprobAllColsInLP(transprob, set, lp);
1966 
1967  /* check if infinite number of pricing rounds should be used */
1968  if( maxpricerounds == -1 )
1969  maxpricerounds = INT_MAX;
1970 
1971  /* pricing (has to be done completely to get a valid lower bound) */
1972  npricerounds = 0;
1973  while( !(*lperror) && mustprice && npricerounds < maxpricerounds )
1974  {
1975  SCIP_Bool enoughvars;
1976  SCIP_RESULT result;
1977  SCIP_Real lb;
1978  SCIP_Bool foundsol;
1979  SCIP_Bool stopearly;
1980  SCIP_Bool stoppricing;
1981  int p;
1982 
1983  assert(lp->flushed);
1984  assert(lp->solved);
1986 
1987  /* check if pricing loop should be aborted */
1988  if( SCIPsolveIsStopped(set, stat, FALSE) )
1989  {
1990  /* do not print the warning message if we stopped because the problem is solved */
1991  if( !SCIPsetIsLE(set, SCIPgetUpperbound(set->scip), SCIPgetLowerbound(set->scip)) )
1992  SCIPmessagePrintWarning(messagehdlr, "pricing has been interrupted -- LP of current node is invalid\n");
1993 
1994  *aborted = TRUE;
1995  break;
1996  }
1997 
1998  /* call primal heuristics which are callable during pricing */
1999  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, SCIP_HEURTIMING_DURINGPRICINGLOOP,
2000  FALSE, &foundsol, &unbounded) );
2001 
2002  /* price problem variables */
2003  SCIPsetDebugMsg(set, "problem variable pricing\n");
2004  assert(SCIPpricestoreGetNVars(pricestore) == 0);
2005  assert(SCIPpricestoreGetNBoundResets(pricestore) == 0);
2006  SCIP_CALL( SCIPpricestoreAddProbVars(pricestore, blkmem, set, stat, transprob, tree, lp, branchcand, eventqueue) );
2007  *npricedcolvars = transprob->ncolvars;
2008 
2009  /* call external pricers to create additional problem variables */
2010  SCIPsetDebugMsg(set, "external variable pricing\n");
2011 
2012  /* sort pricer algorithms by priority */
2013  SCIPsetSortPricers(set);
2014 
2015  /* call external pricer algorithms, that are active for the current problem */
2016  enoughvars = (SCIPsetGetPriceMaxvars(set, pretendroot) == INT_MAX ?
2017  FALSE : SCIPpricestoreGetNVars(pricestore) >= SCIPsetGetPriceMaxvars(set, pretendroot) + 1);
2018  stoppricing = FALSE;
2019  for( p = 0; p < set->nactivepricers && !enoughvars; ++p )
2020  {
2021  SCIP_CALL( SCIPpricerExec(set->pricers[p], set, transprob, lp, pricestore, &lb, &stopearly, &result) );
2022  assert(result == SCIP_DIDNOTRUN || result == SCIP_SUCCESS);
2023  SCIPsetDebugMsg(set, "pricing: pricer %s returned result = %s, lowerbound = %f\n",
2024  SCIPpricerGetName(set->pricers[p]), (result == SCIP_DIDNOTRUN ? "didnotrun" : "success"), lb);
2025  enoughvars = enoughvars || (SCIPsetGetPriceMaxvars(set, pretendroot) == INT_MAX ?
2026  FALSE : SCIPpricestoreGetNVars(pricestore) >= SCIPsetGetPriceMaxvars(set, pretendroot) + 1);
2027  *aborted = ( (*aborted) || (result == SCIP_DIDNOTRUN) );
2028 
2029  /* set stoppricing to TRUE, of the first pricer wants to stop pricing */
2030  if( p == 0 && stopearly )
2031  stoppricing = TRUE;
2032 
2033  /* stoppricing only remains TRUE, if all other pricers want to stop pricing as well */
2034  if( stoppricing && !stopearly )
2035  stoppricing = FALSE;
2036 
2037  /* update lower bound w.r.t. the lower bound given by the pricer */
2038  SCIPnodeUpdateLowerbound(currentnode, stat, set, tree, transprob, origprob, lb);
2039  SCIPsetDebugMsg(set, " -> new lower bound given by pricer %s: %g\n", SCIPpricerGetName(set->pricers[p]), lb);
2040  }
2041 
2042  /* apply the priced variables to the LP */
2043  SCIP_CALL( SCIPpricestoreApplyVars(pricestore, blkmem, set, stat, eventqueue, transprob, tree, lp) );
2044  assert(SCIPpricestoreGetNVars(pricestore) == 0);
2045  assert(!lp->flushed || lp->solved);
2046  mustprice = !lp->flushed || (transprob->ncolvars != *npricedcolvars);
2047  *mustsepa = *mustsepa || !lp->flushed;
2048 
2049  /* after adding columns, the LP should be primal feasible such that the primal simplex is applicable;
2050  * if LP was infeasible, we have to use dual simplex
2051  */
2052  SCIPsetDebugMsg(set, "pricing: solve LP\n");
2053  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, TRUE, FALSE, lperror) );
2054  assert(lp->flushed);
2055  assert(lp->solved || *lperror);
2056 
2057  /* reset bounds temporarily set by pricer to their original values */
2058  SCIPsetDebugMsg(set, "pricing: reset bounds\n");
2059  SCIP_CALL( SCIPpricestoreResetBounds(pricestore, blkmem, set, stat, lp, branchcand, eventqueue) );
2060  assert(SCIPpricestoreGetNVars(pricestore) == 0);
2061  assert(SCIPpricestoreGetNBoundResets(pricestore) == 0);
2062  assert(!lp->flushed || lp->solved || *lperror);
2063 
2064  /* put all initial constraints into the LP */
2065  SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
2066  eventfilter, cliquetable, FALSE, FALSE, &cutoff) );
2067  assert(cutoff == FALSE);
2068 
2069  mustprice = mustprice || !lp->flushed || (transprob->ncolvars != *npricedcolvars);
2070  *mustsepa = *mustsepa || !lp->flushed;
2071 
2072  /* if all pricers wanted to stop pricing, do not do another pricing round (LP value is no valid dual bound in this case) */
2073  if( stoppricing )
2074  {
2075  SCIPsetDebugMsg(set, "pricing: stop pricing and perform early branching\n");
2076  mustprice = FALSE;
2077  *aborted = TRUE;
2078  }
2079 
2080  /* solve LP again after resetting bounds and adding new initial constraints (with dual simplex) */
2081  SCIPsetDebugMsg(set, "pricing: solve LP after resetting bounds and adding new initial constraints\n");
2082  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, FALSE, lperror) );
2083  assert(lp->flushed);
2084  assert(lp->solved || *lperror);
2085 
2086  /* remove previous primal ray, store new one if LP is unbounded */
2087  SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2088 
2089  /* increase pricing round counter */
2090  stat->npricerounds++;
2091  npricerounds++;
2092 
2093  /* display node information line */
2094  if( displayinfo && mustprice )
2095  {
2096  if( (SCIP_VERBLEVEL)set->disp_verblevel >= SCIP_VERBLEVEL_FULL
2097  || ((SCIP_VERBLEVEL)set->disp_verblevel >= SCIP_VERBLEVEL_HIGH && npricerounds % 100 == 1) )
2098  {
2099  SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, TRUE, TRUE) );
2100  }
2101  }
2102 
2103  /* if the LP is unbounded, we can stop pricing */
2104  mustprice = mustprice &&
2108 
2109  /* if the lower bound is already higher than the cutoff bound, we can stop pricing */
2110  mustprice = mustprice && SCIPsetIsLT(set, SCIPnodeGetLowerbound(currentnode), primal->cutoffbound);
2111  }
2112  assert(lp->flushed);
2113  assert(lp->solved || *lperror);
2114 
2115  *aborted = ( (*aborted) || (*lperror) || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_NOTSOLVED
2116  || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_ERROR || npricerounds == maxpricerounds );
2117 
2118  /* set information, whether the current lp is a valid relaxation of the current problem */
2119  SCIPlpSetIsRelax(lp, !(*aborted));
2120 
2121  return SCIP_OKAY;
2122 }
2123 
2124 /** separates cuts of the cut pool */
2125 static
2127  SCIP_CUTPOOL* cutpool, /**< cut pool */
2128  BMS_BLKMEM* blkmem, /**< block memory */
2129  SCIP_SET* set, /**< global SCIP settings */
2130  SCIP_STAT* stat, /**< problem statistics data */
2131  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2132  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
2133  SCIP_LP* lp, /**< current LP data */
2134  SCIP_SEPASTORE* sepastore, /**< separation storage */
2135  SCIP_Bool cutpoolisdelayed, /**< is the cutpool delayed (count cuts found)? */
2136  SCIP_Bool root, /**< are we at the root node? */
2137  int actdepth, /**< the depth of the focus node */
2138  SCIP_Bool* enoughcuts, /**< pointer to store if enough cuts were found in current separation round */
2139  SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
2140  )
2141 {
2142  if( (set->sepa_poolfreq == 0 && actdepth == 0)
2143  || (set->sepa_poolfreq > 0 && actdepth % set->sepa_poolfreq == 0) )
2144  {
2145  SCIP_RESULT result;
2146 
2147  /* in case of the "normal" cutpool the sepastore should be empty since the cutpool is called as first separator;
2148  * in case of the delayed cutpool the sepastore should be also empty because the delayed cutpool is only called if
2149  * the sepastore is empty after all separators and the the "normal" cutpool were called without success;
2150  */
2151  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
2152 
2153  SCIP_CALL( SCIPcutpoolSeparate(cutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, NULL, cutpoolisdelayed, root, &result) );
2154  *cutoff = *cutoff || (result == SCIP_CUTOFF);
2155  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
2156  }
2157 
2158  return SCIP_OKAY;
2159 }
2160 
2161 /** solve the current LP of a node with a price-and-cut loop */
2162 static
2164  BMS_BLKMEM* blkmem, /**< block memory buffers */
2165  SCIP_SET* set, /**< global SCIP settings */
2166  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2167  SCIP_STAT* stat, /**< dynamic problem statistics */
2168  SCIP_MEM* mem, /**< block memory pools */
2169  SCIP_PROB* transprob, /**< transformed problem */
2170  SCIP_PROB* origprob, /**< original problem */
2171  SCIP_PRIMAL* primal, /**< primal data */
2172  SCIP_TREE* tree, /**< branch and bound tree */
2173  SCIP_REOPT* reopt, /**< reoptimization data structure */
2174  SCIP_LP* lp, /**< LP data */
2175  SCIP_PRICESTORE* pricestore, /**< pricing storage */
2176  SCIP_SEPASTORE* sepastore, /**< separation storage */
2177  SCIP_CUTPOOL* cutpool, /**< global cut pool */
2178  SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
2179  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2180  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2181  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
2182  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
2183  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2184  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2185  SCIP_Bool fullseparation, /**< are we in the first prop-and-cut-and-price loop? */
2186  SCIP_Bool* propagateagain, /**< pointer to store whether we want to propagate again */
2187  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
2188  SCIP_Bool* unbounded, /**< pointer to store whether an unbounded ray was found in the LP */
2189  SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
2190  SCIP_Bool* pricingaborted /**< pointer to store whether the pricing was aborted and the lower bound must
2191  * not be used */
2192  )
2193 {
2194  SCIP_NODE* focusnode;
2195  /* cppcheck-suppress unassignedVariable */
2196  SCIP_EVENT event;
2197  SCIP_LPSOLSTAT stalllpsolstat;
2198  SCIP_Real loclowerbound;
2199  SCIP_Real glblowerbound;
2200  SCIP_Real bounddist;
2201  SCIP_Real stalllpobjval;
2202  SCIP_Bool separate;
2203  SCIP_Bool mustprice;
2204  SCIP_Bool mustsepa;
2205  SCIP_Bool delayedsepa;
2206  SCIP_Bool root;
2207  int maxseparounds;
2208  int nsepastallrounds;
2209  int maxnsepastallrounds;
2210  int stallnfracs;
2211  int actdepth;
2212  int npricedcolvars;
2213 
2214  assert(set != NULL);
2215  assert(blkmem != NULL);
2216  assert(stat != NULL);
2217  assert(transprob != NULL);
2218  assert(tree != NULL);
2219  assert(lp != NULL);
2220  assert(pricestore != NULL);
2221  assert(sepastore != NULL);
2222  assert(cutpool != NULL);
2223  assert(delayedcutpool != NULL);
2224  assert(primal != NULL);
2225  assert(cutoff != NULL);
2226  assert(unbounded != NULL);
2227  assert(lperror != NULL);
2228 
2229  focusnode = SCIPtreeGetFocusNode(tree);
2230  assert(focusnode != NULL);
2231  assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
2232  actdepth = SCIPnodeGetDepth(focusnode);
2233  root = (actdepth == 0);
2234 
2235  /* check, if we want to separate at this node */
2236  loclowerbound = SCIPnodeGetLowerbound(focusnode);
2237  glblowerbound = SCIPtreeGetLowerbound(tree, set);
2238  assert(primal->cutoffbound > glblowerbound);
2239  bounddist = (loclowerbound - glblowerbound)/(primal->cutoffbound - glblowerbound);
2240  separate = SCIPsetIsLE(set, bounddist, set->sepa_maxbounddist);
2241  separate = separate && (set->sepa_maxruns == -1 || stat->nruns <= set->sepa_maxruns);
2242 
2243  /* get maximal number of separation rounds */
2244  maxseparounds = (root ? set->sepa_maxroundsroot : set->sepa_maxrounds);
2245  if( maxseparounds == -1 )
2246  maxseparounds = INT_MAX;
2247  if( stat->nruns > 1 && root && set->sepa_maxroundsrootsubrun >= 0 )
2248  maxseparounds = MIN(maxseparounds, set->sepa_maxroundsrootsubrun);
2249  if( !fullseparation && set->sepa_maxaddrounds >= 0 )
2250  maxseparounds = MIN(maxseparounds, stat->nseparounds + set->sepa_maxaddrounds);
2251  maxnsepastallrounds = set->sepa_maxstallrounds;
2252  if( maxnsepastallrounds == -1 )
2253  maxnsepastallrounds = INT_MAX;
2254 
2255  /* solve initial LP of price-and-cut loop */
2256  /* @todo check if LP is always already solved, because of calling solveNodeInitialLP() in solveNodeLP()? */
2257  SCIPsetDebugMsg(set, "node: solve LP with price and cut\n");
2258  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2259  set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2260  assert(lp->flushed);
2261  assert(lp->solved || *lperror);
2262 
2263  /* remove previous primal ray, store new one if LP is unbounded */
2264  SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2265 
2266  /* price-and-cut loop */
2267  npricedcolvars = transprob->ncolvars;
2268  mustprice = TRUE;
2269  mustsepa = separate;
2270  delayedsepa = FALSE;
2271  *cutoff = FALSE;
2272  *unbounded = (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
2273  nsepastallrounds = 0;
2274  stalllpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2275  stalllpobjval = SCIP_REAL_MIN;
2276  stallnfracs = INT_MAX;
2277  lp->installing = FALSE;
2278  while( !(*cutoff) && !(*unbounded) && !(*lperror) && (mustprice || mustsepa || delayedsepa) )
2279  {
2280  SCIPsetDebugMsg(set, "-------- node solving loop --------\n");
2281  assert(lp->flushed);
2282  assert(lp->solved);
2283 
2284  /* solve the LP with pricing in new variables */
2285  while( mustprice && !(*lperror) )
2286  {
2287  SCIP_CALL( SCIPpriceLoop(blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
2288  pricestore, sepastore, cutpool, branchcand, eventqueue, eventfilter, cliquetable, root, root, -1, &npricedcolvars,
2289  &mustsepa, lperror, pricingaborted) );
2290 
2291  mustprice = FALSE;
2292 
2293  assert(lp->flushed);
2294  assert(lp->solved || *lperror);
2295 
2296  /* update lower bound w.r.t. the LP solution */
2297  if( !(*lperror) && !(*pricingaborted) && SCIPlpIsRelax(lp) )
2298  {
2299  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2300  SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2301  SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2302 
2303  /* update node estimate */
2304  SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2305 
2306  if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2307  SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2308  }
2309  else
2310  {
2311  SCIPsetDebugMsg(set, " -> error solving LP or pricing aborted. keeping old bound: %g\n", SCIPnodeGetLowerbound(focusnode));
2312  }
2313 
2314  /* display node information line for root node */
2315  if( root && (SCIP_VERBLEVEL)set->disp_verblevel >= SCIP_VERBLEVEL_HIGH )
2316  {
2317  SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, TRUE, TRUE) );
2318  }
2319 
2320  if( !(*lperror) )
2321  {
2322  /* call propagators that are applicable during LP solving loop only if the node is not cut off */
2323  if( SCIPsetIsLT(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound) )
2324  {
2325  SCIP_Longint oldnboundchgs;
2326  SCIP_Longint oldninitconssadded;
2327  SCIP_Bool postpone;
2328 
2329  oldnboundchgs = stat->nboundchgs;
2330  oldninitconssadded = stat->ninitconssadded;
2331 
2332  SCIPsetDebugMsg(set, " -> LP solved: call propagators that are applicable during LP solving loop\n");
2333 
2334  SCIP_CALL( propagateDomains(blkmem, set, stat, primal, tree, SCIPtreeGetCurrentDepth(tree), 0, FALSE,
2335  SCIP_PROPTIMING_DURINGLPLOOP, cutoff, &postpone) );
2336  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2337  assert(!postpone);
2338 
2339  if( stat->ninitconssadded != oldninitconssadded )
2340  {
2341  SCIPsetDebugMsg(set, "new initial constraints added during propagation: old=%" SCIP_LONGINT_FORMAT ", new=%" SCIP_LONGINT_FORMAT "\n", oldninitconssadded, stat->ninitconssadded);
2342 
2343  SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp,
2344  branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE, cutoff) );
2345  }
2346 
2347  if( !(*cutoff) && !(*unbounded) )
2348  {
2349  /* if we found something, solve LP again */
2350  if( !lp->flushed )
2351  {
2352  SCIPsetDebugMsg(set, " -> found reduction: resolve LP\n");
2353 
2354  /* in the root node, remove redundant rows permanently from the LP */
2355  if( root )
2356  {
2357  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
2358  SCIP_CALL( SCIPlpRemoveRedundantRows(lp, blkmem, set, stat, eventqueue, eventfilter) );
2359  }
2360 
2361  /* resolve LP */
2362  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2363  set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2364  assert(lp->flushed);
2365  assert(lp->solved || *lperror);
2366 
2367  /* remove previous primal ray, store new one if LP is unbounded */
2368  SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2369 
2370  mustprice = TRUE;
2371  *propagateagain = TRUE;
2372  }
2373  /* propagation might have changed the best bound of loose variables, thereby changing the loose objective
2374  * value which is added to the LP value; because of the loose status, the LP might not be reoptimized,
2375  * but the lower bound of the node needs to be updated
2376  */
2377  else if( stat->nboundchgs > oldnboundchgs )
2378  {
2379  *propagateagain = TRUE;
2380 
2381  if( lp->solved && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
2382  {
2383  assert(lp->flushed);
2384  assert(lp->solved);
2385 
2386  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2387  SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2388  SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2389 
2390  /* update node estimate */
2391  SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2392 
2393  if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2394  SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2395  }
2396  }
2397  }
2398  }
2399  }
2400 
2401  /* call primal heuristics that are applicable during node LP solving loop */
2402  if( !*cutoff && !(*unbounded) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2403  {
2404  SCIP_Bool foundsol;
2405 
2406  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, SCIP_HEURTIMING_DURINGLPLOOP,
2407  FALSE, &foundsol, unbounded) );
2408  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2409 
2410  *lperror = *lperror || lp->resolvelperror;
2411  }
2412  }
2413  assert(lp->flushed || *cutoff || *unbounded);
2414  assert(lp->solved || *lperror || *cutoff || *unbounded);
2415 
2416  /* check, if we exceeded the separation round limit */
2417  mustsepa = mustsepa
2418  && stat->nseparounds < maxseparounds
2419  && nsepastallrounds < maxnsepastallrounds
2420  && !(*cutoff);
2421 
2422  /* if separators were delayed, we want to apply a final separation round with the delayed separators */
2423  delayedsepa = delayedsepa && !mustsepa && !(*cutoff); /* if regular separation applies, we ignore delayed separators */
2424  mustsepa = mustsepa || delayedsepa;
2425 
2426  if( mustsepa )
2427  {
2428  /* if the LP is infeasible, unbounded, exceeded the objective limit or a global performance limit was reached,
2429  * we don't need to separate cuts
2430  * (the global limits are only checked at the root node in order to not query system time too often)
2431  */
2432  if( !separate || (*cutoff) || (*unbounded)
2434  || SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound)
2435  || (root && SCIPsolveIsStopped(set, stat, FALSE)) )
2436  {
2437  mustsepa = FALSE;
2438  delayedsepa = FALSE;
2439  }
2440  else
2441  assert(!(*lperror));
2442  }
2443 
2444  /* separation (needs not to be done completely, because we just want to increase the lower bound) */
2445  if( mustsepa )
2446  {
2447  SCIP_Longint olddomchgcount;
2448  SCIP_Longint oldninitconssadded;
2449  SCIP_Bool enoughcuts;
2450 
2451  assert(lp->flushed);
2452  assert(lp->solved);
2454 
2455  olddomchgcount = stat->domchgcount;
2456  oldninitconssadded = stat->ninitconssadded;
2457 
2458  mustsepa = FALSE;
2459  enoughcuts = (SCIPsetGetSepaMaxcuts(set, root) == 0);
2460 
2461  /* global cut pool separation */
2462  if( !enoughcuts && !delayedsepa )
2463  {
2464  SCIP_CALL( cutpoolSeparate(cutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, FALSE, root,
2465  actdepth, &enoughcuts, cutoff) );
2466 
2467  if( *cutoff )
2468  {
2469  SCIPsetDebugMsg(set, " -> global cut pool detected cutoff\n");
2470  }
2471  }
2472  assert(lp->flushed);
2473  assert(lp->solved);
2475 
2476  /* constraint separation */
2477  SCIPsetDebugMsg(set, "constraint separation\n");
2478 
2479  /* separate constraints and LP */
2480  if( !(*cutoff) && !(*lperror) && !enoughcuts && lp->solved )
2481  {
2482  /* apply a separation round */
2483  SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal, tree,
2484  lp, sepastore, actdepth, bounddist, delayedsepa,
2485  &delayedsepa, &enoughcuts, cutoff, lperror, &mustsepa, &mustprice) );
2486  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2487 
2488  /* if we are close to the stall round limit, also call the delayed separators */
2489  if( !(*cutoff) && !(*lperror) && !enoughcuts && lp->solved
2491  && nsepastallrounds >= maxnsepastallrounds-1 && delayedsepa )
2492  {
2493  SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal,
2494  tree, lp, sepastore, actdepth, bounddist, delayedsepa,
2495  &delayedsepa, &enoughcuts, cutoff, lperror, &mustsepa, &mustprice) );
2496  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2497  }
2498  }
2499 
2500  /* delayed global cut pool separation */
2501  if( !(*cutoff) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && SCIPsepastoreGetNCuts(sepastore) == 0 )
2502  {
2503  assert( !(*lperror) );
2504 
2505  SCIP_CALL( cutpoolSeparate(delayedcutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, TRUE,
2506  root, actdepth, &enoughcuts, cutoff) );
2507 
2508  if( *cutoff )
2509  {
2510  SCIPsetDebugMsg(set, " -> delayed global cut pool detected cutoff\n");
2511  }
2513  assert(lp->flushed);
2514  assert(lp->solved);
2515  }
2516 
2517  assert(*cutoff || *lperror || SCIPlpIsSolved(lp));
2518  assert(!SCIPlpIsSolved(lp)
2525 
2526  if( *cutoff || *lperror
2529  {
2530  /* the found cuts are of no use, because the node is infeasible anyway (or we have an error in the LP) */
2531  SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
2532  }
2533  else
2534  {
2535  /* apply found cuts */
2536  SCIP_CALL( SCIPsepastoreApplyCuts(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
2537  branchcand, eventqueue, eventfilter, cliquetable, root, SCIP_EFFICIACYCHOICE_LP, cutoff) );
2538 
2539  if( !(*cutoff) )
2540  {
2541  mustprice = mustprice || !lp->flushed || (transprob->ncolvars != npricedcolvars);
2542  mustsepa = mustsepa || !lp->flushed;
2543 
2544  /* if a new bound change (e.g. a cut with only one column) was found, propagate domains again */
2545  if( stat->domchgcount != olddomchgcount )
2546  {
2547  SCIPsetDebugMsg(set, " -> separation changed bound: propagate again\n");
2548 
2549  *propagateagain = TRUE;
2550 
2551  /* in the root node, remove redundant rows permanently from the LP */
2552  if( root )
2553  {
2554  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
2555  SCIP_CALL( SCIPlpRemoveRedundantRows(lp, blkmem, set, stat, eventqueue, eventfilter) );
2556  }
2557  }
2558 
2559  if( stat->ninitconssadded != oldninitconssadded )
2560  {
2561  SCIPsetDebugMsg(set, "new initial constraints added during propagation: old=%" SCIP_LONGINT_FORMAT ", new=%" SCIP_LONGINT_FORMAT "\n",
2562  oldninitconssadded, stat->ninitconssadded);
2563 
2564  SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp,
2565  branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE, cutoff) );
2566  }
2567 
2568  if( !(*cutoff) )
2569  {
2570  SCIP_Real lpobjval;
2571 
2572  /* solve LP (with dual simplex) */
2573  SCIPsetDebugMsg(set, "separation: solve LP\n");
2574  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2575  set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2576  assert(lp->flushed);
2577  assert(lp->solved || *lperror);
2578 
2579  /* remove previous primal ray, store new one if LP is unbounded */
2580  SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2581 
2582  if( !(*lperror) )
2583  {
2584  SCIP_Bool stalling;
2585 
2586  /* propagation might have changed the best bound of loose variables, thereby changing the loose objective value
2587  * which is added to the LP value; because of the loose status, the LP might not be reoptimized, but the lower
2588  * bound of the node needs to be updated
2589  */
2590  if( stat->domchgcount != olddomchgcount && (!mustprice || mustsepa) && !(*cutoff)
2591  && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
2592  {
2593  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2594  SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2595  SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2596 
2597  /* update node estimate */
2598  SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2599 
2600  if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2601  SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2602  }
2603 
2604  /* check if we are stalling
2605  * If we have an LP solution, then we are stalling if
2606  * we had an LP solution before and
2607  * the LP value did not improve and
2608  * the number of fractional variables did not decrease.
2609  * If we do not have an LP solution, then we are stalling if the solution status of the LP did not change.
2610  */
2612  {
2613  SCIP_Real objreldiff;
2614  int nfracs;
2615 
2616  SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nfracs, NULL,
2617  NULL) );
2618  lpobjval = SCIPlpGetObjval(lp, set, transprob);
2619 
2620  objreldiff = SCIPrelDiff(lpobjval, stalllpobjval);
2621  SCIPsetDebugMsg(set, " -> LP bound moved from %g to %g (reldiff: %g)\n",
2622  stalllpobjval, lpobjval, objreldiff);
2623 
2624  stalling = (stalllpsolstat == SCIP_LPSOLSTAT_OPTIMAL &&
2625  objreldiff <= 1e-04 &&
2626  nfracs >= (0.9 - 0.1 * nsepastallrounds) * stallnfracs);
2627 
2628  stalllpobjval = lpobjval;
2629  stallnfracs = nfracs;
2630  }
2631  else
2632  {
2633  stalling = (stalllpsolstat == SCIPlpGetSolstat(lp));
2634  }
2635 
2636  if( !stalling )
2637  {
2638  nsepastallrounds = 0;
2639  lp->installing = FALSE;
2640  }
2641  else
2642  {
2643  nsepastallrounds++;
2644  }
2645  stalllpsolstat = SCIPlpGetSolstat(lp);
2646 
2647  /* tell LP that we are (close to) stalling */
2648  if( nsepastallrounds >= maxnsepastallrounds-2 )
2649  lp->installing = TRUE;
2650  SCIPsetDebugMsg(set, " -> nsepastallrounds=%d/%d\n", nsepastallrounds, maxnsepastallrounds);
2651  }
2652  }
2653  }
2654  }
2655  assert(*cutoff || *lperror || (lp->flushed && lp->solved)); /* cutoff: LP may be unsolved due to bound changes */
2656 
2657  SCIPsetDebugMsg(set, "separation round %d/%d finished (%d/%d stall rounds): mustprice=%u, mustsepa=%u, delayedsepa=%u, propagateagain=%u\n",
2658  stat->nseparounds, maxseparounds, nsepastallrounds, maxnsepastallrounds, mustprice, mustsepa, delayedsepa, *propagateagain);
2659 
2660  /* increase separation round counter */
2661  stat->nseparounds++;
2662  }
2663  }
2664 
2665  if ( nsepastallrounds >= maxnsepastallrounds )
2666  {
2667  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
2668  "Truncate separation round because of stalling (%d stall rounds).\n", maxnsepastallrounds);
2669  }
2670 
2671  if( !*lperror )
2672  {
2673  /* update pseudo cost values for continuous variables, if it should be delayed */
2674  SCIP_CALL( updatePseudocost(set, stat, transprob, tree, lp, FALSE, set->branch_delaypscost) );
2675  }
2676 
2677  /* update lower bound w.r.t. the LP solution */
2678  if( *cutoff )
2679  {
2680  SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, SCIPsetInfinity(set));
2681  }
2682  else if( !(*lperror) )
2683  {
2684  assert(lp->flushed);
2685  assert(lp->solved);
2686 
2687  if( SCIPlpIsRelax(lp) )
2688  {
2689  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2690  }
2691 
2692  /* update node estimate */
2693  SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2694 
2695  /* issue LPSOLVED event */
2697  {
2699  SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
2700  SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
2701  }
2702 
2703  /* if the LP is a relaxation and we are not solving exactly, then we may analyze an infeasible or bound exceeding
2704  * LP (not necessary in the root node) and cut off the current node
2705  */
2706  if( !set->misc_exactsolve && !root && SCIPlpIsRelax(lp) && SCIPprobAllColsInLP(transprob, set, lp)
2708  {
2709  SCIP_CALL( SCIPconflictAnalyzeLP(conflict, conflictstore, blkmem, set, stat, transprob, origprob, tree, reopt,
2710  lp, branchcand, eventqueue, cliquetable, NULL) );
2711  *cutoff = TRUE;
2712  }
2713  }
2714  /* check for unboundedness */
2715  if( !(*lperror) )
2716  {
2717  *unbounded = (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
2718  /* assert(!(*unbounded) || root); */ /* unboundedness can only happen in the root node; no, of course it can also happens in the tree if a branching did not help to resolve unboundedness */
2719  }
2720 
2721  lp->installing = FALSE;
2722 
2723  SCIPsetDebugMsg(set, " -> final lower bound: %g (LP status: %d, LP obj: %g)\n",
2724  SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp),
2725  (*cutoff || *unbounded) ? SCIPsetInfinity(set) : *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
2726 
2727  return SCIP_OKAY;
2728 }
2729 
2730 /** updates the current lower bound with the pseudo objective value, cuts off node by bounding, and applies conflict
2731  * analysis if the pseudo objective lead to the cutoff
2732  */
2733 static
2735  BMS_BLKMEM* blkmem, /**< block memory buffers */
2736  SCIP_SET* set, /**< global SCIP settings */
2737  SCIP_STAT* stat, /**< dynamic problem statistics */
2738  SCIP_PROB* transprob, /**< tranformed problem after presolve */
2739  SCIP_PROB* origprob, /**< original problem */
2740  SCIP_PRIMAL* primal, /**< primal data */
2741  SCIP_TREE* tree, /**< branch and bound tree */
2742  SCIP_REOPT* reopt, /**< reoptimization data structure */
2743  SCIP_LP* lp, /**< LP data */
2744  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2745  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2746  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2747  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2748  SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
2749  )
2750 {
2751  assert(transprob != NULL);
2752  assert(origprob != NULL);
2753  assert(primal != NULL);
2754  assert(cutoff != NULL);
2755 
2756  if( !(*cutoff) )
2757  {
2758  SCIP_NODE* focusnode;
2759  SCIP_Real pseudoobjval;
2760 
2761  /* get current focus node */
2762  focusnode = SCIPtreeGetFocusNode(tree);
2763 
2764  /* update lower bound w.r.t. the pseudo solution */
2765  pseudoobjval = SCIPlpGetPseudoObjval(lp, set, transprob);
2766  SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, pseudoobjval);
2767  SCIPsetDebugMsg(set, " -> lower bound: %g [%g] (pseudoobj: %g [%g]), cutoff bound: %g [%g]\n",
2768  SCIPnodeGetLowerbound(focusnode), SCIPprobExternObjval(transprob, origprob, set, SCIPnodeGetLowerbound(focusnode)) + SCIPgetOrigObjoffset(set->scip),
2769  pseudoobjval, SCIPprobExternObjval(transprob, origprob, set, pseudoobjval) + SCIPgetOrigObjoffset(set->scip),
2770  primal->cutoffbound, SCIPprobExternObjval(transprob, origprob, set, primal->cutoffbound) + SCIPgetOrigObjoffset(set->scip));
2771 
2772  /* check for infeasible node by bounding */
2773  if( (set->misc_exactsolve && SCIPnodeGetLowerbound(focusnode) >= primal->cutoffbound)
2774  || (!set->misc_exactsolve && SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound)) )
2775  {
2776  SCIPsetDebugMsg(set, "node is cut off by bounding (lower=%g, upper=%g)\n",
2777  SCIPnodeGetLowerbound(focusnode), primal->cutoffbound);
2778  SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, SCIPsetInfinity(set));
2779  *cutoff = TRUE;
2780 
2781  /* call pseudo conflict analysis, if the node is cut off due to the pseudo objective value */
2782  if( pseudoobjval >= primal->cutoffbound && !SCIPsetIsInfinity(set, -pseudoobjval) )
2783  {
2784  SCIP_CALL( SCIPconflictAnalyzePseudo(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cliquetable, NULL) );
2785  }
2786  }
2787  }
2788 
2789  return SCIP_OKAY;
2790 }
2791 
2792 /** marks all relaxators to be unsolved */
2793 static
2795  SCIP_SET* set, /**< global SCIP settings */
2796  SCIP_RELAXATION* relaxation /**< global relaxation data */
2797  )
2798 {
2799  int r;
2800 
2801  assert(set != NULL);
2802  assert(relaxation != NULL);
2803 
2804  SCIPrelaxationSetSolValid(relaxation, FALSE);
2805 
2806  for( r = 0; r < set->nrelaxs; ++r )
2807  SCIPrelaxMarkUnsolved(set->relaxs[r]);
2808 }
2809 
2810 /** solves the current node's LP in a price-and-cut loop */
2811 static
2813  BMS_BLKMEM* blkmem, /**< block memory buffers */
2814  SCIP_SET* set, /**< global SCIP settings */
2815  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2816  SCIP_STAT* stat, /**< dynamic problem statistics */
2817  SCIP_MEM* mem, /**< block memory pools */
2818  SCIP_PROB* origprob, /**< original problem */
2819  SCIP_PROB* transprob, /**< transformed problem after presolve */
2820  SCIP_PRIMAL* primal, /**< primal data */
2821  SCIP_TREE* tree, /**< branch and bound tree */
2822  SCIP_REOPT* reopt, /**< reoptimization data structure */
2823  SCIP_LP* lp, /**< LP data */
2824  SCIP_RELAXATION* relaxation, /**< relaxators */
2825  SCIP_PRICESTORE* pricestore, /**< pricing storage */
2826  SCIP_SEPASTORE* sepastore, /**< separation storage */
2827  SCIP_CUTPOOL* cutpool, /**< global cut pool */
2828  SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
2829  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2830  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2831  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
2832  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
2833  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2834  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2835  SCIP_Bool initiallpsolved, /**< was the initial LP already solved? */
2836  SCIP_Bool fullseparation, /**< are we in the first prop-and-cut-and-price loop? */
2837  SCIP_Bool newinitconss, /**< do we have to add new initial constraints? */
2838  SCIP_Bool* propagateagain, /**< pointer to store whether we want to propagate again */
2839  SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called again */
2840  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
2841  SCIP_Bool* unbounded, /**< pointer to store TRUE, if an unbounded ray was found in the LP */
2842  SCIP_Bool* lperror, /**< pointer to store TRUE, if an unresolved error in LP solving occured */
2843  SCIP_Bool* pricingaborted /**< pointer to store TRUE, if the pricing was aborted and the lower bound
2844  * must not be used */
2845  )
2846 {
2847  SCIP_Longint nlpiterations;
2848  SCIP_Longint nlps;
2849 
2850  assert(stat != NULL);
2851  assert(tree != NULL);
2852  assert(SCIPtreeHasFocusNodeLP(tree));
2853  assert(cutoff != NULL);
2854  assert(unbounded != NULL);
2855  assert(lperror != NULL);
2856  assert(*cutoff == FALSE);
2857  assert(*unbounded == FALSE);
2858  assert(*lperror == FALSE);
2859 
2860  nlps = stat->nlps;
2861  nlpiterations = stat->nlpiterations;
2862 
2863  if( !initiallpsolved )
2864  {
2865  /* load and solve the initial LP of the node */
2866  SCIP_CALL( solveNodeInitialLP(blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
2867  pricestore, sepastore, cutpool, branchcand, eventfilter, eventqueue, cliquetable, newinitconss, cutoff, lperror) );
2868 
2869  assert(*cutoff || *lperror || (lp->flushed && lp->solved));
2870  SCIPsetDebugMsg(set, "price-and-cut-loop: initial LP status: %d, LP obj: %g\n",
2871  SCIPlpGetSolstat(lp),
2872  *cutoff ? SCIPsetInfinity(set) : *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
2873 
2874  /* update initial LP iteration counter */
2875  stat->ninitlps += stat->nlps - nlps;
2876  stat->ninitlpiterations += stat->nlpiterations - nlpiterations;
2877 
2878  /* In the root node, we try if the initial LP solution is feasible to avoid expensive setup of data structures in
2879  * separators; in case the root LP is aborted, e.g., by hitting the time limit, we do not check the LP solution
2880  * since the corresponding data structures have not been updated.
2881  */
2882  if( SCIPtreeGetCurrentDepth(tree) == 0 && !(*cutoff) && !(*lperror)
2884  && !SCIPsolveIsStopped(set, stat, FALSE) )
2885  {
2886  SCIP_Bool checklprows;
2887  SCIP_Bool stored;
2888  SCIP_SOL* sol;
2889  SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
2890 
2891  SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
2892 
2894  checklprows = FALSE;
2895  else
2896  checklprows = TRUE;
2897 
2898 #ifndef NDEBUG
2899  /* in the debug mode we want to explicitly check if the solution is feasible if it was stored */
2900  SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
2901  eventqueue, eventfilter, sol, FALSE, FALSE, TRUE, TRUE, checklprows, &stored) );
2902 
2903  if( stored )
2904  {
2905  SCIP_Bool feasible;
2906 
2907  SCIP_CALL( SCIPsolCheck(sol, set, messagehdlr, blkmem, stat, transprob, FALSE, FALSE, TRUE, TRUE,
2908  checklprows, &feasible) );
2909  assert(feasible);
2910  }
2911 
2912  SCIP_CALL( SCIPsolFree(&sol, blkmem, primal) );
2913 #else
2914  SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
2915  eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, checklprows, &stored) );
2916 #endif
2917  if( stored )
2918  {
2919  stat->nlpsolsfound++;
2920 
2921  if( primal->nbestsolsfound != oldnbestsolsfound )
2922  {
2923  stat->nlpbestsolsfound++;
2924  SCIPstoreSolutionGap(set->scip);
2925  }
2926 
2927  if( set->reopt_enable )
2928  {
2929  assert(reopt != NULL);
2930  SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, tree->focusnode, SCIP_EVENTTYPE_NODEFEASIBLE, lp,
2931  SCIPlpGetSolstat(lp), tree->root == tree->focusnode, TRUE, tree->focusnode->lowerbound,
2932  tree->effectiverootdepth) );
2933  }
2934  }
2935 
2937  *unbounded = TRUE;
2938  }
2939  }
2940  else
2941  {
2942  SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob,
2943  origprob, tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE,
2944  cutoff) );
2945  }
2946  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
2947 
2948  /* check for infeasible node by bounding */
2949  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
2950 #ifdef SCIP_DEBUG
2951  if( *cutoff )
2952  {
2953  if( SCIPtreeGetCurrentDepth(tree) == 0 )
2954  {
2955  SCIPsetDebugMsg(set, "solution cuts off root node, stop solution process\n");
2956  }
2957  else
2958  {
2959  SCIPsetDebugMsg(set, "solution cuts off node\n");
2960  }
2961  }
2962 #endif
2963 
2964  if( !(*cutoff) && !(*lperror) )
2965  {
2966  SCIP_Longint oldninitconssadded;
2967  SCIP_Longint oldnboundchgs;
2968  SCIP_Longint olddomchgcount;
2969  int oldnpricedvars;
2970  int oldncutsapplied;
2971 
2972  oldnpricedvars = transprob->ncolvars;
2973  oldninitconssadded = stat->ninitconssadded;
2974  oldncutsapplied = SCIPsepastoreGetNCutsApplied(sepastore);
2975  oldnboundchgs = stat->nboundchgs;
2976  olddomchgcount = stat->domchgcount;
2977 
2978  /* solve the LP with price-and-cut*/
2979  SCIP_CALL( priceAndCutLoop(blkmem, set, messagehdlr, stat, mem, transprob, origprob, primal, tree, reopt, lp,
2980  pricestore, sepastore, cutpool, delayedcutpool, branchcand, conflict, conflictstore, eventfilter,
2981  eventqueue, cliquetable, fullseparation, propagateagain, cutoff, unbounded, lperror, pricingaborted) );
2982 
2983  /* check if the problem was changed and the relaxation needs to be resolved */
2984  if( (transprob->ncolvars != oldnpricedvars) || (stat->ninitconssadded != oldninitconssadded) ||
2985  (SCIPsepastoreGetNCutsApplied(sepastore) != oldncutsapplied) || (stat->nboundchgs != oldnboundchgs) ||
2986  (stat->domchgcount != olddomchgcount) )
2987  {
2988  *solverelaxagain = TRUE;
2989  markRelaxsUnsolved(set, relaxation);
2990  }
2991 
2992  }
2993  assert(*cutoff || *lperror || (lp->flushed && lp->solved));
2994 
2995  /* if there is no LP error, then *unbounded should be TRUE, iff the LP solution status is unboundedray */
2996  assert(*lperror || ((SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY) == *unbounded));
2997 
2998  /* If pricing was aborted while solving the LP of the node and the node cannot be cut off due to the lower bound computed by the pricer,
2999  * the solving of the LP might be stopped due to the objective limit, but the node may not be cut off, since the LP objective
3000  * is not a feasible lower bound for the solutions in the current subtree.
3001  * In this case, the LP has to be solved to optimality by temporarily removing the cutoff bound.
3002  */
3003  if( (*pricingaborted) && (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_ITERLIMIT)
3004  && !(*cutoff) )
3005  {
3006  SCIP_Real tmpcutoff;
3007 
3008  /* temporarily disable cutoffbound, which also disables the objective limit */
3009  tmpcutoff = lp->cutoffbound;
3011 
3012  lp->solved = FALSE;
3013  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, FALSE, lperror) );
3014 
3015  /* reinstall old cutoff bound */
3016  lp->cutoffbound = tmpcutoff;
3017 
3018  SCIPsetDebugMsg(set, "re-optimized LP without cutoff bound: LP status: %d, LP obj: %g\n",
3019  SCIPlpGetSolstat(lp), *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
3020 
3021  /* lp solstat should not be objlimit, since the cutoff bound was removed temporarily */
3023  /* lp solstat should not be unboundedray, since the lp was dual feasible */
3025  /* there should be no primal ray, since the lp was dual feasible */
3026  assert(primal->primalray == NULL);
3028  {
3029  *cutoff = TRUE;
3030  }
3031  }
3032 
3033  assert(!(*pricingaborted) || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL /* cppcheck-suppress assertWithSideEffect */
3034  || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_NOTSOLVED || SCIPsolveIsStopped(set, stat, FALSE) || (*cutoff));
3035 
3036  assert(*cutoff || *lperror || (lp->flushed && lp->solved));
3037 
3038  /* update node's LP iteration counter */
3039  stat->nnodelps += stat->nlps - nlps;
3040  stat->nnodelpiterations += stat->nlpiterations - nlpiterations;
3041 
3042  /* update number of root node LPs and iterations if the root node was processed */
3043  if( SCIPnodeGetDepth(tree->focusnode) == 0 )
3044  {
3045  stat->nrootlps += stat->nlps - nlps;
3046  stat->nrootlpiterations += stat->nlpiterations - nlpiterations;
3047  }
3048 
3049  return SCIP_OKAY;
3050 }
3051 
3052 /** calls relaxators */
3053 static
3055  SCIP_SET* set, /**< global SCIP settings */
3056  SCIP_STAT* stat, /**< dynamic problem statistics */
3057  SCIP_TREE* tree, /**< branch and bound tree */
3058  SCIP_RELAXATION* relaxation, /**< relaxators */
3059  SCIP_PROB* transprob, /**< transformed problem */
3060  SCIP_PROB* origprob, /**< original problem */
3061  int depth, /**< depth of current node */
3062  SCIP_Bool beforelp, /**< should the relaxators with non-negative or negative priority be called? */
3063  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3064  SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3065  SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3066  SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called
3067  * again */
3068  SCIP_Bool* relaxcalled /**< pointer to store TRUE, if at least one relaxator was called (unmodified
3069  * otherwise) */
3070  )
3071 {
3072  SCIP_RESULT result;
3073  SCIP_Real lowerbound;
3074  int r;
3075 
3076  assert(set != NULL);
3077  assert(relaxation != NULL);
3078  assert(cutoff != NULL);
3079  assert(solvelpagain != NULL);
3080  assert(propagateagain != NULL);
3081  assert(solverelaxagain != NULL);
3082  assert(relaxcalled != NULL);
3083  assert(!(*cutoff));
3084 
3085  /* sort by priority */
3086  SCIPsetSortRelaxs(set);
3087 
3088  for( r = 0; r < set->nrelaxs && !(*cutoff); ++r )
3089  {
3090  if( beforelp != (SCIPrelaxGetPriority(set->relaxs[r]) >= 0) )
3091  continue;
3092 
3093  *relaxcalled = TRUE;
3094 
3095  lowerbound = -SCIPsetInfinity(set);
3096 
3097  /* invalidate relaxation solution */
3098  SCIPrelaxationSetSolValid(relaxation, FALSE);
3099 
3100  SCIP_CALL( SCIPrelaxExec(set->relaxs[r], set, stat, depth, &lowerbound, &result) );
3101 
3102  switch( result )
3103  {
3104  case SCIP_CUTOFF:
3105  *cutoff = TRUE;
3106  SCIPsetDebugMsg(set, " -> relaxator <%s> detected cutoff\n", SCIPrelaxGetName(set->relaxs[r]));
3107  /* @todo does it make sense to proceed if the node is proven to be infeasible? */
3108  return SCIP_OKAY;
3109 
3110  case SCIP_CONSADDED:
3111  *solvelpagain = TRUE; /* the separation for new constraints should be called */
3112  *propagateagain = TRUE; /* the propagation for new constraints should be called */
3113  break;
3114 
3115  case SCIP_REDUCEDDOM:
3116  *solvelpagain = TRUE;
3117  *propagateagain = TRUE;
3118  break;
3119 
3120  case SCIP_SEPARATED:
3121  *solvelpagain = TRUE;
3122  break;
3123 
3124  case SCIP_SUSPENDED:
3125  *solverelaxagain = TRUE;
3126  break;
3127 
3128  case SCIP_SUCCESS:
3129  case SCIP_DIDNOTRUN:
3130  break;
3131 
3132  default:
3133  SCIPerrorMessage("invalid result code <%d> of relaxator <%s>\n", result, SCIPrelaxGetName(set->relaxs[r]));
3134  return SCIP_INVALIDRESULT;
3135  } /*lint !e788*/
3136 
3137  if( result != SCIP_CUTOFF && result != SCIP_DIDNOTRUN && result != SCIP_SUSPENDED )
3138  {
3139  SCIP_NODE* focusnode;
3140 
3141  focusnode = SCIPtreeGetFocusNode(tree);
3142  assert(focusnode != NULL);
3143  assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
3144 
3145  /* update lower bound w.r.t. the lower bound given by the relaxator */
3146  SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, lowerbound);
3147  SCIPsetDebugMsg(set, " -> new lower bound given by relaxator %s: %g\n",
3148  SCIPrelaxGetName(set->relaxs[r]), lowerbound);
3149 
3150  /* update bestrelaxsol and bestrelaxobj; this is only possible if the solution has been marked as valid (via
3151  * SCIPmarkRelaxSolValid())
3152  */
3153  if( lowerbound > SCIPrelaxationGetBestRelaxSolObj(relaxation) && SCIPrelaxationIsSolValid(relaxation) &&
3154  SCIPrelaxIncludesLp(set->relaxs[r]) )
3155  {
3156  int i;
3157 
3158  SCIPsetDebugMsg(set, "update best relaxation solution\n");
3159 
3160  SCIPrelaxationSetBestRelaxSolObj(relaxation, lowerbound);
3161 
3162  for( i = 0; i < transprob->nvars; ++i )
3163  {
3164  assert(transprob->vars[i] != NULL);
3165 
3166  SCIP_CALL( SCIPsolSetVal(SCIPrelaxationGetBestRelaxSol(relaxation), set, stat, tree, transprob->vars[i],
3167  SCIPvarGetRelaxSol(transprob->vars[i], set)) );
3168  }
3169  }
3170  }
3171  }
3172 
3173  return SCIP_OKAY;
3174 }
3175 
3176 /** enforces constraints by branching, separation, or domain reduction */
3177 static
3179  BMS_BLKMEM* blkmem, /**< block memory buffers */
3180  SCIP_SET* set, /**< global SCIP settings */
3181  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3182  SCIP_STAT* stat, /**< dynamic problem statistics */
3183  SCIP_PROB* prob, /**< transformed problem after presolve */
3184  SCIP_TREE* tree, /**< branch and bound tree */
3185  SCIP_LP* lp, /**< LP data */
3186  SCIP_RELAXATION* relaxation, /**< global relaxation data */
3187  SCIP_SEPASTORE* sepastore, /**< separation storage */
3188  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3189  SCIP_Bool* branched, /**< pointer to store whether a branching was created */
3190  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3191  SCIP_Bool* infeasible, /**< pointer to store TRUE, if the LP/pseudo solution is infeasible */
3192  SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3193  SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3194  SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called again */
3195  SCIP_Bool forced /**< should enforcement of pseudo solution be forced? */
3196  )
3197 {
3198  SCIP_RESULT result;
3199  SCIP_Real pseudoobjval;
3200  SCIP_Bool resolved;
3201  SCIP_Bool objinfeasible;
3202  SCIP_Bool enforcerelaxsol;
3203  int h;
3204 
3205  assert(set != NULL);
3206  assert(stat != NULL);
3207  assert(tree != NULL);
3208  assert(SCIPtreeGetFocusNode(tree) != NULL);
3209  assert(branched != NULL);
3210  assert(cutoff != NULL);
3211  assert(infeasible != NULL);
3212  assert(propagateagain != NULL);
3213  assert(solvelpagain != NULL);
3214  assert(solverelaxagain != NULL);
3215  assert(!(*cutoff));
3216  assert(!(*propagateagain));
3217  assert(!(*solvelpagain));
3218  assert(!(*solverelaxagain));
3219 
3220  *branched = FALSE;
3221  /**@todo avoid checking the same pseudosolution twice */
3222 
3223 
3224  /* enforce (best) relaxation solution if the LP has a worse objective value */
3225  enforcerelaxsol = (! SCIPsetIsInfinity(set, -1 * SCIPrelaxationGetBestRelaxSolObj(relaxation))) && (!SCIPtreeHasFocusNodeLP(tree)
3226  || SCIPsetIsGT(set, SCIPrelaxationGetBestRelaxSolObj(relaxation), SCIPlpGetObjval(lp, set, prob)));
3227 
3228  /* check if all constraint handlers implement the enforelax callback, otherwise enforce the LP solution */
3229  for( h = 0; h < set->nconshdlrs && enforcerelaxsol; ++h )
3230  {
3231  if( set->conshdlrs_enfo[h]->consenforelax == NULL && ((! set->conshdlrs_enfo[h]->needscons) ||
3232  (set->conshdlrs_enfo[h]->nconss > 0)) )
3233  {
3234  SCIP_VERBLEVEL verblevel;
3235 
3236  enforcerelaxsol = FALSE;
3237 
3238  verblevel = SCIP_VERBLEVEL_FULL;
3239 
3240  if( !stat->disableenforelaxmsg && set->disp_verblevel == SCIP_VERBLEVEL_HIGH )
3241  {
3242  verblevel = SCIP_VERBLEVEL_HIGH;
3243 
3244  /* remember that the disable relaxation enforcement message was posted and only post it again if the
3245  * verblevel is SCIP_VERBLEVEL_FULL
3246  */
3247  stat->disableenforelaxmsg = TRUE;
3248  }
3249  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, verblevel, "Disable enforcement of relaxation solutions"
3250  " since constraint handler %s does not implement enforelax-callback\n",
3251  SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3252  }
3253  }
3254 
3255  /* enforce constraints by branching, applying additional cutting planes (if LP is being processed),
3256  * introducing new constraints, or tighten the domains
3257  */
3258 #ifndef SCIP_NDEBUG
3259  if( (! SCIPsetIsInfinity(set, -1 * SCIPrelaxationGetBestRelaxSolObj(relaxation))) && (!SCIPtreeHasFocusNodeLP(tree)
3260  || SCIPsetIsGT(set, SCIPrelaxationGetBestRelaxSolObj(relaxation), SCIPlpGetObjval(lp, set, prob))))
3261  {
3262  SCIPsetDebugMsg(set, "enforcing constraints on relaxation solution\n");
3263  }
3264  else
3265  {
3266  SCIPsetDebugMsg(set, "enforcing constraints on %s solution\n", SCIPtreeHasFocusNodeLP(tree) ? "LP" : "pseudo");
3267  }
3268 #endif
3269 
3270  /* check, if the solution is infeasible anyway due to it's objective value */
3271  if( SCIPtreeHasFocusNodeLP(tree) || enforcerelaxsol )
3272  objinfeasible = FALSE;
3273  else
3274  {
3275  pseudoobjval = SCIPlpGetPseudoObjval(lp, set, prob);
3276  objinfeasible = SCIPsetIsFeasLT(set, pseudoobjval, SCIPnodeGetLowerbound(SCIPtreeGetFocusNode(tree)));
3277  }
3278 
3279  /* during constraint enforcement, generated cuts should enter the LP in any case; otherwise, a constraint handler
3280  * would fail to enforce its constraints if it relies on the modification of the LP relaxation
3281  */
3282  SCIPsepastoreStartForceCuts(sepastore);
3283 
3284  /* enforce constraints until a handler resolved an infeasibility with cutting off the node, branching,
3285  * reducing a domain, or separating a cut
3286  * if a constraint handler introduced new constraints to enforce his constraints, the newly added constraints
3287  * have to be enforced themselves
3288  */
3289  resolved = FALSE;
3290 
3291  for( h = 0; h < set->nconshdlrs && !resolved; ++h )
3292  {
3293  assert(SCIPsepastoreGetNCuts(sepastore) == 0); /* otherwise, the LP should have been resolved first */
3294 
3295  /* enforce LP, pseudo, or relaxation solution */
3296  if( enforcerelaxsol )
3297  {
3298  SCIPsetDebugMsg(set, "enforce relaxation solution with value %g\n", SCIPrelaxationGetBestRelaxSolObj(relaxation));
3299 
3300  SCIP_CALL( SCIPconshdlrEnforceRelaxSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, sepastore,
3301  SCIPrelaxationGetBestRelaxSol(relaxation), *infeasible, &result) );
3302  }
3303  else if( SCIPtreeHasFocusNodeLP(tree) )
3304  {
3305 
3306  SCIPsetDebugMsg(set, "enforce LP solution with value %g\n", SCIPlpGetObjval(lp, set, prob));
3307 
3308  assert(lp->flushed);
3309  assert(lp->solved);
3311  SCIP_CALL( SCIPconshdlrEnforceLPSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, sepastore, *infeasible,
3312  &result) );
3313  }
3314  else
3315  {
3316  SCIP_CALL( SCIPconshdlrEnforcePseudoSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, branchcand, *infeasible,
3317  objinfeasible, forced, &result) );
3318  if( SCIPsepastoreGetNCuts(sepastore) != 0 )
3319  {
3320  SCIPerrorMessage("pseudo enforcing method of constraint handler <%s> separated cuts\n",
3321  SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3322  return SCIP_INVALIDRESULT;
3323  }
3324  }
3325  SCIPsetDebugMsg(set, "enforcing of <%s> returned result %d\n", SCIPconshdlrGetName(set->conshdlrs_enfo[h]), result);
3326 
3327  switch( result )
3328  {
3329  case SCIP_CUTOFF:
3330  assert(tree->nchildren == 0);
3331  *cutoff = TRUE;
3332  *infeasible = TRUE;
3333  resolved = TRUE;
3334  SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in enforcement\n",
3335  SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3336  break;
3337 
3338  case SCIP_CONSADDED:
3339  assert(tree->nchildren == 0);
3340  *infeasible = TRUE;
3341  *propagateagain = TRUE; /* the propagation for new constraints should be called */
3342  *solvelpagain = TRUE; /* the separation for new constraints should be called */
3343  *solverelaxagain = TRUE;
3344  markRelaxsUnsolved(set, relaxation);
3345  resolved = TRUE;
3346  break;
3347 
3348  case SCIP_REDUCEDDOM:
3349  assert(tree->nchildren == 0);
3350  *infeasible = TRUE;
3351  *propagateagain = TRUE;
3352  *solvelpagain = TRUE;
3353  *solverelaxagain = TRUE;
3354  markRelaxsUnsolved(set, relaxation);
3355  resolved = TRUE;
3356  break;
3357 
3358  case SCIP_SEPARATED:
3359  assert(tree->nchildren == 0);
3360  assert(SCIPsepastoreGetNCuts(sepastore) > 0);
3361  *infeasible = TRUE;
3362  *solvelpagain = TRUE;
3363  *solverelaxagain = TRUE;
3364  markRelaxsUnsolved(set, relaxation);
3365  resolved = TRUE;
3366  break;
3367 
3368  case SCIP_BRANCHED:
3369  assert(tree->nchildren >= 1);
3370  assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3371  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3372  *infeasible = TRUE;
3373  *branched = TRUE;
3374  resolved = TRUE;
3375 
3376  /* increase the number of internal nodes */
3377  stat->ninternalnodes++;
3378  stat->ntotalinternalnodes++;
3379  break;
3380 
3381  case SCIP_SOLVELP:
3382  assert(!SCIPtreeHasFocusNodeLP(tree));
3383  assert(tree->nchildren == 0);
3384  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3385  *infeasible = TRUE;
3386  *solvelpagain = TRUE;
3387  resolved = TRUE;
3388  SCIPtreeSetFocusNodeLP(tree, TRUE); /* the node's LP must be solved */
3389  break;
3390 
3391  case SCIP_INFEASIBLE:
3392  assert(tree->nchildren == 0);
3393  assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3394  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3395  *infeasible = TRUE;
3396  break;
3397 
3398  case SCIP_FEASIBLE:
3399  assert(tree->nchildren == 0);
3400  assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3401  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3402  break;
3403 
3404  case SCIP_DIDNOTRUN:
3405  assert(tree->nchildren == 0);
3406  assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3407  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3408  assert(objinfeasible);
3409  *infeasible = TRUE;
3410  break;
3411 
3412  default:
3413  SCIPerrorMessage("invalid result code <%d> from enforcing method of constraint handler <%s>\n",
3414  result, SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3415  return SCIP_INVALIDRESULT;
3416  } /*lint !e788*/
3417 
3418  /* the enforcement method may add a primal solution, after which the LP status could be set to
3419  * objective limit reached
3420  */
3422  {
3423  *cutoff = TRUE;
3424  *infeasible = TRUE;
3425  resolved = TRUE;
3426  SCIPsetDebugMsg(set, " -> LP exceeded objective limit\n");
3427 
3428  /* If we used the probing mode during branching, it might happen that we added a constraint or global bound
3429  * and returned SCIP_CONSADDED or SCIP_REDUCEDDOM, but when reoptimizing the LP after ending the probing mode,
3430  * this leads to hitting the objective limit. In this case, we do not need to propagate or solve the LP again.
3431  */
3432  *propagateagain = FALSE;
3433  *solvelpagain = FALSE;
3434  }
3435 
3436  assert(!(*branched) || (resolved && !(*cutoff) && *infeasible && !(*propagateagain) && !(*solvelpagain)));
3437  assert(!(*cutoff) || (resolved && !(*branched) && *infeasible && !(*propagateagain) && !(*solvelpagain)));
3438  assert(*infeasible || (!resolved && !(*branched) && !(*cutoff) && !(*propagateagain) && !(*solvelpagain)));
3439  assert(!(*propagateagain) || (resolved && !(*branched) && !(*cutoff) && *infeasible));
3440  assert(!(*solvelpagain) || (resolved && !(*branched) && !(*cutoff) && *infeasible));
3441  }
3442  assert(!objinfeasible || *infeasible);
3443  assert(resolved == (*branched || *cutoff || *propagateagain || *solvelpagain));
3444  assert(*cutoff || *solvelpagain || SCIPsepastoreGetNCuts(sepastore) == 0);
3445 
3446  /* deactivate the cut forcing of the constraint enforcement */
3447  SCIPsepastoreEndForceCuts(sepastore);
3448 
3449  SCIPsetDebugMsg(set, " -> enforcing result: branched=%u, cutoff=%u, infeasible=%u, propagateagain=%u, solvelpagain=%u, resolved=%u\n",
3450  *branched, *cutoff, *infeasible, *propagateagain, *solvelpagain, resolved);
3451 
3452  return SCIP_OKAY;
3453 }
3454 
3455 /** applies the cuts stored in the separation store, or clears the store if the node can be cut off */
3456 static
3458  BMS_BLKMEM* blkmem, /**< block memory buffers */
3459  SCIP_SET* set, /**< global SCIP settings */
3460  SCIP_STAT* stat, /**< dynamic problem statistics */
3461  SCIP_PROB* transprob, /**< transformed problem */
3462  SCIP_PROB* origprob, /**< original problem */
3463  SCIP_TREE* tree, /**< branch and bound tree */
3464  SCIP_REOPT* reopt, /**< reotimization data structure */
3465  SCIP_LP* lp, /**< LP data */
3466  SCIP_RELAXATION* relaxation, /**< relaxators */
3467  SCIP_SEPASTORE* sepastore, /**< separation storage */
3468  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3469  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3470  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
3471  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3472  SCIP_Bool root, /**< is this the initial root LP? */
3473  SCIP_EFFICIACYCHOICE efficiacychoice, /**< type of solution to base efficiacy computation on */
3474  SCIP_Bool* cutoff, /**< pointer to whether the node can be cut off */
3475  SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3476  SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3477  SCIP_Bool* solverelaxagain /**< pointer to store TRUE, if the node's relaxation has to be solved again */
3478  )
3479 {
3480  assert(stat != NULL);
3481  assert(cutoff != NULL);
3482  assert(propagateagain != NULL);
3483  assert(solvelpagain != NULL);
3484 
3485  if( *cutoff )
3486  {
3487  /* the found cuts are of no use, because the node is infeasible anyway (or we have an error in the LP) */
3488  SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
3489  }
3490  else if( SCIPsepastoreGetNCuts(sepastore) > 0 )
3491  {
3492  SCIP_Longint olddomchgcount;
3493  int oldncutsapplied;
3494 
3495  olddomchgcount = stat->domchgcount;
3496  oldncutsapplied = SCIPsepastoreGetNCutsApplied(sepastore);
3497  SCIP_CALL( SCIPsepastoreApplyCuts(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
3498  eventqueue, eventfilter, cliquetable, root, efficiacychoice, cutoff) );
3499  *propagateagain = *propagateagain || (stat->domchgcount != olddomchgcount);
3500  *solvelpagain = TRUE;
3501  if( (stat->domchgcount != olddomchgcount) || (SCIPsepastoreGetNCutsApplied(sepastore) != oldncutsapplied) )
3502  {
3503  *solverelaxagain = TRUE;
3504  markRelaxsUnsolved(set, relaxation);
3505  }
3506  }
3507 
3508  return SCIP_OKAY;
3509 }
3510 
3511 /** updates the cutoff, propagateagain, and solverelaxagain status of the current solving loop */
3512 static
3514  SCIP_SET* set, /**< global SCIP settings */
3515  SCIP_STAT* stat, /**< dynamic problem statistics */
3516  SCIP_TREE* tree, /**< branch and bound tree */
3517  int depth, /**< depth of current node */
3518  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3519  SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3520  SCIP_Bool* solverelaxagain /**< pointer to store TRUE, if at least one relaxator should be called again */
3521  )
3522 {
3523  SCIP_NODE* focusnode;
3524  int r;
3525 
3526  assert(set != NULL);
3527  assert(stat != NULL);
3528  assert(cutoff != NULL);
3529  assert(propagateagain != NULL);
3530  assert(solverelaxagain != NULL);
3531 
3532  /* check, if the path was cutoff */
3533  *cutoff = *cutoff || (tree->cutoffdepth <= depth);
3534 
3535  /* check if branching was already performed */
3536  if( tree->nchildren == 0 )
3537  {
3538  /* check, if the focus node should be repropagated */
3539  focusnode = SCIPtreeGetFocusNode(tree);
3540  *propagateagain = *propagateagain || SCIPnodeIsPropagatedAgain(focusnode);
3541 
3542  /* check, if one of the external relaxations should be solved again */
3543  for( r = 0; r < set->nrelaxs && !(*solverelaxagain); ++r )
3544  *solverelaxagain = *solverelaxagain || ( !SCIPrelaxIsSolved(set->relaxs[r], stat) );
3545  }
3546  else
3547  {
3548  /* if branching was performed, avoid another node loop iteration */
3549  *propagateagain = FALSE;
3550  *solverelaxagain = FALSE;
3551  }
3552 }
3553 
3554 /** propagate domains and solve relaxation and lp */
3555 static
3557  BMS_BLKMEM* blkmem, /**< block memory buffers */
3558  SCIP_SET* set, /**< global SCIP settings */
3559  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3560  SCIP_STAT* stat, /**< dynamic problem statistics */
3561  SCIP_MEM* mem, /**< block memory pools */
3562  SCIP_PROB* origprob, /**< original problem */
3563  SCIP_PROB* transprob, /**< transformed problem after presolve */
3564  SCIP_PRIMAL* primal, /**< primal data */
3565  SCIP_TREE* tree, /**< branch and bound tree */
3566  SCIP_REOPT* reopt, /**< reoptimization data structure */
3567  SCIP_LP* lp, /**< LP data */
3568  SCIP_RELAXATION* relaxation, /**< global relaxation data */
3569  SCIP_PRICESTORE* pricestore, /**< pricing storage */
3570  SCIP_SEPASTORE* sepastore, /**< separation storage */
3571  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3572  SCIP_CUTPOOL* cutpool, /**< global cut pool */
3573  SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
3574  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3575  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
3576  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3577  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3578  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3579  SCIP_NODE* focusnode, /**< focused node */
3580  int actdepth, /**< depth in the b&b tree */
3581  SCIP_Bool propagate, /**< should we propagate */
3582  SCIP_Bool solvelp, /**< should we solve the lp */
3583  SCIP_Bool solverelax, /**< should we solve the relaxation */
3584  SCIP_Bool forcedlpsolve, /**< is there a need for a solve lp */
3585  SCIP_Bool initiallpsolved, /**< was the initial LP already solved? */
3586  SCIP_Bool fullseparation, /**< are we in the first prop-and-cut-and-price loop? */
3587  SCIP_Longint* afterlpproplps, /**< pointer to store the last LP count for which AFTERLP propagation was performed */
3588  SCIP_HEURTIMING* heurtiming, /**< timing for running heuristics after propagation call */
3589  int* nlperrors, /**< pointer to store the number of lp errors */
3590  SCIP_Bool* fullpropagation, /**< pointer to store whether we want to do a fullpropagation next time */
3591  SCIP_Bool* propagateagain, /**< pointer to store whether we want to propagate again */
3592  SCIP_Bool* lpsolved, /**< pointer to store whether the lp was solved */
3593  SCIP_Bool* relaxcalled, /**< pointer to store whether a relaxator was called; initialized with last loop's result */
3594  SCIP_Bool* solvelpagain, /**< pointer to store whether we want to solve the lp again */
3595  SCIP_Bool* solverelaxagain, /**< pointer to store whether we want to solve the relaxation again */
3596  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
3597  SCIP_Bool* postpone, /**< pointer to store whether the node should be postponed */
3598  SCIP_Bool* unbounded, /**< pointer to store whether the focus node is unbounded */
3599  SCIP_Bool* stopped, /**< pointer to store whether solving was interrupted */
3600  SCIP_Bool* lperror, /**< pointer to store TRUE, if an unresolved error in LP solving occured */
3601  SCIP_Bool* pricingaborted, /**< pointer to store TRUE, if the pricing was aborted and the lower bound must not be used */
3602  SCIP_Bool* forcedenforcement /**< pointer to store whether the enforcement of pseudo solution should be forced */
3603  )
3604 {
3605  SCIP_Bool newinitconss;
3606 
3607  assert(set != NULL);
3608  assert(stat != NULL);
3609  assert(origprob != NULL);
3610  assert(transprob != NULL);
3611  assert(tree != NULL);
3612  assert(lp != NULL);
3613  assert(primal != NULL);
3614  assert(pricestore != NULL);
3615  assert(sepastore != NULL);
3616  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3617  assert(branchcand != NULL);
3618  assert(cutpool != NULL);
3619  assert(delayedcutpool != NULL);
3620  assert(conflict != NULL);
3621  assert(SCIPconflictGetNConflicts(conflict) == 0);
3622  assert(eventfilter != NULL);
3623  assert(eventqueue != NULL);
3624  assert(focusnode != NULL);
3625  assert(heurtiming != NULL);
3626  assert(nlperrors != NULL);
3627  assert(fullpropagation != NULL);
3628  assert(propagateagain != NULL);
3629  assert(afterlpproplps != NULL);
3630  assert(lpsolved != NULL);
3631  assert(solvelpagain != NULL);
3632  assert(solverelaxagain != NULL);
3633  assert(cutoff != NULL);
3634  assert(postpone != NULL);
3635  assert(unbounded != NULL);
3636  assert(lperror != NULL);
3637  assert(pricingaborted != NULL);
3638  assert(forcedenforcement != NULL);
3639 
3640  newinitconss = FALSE;
3641 
3642  if( !(*cutoff) && !(*postpone) )
3643  {
3644  SCIP_Longint oldninitconssadded;
3645  SCIP_Longint oldnboundchgs;
3646  SCIP_Bool lpwasflushed;
3647 
3648  lpwasflushed = lp->flushed;
3649  oldnboundchgs = stat->nboundchgs;
3650  oldninitconssadded = stat->ninitconssadded;
3651 
3652  /* call after LP propagators */
3653  if( ((*afterlpproplps) < stat->nnodelps && (*lpsolved)) || (*relaxcalled) )
3654  {
3655  SCIP_CALL( propagateDomains(blkmem, set, stat, primal, tree, SCIPtreeGetCurrentDepth(tree), 0, *fullpropagation,
3656  SCIP_PROPTIMING_AFTERLPLOOP, cutoff, postpone) );
3657  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3658 
3659  /* check, if the path was cutoff */
3660  *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3661  *afterlpproplps = stat->nnodelps;
3662  propagate = propagate || (stat->nboundchgs > oldnboundchgs);
3663  }
3664 
3665  /* call before LP propagators */
3666  if( propagate && !(*cutoff) )
3667  {
3668  SCIP_CALL( propagateDomains(blkmem, set, stat, primal, tree, SCIPtreeGetCurrentDepth(tree), 0, *fullpropagation,
3669  SCIP_PROPTIMING_BEFORELP, cutoff, postpone) );
3670  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3671  }
3672 
3673  newinitconss = (stat->ninitconssadded != oldninitconssadded);
3674  *fullpropagation = FALSE;
3675 
3676  /* check, if the path was cutoff */
3677  *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3678 
3679  /* if the LP was flushed and is now no longer flushed, a bound change occurred, and the LP has to be resolved;
3680  * we also have to solve the LP if new intial constraints were added which need to be added to the LP
3681  */
3682  solvelp = solvelp || (lpwasflushed && (!lp->flushed || newinitconss));
3683  solverelax = solverelax || newinitconss;
3684 
3685  /* the number of bound changes was increased by the propagation call, thus the relaxation should be solved again */
3686  if( stat->nboundchgs > oldnboundchgs )
3687  {
3688  /* propagation might have changed the best bound of loose variables, thereby changing the loose objective value
3689  * which is added to the LP value; because of the loose status, the LP might not be reoptimized, but the lower
3690  * bound of the node needs to be updated
3691  */
3692  if( !solvelp && lp->flushed && lp->solved && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
3693  {
3694  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
3695  SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
3696  SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
3697 
3698  if( SCIPtreeHasFocusNodeLP(tree) )
3699  {
3700  /* update node estimate */
3701  SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
3702 
3703  if( actdepth == 0 && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
3704  SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
3705  }
3706  }
3707 
3708  solverelax = TRUE;
3709  markRelaxsUnsolved(set, relaxation);
3710  }
3711 
3712  /* update lower bound with the pseudo objective value, and cut off node by bounding */
3713  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
3714  conflict, cliquetable, cutoff) );
3715  }
3716  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3717 
3718  if( *postpone )
3719  return SCIP_OKAY;
3720 
3721  /* call primal heuristics that are applicable after propagation loop before lp solve;
3722  * the first time we go here, we call the before node heuristics instead
3723  */
3724  if( !(*cutoff) && !SCIPtreeProbing(tree) )
3725  {
3726  /* if the heuristics find a new incumbent solution, propagate again */
3727  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, *heurtiming,
3728  FALSE, propagateagain, unbounded) );
3729  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3730 
3731  *heurtiming = SCIP_HEURTIMING_AFTERPROPLOOP;
3732 
3733  /* check if primal heuristics found a solution and we therefore reached a solution limit */
3734  if( SCIPsolveIsStopped(set, stat, FALSE) )
3735  {
3736  /* cppcheck-suppress unassignedVariable */
3737  SCIP_NODE* node;
3738 
3739  /* we reached a solution limit and do not want to continue the processing of the current node, but in order to
3740  * allow restarting the optimization process later, we need to create a "branching" with only one child node that
3741  * is a copy of the focusnode
3742  */
3744  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, 1.0, focusnode->estimate) );
3745  assert(tree->nchildren >= 1);
3746  *stopped = TRUE;
3747  return SCIP_OKAY;
3748  }
3749 
3750  /* if diving produced an LP error, switch back to non-LP node */
3751  if( lp->resolvelperror )
3752  {
3754  lp->resolvelperror = FALSE;
3755  }
3756 
3757  if( *propagateagain )
3758  {
3759  *solvelpagain = solvelp;
3760  *solverelaxagain = solverelax;
3761 
3762  return SCIP_OKAY;
3763  }
3764  }
3765 
3766  /* solve external relaxations with non-negative priority */
3767  *relaxcalled = FALSE;
3768  if( solverelax && !(*cutoff) )
3769  {
3770  /* initialize value for the best relaxation solution */
3772 
3773  /* clear the storage of external branching candidates */
3774  SCIPbranchcandClearExternCands(branchcand);
3775 
3776  SCIP_CALL( solveNodeRelax(set, stat, tree, relaxation, transprob, origprob, actdepth, TRUE,
3777  cutoff, propagateagain, solvelpagain, solverelaxagain, relaxcalled) );
3778  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3779 
3780  /* check, if the path was cutoff */
3781  *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3782 
3783  /* apply found cuts */
3784  SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
3785  eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_RELAX, cutoff, propagateagain,
3786  solvelpagain, solverelaxagain) );
3787 
3788  /* update lower bound with the pseudo objective value, and cut off node by bounding */
3789  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
3790  }
3791  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3792 
3793  /* check, if we want to solve the LP at this node */
3794  if( solvelp && !(*cutoff) && SCIPtreeHasFocusNodeLP(tree) )
3795  {
3796  *lperror = FALSE;
3797  *unbounded = FALSE;
3798 
3799  /* solve the node's LP */
3800  SCIP_CALL( solveNodeLP(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp, relaxation, pricestore,
3801  sepastore, cutpool, delayedcutpool, branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable,
3802  initiallpsolved, fullseparation, newinitconss, propagateagain, solverelaxagain, cutoff, unbounded, lperror, pricingaborted) );
3803 
3804  *lpsolved = TRUE;
3805  *solvelpagain = FALSE;
3806  SCIPsetDebugMsg(set, " -> LP status: %d, LP obj: %g, iter: %" SCIP_LONGINT_FORMAT ", count: %" SCIP_LONGINT_FORMAT "\n",
3807  SCIPlpGetSolstat(lp),
3808  *cutoff ? SCIPsetInfinity(set) : (*lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob)),
3809  stat->nlpiterations, stat->lpcount);
3810 
3811  /* check, if the path was cutoff */
3812  *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3813 
3814  /* if an error occured during LP solving, switch to pseudo solution */
3815  if( *lperror )
3816  {
3817  if( forcedlpsolve )
3818  {
3819  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
3820  stat->nnodes, stat->nlps);
3821  return SCIP_LPERROR;
3822  }
3824  ++(*nlperrors);
3825  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, actdepth == 0 ? SCIP_VERBLEVEL_HIGH : SCIP_VERBLEVEL_FULL,
3826  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
3827  stat->nnodes, stat->nlps, *nlperrors);
3828  }
3829 
3831  {
3833  *forcedenforcement = TRUE;
3834 
3835  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, actdepth == 0 ? SCIP_VERBLEVEL_HIGH : SCIP_VERBLEVEL_FULL,
3836  "(node %" SCIP_LONGINT_FORMAT ") LP solver hit %s limit in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead\n",
3837  stat->nnodes, SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_TIMELIMIT ? "time" : "iteration", stat->nlps);
3838  }
3839 
3841  {
3842  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
3843  "(node %" SCIP_LONGINT_FORMAT ") LP relaxation is unbounded (LP %" SCIP_LONGINT_FORMAT ")\n", stat->nnodes, stat->nlps);
3844  }
3845 
3846  /* if we solve exactly, the LP claims to be infeasible but the infeasibility could not be proved,
3847  * we have to forget about the LP and use the pseudo solution instead
3848  */
3849  if( !(*cutoff) && !(*lperror) && (set->misc_exactsolve || *pricingaborted) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_INFEASIBLE
3850  && SCIPnodeGetLowerbound(focusnode) < primal->cutoffbound )
3851  {
3852  if( SCIPbranchcandGetNPseudoCands(branchcand) == 0 && transprob->ncontvars > 0 )
3853  {
3854  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") could not prove infeasibility of LP %" SCIP_LONGINT_FORMAT " (exactsolve=%u, pricingaborted=%u), all variables are fixed, %d continuous vars\n",
3855  stat->nnodes, stat->nlps, set->misc_exactsolve, *pricingaborted, transprob->ncontvars);
3856  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") -> have to call PerPlex() (feature not yet implemented)\n", stat->nnodes);
3857  /**@todo call PerPlex */
3858  return SCIP_LPERROR;
3859  }
3860  else
3861  {
3863  *forcedenforcement = TRUE;
3864 
3865  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
3866  "(node %" SCIP_LONGINT_FORMAT ") could not prove infeasibility of LP %" SCIP_LONGINT_FORMAT " (exactsolve=%u, pricingaborted=%u) -- using pseudo solution (%d unfixed vars) instead\n",
3867  stat->nnodes, stat->nlps, set->misc_exactsolve, *pricingaborted, SCIPbranchcandGetNPseudoCands(branchcand));
3868  }
3869  }
3870 
3871  /* update lower bound with the pseudo objective value, and cut off node by bounding */
3872  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict,
3873  cliquetable, cutoff) );
3874  }
3875  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3876  assert(*cutoff || !SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3877 
3878  /* reset solverelaxagain if no relaxations were solved up to this point (the LP-changes are already included in
3879  * relaxators called after the LP)
3880  */
3881  *solverelaxagain = *solverelaxagain && *relaxcalled;
3882 
3883  /* solve external relaxations with negative priority */
3884  if( solverelax && !(*cutoff) )
3885  {
3886  SCIP_CALL( solveNodeRelax(set, stat, tree, relaxation, transprob, origprob, actdepth, FALSE, cutoff,
3887  propagateagain, solvelpagain, solverelaxagain, relaxcalled) );
3888  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3889 
3890  /* check, if the path was cutoff */
3891  *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3892 
3893  /* apply found cuts */
3894  SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
3895  eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_RELAX, cutoff, propagateagain,
3896  solvelpagain, solverelaxagain) );
3897 
3898  /* update lower bound with the pseudo objective value, and cut off node by bounding */
3899  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict,
3900  cliquetable, cutoff) );
3901  }
3902  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3903 
3904  return SCIP_OKAY;
3905 }
3906 
3907 /** check if a restart can be performed */
3908 #ifndef NDEBUG
3909 static
3911  SCIP_SET* set, /**< global SCIP settings */
3912  SCIP_STAT* stat /**< dynamic problem statistics */
3913  )
3914 {
3915  assert(set != NULL);
3916  assert(stat != NULL);
3917 
3918  return (set->nactivepricers == 0 && !set->reopt_enable
3919  && (set->presol_maxrestarts == -1 || stat->nruns <= set->presol_maxrestarts)
3920  && (set->limit_restarts == -1 || stat->nruns <= set->limit_restarts));
3921 }
3922 #else
3923 #define restartAllowed(set,stat) ((set)->nactivepricers == 0 && !set->reopt_enable && ((set)->presol_maxrestarts == -1 || (stat)->nruns <= (set)->presol_maxrestarts) \
3924  && (set->limit_restarts == -1 || stat->nruns <= set->limit_restarts))
3925 #endif
3926 
3927 /** solves the focus node */
3928 static
3930  BMS_BLKMEM* blkmem, /**< block memory buffers */
3931  SCIP_SET* set, /**< global SCIP settings */
3932  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3933  SCIP_STAT* stat, /**< dynamic problem statistics */
3934  SCIP_MEM* mem, /**< block memory pools */
3935  SCIP_PROB* origprob, /**< original problem */
3936  SCIP_PROB* transprob, /**< transformed problem after presolve */
3937  SCIP_PRIMAL* primal, /**< primal data */
3938  SCIP_TREE* tree, /**< branch and bound tree */
3939  SCIP_REOPT* reopt, /**< reoptimization data structure */
3940  SCIP_LP* lp, /**< LP data */
3941  SCIP_RELAXATION* relaxation, /**< global relaxation data */
3942  SCIP_PRICESTORE* pricestore, /**< pricing storage */
3943  SCIP_SEPASTORE* sepastore, /**< separation storage */
3944  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3945  SCIP_CUTPOOL* cutpool, /**< global cut pool */
3946  SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
3947  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3948  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
3949  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3950  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3951  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3952  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
3953  SCIP_Bool* postpone, /**< pointer to store whether the node should be postponed */
3954  SCIP_Bool* unbounded, /**< pointer to store whether the focus node is unbounded */
3955  SCIP_Bool* infeasible, /**< pointer to store whether the focus node's solution is infeasible */
3956  SCIP_Bool* restart, /**< should solving process be started again with presolving? */
3957  SCIP_Bool* afternodeheur, /**< pointer to store whether AFTERNODE heuristics were already called */
3958  SCIP_Bool* stopped /**< pointer to store whether solving was interrupted */
3959  )
3960 {
3961  SCIP_NODE* focusnode;
3962  SCIP_Longint lastdomchgcount;
3963  SCIP_Longint afterlpproplps;
3964  SCIP_Real restartfac;
3965  SCIP_Longint lastlpcount;
3966  SCIP_HEURTIMING heurtiming;
3967  int actdepth;
3968  int nlperrors;
3969  int nloops;
3970  SCIP_Bool foundsol = FALSE;
3971  SCIP_Bool focusnodehaslp;
3972  SCIP_Bool lpsolved;
3973  SCIP_Bool initiallpsolved;
3974  SCIP_Bool fullseparation;
3975  SCIP_Bool solverelaxagain;
3976  SCIP_Bool solvelpagain;
3977  SCIP_Bool propagateagain;
3978  SCIP_Bool fullpropagation;
3979  SCIP_Bool branched;
3980  SCIP_Bool forcedlpsolve;
3981  SCIP_Bool wasforcedlpsolve;
3982  SCIP_Bool pricingaborted;
3983 
3984  assert(set != NULL);
3985  assert(stat != NULL);
3986  assert(origprob != NULL);
3987  assert(transprob != NULL);
3988  assert(tree != NULL);
3989  assert(primal != NULL);
3990  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3991  assert(SCIPconflictGetNConflicts(conflict) == 0);
3992  assert(cutoff != NULL);
3993  assert(postpone != NULL);
3994  assert(unbounded != NULL);
3995  assert(infeasible != NULL);
3996  assert(restart != NULL);
3997  assert(afternodeheur != NULL);
3998 
3999  *cutoff = FALSE;
4000  *postpone = FALSE;
4001  *unbounded = FALSE;
4002  *infeasible = FALSE;
4003  *restart = FALSE;
4004  *afternodeheur = FALSE;
4005  *stopped = FALSE;
4006  pricingaborted = FALSE;
4007 
4008  focusnode = SCIPtreeGetFocusNode(tree);
4009  assert(focusnode != NULL);
4010  assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
4011  actdepth = SCIPnodeGetDepth(focusnode);
4012 
4013  /* invalidate relaxation solution */
4014  SCIPrelaxationSetSolValid(relaxation, FALSE);
4015 
4016  /* clear the storage of external branching candidates */
4017  SCIPbranchcandClearExternCands(branchcand);
4018 
4019  SCIPsetDebugMsg(set, "Processing node %" SCIP_LONGINT_FORMAT " in depth %d, %d siblings\n",
4020  stat->nnodes, actdepth, tree->nsiblings);
4021  SCIPsetDebugMsg(set, "current pseudosolution: obj=%g\n", SCIPlpGetPseudoObjval(lp, set, transprob));
4022  /*debug(SCIPprobPrintPseudoSol(transprob, set));*/
4023 
4024  /* check, if we want to solve the LP at the selected node:
4025  * - solve the LP, if the lp solve depth and frequency demand solving
4026  * - solve the root LP, if the LP solve frequency is set to 0
4027  * - solve the root LP, if there are continuous variables present
4028  * - don't solve the node if its cut off by the pseudo objective value anyway
4029  */
4030  focusnodehaslp = (set->lp_solvedepth == -1 || actdepth <= set->lp_solvedepth);
4031  focusnodehaslp = focusnodehaslp && (set->lp_solvefreq >= 1 && actdepth % set->lp_solvefreq == 0);
4032  focusnodehaslp = focusnodehaslp || (actdepth == 0 && set->lp_solvefreq == 0);
4033  focusnodehaslp = focusnodehaslp && SCIPsetIsLT(set, SCIPlpGetPseudoObjval(lp, set, transprob), primal->cutoffbound);
4034  focusnodehaslp = set->reopt_enable ? focusnodehaslp && SCIPreoptGetSolveLP(reopt, set, focusnode) : focusnodehaslp;
4035  SCIPtreeSetFocusNodeLP(tree, focusnodehaslp);
4036 
4037  /* external node solving loop:
4038  * - propagate domains
4039  * - solve SCIP_LP
4040  * - enforce constraints
4041  * if a constraint handler adds constraints to enforce its own constraints, both, propagation and LP solving
4042  * is applied again (if applicable on current node); however, if the new constraints don't have the enforce flag set,
4043  * it is possible, that the current infeasible solution is not cut off; in this case, we have to declare the solution
4044  * infeasible and perform a branching
4045  */
4046  lastdomchgcount = stat->domchgcount;
4047  lastlpcount = stat->lpcount;
4048  initiallpsolved = FALSE;
4049  fullseparation = TRUE;
4050  heurtiming = SCIP_HEURTIMING_BEFORENODE;
4051  nlperrors = 0;
4052  stat->npricerounds = 0;
4053  stat->nseparounds = 0;
4054  solverelaxagain = TRUE;
4055  solvelpagain = TRUE;
4056  propagateagain = TRUE;
4057  fullpropagation = TRUE;
4058  forcedlpsolve = FALSE;
4059  nloops = 0;
4060 
4061  /* reset best relaxation solution */
4062  SCIP_CALL( SCIPsolSetUnknown(SCIPrelaxationGetBestRelaxSol(relaxation), stat, tree) );
4064 
4065  while( !(*cutoff) && !(*postpone) && (solverelaxagain || solvelpagain || propagateagain) && nlperrors < MAXNLPERRORS && !(*restart) )
4066  {
4067  SCIP_Bool lperror;
4068  SCIP_Bool solverelax;
4069  SCIP_Bool solvelp;
4070  SCIP_Bool propagate;
4071  SCIP_Bool forcedenforcement;
4072  SCIP_Bool relaxcalled;
4073 
4074  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4075 
4076  *unbounded = FALSE;
4077  *infeasible = FALSE;
4078  foundsol = FALSE;
4079 
4080  nloops++;
4081  lperror = FALSE;
4082  lpsolved = FALSE;
4083  relaxcalled = FALSE;
4084  forcedenforcement = FALSE;
4085  afterlpproplps = -1L;
4086 
4087  while( !lperror && !(*cutoff) && (propagateagain || solvelpagain || solverelaxagain
4088  || (afterlpproplps < stat->nnodelps && lpsolved) || relaxcalled) )
4089  {
4090  solverelax = solverelaxagain;
4091  solverelaxagain = FALSE;
4092  solvelp = solvelpagain;
4093  solvelpagain = FALSE;
4094  propagate = propagateagain;
4095  propagateagain = FALSE;
4096 
4097  /* update lower bound with the pseudo objective value, and cut off node by bounding */
4098  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
4099  conflict, cliquetable, cutoff) );
4100 
4101  /* propagate domains before lp solving and solve relaxation and lp */
4102  SCIPsetDebugMsg(set, " -> node solving loop: call propagators that are applicable before%s LP is solved\n",
4103  lpsolved ? " and after" : "");
4104  SCIP_CALL( propAndSolve(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp,
4105  relaxation, pricestore, sepastore, branchcand, cutpool, delayedcutpool, conflict, conflictstore, eventfilter,
4106  eventqueue, cliquetable, focusnode, actdepth, propagate, solvelp, solverelax, forcedlpsolve, initiallpsolved,
4107  fullseparation, &afterlpproplps, &heurtiming, &nlperrors, &fullpropagation, &propagateagain, &lpsolved, &relaxcalled,
4108  &solvelpagain, &solverelaxagain, cutoff, postpone, unbounded, stopped, &lperror, &pricingaborted, &forcedenforcement) );
4109  initiallpsolved |= lpsolved;
4110 
4111  /* time or solution limit was hit and we already created a dummy child node to terminate fast */
4112  if( *stopped )
4113  return SCIP_OKAY;
4114 
4115  }
4116  fullseparation = FALSE;
4117 
4118  /* reset relaxation solution to best solution found, this might be important for heuristics depending on the relaxation solution */
4119  if( ! SCIPsetIsInfinity(set, -1 * SCIPrelaxationGetBestRelaxSolObj(relaxation)) )
4120  {
4121  SCIP_Real val;
4122  int i;
4123 
4124  for( i = 0; i < transprob->nvars; ++i )
4125  {
4126  assert(transprob->vars[i] != NULL);
4127 
4128  val = SCIPsolGetVal(SCIPrelaxationGetBestRelaxSol(relaxation), set, stat, transprob->vars[i]);
4129  SCIP_CALL( SCIPvarSetRelaxSol(transprob->vars[i], set, relaxation, val, TRUE) );
4130  }
4131 
4132  /* we have found at least one valid relaxation solution -> validate values stored in the variables */
4133  SCIPrelaxationSetSolValid(relaxation, TRUE);
4134  }
4135 
4136  /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4137  updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4138 
4139  /* call primal heuristics that should be applied after the LP relaxation of the node was solved;
4140  * if this is the first loop of the root node, call also AFTERNODE heuristics already here, since they might help
4141  * to improve the primal bound, thereby producing additional reduced cost strengthenings and strong branching
4142  * bound fixings which also might lead to a restart
4143  */
4144  if( !(*postpone) && (!(*cutoff) || SCIPtreeGetNNodes(tree) > 0) )
4145  {
4146  if( actdepth == 0 && !(*afternodeheur) )
4147  {
4148  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL,
4149  SCIP_HEURTIMING_AFTERLPLOOP | SCIP_HEURTIMING_AFTERNODE, *cutoff, &foundsol, unbounded) );
4150  *afternodeheur = TRUE; /* the AFTERNODE heuristics should not be called again after the node */
4151  }
4152  else if( lpsolved || (! SCIPsetIsInfinity(set, -1 * SCIPrelaxationGetBestRelaxSolObj(relaxation))) )
4153  {
4154  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, SCIP_HEURTIMING_AFTERLPLOOP,
4155  *cutoff, &foundsol, unbounded) );
4156  }
4157  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4158 
4159  /* heuristics might have found a solution or set the cutoff bound such that the current node is cut off */
4160  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4161  }
4162 
4163  /* check if heuristics leave us with an invalid LP */
4164  if( lp->resolvelperror )
4165  {
4166  if( forcedlpsolve )
4167  {
4168  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
4169  stat->nnodes, stat->nlps);
4170  return SCIP_LPERROR;
4171  }
4173  lp->resolvelperror = FALSE;
4174  nlperrors++;
4175  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4176  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
4177  stat->nnodes, stat->nlps, nlperrors);
4178  }
4179 
4180  if( pricingaborted && !(*cutoff) && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL )
4181  {
4182 
4184 
4185  /* if we just ran into the time limit this is not really a numerical trouble;
4186  * however, if this is not the case, we print messages about numerical troubles in the current LP
4187  */
4188  if( !SCIPsolveIsStopped(set, stat, FALSE) )
4189  {
4190  if( forcedlpsolve )
4191  {
4192  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
4193  stat->nnodes, stat->nlps);
4194  return SCIP_LPERROR;
4195  }
4196  nlperrors++;
4197  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4198  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
4199  stat->nnodes, stat->nlps, nlperrors);
4200  }
4201  }
4202 
4203  /* if an improved solution was found, propagate and solve the relaxations again */
4204  if( foundsol )
4205  {
4206  propagateagain = TRUE;
4207  solvelpagain = TRUE;
4208  solverelaxagain = TRUE;
4209  markRelaxsUnsolved(set, relaxation);
4210  }
4211 
4212  /* enforce constraints */
4213  branched = FALSE;
4214  if( !(*postpone) && !(*cutoff) && !solverelaxagain && !solvelpagain && !propagateagain )
4215  {
4216  /* if the solution changed since the last enforcement, we have to completely reenforce it; otherwise, we
4217  * only have to enforce the additional constraints added in the last enforcement, but keep the infeasible
4218  * flag TRUE in order to not declare the infeasible solution feasible due to disregarding the already
4219  * enforced constraints
4220  */
4221  if( lastdomchgcount != stat->domchgcount || lastlpcount != stat->lpcount )
4222  {
4223  lastdomchgcount = stat->domchgcount;
4224  lastlpcount = stat->lpcount;
4225  *infeasible = FALSE;
4226  }
4227 
4228  /* call constraint enforcement */
4229  SCIP_CALL( enforceConstraints(blkmem, set, messagehdlr, stat, transprob, tree, lp, relaxation, sepastore,
4230  branchcand, &branched, cutoff, infeasible, &propagateagain, &solvelpagain, &solverelaxagain,
4231  forcedenforcement) );
4232  assert(branched == (tree->nchildren > 0));
4233  assert(!branched || (!(*cutoff) && *infeasible && !propagateagain && !solvelpagain));
4234  assert(!(*cutoff) || (!branched && *infeasible && !propagateagain && !solvelpagain));
4235  assert(*infeasible || (!branched && !(*cutoff) && !propagateagain && !solvelpagain));
4236  assert(!propagateagain || (!branched && !(*cutoff) && *infeasible));
4237  assert(!solvelpagain || (!branched && !(*cutoff) && *infeasible));
4238 
4239  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4240 
4241  /* apply found cuts */
4242  SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4243  eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_LP, cutoff, &propagateagain,
4244  &solvelpagain, &solverelaxagain) );
4245 
4246  /* update lower bound with the pseudo objective value, and cut off node by bounding */
4247  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4248 
4249  /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4250  updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4251  }
4252  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4253 
4254  /* The enforcement detected no infeasibility, so, no branching was performed,
4255  * but the pricing was aborted and the current feasible solution does not have to be the
4256  * best solution in the current subtree --> we have to do a pseudo branching,
4257  * so we set infeasible TRUE and add the current solution to the solution pool
4258  */
4259  if( pricingaborted && !(*infeasible) && !(*cutoff) && !(*postpone) )
4260  {
4261  SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
4262  SCIP_SOL* sol;
4263  SCIP_Bool stored;
4264 
4265  /* in case the relaxation was enforced add this solution, otherwise decide between LP and pseudosol */
4266  if( (! SCIPsetIsInfinity(set, -1 * SCIPrelaxationGetBestRelaxSolObj(relaxation))) && (!SCIPtreeHasFocusNodeLP(tree)
4267  || SCIPsetIsGT(set, SCIPrelaxationGetBestRelaxSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
4268  {
4269  SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4270  eventqueue, eventfilter, SCIPrelaxationGetBestRelaxSol(relaxation), FALSE, FALSE, TRUE, TRUE, TRUE,
4271  &stored) );
4272 
4273  if( stored )
4274  {
4275  stat->nrelaxsolsfound++;
4276 
4277  if( primal->nbestsolsfound != oldnbestsolsfound )
4278  {
4279  stat->nrelaxbestsolsfound++;
4280  SCIPstoreSolutionGap(set->scip);
4281  }
4282  }
4283  }
4284  else
4285  {
4286  SCIP_CALL( SCIPsolCreateCurrentSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4287  SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4288  eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
4289 
4290  if( stored )
4291  {
4292  stat->nlpsolsfound++;
4293 
4294  if( primal->nbestsolsfound != oldnbestsolsfound )
4295  {
4296  stat->nlpbestsolsfound++;
4297  SCIPstoreSolutionGap(set->scip);
4298  }
4299  }
4300  }
4301 
4302  *infeasible = TRUE;
4303  }
4304 
4305  /* if the node is infeasible, but no constraint handler could resolve the infeasibility
4306  * -> branch on LP, external candidates, or the pseudo solution
4307  * -> e.g. select non-fixed binary or integer variable x with value x', create three
4308  * sons: x <= x'-1, x = x', and x >= x'+1.
4309  * In the left and right branch, the current solution is cut off. In the middle
4310  * branch, the constraints can hopefully reduce domains of other variables to cut
4311  * off the current solution.
4312  * In LP branching, we cannot allow adding constraints, because this does not necessary change the LP and can
4313  * therefore lead to an infinite loop.
4314  */
4315  wasforcedlpsolve = forcedlpsolve;
4316  forcedlpsolve = FALSE;
4317  if( (*infeasible) && !(*cutoff) && !(*postpone)
4318  && (!(*unbounded) || SCIPbranchcandGetNExternCands(branchcand) > 0 || SCIPbranchcandGetNPseudoCands(branchcand) > 0)
4319  && !solverelaxagain && !solvelpagain && !propagateagain && !branched )
4320  {
4321  SCIP_RESULT result;
4322  int nlpcands;
4323 
4324  result = SCIP_DIDNOTRUN;
4325 
4326  if( SCIPtreeHasFocusNodeLP(tree) )
4327  {
4328  SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nlpcands, NULL, NULL) );
4329  }
4330  else
4331  nlpcands = 0;
4332 
4333  if( nlpcands > 0 )
4334  {
4335  /* branch on LP solution */
4336  SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on LP solution with %d fractionals\n",
4337  SCIPnodeGetDepth(focusnode), nlpcands);
4338  SCIP_CALL( SCIPbranchExecLP(blkmem, set, stat, transprob, origprob, tree, reopt, lp, sepastore, branchcand,
4339  eventqueue, primal->cutoffbound, FALSE, &result) );
4340  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4341  assert(result != SCIP_DIDNOTRUN && result != SCIP_DIDNOTFIND);
4342  }
4343  else
4344  {
4345  if( SCIPbranchcandGetNExternCands(branchcand) > 0 )
4346  {
4347  /* branch on external candidates */
4348  SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on %d external branching candidates.\n",
4349  SCIPnodeGetDepth(focusnode), SCIPbranchcandGetNExternCands(branchcand));
4350  SCIP_CALL( SCIPbranchExecExtern(blkmem, set, stat, transprob, origprob, tree, reopt, lp, sepastore, branchcand,
4351  eventqueue, primal->cutoffbound, TRUE, &result) );
4352  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4353  }
4354 
4355  if( result == SCIP_DIDNOTRUN || result == SCIP_DIDNOTFIND )
4356  {
4357  /* branch on pseudo solution */
4358  SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on pseudo solution with %d unfixed integers\n",
4359  SCIPnodeGetDepth(focusnode), SCIPbranchcandGetNPseudoCands(branchcand));
4360  SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
4361  primal->cutoffbound, TRUE, &result) );
4362  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4363  }
4364 
4365  /* SCIP cannot guarantee convergence if it is necessary to branch on unbounded variables */
4366  if( result == SCIP_BRANCHED )
4367  {
4368  SCIP_VAR* var = stat->lastbranchvar;
4369 
4370  if( var != NULL && !stat->branchedunbdvar && (SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var))
4371  || SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var))) )
4372  {
4373  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_NORMAL,
4374  "Starting spatial branch-and-bound on unbounded variable <%s> ([%g,%g]) - cannot guarantee finite termination.\n",
4376  stat->branchedunbdvar = TRUE;
4377  }
4378  }
4379  }
4380 
4381  switch( result )
4382  {
4383  case SCIP_CUTOFF:
4384  assert(tree->nchildren == 0);
4385  *cutoff = TRUE;
4386  SCIPsetDebugMsg(set, " -> branching rule detected cutoff\n");
4387  break;
4388  case SCIP_CONSADDED:
4389  assert(tree->nchildren == 0);
4390  if( nlpcands > 0 )
4391  {
4392  SCIPerrorMessage("LP branching rule added constraint, which was not allowed this time\n");
4393  return SCIP_INVALIDRESULT;
4394  }
4395  propagateagain = TRUE;
4396  solvelpagain = TRUE;
4397  solverelaxagain = TRUE;
4398  markRelaxsUnsolved(set, relaxation);
4399  break;
4400  case SCIP_REDUCEDDOM:
4401  assert(tree->nchildren == 0);
4402  propagateagain = TRUE;
4403  solvelpagain = TRUE;
4404  solverelaxagain = TRUE;
4405  markRelaxsUnsolved(set, relaxation);
4406  break;
4407  case SCIP_SEPARATED:
4408  assert(tree->nchildren == 0);
4409  assert(SCIPsepastoreGetNCuts(sepastore) > 0);
4410  solvelpagain = TRUE;
4411  solverelaxagain = TRUE;
4412  markRelaxsUnsolved(set, relaxation);
4413  break;
4414  case SCIP_BRANCHED:
4415  assert(tree->nchildren >= 1);
4416  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4417  branched = TRUE;
4418 
4419  /* increase the number of internal nodes */
4420  stat->ninternalnodes++;
4421  stat->ntotalinternalnodes++;
4422  break;
4423  case SCIP_DIDNOTFIND: /*lint -fallthrough*/
4424  case SCIP_DIDNOTRUN:
4425  /* all integer variables in the infeasible solution are fixed,
4426  * - if no continuous variables exist and all variables are known, the infeasible pseudo solution is completely
4427  * fixed, and the node can be cut off
4428  * - if at least one continuous variable exists or we do not know all variables due to external pricers, we
4429  * cannot resolve the infeasibility by branching -> solve LP (and maybe price in additional variables)
4430  */
4431  assert(tree->nchildren == 0);
4432  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4433  assert(SCIPbranchcandGetNPseudoCands(branchcand) == 0);
4434 
4435  if( transprob->ncontvars == 0 && set->nactivepricers == 0 )
4436  {
4437  *cutoff = TRUE;
4438  SCIPsetDebugMsg(set, " -> cutoff because all variables are fixed in current node\n");
4439  }
4440  else
4441  {
4442  /* feasible LP solutions with all integers fixed must be feasible
4443  * if also no external branching candidates were available
4444  */
4445  assert(!SCIPtreeHasFocusNodeLP(tree) || pricingaborted);
4446 
4448  {
4449  SCIP_NODE* node;
4450 
4451  /* as we hit the time or iteration limit or another interrupt (e.g., gap limit), we do not want to solve the LP again.
4452  * in order to terminate correctly, we create a "branching" with only one child node
4453  * that is a copy of the focusnode
4454  */
4455  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, 1.0, focusnode->estimate) );
4456  assert(tree->nchildren >= 1);
4457  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4458  branched = TRUE;
4459  }
4460  else
4461  {
4462  SCIP_VERBLEVEL verblevel;
4463 
4464  if( pricingaborted )
4465  {
4466  SCIPerrorMessage("pricing was aborted, but no branching could be created!\n");
4467  return SCIP_INVALIDRESULT;
4468  }
4469 
4470  if( wasforcedlpsolve )
4471  {
4472  assert(SCIPtreeHasFocusNodeLP(tree));
4473  SCIPerrorMessage("LP was solved, all integers fixed, some constraint still infeasible, but no branching could be created!\n");
4474  return SCIP_INVALIDRESULT;
4475  }
4476 
4477  verblevel = SCIP_VERBLEVEL_FULL;
4478 
4479  if( !tree->forcinglpmessage && set->disp_verblevel == SCIP_VERBLEVEL_HIGH )
4480  {
4481  verblevel = SCIP_VERBLEVEL_HIGH;
4482 
4483  /* remember that the forcing LP solving message was posted and do only post it again if the
4484  * verblevel is SCIP_VERBLEVEL_FULL
4485  */
4486  tree->forcinglpmessage = TRUE;
4487  }
4488 
4489  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, verblevel,
4490  "(node %" SCIP_LONGINT_FORMAT ") forcing the solution of an LP (last LP %" SCIP_LONGINT_FORMAT ")...\n", stat->nnodes, stat->nlps);
4491 
4492  /* solve the LP in the next loop */
4494  solvelpagain = TRUE;
4495  forcedlpsolve = TRUE; /* this LP must be solved without error - otherwise we have to abort */
4496  }
4497  }
4498  break;
4499  default:
4500  SCIPerrorMessage("invalid result code <%d> from SCIPbranchLP(), SCIPbranchExt() or SCIPbranchPseudo()\n", result);
4501  return SCIP_INVALIDRESULT;
4502  } /*lint !e788*/
4503  assert(*cutoff || solvelpagain || propagateagain || branched); /* something must have been done */
4504  assert(!(*cutoff) || (!solvelpagain && !propagateagain && !branched));
4505  assert(!solvelpagain || (!(*cutoff) && !branched));
4506  assert(!propagateagain || (!(*cutoff) && !branched));
4507  assert(!branched || (!solvelpagain && !propagateagain));
4508  assert(branched == (tree->nchildren > 0));
4509 
4510  /* apply found cuts */
4511  SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4512  eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_LP, cutoff, &propagateagain,
4513  &solvelpagain, &solverelaxagain) );
4514 
4515  /* update lower bound with the pseudo objective value, and cut off node by bounding */
4516  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4517 
4518  /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4519  updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4520  }
4521 
4522  /* check for immediate restart */
4523  *restart = *restart || (actdepth == 0 && restartAllowed(set, stat) && (stat->userrestart
4524  || (stat->nrootintfixingsrun > set->presol_immrestartfac * (transprob->nvars - transprob->ncontvars)
4525  && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars))) );
4526 
4527  SCIPsetDebugMsg(set, "node solving iteration %d finished: cutoff=%u, postpone=%u, propagateagain=%u, solverelaxagain=%u, solvelpagain=%u, nlperrors=%d, restart=%u\n",
4528  nloops, *cutoff, *postpone, propagateagain, solverelaxagain, solvelpagain, nlperrors, *restart);
4529  }
4530  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4531  assert(*cutoff || SCIPconflictGetNConflicts(conflict) == 0);
4532 
4533  /* flush the conflict set storage */
4534  SCIP_CALL( SCIPconflictFlushConss(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cliquetable) );
4535 
4536  /* check for too many LP errors */
4537  if( nlperrors >= MAXNLPERRORS )
4538  {
4539  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- aborting\n", stat->nnodes, stat->nlps);
4540  return SCIP_LPERROR;
4541  }
4542 
4543  /* check for final restart */
4544  restartfac = set->presol_subrestartfac;
4545  if( actdepth == 0 )
4546  restartfac = MIN(restartfac, set->presol_restartfac);
4547  *restart = *restart || (restartAllowed(set, stat) && (stat->userrestart
4548  || (stat->nrootintfixingsrun > restartfac * (transprob->nvars - transprob->ncontvars)
4549  && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars))) );
4550 
4551  /* remember the last root LP solution */
4552  if( actdepth == 0 && !(*cutoff) && !(*unbounded) && !(*postpone) )
4553  {
4554  /* the root pseudo objective value and pseudo objective value should be equal in the root node */
4555  assert(SCIPsetIsFeasEQ(set, SCIPlpGetGlobalPseudoObjval(lp, set, transprob), SCIPlpGetPseudoObjval(lp, set, transprob)));
4556 
4557  SCIPprobStoreRootSol(transprob, set, stat, lp, SCIPtreeHasFocusNodeLP(tree));
4558  }
4559 
4560  /* check for cutoff */
4561  if( *cutoff )
4562  {
4563  SCIPsetDebugMsg(set, "node is cut off\n");
4564 
4565  SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, SCIPsetInfinity(set));
4566  *infeasible = TRUE;
4567  SCIP_CALL( SCIPdebugRemoveNode(blkmem, set, focusnode) ); /*lint !e506 !e774*/
4568  }
4569  else if( !(*unbounded) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && lp->looseobjvalinf == 0 )
4570  {
4571  /* update the regression statistic nlpbranchcands and LP objective value */
4572  int nlpbranchcands;
4573  SCIP_Real lpobjval;
4574 
4575  /* get number of LP candidate variables */
4576  SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nlpbranchcands, NULL, NULL) );
4577 
4578  /* get LP objective value */
4579  lpobjval = SCIPlpGetObjval(lp, set, transprob);
4580  assert(lpobjval != SCIP_INVALID && !SCIPsetIsInfinity(set, REALABS(lpobjval))); /*lint !e777*/
4581 
4582  /* add the observation to the regression */
4583  SCIPregressionAddObservation(stat->regressioncandsobjval, (SCIP_Real)nlpbranchcands, lpobjval);
4584  }
4585 
4586  return SCIP_OKAY;
4587 }
4588 
4589 /** if feasible, adds current solution to the solution storage */
4590 static
4592  BMS_BLKMEM* blkmem, /**< block memory buffers */
4593  SCIP_SET* set, /**< global SCIP settings */
4594  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4595  SCIP_STAT* stat, /**< dynamic problem statistics */
4596  SCIP_PROB* origprob, /**< original problem */
4597  SCIP_PROB* transprob, /**< transformed problem after presolve */
4598  SCIP_PRIMAL* primal, /**< primal data */
4599  SCIP_RELAXATION* relaxation, /**< global relaxation data */
4600  SCIP_TREE* tree, /**< branch and bound tree */
4601  SCIP_REOPT* reopt, /**< reoptimization data structure */
4602  SCIP_LP* lp, /**< LP data */
4603  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4604  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4605  SCIP_Bool checksol /**< should the solution be checked? */
4606  )
4607 {
4608  SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
4609  SCIP_SOL* sol;
4610  SCIP_Bool foundsol;
4611 
4612  /* found a feasible solution */
4613  if( (! SCIPsetIsInfinity(set, -1 * SCIPrelaxationGetBestRelaxSolObj(relaxation))) && (!SCIPtreeHasFocusNodeLP(tree)
4614  || SCIPsetIsGT(set, SCIPrelaxationGetBestRelaxSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
4615  {
4616  /* start clock for relaxation solutions */
4617  SCIPclockStart(stat->relaxsoltime, set);
4618 
4619  if( checksol || set->misc_exactsolve )
4620  {
4621  /* if we want to solve exactly, we have to check the solution exactly again */
4622  SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4623  eventqueue, eventfilter, SCIPrelaxationGetBestRelaxSol(relaxation), FALSE, FALSE, TRUE, TRUE, TRUE,
4624  &foundsol) );
4625  }
4626  else
4627  {
4628  SCIP_CALL( SCIPprimalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4629  eventqueue, eventfilter, SCIPrelaxationGetBestRelaxSol(relaxation), &foundsol) );
4630  }
4631 
4632  if( foundsol )
4633  {
4634  stat->nrelaxsolsfound++;
4635 
4636  if( primal->nbestsolsfound != oldnbestsolsfound )
4637  {
4638  stat->nrelaxbestsolsfound++;
4639  SCIPstoreSolutionGap(set->scip);
4640  }
4641  }
4642 
4643  /* stop clock for relaxation solutions */
4644  SCIPclockStop(stat->relaxsoltime, set);
4645 
4646  }
4647  else if( SCIPtreeHasFocusNodeLP(tree) )
4648  {
4649  assert(lp->primalfeasible);
4650 
4651  /* start clock for LP solutions */
4652  SCIPclockStart(stat->lpsoltime, set);
4653 
4654  /* add solution to storage */
4655  SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4656  if( checksol || set->misc_exactsolve )
4657  {
4658  /* if we want to solve exactly, we have to check the solution exactly again */
4659  SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4660  eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &foundsol) );
4661  }
4662  else
4663  {
4664  SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4665  eventqueue, eventfilter, &sol, &foundsol) );
4666  }
4667 
4668  if( foundsol )
4669  {
4670  stat->nlpsolsfound++;
4671 
4672  if( primal->nbestsolsfound != oldnbestsolsfound )
4673  {
4674  stat->nlpbestsolsfound++;
4675  SCIPstoreSolutionGap(set->scip);
4676  }
4677  }
4678 
4679  /* stop clock for LP solutions */
4680  SCIPclockStop(stat->lpsoltime, set);
4681  }
4682  else
4683  {
4684  /* start clock for pseudo solutions */
4685  SCIPclockStart(stat->pseudosoltime, set);
4686 
4687  /* add solution to storage */
4688  SCIP_CALL( SCIPsolCreatePseudoSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4689  if( checksol || set->misc_exactsolve )
4690  {
4691  /* if we want to solve exactly, we have to check the solution exactly again */
4692  SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4693  eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &foundsol) );
4694  }
4695  else
4696  {
4697  SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4698  eventqueue, eventfilter, &sol, &foundsol) );
4699  }
4700 
4701  /* stop clock for pseudo solutions */
4702  SCIPclockStop(stat->pseudosoltime, set);
4703 
4704  if( foundsol )
4705  {
4706  stat->npssolsfound++;
4707 
4708  if( primal->nbestsolsfound != oldnbestsolsfound )
4709  {
4710  stat->npsbestsolsfound++;
4711  SCIPstoreSolutionGap(set->scip);
4712  }
4713  }
4714  }
4715 
4716  return SCIP_OKAY;
4717 }
4718 
4719 /** main solving loop */
4721  BMS_BLKMEM* blkmem, /**< block memory buffers */
4722  SCIP_SET* set, /**< global SCIP settings */
4723  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4724  SCIP_STAT* stat, /**< dynamic problem statistics */
4725  SCIP_MEM* mem, /**< block memory pools */
4726  SCIP_PROB* origprob, /**< original problem */
4727  SCIP_PROB* transprob, /**< transformed problem after presolve */
4728  SCIP_PRIMAL* primal, /**< primal data */
4729  SCIP_TREE* tree, /**< branch and bound tree */
4730  SCIP_REOPT* reopt, /**< reoptimization data structure */
4731  SCIP_LP* lp, /**< LP data */
4732  SCIP_RELAXATION* relaxation, /**< global relaxation data */
4733  SCIP_PRICESTORE* pricestore, /**< pricing storage */
4734  SCIP_SEPASTORE* sepastore, /**< separation storage */
4735  SCIP_CUTPOOL* cutpool, /**< global cut pool */
4736  SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
4737  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4738  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4739  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
4740  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4741  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4742  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4743  SCIP_Bool* restart /**< should solving process be started again with presolving? */
4744  )
4745 {
4746  SCIP_NODESEL* nodesel;
4747  SCIP_NODE* focusnode;
4748  SCIP_NODE* nextnode;
4749  SCIP_EVENT event;
4750  SCIP_Real restartfac;
4751  SCIP_Real restartconfnum;
4752  int nnodes;
4753  int depth;
4754  SCIP_Bool cutoff;
4755  SCIP_Bool postpone;
4756  SCIP_Bool unbounded;
4757  SCIP_Bool infeasible;
4758  SCIP_Bool foundsol;
4759 
4760  assert(set != NULL);
4761  assert(blkmem != NULL);
4762  assert(stat != NULL);
4763  assert(transprob != NULL);
4764  assert(tree != NULL);
4765  assert(lp != NULL);
4766  assert(pricestore != NULL);
4767  assert(sepastore != NULL);
4768  assert(branchcand != NULL);
4769  assert(cutpool != NULL);
4770  assert(delayedcutpool != NULL);
4771  assert(primal != NULL);
4772  assert(eventfilter != NULL);
4773  assert(eventqueue != NULL);
4774  assert(restart != NULL);
4775 
4776  /* check for immediate restart (if problem solving marked to be restarted was aborted) */
4777  restartfac = set->presol_subrestartfac;
4778  if( SCIPtreeGetCurrentDepth(tree) == 0 )
4779  restartfac = MIN(restartfac, set->presol_restartfac);
4780  *restart = restartAllowed(set, stat) && (stat->userrestart
4781  || (stat->nrootintfixingsrun > restartfac * (transprob->nvars - transprob->ncontvars)
4782  && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars)) );
4783 
4784  /* calculate the number of successful conflict analysis calls that should trigger a restart */
4785  if( set->conf_restartnum > 0 )
4786  {
4787  int i;
4788 
4789  restartconfnum = (SCIP_Real)set->conf_restartnum;
4790  for( i = 0; i < stat->nconfrestarts; ++i )
4791  restartconfnum *= set->conf_restartfac;
4792  }
4793  else
4794  restartconfnum = SCIP_REAL_MAX;
4795  assert(restartconfnum >= 0.0);
4796 
4797  /* switch status to UNKNOWN */
4798  stat->status = SCIP_STATUS_UNKNOWN;
4799 
4800  focusnode = NULL;
4801  nextnode = NULL;
4802  unbounded = FALSE;
4803  postpone = FALSE;
4804 
4805  while( !SCIPsolveIsStopped(set, stat, TRUE) && !(*restart) )
4806  {
4807  SCIP_Longint nsuccessconflicts;
4808  SCIP_Bool afternodeheur;
4809  SCIP_Bool stopped;
4810  SCIP_Bool branched;
4811 
4812  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4813 
4814  foundsol = FALSE;
4815  infeasible = FALSE;
4816 
4817  do
4818  {
4819  /* update the memory saving flag, switch algorithms respectively */
4820  SCIPstatUpdateMemsaveMode(stat, set, messagehdlr, mem);
4821 
4822  /* get the current node selector */
4823  nodesel = SCIPsetGetNodesel(set, stat);
4824 
4825  /* inform tree about the current node selector */
4826  SCIP_CALL( SCIPtreeSetNodesel(tree, set, messagehdlr, stat, nodesel) );
4827 
4828  /* the next node was usually already selected in the previous solving loop before the primal heuristics were
4829  * called, because they need to know, if the next node will be a child/sibling (plunging) or not;
4830  * if the heuristics found a new best solution that cut off some of the nodes, the node selector must be called
4831  * again, because the selected next node may be invalid due to cut off
4832  */
4833  if( nextnode == NULL )
4834  {
4835  /* select next node to process */
4836  SCIP_CALL( SCIPnodeselSelect(nodesel, set, &nextnode) );
4837  }
4838  focusnode = nextnode;
4839  nextnode = NULL;
4840  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4841 
4842  /* start node activation timer */
4843  SCIPclockStart(stat->nodeactivationtime, set);
4844 
4845  /* focus selected node */
4846  SCIP_CALL( SCIPnodeFocus(&focusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt,
4847  lp, branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, FALSE, FALSE) );
4848  if( cutoff )
4849  stat->ndelayedcutoffs++;
4850 
4851  /* stop node activation timer */
4852  SCIPclockStop(stat->nodeactivationtime, set);
4853 
4854  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4855  }
4856  while( cutoff ); /* select new node, if the current one was located in a cut off subtree */
4857 
4858  assert(SCIPtreeGetCurrentNode(tree) == focusnode);
4859  assert(SCIPtreeGetFocusNode(tree) == focusnode);
4860 
4861  /* if no more node was selected, we finished optimization */
4862  if( focusnode == NULL )
4863  {
4864  assert(SCIPtreeGetNNodes(tree) == 0);
4865  break;
4866  }
4867 
4868  /* update maxdepth and node count statistics */
4869  depth = SCIPnodeGetDepth(focusnode);
4870  stat->maxdepth = MAX(stat->maxdepth, depth);
4871  stat->maxtotaldepth = MAX(stat->maxtotaldepth, depth);
4872  stat->nnodes++;
4873  stat->ntotalnodes++;
4874 
4875  /* update reference bound statistic, if available */
4876  if( SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), stat->referencebound) )
4877  stat->nnodesaboverefbound++;
4878 
4879  /* issue NODEFOCUSED event */
4881  SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
4882  SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
4883 
4884  /* solve focus node */
4885  SCIP_CALL( solveNode(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp, relaxation,
4886  pricestore, sepastore, branchcand, cutpool, delayedcutpool, conflict, conflictstore, eventfilter, eventqueue,
4887  cliquetable, &cutoff, &postpone, &unbounded, &infeasible, restart, &afternodeheur, &stopped) );
4888  assert(!cutoff || infeasible);
4889  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4890  assert(SCIPtreeGetCurrentNode(tree) == focusnode);
4891  assert(SCIPtreeGetFocusNode(tree) == focusnode);
4892 
4893  branched = (tree->nchildren > 0);
4894 
4895  if( stopped )
4896  break;
4897 
4898  /* check for restart */
4899  if( !(*restart) && !postpone )
4900  {
4901  /* change color of node in visualization */
4902  SCIPvisualSolvedNode(stat->visual, set, stat, focusnode);
4903 
4904  /* check, if the current solution is feasible */
4905  if( !infeasible )
4906  {
4907  SCIP_Bool feasible;
4908 
4909  assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
4910  assert(!cutoff);
4911 
4912  /* in the unbounded case, we check the solution w.r.t. the original problem, because we do not want to rely
4913  * on the LP feasibility and integrality is not checked for unbounded solutions, anyway
4914  */
4915  if( unbounded )
4916  {
4917  SCIP_SOL* sol;
4918 
4919  if( (! SCIPsetIsInfinity(set, -1 * SCIPrelaxationGetBestRelaxSolObj(relaxation))) && (!SCIPtreeHasFocusNodeLP(tree)
4920  || SCIPsetIsGT(set, SCIPrelaxationGetBestRelaxSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
4921  {
4922  sol = SCIPrelaxationGetBestRelaxSol(relaxation);
4923  }
4924  else if( SCIPtreeHasFocusNodeLP(tree) )
4925  {
4926  SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4927  }
4928  else
4929  {
4930  SCIP_CALL( SCIPsolCreatePseudoSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4931  }
4932  SCIP_CALL( SCIPcheckSolOrig(set->scip, sol, &feasible, FALSE, FALSE) );
4933 
4934  SCIP_CALL( SCIPsolFree(&sol, blkmem, primal) );
4935  }
4936  else
4937  feasible = TRUE;
4938 
4939  /* node solution is feasible: add it to the solution store */
4940  if( feasible )
4941  {
4942  SCIP_CALL( addCurrentSolution(blkmem, set, messagehdlr, stat, origprob, transprob, primal, relaxation, tree, reopt,
4943  lp, eventqueue, eventfilter, FALSE) );
4944 
4945  /* update the cutoff pointer if the new solution made the cutoff bound equal to the lower bound */
4946  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, &cutoff) );
4947 
4948 
4949  /* increment number of feasible leaf nodes */
4950  stat->nfeasleaves++;
4951 
4952  /* issue NODEFEASIBLE event */
4954  SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
4955  SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
4956 
4957  if( set->reopt_enable )
4958  {
4959  assert(reopt != NULL);
4960  SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEFEASIBLE, lp,
4961  SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
4962  focusnode->lowerbound, tree->effectiverootdepth) );
4963  }
4964  }
4965  }
4966  else if( !unbounded )
4967  {
4968  /* node solution is not feasible */
4969  if( !branched )
4970  {
4971  assert(tree->nchildren == 0);
4972 
4973  /* change color of node in visualization output */
4974  SCIPvisualCutoffNode(stat->visual, set, stat, focusnode, TRUE);
4975 
4976  /* issue NODEINFEASIBLE event */
4978 
4979  /* we only increase the number of objective leaf nodes if we hit the LP objective limit; we might have also
4980  * hit the objective limit at a node that is actually infeasible, or a dual reduction led to an infeasibility prior
4981  * to LP solving such that the node will be marked as infeasible */
4983  stat->nobjleaves++;
4984  else
4985  stat->ninfeasleaves++;
4986 
4987  if( set->reopt_enable )
4988  {
4989  assert(reopt != NULL);
4990  SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEINFEASIBLE, lp,
4991  SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
4992  focusnode->lowerbound, tree->effectiverootdepth) );
4993  }
4994 
4995  /* increase the cutoff counter of the branching variable */
4996  if( stat->lastbranchvar != NULL )
4997  {
4998  SCIP_CALL( SCIPvarIncCutoffSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
4999  }
5000  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
5001  }
5002  else
5003  {
5004  assert(tree->nchildren > 0);
5005 
5006  /* issue NODEBRANCHED event */
5008 
5009  if( set->reopt_enable )
5010  {
5011  assert(reopt != NULL);
5012  SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEBRANCHED, lp,
5013  SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
5014  focusnode->lowerbound, tree->effectiverootdepth) );
5015  }
5016  }
5017  SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
5018  SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
5019  }
5020  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5021 
5022  /* if no branching was created, the node was not cut off, but its lower bound is still smaller than
5023  * the cutoff bound, we have to branch on a non-fixed variable;
5024  * this can happen, if we want to solve exactly, the current solution was declared feasible by the
5025  * constraint enforcement, but in exact solution checking it was found out to be infeasible;
5026  * in this case, no branching would have been generated by the enforcement of constraints, but we
5027  * have to further investigate the current sub tree;
5028  * note that we must noch check tree->nchildren > 0 here to determine whether we branched, we rather
5029  * check it directly after solveNode() and store the result, because an event handler might impose a
5030  * new cutoff bound (as is the case in ParaSCIP)
5031  */
5032  if( !cutoff && !unbounded && !branched && SCIPnodeGetLowerbound(focusnode) < primal->cutoffbound )
5033  {
5034  SCIP_RESULT result;
5035 
5036  assert(set->misc_exactsolve);
5037 
5038  do
5039  {
5040  result = SCIP_DIDNOTRUN;
5041  if( SCIPbranchcandGetNPseudoCands(branchcand) == 0 )
5042  {
5043  if( transprob->ncontvars > 0 )
5044  {
5045  /**@todo call PerPlex */
5046  SCIPerrorMessage("cannot branch on all-fixed LP -- have to call PerPlex instead\n");
5047  }
5048  }
5049  else
5050  {
5051  SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
5052  eventqueue, primal->cutoffbound, FALSE, &result) );
5053  assert(result != SCIP_DIDNOTRUN && result != SCIP_DIDNOTFIND);
5054  }
5055  }
5056  while( result == SCIP_REDUCEDDOM );
5057  }
5058  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5059 
5060  /* select node to process in next solving loop; the primal heuristics need to know whether a child/sibling
5061  * (plunging) will be selected as next node or not
5062  */
5063  SCIP_CALL( SCIPnodeselSelect(nodesel, set, &nextnode) );
5064  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5065 
5066  /* call primal heuristics that should be applied after the node was solved */
5067  nnodes = SCIPtreeGetNNodes(tree);
5068  stopped = SCIPsolveIsStopped(set, stat, FALSE);
5069  if( !afternodeheur && (!cutoff || nnodes > 0) && !stopped )
5070  {
5071  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, nextnode, SCIP_HEURTIMING_AFTERNODE,
5072  cutoff, &foundsol, &unbounded) );
5073  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5074 
5075  stopped = SCIPsolveIsStopped(set, stat, FALSE);
5076  }
5077 
5078  /* if the heuristics found a new best solution that cut off some of the nodes, the node selector must be called
5079  * again, because the selected next node may be invalid due to cut off
5080  */
5081  assert(!tree->cutoffdelayed);
5082 
5083  if( nnodes != SCIPtreeGetNNodes(tree) || stopped )
5084  nextnode = NULL;
5085  }
5086  else if( !infeasible && !postpone )
5087  {
5088  /* The current solution was not proven to be infeasible, but due to the restart, this does not mean that it is
5089  * feasible, we might just have skipped the check. Thus, we try to add it to the solution store, but check it
5090  * again.
5091  */
5092  SCIP_CALL( addCurrentSolution(blkmem, set, messagehdlr, stat, origprob, transprob, primal, relaxation, tree, reopt, lp,
5093  eventqueue, eventfilter, TRUE) );
5094 
5095  if( set->reopt_enable )
5096  {
5097  assert(reopt != NULL);
5098  SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEFEASIBLE, lp,
5099  SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode, focusnode->lowerbound,
5100  tree->effectiverootdepth) );
5101  }
5102  }
5103  /* we want to put the focusnode back into the leaf queue if it was postponed */
5104  else if( postpone )
5105  {
5106  SCIP_NODE* newfocusnode = NULL;
5107 
5108  /* @todo should we re-install the old focus node in order to somehow set the forks more clever? */
5109  SCIP_CALL( SCIPnodeFocus(&newfocusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
5110  branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, TRUE, FALSE) );
5111  }
5112  /* compute number of successfully applied conflicts */
5113  nsuccessconflicts = SCIPconflictGetNPropSuccess(conflict) + SCIPconflictGetNInfeasibleLPSuccess(conflict)
5115  + SCIPconflictGetNPseudoSuccess(conflict);
5116 
5117  /* trigger restart due to conflicts and the restart parameters allow another restart */
5118  if( nsuccessconflicts >= restartconfnum && restartAllowed(set, stat) )
5119  {
5120  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
5121  "(run %d, node %" SCIP_LONGINT_FORMAT ") restarting after %" SCIP_LONGINT_FORMAT " successful conflict analysis calls\n",
5122  stat->nruns, stat->nnodes, nsuccessconflicts);
5123  *restart = TRUE;
5124 
5125  stat->nconfrestarts++;
5126  }
5127 
5128  /* restart if the userrestart was set to true, we have still some nodes left and the restart parameters allow
5129  * another restart
5130  */
5131  *restart = *restart || (stat->userrestart && SCIPtreeGetNNodes(tree) > 0 && restartAllowed(set, stat));
5132  if( restartAllowed(set, stat) && set->limit_autorestartnodes == stat->nnodes && stat->ntotalnodes - stat->nruns + 1 == set->limit_autorestartnodes )
5133  {
5134  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
5135  "(run %d, node %" SCIP_LONGINT_FORMAT ") restarting: triggering parameter controlled restart)\n",
5136  stat->nruns, stat->nnodes);
5137  *restart = TRUE;
5138  }
5139  /* if restart limit was exceeded, change the status; if status is different from unknown, ie some other limit was
5140  * hit, leave it unchanged
5141  */
5142  if( *restart && stat->status == SCIP_STATUS_UNKNOWN && set->limit_restarts >= 0 && stat->nruns > set->limit_restarts )
5143  {
5144  *restart = FALSE;
5146  }
5147 
5148  /* display node information line */
5149  SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, (SCIPnodeGetDepth(focusnode) == 0) && infeasible && !foundsol, TRUE) );
5150 
5151  SCIPsetDebugMsg(set, "Processing of node %" SCIP_LONGINT_FORMAT " in depth %d finished. %d siblings, %d children, %d leaves left\n",
5152  stat->nnodes, SCIPnodeGetDepth(focusnode), tree->nsiblings, tree->nchildren, SCIPtreeGetNLeaves(tree));
5153  SCIPsetDebugMsg(set, "**********************************************************************\n");
5154  }
5155 
5156  /* update the primal-dual integral if node or time limits were hit or an interruption signal was called */
5157  if( SCIPsolveIsStopped(set, stat, TRUE) )
5158  {
5159  SCIPstatUpdatePrimalDualIntegral(stat, set, transprob, origprob, SCIPsetInfinity(set), -SCIPsetInfinity(set));
5160  }
5161 
5162  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5163 
5164  SCIPsetDebugMsg(set, "Problem solving finished with status %u (restart=%u, userrestart=%u)\n", stat->status, *restart, stat->userrestart);
5165 
5166  /* cuts off nodes with lower bound is not better than given cutoff bound, manually; this necessary to ensure that
5167  * SCIP terminates with a proper solve stage
5168  */
5169  SCIP_CALL( SCIPtreeCutoff(tree, reopt, blkmem, set, stat, eventqueue, lp, primal->cutoffbound) );
5170 
5171  /* if the current node is the only remaining node, and if its lower bound exceeds the upper bound, we have
5172  * to delete it manually in order to get to the SOLVED stage instead of thinking, that only the gap limit
5173  * was reached (this may happen, if the current node is the one defining the global lower bound and a
5174  * feasible solution with the same value was found at this node)
5175  */
5176  if( tree->focusnode != NULL && SCIPtreeGetNNodes(tree) == 0
5177  && SCIPsetIsGE(set, tree->focusnode->lowerbound, primal->cutoffbound) )
5178  {
5179  if( set->reopt_enable )
5180  {
5181  assert(reopt != NULL);
5183  SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode, tree->focusnode->lowerbound,
5184  tree->effectiverootdepth) );
5185  }
5186 
5187  focusnode = NULL;
5188  SCIP_CALL( SCIPnodeFocus(&focusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
5189  branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, FALSE, FALSE) );
5190  }
5191 
5192  /* check whether we finished solving */
5193  if( SCIPtreeGetNNodes(tree) == 0 && SCIPtreeGetCurrentNode(tree) == NULL )
5194  {
5195  /* no restart necessary */
5196  *restart = FALSE;
5197 
5198  /* set the solution status */
5199  if( unbounded )
5200  {
5201  if( primal->nsols > 0 )
5202  {
5203  /* switch status to UNBOUNDED */
5204  stat->status = SCIP_STATUS_UNBOUNDED;
5205  }
5206  else
5207  {
5208  /* switch status to INFORUNB */
5209  stat->status = SCIP_STATUS_INFORUNBD;
5210  }
5211  }
5212  else if( primal->nlimsolsfound == 0 )
5213  {
5214  assert(primal->nsols == 0 || SCIPsetIsGT(set, SCIPsolGetObj(primal->sols[0], set, transprob, origprob),
5215  SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(transprob, set))));
5216 
5217  /* switch status to INFEASIBLE */
5219  }
5220  else
5221  {
5222  /* switch status to OPTIMAL */
5223  stat->status = SCIP_STATUS_OPTIMAL;
5224  }
5225  }
5226 
5227  return SCIP_OKAY;
5228 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Real cutoffbound
Definition: struct_primal.h:46
internal methods for separators
SCIP_Longint SCIPconflictGetNStrongbranchSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:7829
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
#define SCIP_HEURTIMING_DURINGLPLOOP
Definition: type_timing.h:71
SCIP_RETCODE SCIPlpGetProvedLowerbound(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *bound)
Definition: lp.c:15619
void SCIPpricestoreEndInitialLP(SCIP_PRICESTORE *pricestore)
Definition: pricestore.c:158
SCIP_SOL * primalray
Definition: struct_primal.h:52
SCIP_Bool SCIPsolveIsStopped(SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool checknodelimits)
Definition: solve.c:71
SCIP_RETCODE SCIPconshdlrEnforcePseudoSol(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_BRANCHCAND *branchcand, SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_Bool forced, SCIP_RESULT *result)
Definition: cons.c:3480
static SCIP_RETCODE solveNodeInitialLP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool newinitconss, SCIP_Bool *cutoff, SCIP_Bool *lperror)
Definition: solve.c:1339
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5517
SCIP_Longint ninfeasleaves
Definition: struct_stat.h:75
SCIP_RETCODE SCIPconflictAnalyzeLP(SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, 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_Bool *success)
Definition: conflict.c:7229
#define SCIP_EVENTTYPE_LPSOLVED
Definition: type_event.h:84
SCIP_Real firstlpdualbound
Definition: struct_stat.h:116
SCIP_Bool SCIPrelaxIncludesLp(SCIP_RELAX *relax)
Definition: relax.c:522
static SCIP_RETCODE applyBounding(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CONFLICT *conflict, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition: solve.c:2734
internal methods for managing events
static SCIP_RETCODE solveNodeLP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_MEM *mem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_CUTPOOL *delayedcutpool, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool initiallpsolved, SCIP_Bool fullseparation, SCIP_Bool newinitconss, SCIP_Bool *propagateagain, SCIP_Bool *solverelaxagain, SCIP_Bool *cutoff, SCIP_Bool *unbounded, SCIP_Bool *lperror, SCIP_Bool *pricingaborted)
Definition: solve.c:2812
SCIP_Longint nnodelpiterations
Definition: struct_stat.h:63
static void markRelaxsUnsolved(SCIP_SET *set, SCIP_RELAXATION *relaxation)
Definition: solve.c:2794
int SCIPheurGetPriority(SCIP_HEUR *heur)
Definition: heur.c:1242
static SCIP_RETCODE separationRoundLP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, int actdepth, SCIP_Real bounddist, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *enoughcuts, SCIP_Bool *cutoff, SCIP_Bool *lperror, SCIP_Bool *mustsepa, SCIP_Bool *mustprice)
Definition: solve.c:1503
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:86
SCIP_RETCODE SCIPnodeCreateChild(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: tree.c:960
SCIP_RETCODE SCIPconshdlrEnforceLPSol(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_SEPASTORE *sepastore, SCIP_Bool solinfeasible, SCIP_RESULT *result)
Definition: cons.c:3275
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5575
SCIP_Longint nlpsolsfound
Definition: struct_stat.h:90
internal methods for storing primal CIP solutions
SCIP_Bool SCIPtreeHasFocusNodeLP(SCIP_TREE *tree)
Definition: tree.c:8074
SCIP_STATUS status
Definition: struct_stat.h:165
SCIP_Longint nlpiterations
Definition: struct_stat.h:53
const char * SCIPpricerGetName(SCIP_PRICER *pricer)
Definition: pricer.c:550
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:16899
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:17569
#define SCIPdebugRemoveNode(blkmem, set, node)
Definition: debug.h:257
SCIP_RETCODE SCIPreoptApplyCuts(SCIP_REOPT *reopt, SCIP_NODE *node, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_Bool root)
Definition: reopt.c:7680
void SCIPlpSetIsRelax(SCIP_LP *lp, SCIP_Bool relax)
Definition: lp.c:16836
SCIP_Longint externmemestim
Definition: struct_stat.h:114
internal methods for branch and bound tree
SCIP_Longint nfeasleaves
Definition: struct_stat.h:74
void SCIPtreeSetFocusNodeLP(SCIP_TREE *tree, SCIP_Bool solvelp)
Definition: tree.c:8084
SCIP_Longint SCIPconflictGetNPropSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:4438
int nremovablecols
Definition: struct_lp.h:310
static SCIP_RETCODE updatePrimalRay(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_Bool lperror)
Definition: solve.c:1272
SCIP_Bool primalfeasible
Definition: struct_lp.h:346
enum SCIP_Efficiacychoice SCIP_EFFICIACYCHOICE
int SCIPgetNConcurrentSolvers(SCIP *scip)
Definition: concurrent.c:107
unsigned int boundchgtype
Definition: struct_var.h:113
BMS_BUFMEM * buffer
Definition: struct_mem.h:41
int npricerounds
Definition: struct_stat.h:210
int SCIPpricestoreGetNVars(SCIP_PRICESTORE *pricestore)
Definition: pricestore.c:601
SCIP_RETCODE SCIPlpFlush(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:8416
void SCIPprobUpdateBestRootSol(SCIP_PROB *prob, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: prob.c:1742
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5915
static SCIP_RETCODE updateEstimate(SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand)
Definition: solve.c:1026
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7192
SCIP_Longint nlps
Definition: struct_stat.h:171
SCIP_RETCODE SCIPdispPrintLine(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, FILE *file, SCIP_Bool forcedisplay, SCIP_Bool endline)
Definition: disp.c:363
SCIP_Longint ninitconssadded
Definition: struct_stat.h:112
static SCIP_Bool isPseudocostUpdateValid(SCIP_VAR *var, SCIP_SET *set, SCIP_Real oldlpsolval, SCIP_Bool updateintegers, SCIP_Bool updatecontinuous)
Definition: solve.c:643
SCIP_RETCODE SCIPtreeSetNodesel(SCIP_TREE *tree, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_NODESEL *nodesel)
Definition: tree.c:4995
SCIP_RETCODE SCIPeventChgType(SCIP_EVENT *event, SCIP_EVENTTYPE eventtype)
Definition: event.c:969
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16756
SCIP_RETCODE SCIPprimalTrySol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: primal.c:1435
internal methods for clocks and timing issues
void SCIPstatUpdateMemsaveMode(SCIP_STAT *stat, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_MEM *mem)
Definition: stat.c:587
SCIP_Longint ntotalnodes
Definition: struct_stat.h:76
int SCIPbranchcandGetNPseudoCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:823
unsigned int SCIP_HEURTIMING
Definition: type_timing.h:97
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:124
SCIP_Real lastbranchvalue
Definition: struct_stat.h:129
SCIP_Longint nrootfirstlpiterations
Definition: struct_stat.h:55
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17225
int SCIPpropGetPriority(SCIP_PROP *prop)
Definition: prop.c:907
SCIP_Longint SCIPconflictGetNInfeasibleLPSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:7396
#define SCIP_HEURTIMING_BEFORENODE
Definition: type_timing.h:70
void SCIPrelaxationSetSolValid(SCIP_RELAXATION *relaxation, SCIP_Bool isvalid)
Definition: relax.c:664
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:166
void SCIPsepastoreStartForceCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:148
SCIP_RETCODE SCIPconstructCurrentLP(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_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool newinitconss, SCIP_Bool *cutoff)
Definition: solve.c:1218
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5379
SCIP_Real SCIPrelaxationGetBestRelaxSolObj(SCIP_RELAXATION *relaxation)
Definition: relax.c:738
SCIP_Real SCIPlpGetGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:12694
int nclockskipsleft
Definition: struct_stat.h:252
SCIP_SOL ** sols
Definition: struct_primal.h:48
unsigned int nboundchgs
Definition: struct_var.h:122
int SCIPsepastoreGetNCutsApplied(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1358
#define SCIP_PROPTIMING_DURINGLPLOOP
Definition: type_timing.h:57
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:350
void SCIPsetSortHeurs(SCIP_SET *set)
Definition: set.c:4165
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPeventProcess(SCIP_EVENT *event, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter)
Definition: event.c:1460
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:17581
SCIP_NODESEL * SCIPsetGetNodesel(SCIP_SET *set, SCIP_STAT *stat)
Definition: set.c:4363
SCIP_Bool solved
Definition: struct_lp.h:345
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:9618
SCIP_RETCODE SCIPbranchExecPseudo(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_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:2648
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:280
SCIP_Longint nrootlps
Definition: struct_stat.h:172
void SCIPresetInterrupted(void)
Definition: interrupt.c:155
SCIP_Bool SCIPreoptGetSolveLP(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node)
Definition: reopt.c:7813
SCIP_RETCODE SCIPconshdlrInitLP(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_Bool initkeptconss, SCIP_Bool *cutoff)
Definition: cons.c:2683
SCIP_Bool sbprobing
Definition: struct_tree.h:231
SCIP_RETCODE SCIPheurExec(SCIP_HEUR *heur, SCIP_SET *set, SCIP_PRIMAL *primal, int depth, int lpstateforkdepth, SCIP_HEURTIMING heurtiming, SCIP_Bool nodeinfeasible, int *ndelayedheurs, SCIP_RESULT *result)
Definition: heur.c:991
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
Definition: sepa.c:632
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPtreeLoadLPState(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: tree.c:3449
#define SCIP_HEURTIMING_AFTERNODE
Definition: type_timing.h:92
#define SCIP_EVENTTYPE_NODEFOCUSED
Definition: type_event.h:77
SCIP_Real SCIPprobInternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:2036
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1834
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:8132
SCIP_RETCODE SCIPsolSetUnknown(SCIP_SOL *sol, SCIP_STAT *stat, SCIP_TREE *tree)
Definition: sol.c:969
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16862
enum SCIP_VerbLevel SCIP_VERBLEVEL
Definition: type_message.h:48
internal methods for branching rules and branching candidate storage
void SCIPbranchcandClearExternCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:668
#define SCIP_HEURTIMING_AFTERLPLOOP
Definition: type_timing.h:72
SCIP_Real estimate
Definition: struct_tree.h:133
SCIP_FORK * fork
Definition: struct_tree.h:142
SCIP_NODE * SCIPtreeGetFocusNode(SCIP_TREE *tree)
Definition: tree.c:8040
void SCIPregressionAddObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:369
SCIP_RETCODE SCIPeventChgNode(SCIP_EVENT *event, SCIP_NODE *node)
Definition: event.c:1203
int maxtotaldepth
Definition: struct_stat.h:214
SCIP_RETCODE SCIPlpSolveAndEval(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_Longint itlim, SCIP_Bool limitresolveiters, SCIP_Bool aging, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:11960
SCIP_Real SCIPlpGetPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:12723
#define SCIP_HEURTIMING_DURINGPRICINGLOOP
Definition: type_timing.h:85
SCIP_RETCODE SCIPconshdlrSeparateLP(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, int depth, SCIP_Bool execdelayed, SCIP_RESULT *result)
Definition: cons.c:2790
void SCIPvisualSolvedNode(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_NODE *node)
Definition: visual.c:460
SCIP_Longint nnodesaboverefbound
Definition: struct_stat.h:84
SCIP_SOL * SCIPrelaxationGetBestRelaxSol(SCIP_RELAXATION *relaxation)
Definition: relax.c:717
SCIP_Bool SCIPrelaxationIsSolValid(SCIP_RELAXATION *relaxation)
Definition: relax.c:675
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7182
methods for creating output for visualization tools (VBC, BAK)
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:13682
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1841
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
static void updateLoopStatus(SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, int depth, SCIP_Bool *cutoff, SCIP_Bool *propagateagain, SCIP_Bool *solverelaxagain)
Definition: solve.c:3513
int maxdepth
Definition: struct_stat.h:213
int looseobjvalinf
Definition: struct_lp.h:316
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:12527
SCIP_VISUAL * visual
Definition: struct_stat.h:163
SCIP_Longint nlpbestsolsfound
Definition: struct_stat.h:94
static SCIP_RETCODE priceAndCutLoop(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_MEM *mem, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_CUTPOOL *delayedcutpool, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool fullseparation, SCIP_Bool *propagateagain, SCIP_Bool *cutoff, SCIP_Bool *unbounded, SCIP_Bool *lperror, SCIP_Bool *pricingaborted)
Definition: solve.c:2163
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:251
internal methods for LP management
SCIP_Real lpobjval
Definition: struct_tree.h:100
SCIP_Bool SCIPtreeIsFocusNodeLPConstructed(SCIP_TREE *tree)
Definition: tree.c:8095
void SCIPpricestoreStartInitialLP(SCIP_PRICESTORE *pricestore)
Definition: pricestore.c:146
int SCIPconshdlrGetSepaPriority(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4969
static SCIP_RETCODE enforceConstraints(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_Bool *branched, SCIP_Bool *cutoff, SCIP_Bool *infeasible, SCIP_Bool *propagateagain, SCIP_Bool *solvelpagain, SCIP_Bool *solverelaxagain, SCIP_Bool forced)
Definition: solve.c:3178
int nremovablerows
Definition: struct_lp.h:314
SCIP_PROPTIMING SCIPconshdlrGetPropTiming(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5119
int SCIPpricestoreGetNBoundResets(SCIP_PRICESTORE *pricestore)
Definition: pricestore.c:612
internal methods for collecting primal CIP solutions and primal informations
#define SCIP_HEURTIMING_AFTERPSEUDOPLUNGE
Definition: type_timing.h:82
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1286
int SCIPsetGetSepaMaxcuts(SCIP_SET *set, SCIP_Bool root)
Definition: set.c:5247
SCIP_RETCODE SCIPnodeselSelect(SCIP_NODESEL *nodesel, SCIP_SET *set, SCIP_NODE **selnode)
Definition: nodesel.c:952
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:16654
#define SAFETYFACTOR
Definition: solve.c:66
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5611
internal methods for propagators
void SCIPrelaxationSetBestRelaxSolObj(SCIP_RELAXATION *relaxation, SCIP_Real obj)
Definition: relax.c:727
#define SCIP_EVENTTYPE_NODEFEASIBLE
Definition: type_event.h:78
SCIP_Longint SCIPgetConcurrentMemTotal(SCIP *scip)
Definition: concurrent.c:278
int SCIPtreeGetFocusDepth(SCIP_TREE *tree)
Definition: tree.c:8057
SCIP_RETCODE SCIPsepaExecSol(SCIP_SEPA *sepa, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, int depth, SCIP_Bool execdelayed, SCIP_RESULT *result)
Definition: sepa.c:440
#define SCIP_EVENTTYPE_NODEBRANCHED
Definition: type_event.h:80
SCIP_RETCODE SCIPbranchExecLP(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_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:2415
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:17601
SCIP_Real SCIPprobGetObjlim(SCIP_PROB *prob, SCIP_SET *set)
Definition: prob.c:2216
int SCIPbranchcandGetNExternCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:476
SCIP_RETCODE SCIPconflictAnalyzePseudo(SCIP_CONFLICT *conflict, 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_Bool *success)
Definition: conflict.c:7901
int nconfrestarts
Definition: struct_stat.h:198
SCIP_RETCODE SCIPsolveCIP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_MEM *mem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_CUTPOOL *delayedcutpool, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *restart)
Definition: solve.c:4720
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5557
SCIP_Real SCIPclockGetLastTime(SCIP_CLOCK *clck)
Definition: clock.c:508
SCIP_DOMCHG * domchg
Definition: struct_tree.h:147
SCIP_Bool forcinglpmessage
Definition: struct_tree.h:229
SCIP_Bool SCIPtreeProbing(SCIP_TREE *tree)
Definition: tree.c:8014
int nsiblings
Definition: struct_tree.h:210
BMS_BUFMEM * SCIPbuffer(SCIP *scip)
Definition: scip.c:45768
int cutoffdepth
Definition: struct_tree.h:216
void SCIPnodeUpdateLowerbound(SCIP_NODE *node, SCIP_STAT *stat, SCIP_SET *set, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_Real newbound)
Definition: tree.c:2279
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13780
SCIP_Longint nobjleaves
Definition: struct_stat.h:73
SCIP_Real SCIPsolGetObj(SCIP_SOL *sol, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob)
Definition: sol.c:1480
SCIP_Longint npssolsfound
Definition: struct_stat.h:92
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1181
SCIP_RETCODE SCIPprimalTrySolFree(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: primal.c:1505
SCIP_Bool installing
Definition: struct_lp.h:354
int prevrunnvars
Definition: struct_stat.h:203
internal methods for storing and manipulating the main problem
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
void SCIPmessagePrintVerbInfo(SCIP_MESSAGEHDLR *messagehdlr, SCIP_VERBLEVEL verblevel, SCIP_VERBLEVEL msgverblevel, const char *formatstr,...)
Definition: message.c:668
void SCIPstoreSolutionGap(SCIP *scip)
Definition: scip.c:45015
SCIP_Longint lpcount
Definition: struct_stat.h:169
SCIP_Longint nbestsolsfound
Definition: struct_primal.h:42
methods for block memory pools and memory buffers
#define SCIP_HEURTIMING_AFTERLPNODE
Definition: type_timing.h:73
SCIP_Longint bestsolnode
Definition: struct_stat.h:102
SCIP_RETCODE SCIPnodeFocus(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff, SCIP_Bool postponed, SCIP_Bool exitsolve)
Definition: tree.c:4216
SCIP_RETCODE SCIPsolCreateCurrentSol(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_HEUR *heur)
Definition: sol.c:647
SCIP_CLOCK * pseudosoltime
Definition: struct_stat.h:153
void SCIPnodeMarkPropagated(SCIP_NODE *node, SCIP_TREE *tree)
Definition: tree.c:1212
SCIP_Longint nrelaxbestsolsfound
Definition: struct_stat.h:95
SCIP_NODE ** path
Definition: struct_tree.h:176
#define MAXNCLOCKSKIPS
Definition: solve.c:64
SCIP_NODE * focuslpstatefork
Definition: struct_tree.h:184
SCIP_RETCODE SCIPsolSetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_VAR *var, SCIP_Real val)
Definition: sol.c:1015
int SCIPrelaxGetPriority(SCIP_RELAX *relax)
Definition: relax.c:466
SCIP_Longint ninitlpiterations
Definition: struct_stat.h:64
int SCIPsepastoreGetNCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1328
SCIP_RETCODE SCIPcheckSolOrig(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *feasible, SCIP_Bool printreason, SCIP_Bool completely)
Definition: scip.c:40313
static SCIP_RETCODE propagationRound(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_TREE *tree, int depth, SCIP_Bool fullpropagation, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *propagain, SCIP_PROPTIMING timingmask, SCIP_Bool *cutoff, SCIP_Bool *postpone)
Definition: solve.c:364
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16555
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:428
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:3715
static SCIP_RETCODE addCurrentSolution(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_PRIMAL *primal, SCIP_RELAXATION *relaxation, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool checksol)
Definition: solve.c:4591
SCIP_Bool SCIPnodeIsPropagatedAgain(SCIP_NODE *node)
Definition: tree.c:7937
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:417
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1838
SCIP_RETCODE SCIPbranchcandGetLPCands(SCIP_BRANCHCAND *branchcand, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: branch.c:404
SCIP_Real cutoffbound
Definition: struct_lp.h:273
SCIP_REGRESSION * regressioncandsobjval
Definition: struct_stat.h:52
SCIP_RETCODE SCIPtreeLoadLP(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_Bool *initroot)
Definition: tree.c:3321
#define NULL
Definition: lpi_spx1.cpp:137
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13167
int nseparounds
Definition: struct_stat.h:211
SCIP_Bool userinterrupt
Definition: struct_stat.h:254
#define REALABS(x)
Definition: def.h:169
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17543
internal methods for node selectors and node priority queues
internal methods for variable pricers
const char * SCIPrelaxGetName(SCIP_RELAX *relax)
Definition: relax.c:446
#define SCIP_PROPTIMING_AFTERLPLOOP
Definition: type_timing.h:58
void SCIPsetSortProps(SCIP_SET *set)
Definition: set.c:3988
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:316
#define NINITCALLS
Definition: solve.c:65
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:42550
SCIP_RETCODE SCIPconshdlrEnforceRelaxSol(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_SEPASTORE *sepastore, SCIP_SOL *relaxsol, SCIP_Bool solinfeasible, SCIP_RESULT *result)
Definition: cons.c:3076
#define SCIP_HEURTIMING_DURINGPRESOLLOOP
Definition: type_timing.h:87
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:16674
void SCIPrelaxMarkUnsolved(SCIP_RELAX *relax)
Definition: relax.c:585
static SCIP_RETCODE updatePseudocost(SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_LP *lp, SCIP_Bool updateintegers, SCIP_Bool updatecontinuous)
Definition: solve.c:710
enum PseudocostFlag PSEUDOCOSTFLAG
Definition: solve.c:706
SCIP_Longint SCIPconflictGetNPseudoSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:8066
SCIP_Bool resolvelperror
Definition: struct_lp.h:361
#define SCIP_HEURTIMING_BEFOREPRESOL
Definition: type_timing.h:86
internal methods for storing priced variables
internal methods for relaxators
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5539
SCIP_LPI * SCIPlpGetLPI(SCIP_LP *lp)
Definition: lp.c:16826
SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:12543
internal methods for storing separated cuts
#define MAXNLPERRORS
Definition: solve.c:63
void SCIPsetSortRelaxs(SCIP_SET *set)
Definition: set.c:3837
methods for catching the user CTRL-C interrupt
data structures and methods for collecting reoptimization information
internal methods for problem variables
the function declarations for the synchronization store
void SCIPnodeSetEstimate(SCIP_NODE *node, SCIP_SET *set, SCIP_Real newestimate)
Definition: tree.c:2371
SCIP_Bool SCIPsepaWasLPDelayed(SCIP_SEPA *sepa)
Definition: sepa.c:869
SCIP_Bool userrestart
Definition: struct_stat.h:255
SCIP_Longint nisstoppedcalls
Definition: struct_stat.h:193
static SCIP_RETCODE solveNodeRelax(SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_RELAXATION *relaxation, SCIP_PROB *transprob, SCIP_PROB *origprob, int depth, SCIP_Bool beforelp, SCIP_Bool *cutoff, SCIP_Bool *propagateagain, SCIP_Bool *solvelpagain, SCIP_Bool *solverelaxagain, SCIP_Bool *relaxcalled)
Definition: solve.c:3054
public data structures and miscellaneous methods
SCIP_RETCODE SCIPvarIncCutoffSum(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
Definition: var.c:14920
PseudocostFlag
Definition: solve.c:700
SCIP_RETCODE SCIPpricestoreApplyVars(SCIP_PRICESTORE *pricestore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_LP *lp)
Definition: pricestore.c:472
SCIP_VAR * var
Definition: struct_var.h:89
#define SCIP_Bool
Definition: def.h:61
SCIP_Bool SCIPinterrupted(void)
Definition: interrupt.c:147
SCIP_RETCODE SCIPreoptCheckCutoff(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_EVENTTYPE eventtype, SCIP_LP *lp, SCIP_LPSOLSTAT lpsolstat, SCIP_Bool isrootnode, SCIP_Bool isfocusnode, SCIP_Real lowerbound, int effectiverootdepth)
Definition: reopt.c:5921
unsigned int boundtype
Definition: struct_var.h:91
SCIP_Bool SCIPrelaxIsSolved(SCIP_RELAX *relax, SCIP_STAT *stat)
Definition: relax.c:573
int ncontvars
Definition: struct_prob.h:65
SCIP_Bool SCIPconshdlrWasPropagationDelayed(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5089
unsigned int depth
Definition: struct_tree.h:148
SCIP_RETCODE SCIPprintRay(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip.c:39023
SCIP_SYNCSTORE * SCIPgetSyncstore(SCIP *scip)
Definition: scip.c:41293
SCIP_Bool branchedunbdvar
Definition: struct_stat.h:259
union SCIP_Node::@9 data
SCIP_RETCODE SCIPsolCreate(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_HEUR *heur)
Definition: sol.c:276
SCIP_Real SCIPgetGap(SCIP *scip)
Definition: scip.c:42808
SCIP_Bool SCIPheurShouldBeExecuted(SCIP_HEUR *heur, int depth, int lpstateforkdepth, SCIP_HEURTIMING heurtiming, SCIP_Bool *delayed)
Definition: heur.c:929
#define MAX(x, y)
Definition: tclique_def.h:75
methods for debugging
SCIP_RETCODE SCIPpricestoreAddProbVars(SCIP_PRICESTORE *pricestore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: pricestore.c:343
static SCIP_Bool restartAllowed(SCIP_SET *set, SCIP_STAT *stat)
Definition: solve.c:3910
#define SCIPsetDebugMsg
Definition: set.h:1870
#define SCIP_EVENTTYPE_NODEINFEASIBLE
Definition: type_event.h:79
SCIP_Bool SCIPconshdlrWasLPSeparationDelayed(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5069
SCIP_Real oldbound
Definition: struct_var.h:107
SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
Definition: prob.c:2204
SCIP_RETCODE SCIPconshdlrPropagate(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, int depth, SCIP_Bool fullpropagation, SCIP_Bool execdelayed, SCIP_Bool instrongbranching, SCIP_PROPTIMING proptiming, SCIP_RESULT *result)
Definition: cons.c:3738
static SCIP_RETCODE propagateDomains(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_TREE *tree, int depth, int maxproprounds, SCIP_Bool fullpropagation, SCIP_PROPTIMING timingmask, SCIP_Bool *cutoff, SCIP_Bool *postpone)
Definition: solve.c:534
SCIP_RETCODE SCIPpricestoreAddVar(SCIP_PRICESTORE *pricestore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_VAR *var, SCIP_Real score, SCIP_Bool root)
Definition: pricestore.c:170
SCIP_RETCODE SCIPpropagateDomains(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CONFLICT *conflict, SCIP_CLIQUETABLE *cliquetable, int depth, int maxproprounds, SCIP_PROPTIMING timingmask, SCIP_Bool *cutoff)
Definition: solve.c:610
SCIP_RETCODE SCIPsepaExecLP(SCIP_SEPA *sepa, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, int depth, SCIP_Real bounddist, SCIP_Bool execdelayed, SCIP_RESULT *result)
Definition: sepa.c:334
SCIP_Bool SCIPtreeHasCurrentNodeLP(SCIP_TREE *tree)
Definition: tree.c:8149
int SCIPconflictGetNConflicts(SCIP_CONFLICT *conflict)
Definition: conflict.c:2467
#define SCIP_PROPTIMING_BEFORELP
Definition: type_timing.h:56
SCIP_RETCODE SCIPseparationRound(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, int actdepth, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *cutoff)
Definition: solve.c:1858
internal methods for storing cuts in a cut pool
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13228
void SCIPsepastoreEndInitialLP(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:136
SCIP_Bool cutoffdelayed
Definition: struct_tree.h:223
SCIP_RETCODE SCIPlpRemoveRedundantRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:15060
#define SCIP_EVENTTYPE_FIRSTLPSOLVED
Definition: type_event.h:83
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5937
SCIP_CLOCK * relaxsoltime
Definition: struct_stat.h:152
void SCIPsepastoreStartInitialLP(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:124
int ncolvars
Definition: struct_prob.h:66
void SCIPprobStoreRootSol(SCIP_PROB *prob, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Bool roothaslp)
Definition: prob.c:1715
helper functions for concurrent scip solvers
static SCIP_RETCODE solveNode(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_MEM *mem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_CUTPOOL *cutpool, SCIP_CUTPOOL *delayedcutpool, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff, SCIP_Bool *postpone, SCIP_Bool *unbounded, SCIP_Bool *infeasible, SCIP_Bool *restart, SCIP_Bool *afternodeheur, SCIP_Bool *stopped)
Definition: solve.c:3929
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:887
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:17589
#define SCIP_REAL_MAX
Definition: def.h:146
SCIP_Longint nrootlpiterations
Definition: struct_stat.h:54
SCIP_Real newbound
Definition: struct_var.h:83
#define SCIP_REAL_MIN
Definition: def.h:147
SCIP_RETCODE SCIPpricestoreResetBounds(SCIP_PRICESTORE *pricestore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: pricestore.c:561
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:152
SCIP_RETCODE SCIPprimalHeuristics(SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_NODE *nextnode, SCIP_HEURTIMING heurtiming, SCIP_Bool nodeinfeasible, SCIP_Bool *foundsol, SCIP_Bool *unbounded)
Definition: solve.c:177
SCIP_RETCODE SCIPprimalAddSolFree(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL **sol, SCIP_Bool *stored)
Definition: primal.c:1211
SCIP_Bool SCIPsepaWasSolDelayed(SCIP_SEPA *sepa)
Definition: sepa.c:879
SCIP_Bool SCIPpropWasDelayed(SCIP_PROP *prop)
Definition: prop.c:1092
SCIP_Longint SCIPconflictGetNBoundexceedingLPSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:7476
unsigned int SCIP_PROPTIMING
Definition: type_timing.h:66
internal methods for conflict analysis
SCIP_RETCODE SCIPpriceLoop(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool pretendroot, SCIP_Bool displayinfo, int maxpricerounds, int *npricedcolvars, SCIP_Bool *mustsepa, SCIP_Bool *lperror, SCIP_Bool *aborted)
Definition: solve.c:1909
internal methods for main solving loop and node processing
size_t BMSgetNUsedBufferMemory(BMS_BUFMEM *buffer)
Definition: memory.c:3162
SCIP_Longint domchgcount
Definition: struct_stat.h:103
SCIP_RETCODE SCIPsolCreateLPSol(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_HEUR *heur)
Definition: sol.c:560
SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
Definition: tree.c:8115
SCIP_CLOCK * solvingtime
Definition: struct_stat.h:140
SCIP_Bool flushed
Definition: struct_lp.h:344
SCIP_PROPTIMING SCIPpropGetTimingmask(SCIP_PROP *prop)
Definition: prop.c:1222
unsigned int pseudocostflag
Definition: struct_var.h:276
SCIP_Longint npsbestsolsfound
Definition: struct_stat.h:96
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_RETCODE SCIPpropExec(SCIP_PROP *prop, SCIP_SET *set, SCIP_STAT *stat, int depth, SCIP_Bool execdelayed, SCIP_Bool instrongbranching, SCIP_PROPTIMING proptiming, SCIP_RESULT *result)
Definition: prop.c:590
SCIP_Real lowerbound
Definition: struct_tree.h:132
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5593
SCIP_Longint nboundchgs
Definition: struct_stat.h:104
SCIP_RETCODE SCIPprimalAddSol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL *sol, SCIP_Bool *stored)
Definition: primal.c:1143
#define SCIP_HEURTIMING_AFTERPSEUDONODE
Definition: type_timing.h:76
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:7162
SCIP_Longint SCIPgetNBestSolsFound(SCIP *scip)
Definition: scip.c:42945
#define SCIP_Real
Definition: def.h:145
void SCIPvisualCutoffNode(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_NODE *node, SCIP_Bool infeasible)
Definition: visual.c:520
internal methods for problem statistics
SCIP_VAR ** vars
Definition: struct_prob.h:55
void SCIPstatUpdatePrimalDualIntegral(SCIP_STAT *stat, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_Real upperbound, SCIP_Real lowerbound)
Definition: stat.c:394
static SCIP_RETCODE cutpoolSeparate(SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, SCIP_Bool cutpoolisdelayed, SCIP_Bool root, int actdepth, SCIP_Bool *enoughcuts, SCIP_Bool *cutoff)
Definition: solve.c:2126
SCIP_Bool SCIPlpIsSolved(SCIP_LP *lp)
Definition: lp.c:16859
static SCIP_RETCODE initLP(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_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool root, SCIP_Bool *cutoff)
Definition: solve.c:1142
#define MIN(x, y)
Definition: memory.c:75
SCIP_Real referencebound
Definition: struct_stat.h:138
void SCIPsetSortPricers(SCIP_SET *set)
Definition: set.c:3455
SCIP_RETCODE SCIPconflictFlushConss(SCIP_CONFLICT *conflict, 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)
Definition: conflict.c:2258
SCIP_Longint ntotalinternalnodes
Definition: struct_stat.h:77
int effectiverootdepth
Definition: struct_tree.h:213
#define SCIP_INVALID
Definition: def.h:165
internal methods for constraints and constraint handlers
SCIP_Bool SCIPlpIsRelax(SCIP_LP *lp)
Definition: lp.c:16849
static SCIP_RETCODE propAndSolve(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_MEM *mem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_CUTPOOL *cutpool, SCIP_CUTPOOL *delayedcutpool, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_NODE *focusnode, int actdepth, SCIP_Bool propagate, SCIP_Bool solvelp, SCIP_Bool solverelax, SCIP_Bool forcedlpsolve, SCIP_Bool initiallpsolved, SCIP_Bool fullseparation, SCIP_Longint *afterlpproplps, SCIP_HEURTIMING *heurtiming, int *nlperrors, SCIP_Bool *fullpropagation, SCIP_Bool *propagateagain, SCIP_Bool *lpsolved, SCIP_Bool *relaxcalled, SCIP_Bool *solvelpagain, SCIP_Bool *solverelaxagain, SCIP_Bool *cutoff, SCIP_Bool *postpone, SCIP_Bool *unbounded, SCIP_Bool *stopped, SCIP_Bool *lperror, SCIP_Bool *pricingaborted, SCIP_Bool *forcedenforcement)
Definition: solve.c:3556
SCIP_RETCODE SCIPcutpoolSeparate(SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, SCIP_Bool cutpoolisdelayed, SCIP_Bool root, SCIP_RESULT *result)
Definition: cutpool.c:662
SCIP_Bool SCIPsyncstoreSolveIsStopped(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:226
SCIP_Real SCIPgetOrigObjoffset(SCIP *scip)
Definition: scip.c:11011
SCIP_Bool SCIPnodeIsActive(SCIP_NODE *node)
Definition: tree.c:7927
#define SCIP_Longint
Definition: def.h:130
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:162
SCIP_RETCODE SCIPlpGetPrimalRay(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *ray)
Definition: lp.c:14235
SCIP_RETCODE SCIPnodeUpdateLowerboundLP(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp)
Definition: tree.c:2319
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16720
SCIP_Bool disableenforelaxmsg
Definition: struct_stat.h:260
SCIP_CLOCK * nodeactivationtime
Definition: struct_stat.h:155
SCIP_Real firstlptime
Definition: struct_stat.h:128
#define SCIP_HEURTIMING_AFTERLPPLUNGE
Definition: type_timing.h:79
SCIP_Longint SCIPgetNLimSolsFound(SCIP *scip)
Definition: scip.c:42918
int nchildren
Definition: struct_tree.h:208
SCIP_RETCODE SCIPconshdlrSeparateSol(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, int depth, SCIP_Bool execdelayed, SCIP_RESULT *result)
Definition: cons.c:2947
SCIP_Longint ninternalnodes
Definition: struct_stat.h:72
SCIP_Real newbound
Definition: struct_var.h:108
SCIP_Real SCIPprobExternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:2014
#define nnodes
Definition: gastrans.c:65
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17235
SCIP_Real SCIPtreeGetLowerbound(SCIP_TREE *tree, SCIP_SET *set)
Definition: tree.c:6985
SCIP_RETCODE SCIPtreeCutoff(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real cutoffbound)
Definition: tree.c:5023
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:42699
SCIP_RETCODE SCIPsolCreatePseudoSol(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_HEUR *heur)
Definition: sol.c:626
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:89
SCIP_Longint nnodelps
Definition: struct_stat.h:183
common defines and data types used in all packages of SCIP
SCIP_Longint nnodes
Definition: struct_stat.h:71
int nrootintfixingsrun
Definition: struct_stat.h:202
SCIP_RETCODE SCIPpricerExec(SCIP_PRICER *pricer, SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, SCIP_PRICESTORE *pricestore, SCIP_Real *lowerbound, SCIP_Bool *stopearly, SCIP_RESULT *result)
Definition: pricer.c:424
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:396
int SCIPtreeGetNLeaves(SCIP_TREE *tree)
Definition: tree.c:7977
SCIP_NODE * root
Definition: struct_tree.h:174
internal methods for primal heuristics
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:78
SCIP_Bool SCIPconshdlrWasSolSeparationDelayed(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5079
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
SCIP_Longint nrelaxsolsfound
Definition: struct_stat.h:91
static SCIP_RETCODE applyCuts(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_RELAXATION *relaxation, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool root, SCIP_EFFICIACYCHOICE efficiacychoice, SCIP_Bool *cutoff, SCIP_Bool *propagateagain, SCIP_Bool *solvelpagain, SCIP_Bool *solverelaxagain)
Definition: solve.c:3457
SCIP_RETCODE SCIPbranchExecExtern(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_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:2517
int SCIPtreeGetNNodes(SCIP_TREE *tree)
Definition: tree.c:7987
#define SCIPABORT()
Definition: def.h:288
SCIP_RETCODE SCIPinitConssLP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, 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_Bool firstsubtreeinit, SCIP_Bool *cutoff)
Definition: solve.c:1076
SCIP_Longint nlimsolsfound
Definition: struct_primal.h:40
void SCIPsetSortSepas(SCIP_SET *set)
Definition: set.c:3911
static SCIP_RETCODE separationRoundSol(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, int actdepth, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *enoughcuts, SCIP_Bool *cutoff)
Definition: solve.c:1716
SCIP_RETCODE SCIPsolCheck(SCIP_SOL *sol, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *feasible)
Definition: sol.c:1581
void SCIPsepastoreEndForceCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:159
SCIP_RETCODE SCIPrelaxExec(SCIP_RELAX *relax, SCIP_SET *set, SCIP_STAT *stat, int depth, SCIP_Real *lowerbound, SCIP_RESULT *result)
Definition: relax.c:295
int SCIPsepaGetPriority(SCIP_SEPA *sepa)
Definition: sepa.c:652
SCIP_Longint ninitlps
Definition: struct_stat.h:184
#define SCIP_HEURTIMING_AFTERPROPLOOP
Definition: type_timing.h:88
SCIP callable library.
static SCIP_RETCODE separationRoundResolveLP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_Bool *lperror, SCIP_Bool *mustsepa, SCIP_Bool *mustprice)
Definition: solve.c:1462
SCIP_Longint ndelayedcutoffs
Definition: struct_stat.h:86
SCIP_CLOCK * lpsoltime
Definition: struct_stat.h:151
SCIP_NODE * focusnode
Definition: struct_tree.h:179
SCIP_RETCODE SCIPsolFree(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_PRIMAL *primal)
Definition: sol.c:739
int SCIPsetGetPriceMaxvars(SCIP_SET *set, SCIP_Bool root)
Definition: set.c:5233
internal methods for displaying runtime statistics