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 = FALSE;
1239 
1240  assert(tree != NULL);
1241  assert(cutoff != NULL);
1242 
1243  *cutoff = FALSE;
1244 
1246  {
1247  /* inform separation storage, that LP is now filled with initial data */
1248  SCIPsepastoreStartInitialLP(sepastore);
1249 
1250  if( tree->correctlpdepth >= 0 )
1251  {
1252  int i;
1253 
1254  for( i = tree->pathnlprows[tree->correctlpdepth]; i < lp->nrows; ++i )
1255  {
1256  /* keep all active global cuts that where applied in the previous node in the lp */
1257  if( !lp->rows[i]->local && lp->rows[i]->age == 0 )
1258  {
1259  SCIP_CALL( SCIPsepastoreAddCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, lp->rows[i], TRUE, (SCIPtreeGetCurrentDepth(tree) == 0), cutoff) );
1260  }
1261  }
1262  }
1263 
1264  if( !(*cutoff) )
1265  {
1266  /* load the LP into the solver and load the LP state */
1267  SCIPsetDebugMsg(set, "loading LP\n");
1268  SCIP_CALL( SCIPtreeLoadLP(tree, blkmem, set, eventqueue, eventfilter, lp, &initroot) );
1269  assert(initroot || SCIPnodeGetDepth(SCIPtreeGetFocusNode(tree)) > 0);
1270  assert(SCIPtreeIsFocusNodeLPConstructed(tree));
1271 
1272  /* apply cuts */
1273  SCIP_CALL( SCIPsepastoreApplyCuts(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
1274  eventqueue, eventfilter, cliquetable, (SCIPtreeGetCurrentDepth(tree) == 0), SCIP_EFFICIACYCHOICE_LP, cutoff) );
1275  }
1276  else
1277  {
1278  /* the current node will be cut off; we clear the sepastore */
1279  SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
1280  }
1281 
1282  /* inform separation storage, that initial LP setup is now finished */
1283  SCIPsepastoreEndInitialLP(sepastore);
1284 
1285  if( !(*cutoff) )
1286  {
1287  /* setup initial LP relaxation of node */
1288  SCIP_CALL( initLP(blkmem, set, stat, transprob, origprob, tree, reopt, lp, pricestore, sepastore, cutpool, branchcand,
1289  eventqueue, eventfilter, cliquetable, initroot, cutoff) );
1290  }
1291  }
1292  else if( newinitconss )
1293  {
1294  SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob,
1295  origprob, tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE,
1296  cutoff) );
1297  }
1298 
1299  return SCIP_OKAY;
1300 }
1301 
1302 /** updates the primal ray stored in primal data
1303  * clears previously stored primal ray, if existing and there was no LP error
1304  * stores current primal ray, if LP is unbounded and there has been no error
1305  */
1306 static
1308  BMS_BLKMEM* blkmem, /**< block memory buffers */
1309  SCIP_SET* set, /**< global SCIP settings */
1310  SCIP_STAT* stat, /**< dynamic problem statistics */
1311  SCIP_PROB* prob, /**< transformed problem after presolve */
1312  SCIP_PRIMAL* primal, /**< primal data */
1313  SCIP_TREE* tree, /**< branch and bound tree */
1314  SCIP_LP* lp, /**< LP data */
1315  SCIP_Bool lperror /**< has there been an LP error? */
1316  )
1317 {
1318  assert(blkmem != NULL);
1319  assert(set != NULL);
1320  assert(stat != NULL);
1321  assert(prob != NULL);
1322  assert(primal != NULL);
1323  assert(tree != NULL);
1324  assert(lp != NULL);
1325 
1326  if( lperror )
1327  return SCIP_OKAY;
1328 
1329  /* clear previously stored primal ray, if any */
1330  if( primal->primalray != NULL )
1331  {
1332  SCIP_CALL( SCIPsolFree(&primal->primalray, blkmem, primal) );
1333  }
1334 
1335  /* store unbounded ray, if LP is unbounded */
1337  {
1338  SCIP_VAR** vars;
1339  SCIP_Real* ray;
1340  int nvars;
1341  int i;
1342 
1343  SCIPsetDebugMsg(set, "LP is unbounded, store primal ray\n");
1344 
1345  vars = prob->vars;
1346  nvars = prob->nvars;
1347 
1348  /* get buffer memory for storing the ray and load the ray values into it */
1349  SCIP_CALL( SCIPsetAllocBufferArray(set, &ray, nvars) );
1350  BMSclearMemoryArray(ray, nvars);
1351  SCIP_CALL( SCIPlpGetPrimalRay(lp, set, ray) );
1352 
1353  /* create solution to store the primal ray in */
1354  assert(primal->primalray == NULL);
1355  SCIP_CALL( SCIPsolCreate(&primal->primalray, blkmem, set, stat, primal, tree, NULL) );
1356 
1357  /* set values of all active variable in the solution that represents the primal ray */
1358  for( i = 0; i < nvars; i++ )
1359  {
1360  SCIP_CALL( SCIPsolSetVal(primal->primalray, set, stat, tree, vars[i], ray[i]) );
1361  }
1362 
1363  SCIPdebug( SCIP_CALL( SCIPprintRay(set->scip, primal->primalray, NULL, FALSE) ) );
1364 
1365  /* free memory for buffering the ray values */
1366  SCIPsetFreeBufferArray(set, &ray);
1367  }
1368 
1369  return SCIP_OKAY;
1370 }
1371 
1372 /** load and solve the initial LP of a node */
1373 static
1375  BMS_BLKMEM* blkmem, /**< block memory buffers */
1376  SCIP_SET* set, /**< global SCIP settings */
1377  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1378  SCIP_STAT* stat, /**< dynamic problem statistics */
1379  SCIP_PROB* transprob, /**< transformed problem after presolve */
1380  SCIP_PROB* origprob, /**< original problem */
1381  SCIP_PRIMAL* primal, /**< primal data */
1382  SCIP_TREE* tree, /**< branch and bound tree */
1383  SCIP_REOPT* reopt, /**< reoptimization data structure */
1384  SCIP_LP* lp, /**< LP data */
1385  SCIP_PRICESTORE* pricestore, /**< pricing storage */
1386  SCIP_SEPASTORE* sepastore, /**< separation storage */
1387  SCIP_CUTPOOL* cutpool, /**< global cutpool */
1388  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1389  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1390  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1391  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1392  SCIP_Bool newinitconss, /**< do we have to add new initial constraints? */
1393  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
1394  SCIP_Bool* lperror /**< pointer to store whether an unresolved error in LP solving occured */
1395  )
1396 {
1397  /* initializing variables for compiler warnings, which are not correct */
1398  SCIP_Real starttime = 0.0;
1399  SCIP_Longint nlpiterations = 0;
1400  SCIP_NODE* focusnode;
1401 
1402  assert(stat != NULL);
1403  assert(tree != NULL);
1404  assert(lp != NULL);
1405  assert(cutoff != NULL);
1406  assert(lperror != NULL);
1407  assert(SCIPtreeGetFocusNode(tree) != NULL);
1409 
1410  *cutoff = FALSE;
1411  *lperror = FALSE;
1412 
1413  /* load the LP into the solver */
1414  SCIP_CALL( SCIPconstructCurrentLP(blkmem, set, stat, transprob, origprob, tree, reopt, lp, pricestore, sepastore, cutpool,
1415  branchcand, eventqueue, eventfilter, cliquetable, newinitconss, cutoff) );
1416 
1417  if( *cutoff )
1418  return SCIP_OKAY;
1419 
1420  /* load the LP state */
1421  SCIP_CALL( SCIPtreeLoadLPState(tree, blkmem, set, stat, eventqueue, lp) );
1422 
1423  focusnode = SCIPtreeGetFocusNode(tree);
1424 
1425  /* store current LP iteration count and solving time if we are at the root node */
1426  if( focusnode->depth == 0 )
1427  {
1428  nlpiterations = stat->nlpiterations;
1429  starttime = SCIPclockGetTime(stat->solvingtime);
1430  }
1431 
1432  /* solve initial LP */
1433  SCIPsetDebugMsg(set, "node: solve initial LP\n");
1434  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
1435  SCIPnodeGetDepth(SCIPtreeGetFocusNode(tree)) == 0 ? set->lp_rootiterlim : set->lp_iterlim, TRUE, TRUE, FALSE, lperror) );
1436  assert(lp->flushed);
1437  assert(lp->solved || *lperror);
1438 
1439  /* save time for very first LP in root node */
1440  if ( stat->nnodelps == 0 && focusnode->depth == 0 )
1441  {
1442  stat->firstlptime = SCIPclockGetTime(stat->solvingtime) - starttime;
1443  }
1444 
1445  /* remove previous primal ray, store new one if LP is unbounded */
1446  SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
1447 
1448  if( !(*lperror) )
1449  {
1450  /* cppcheck-suppress unassignedVariable */
1451  SCIP_EVENT event;
1452 
1454  {
1455  /* issue FIRSTLPSOLVED event */
1458  SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
1459  }
1460 
1461  /* update pseudo cost values for integer variables (always) and for continuous variables (if not delayed) */
1462  SCIP_CALL( updatePseudocost(set, stat, transprob, tree, lp, TRUE, !set->branch_delaypscost) );
1463 
1464  /* update lower bound of current node w.r.t. initial lp */
1465  assert(!(*cutoff));
1468  && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
1469  {
1470  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
1471 
1472  /* if this is the first LP solved at the root, store its iteration count and solution value */
1473  if( stat->nnodelps == 0 && focusnode->depth == 0 )
1474  {
1475  SCIP_Real lowerbound;
1476 
1477  assert(stat->nrootfirstlpiterations == 0);
1478  stat->nrootfirstlpiterations = stat->nlpiterations - nlpiterations;
1479 
1480  if( set->misc_exactsolve )
1481  {
1482  SCIP_CALL( SCIPlpGetProvedLowerbound(lp, set, &lowerbound) );
1483  }
1484  else
1485  lowerbound = SCIPlpGetObjval(lp, set, transprob);
1486 
1487  stat->firstlpdualbound = SCIPprobExternObjval(transprob, origprob, set, lowerbound);
1488  }
1489  }
1490  }
1491 
1492  return SCIP_OKAY;
1493 }
1494 
1495 /** makes sure the LP is flushed and solved */
1496 static
1498  BMS_BLKMEM* blkmem, /**< block memory buffers */
1499  SCIP_SET* set, /**< global SCIP settings */
1500  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1501  SCIP_STAT* stat, /**< dynamic problem statistics */
1502  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1503  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1504  SCIP_PROB* prob, /**< transformed problem after presolve */
1505  SCIP_PRIMAL* primal, /**< primal data */
1506  SCIP_TREE* tree, /**< branch and bound tree */
1507  SCIP_LP* lp, /**< LP data */
1508  SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
1509  SCIP_Bool* mustsepa, /**< pointer to store TRUE if additional separation rounds should be performed */
1510  SCIP_Bool* mustprice /**< pointer to store TRUE if additional pricing rounds should be performed */
1511  )
1512 {
1513  assert(lp != NULL);
1514  assert(lperror != NULL);
1515  assert(mustsepa != NULL);
1516  assert(mustprice != NULL);
1517 
1518  /* if bound changes were applied in the separation round, we have to resolve the LP */
1519  if( !lp->flushed )
1520  {
1521  /* solve LP (with dual simplex) */
1522  SCIPsetDebugMsg(set, "separation: resolve LP\n");
1523  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, prob, set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
1524  assert(lp->flushed);
1525  assert(lp->solved || *lperror);
1526  *mustsepa = TRUE;
1527  *mustprice = TRUE;
1528 
1529  /* remove previous primal ray, store new one if LP is unbounded */
1530  SCIP_CALL( updatePrimalRay(blkmem, set, stat, prob, primal, tree, lp, *lperror) );
1531  }
1532 
1533  return SCIP_OKAY;
1534 }
1535 
1536 /** applies one round of LP separation */
1537 static
1539  BMS_BLKMEM* blkmem, /**< block memory buffers */
1540  SCIP_SET* set, /**< global SCIP settings */
1541  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1542  SCIP_STAT* stat, /**< dynamic problem statistics */
1543  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1544  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1545  SCIP_PROB* prob, /**< transformed problem after presolve */
1546  SCIP_PRIMAL* primal, /**< primal data */
1547  SCIP_TREE* tree, /**< branch and bound tree */
1548  SCIP_LP* lp, /**< LP data */
1549  SCIP_SEPASTORE* sepastore, /**< separation storage */
1550  int actdepth, /**< current depth in the tree */
1551  SCIP_Real bounddist, /**< current relative distance of local dual bound to global dual bound */
1552  SCIP_Bool allowlocal, /**< should the separators be asked to separate local cuts */
1553  SCIP_Bool onlydelayed, /**< should only delayed separators be called? */
1554  SCIP_Bool* delayed, /**< pointer to store whether a separator was delayed */
1555  SCIP_Bool* enoughcuts, /**< pointer to store whether enough cuts have been found this round */
1556  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
1557  SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
1558  SCIP_Bool* mustsepa, /**< pointer to store TRUE if additional separation rounds should be performed */
1559  SCIP_Bool* mustprice /**< pointer to store TRUE if additional pricing rounds should be performed */
1560  )
1561 {
1562  SCIP_RESULT result;
1563  int i;
1564  SCIP_Bool consadded;
1565  SCIP_Bool root;
1566 
1567  assert(set != NULL);
1568  assert(lp != NULL);
1569  assert(set->conshdlrs_sepa != NULL);
1570  assert(delayed != NULL);
1571  assert(enoughcuts != NULL);
1572  assert(cutoff != NULL);
1573  assert(lperror != NULL);
1574 
1575  root = (actdepth == 0);
1576  *delayed = FALSE;
1577  *enoughcuts = (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root));
1578  *lperror = FALSE;
1579  consadded = FALSE;
1580 
1581  SCIPsetDebugMsg(set, "calling separators on LP solution in depth %d (onlydelayed: %u)\n", actdepth, onlydelayed);
1582 
1583  /* sort separators by priority */
1584  SCIPsetSortSepas(set);
1585 
1586  /* call LP separators with nonnegative priority */
1587  for( i = 0; i < set->nsepas && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1589  ++i )
1590  {
1591 #ifndef NDEBUG
1592  size_t nusedbuffer = BMSgetNUsedBufferMemory(SCIPbuffer(set->scip));
1593 #endif
1594 
1595  if( SCIPsepaGetPriority(set->sepas[i]) < 0 )
1596  continue;
1597 
1598  if( onlydelayed && !SCIPsepaWasLPDelayed(set->sepas[i]) )
1599  continue;
1600 
1601  SCIPsetDebugMsg(set, " -> executing separator <%s> with priority %d\n",
1602  SCIPsepaGetName(set->sepas[i]), SCIPsepaGetPriority(set->sepas[i]));
1603  SCIP_CALL( SCIPsepaExecLP(set->sepas[i], set, stat, sepastore, actdepth, bounddist, allowlocal, onlydelayed, &result) );
1604 #ifndef NDEBUG
1605  if( BMSgetNUsedBufferMemory(SCIPbuffer(set->scip)) > nusedbuffer )
1606  {
1607  SCIPerrorMessage("Buffer not completely freed after executing separator <%s>\n", SCIPsepaGetName(set->sepas[i]));
1608  SCIPABORT();
1609  }
1610 #endif
1611  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1612  consadded = consadded || (result == SCIP_CONSADDED);
1613  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1614  *delayed = *delayed || (result == SCIP_DELAYED);
1615 
1616  if( !(*cutoff) )
1617  {
1618  /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1619  SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1620  }
1621  else
1622  {
1623  SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1624  }
1625 
1626  /* if we work off the delayed separators, we stop immediately if a cut was found */
1627  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1628  {
1629  SCIPsetDebugMsg(set, " -> delayed separator <%s> found a cut\n", SCIPsepaGetName(set->sepas[i]));
1630  *delayed = TRUE;
1631  return SCIP_OKAY;
1632  }
1633  }
1634 
1635  /* try separating constraints of the constraint handlers */
1636  for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1638  ++i )
1639  {
1640  if( onlydelayed && !SCIPconshdlrWasLPSeparationDelayed(set->conshdlrs_sepa[i]) )
1641  continue;
1642 
1643  SCIPsetDebugMsg(set, " -> executing separation of constraint handler <%s> with priority %d\n",
1644  SCIPconshdlrGetName(set->conshdlrs_sepa[i]), SCIPconshdlrGetSepaPriority(set->conshdlrs_sepa[i]));
1645  SCIP_CALL( SCIPconshdlrSeparateLP(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, actdepth, onlydelayed,
1646  &result) );
1647 
1648  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1649  consadded = consadded || (result == SCIP_CONSADDED);
1650  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1651  *delayed = *delayed || (result == SCIP_DELAYED);
1652 
1653  if( !(*cutoff) )
1654  {
1655  /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1656  SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1657  }
1658  else
1659  {
1660  SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n", SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1661  }
1662 
1663  /* if we work off the delayed separators, we stop immediately if a cut was found */
1664  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1665  {
1666  SCIPsetDebugMsg(set, " -> delayed constraint handler <%s> found a cut\n",
1667  SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1668  *delayed = TRUE;
1669  return SCIP_OKAY;
1670  }
1671  }
1672 
1673  /* call LP separators with negative priority */
1674  for( i = 0; i < set->nsepas && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1676  ++i )
1677  {
1678  if( SCIPsepaGetPriority(set->sepas[i]) >= 0 )
1679  continue;
1680 
1681  if( onlydelayed && !SCIPsepaWasLPDelayed(set->sepas[i]) )
1682  continue;
1683 
1684  SCIPsetDebugMsg(set, " -> executing separator <%s> with priority %d\n",
1685  SCIPsepaGetName(set->sepas[i]), SCIPsepaGetPriority(set->sepas[i]));
1686  SCIP_CALL( SCIPsepaExecLP(set->sepas[i], set, stat, sepastore, actdepth, bounddist, allowlocal, onlydelayed, &result) );
1687 
1688  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1689  consadded = consadded || (result == SCIP_CONSADDED);
1690  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1691  *delayed = *delayed || (result == SCIP_DELAYED);
1692 
1693  if( !(*cutoff) )
1694  {
1695  /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1696  SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1697  }
1698  else
1699  {
1700  SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1701  }
1702 
1703  /* if we work off the delayed separators, we stop immediately if a cut was found */
1704  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1705  {
1706  SCIPsetDebugMsg(set, " -> delayed separator <%s> found a cut\n", SCIPsepaGetName(set->sepas[i]));
1707  *delayed = TRUE;
1708  return SCIP_OKAY;
1709  }
1710  }
1711 
1712  /* process the constraints that were added during this separation round */
1713  while( consadded )
1714  {
1715  assert(!onlydelayed);
1716  consadded = FALSE;
1717 
1718  for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1720  ++i )
1721  {
1722  SCIPsetDebugMsg(set, " -> executing separation of constraint handler <%s> with priority %d\n",
1723  SCIPconshdlrGetName(set->conshdlrs_sepa[i]), SCIPconshdlrGetSepaPriority(set->conshdlrs_sepa[i]));
1724  SCIP_CALL( SCIPconshdlrSeparateLP(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, actdepth, onlydelayed,
1725  &result) );
1726 
1727  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1728  consadded = consadded || (result == SCIP_CONSADDED);
1729  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1730  *delayed = *delayed || (result == SCIP_DELAYED);
1731 
1732  if( !(*cutoff) )
1733  {
1734  /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1735  SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1736  }
1737  else
1738  {
1739  SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n", SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1740  }
1741  }
1742  }
1743 
1744  SCIPsetDebugMsg(set, " -> separation round finished: delayed=%u, enoughcuts=%u, lpflushed=%u, cutoff=%u\n",
1745  *delayed, *enoughcuts, lp->flushed, *cutoff);
1746 
1747  return SCIP_OKAY;
1748 }
1749 
1750 /** applies one round of separation on the given primal solution */
1751 static
1753  BMS_BLKMEM* blkmem, /**< block memory buffers */
1754  SCIP_SET* set, /**< global SCIP settings */
1755  SCIP_STAT* stat, /**< dynamic problem statistics */
1756  SCIP_SEPASTORE* sepastore, /**< separation storage */
1757  SCIP_SOL* sol, /**< primal solution that should be separated, or NULL for LP solution */
1758  int actdepth, /**< current depth in the tree */
1759  SCIP_Bool allowlocal, /**< should the separator be asked to separate local cuts */
1760  SCIP_Bool onlydelayed, /**< should only delayed separators be called? */
1761  SCIP_Bool* delayed, /**< pointer to store whether a separator was delayed */
1762  SCIP_Bool* enoughcuts, /**< pointer to store whether enough cuts have been found this round */
1763  SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
1764  )
1765 {
1766  SCIP_RESULT result;
1767  int i;
1768  SCIP_Bool consadded;
1769  SCIP_Bool root;
1770 
1771  assert(set != NULL);
1772  assert(set->conshdlrs_sepa != NULL);
1773  assert(delayed != NULL);
1774  assert(enoughcuts != NULL);
1775  assert(cutoff != NULL);
1776 
1777  *delayed = FALSE;
1778  *enoughcuts = FALSE;
1779  consadded = FALSE;
1780  root = (actdepth == 0);
1781 
1782  SCIPsetDebugMsg(set, "calling separators on primal solution in depth %d (onlydelayed: %u)\n", actdepth, onlydelayed);
1783 
1784  /* sort separators by priority */
1785  SCIPsetSortSepas(set);
1786 
1787  /* call separators with nonnegative priority */
1788  for( i = 0; i < set->nsepas && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
1789  {
1790  if( SCIPsepaGetPriority(set->sepas[i]) < 0 )
1791  continue;
1792 
1793  if( onlydelayed && !SCIPsepaWasSolDelayed(set->sepas[i]) )
1794  continue;
1795 
1796  SCIP_CALL( SCIPsepaExecSol(set->sepas[i], set, stat, sepastore, sol, actdepth, allowlocal, onlydelayed, &result) );
1797  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1798  consadded = consadded || (result == SCIP_CONSADDED);
1799  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1800  *delayed = *delayed || (result == SCIP_DELAYED);
1801  if( *cutoff )
1802  {
1803  SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1804  }
1805 
1806  /* if we work off the delayed separators, we stop immediately if a cut was found */
1807  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1808  {
1809  *delayed = TRUE;
1810  return SCIP_OKAY;
1811  }
1812  }
1813 
1814  /* try separating constraints of the constraint handlers */
1815  for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
1816  {
1817  if( onlydelayed && !SCIPconshdlrWasSolSeparationDelayed(set->conshdlrs_sepa[i]) )
1818  continue;
1819 
1820  SCIP_CALL( SCIPconshdlrSeparateSol(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, sol, actdepth, onlydelayed,
1821  &result) );
1822  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1823  consadded = consadded || (result == SCIP_CONSADDED);
1824  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1825  *delayed = *delayed || (result == SCIP_DELAYED);
1826  if( *cutoff )
1827  {
1828  SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n",
1829  SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1830  }
1831 
1832  /* if we work off the delayed separators, we stop immediately if a cut was found */
1833  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1834  {
1835  *delayed = TRUE;
1836  return SCIP_OKAY;
1837  }
1838  }
1839 
1840  /* call separators with negative priority */
1841  for( i = 0; i < set->nsepas && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
1842  {
1843  if( SCIPsepaGetPriority(set->sepas[i]) >= 0 )
1844  continue;
1845 
1846  if( onlydelayed && !SCIPsepaWasSolDelayed(set->sepas[i]) )
1847  continue;
1848 
1849  SCIP_CALL( SCIPsepaExecSol(set->sepas[i], set, stat, sepastore, sol, actdepth, allowlocal, onlydelayed, &result) );
1850  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1851  consadded = consadded || (result == SCIP_CONSADDED);
1852  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1853  *delayed = *delayed || (result == SCIP_DELAYED);
1854  if( *cutoff )
1855  {
1856  SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1857  }
1858 
1859  /* if we work off the delayed separators, we stop immediately if a cut was found */
1860  if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1861  {
1862  *delayed = TRUE;
1863  return SCIP_OKAY;
1864  }
1865  }
1866 
1867  /* process the constraints that were added during this separation round */
1868  while( consadded )
1869  {
1870  assert(!onlydelayed);
1871  consadded = FALSE;
1872 
1873  for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
1874  {
1875  SCIP_CALL( SCIPconshdlrSeparateSol(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, sol, actdepth, onlydelayed, &result) );
1876  *cutoff = *cutoff || (result == SCIP_CUTOFF);
1877  consadded = consadded || (result == SCIP_CONSADDED);
1878  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
1879  *delayed = *delayed || (result == SCIP_DELAYED);
1880  if( *cutoff )
1881  {
1882  SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n",
1883  SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1884  }
1885  }
1886  }
1887 
1888  SCIPsetDebugMsg(set, " -> separation round finished: delayed=%u, enoughcuts=%u, cutoff=%u\n",
1889  *delayed, *enoughcuts, *cutoff);
1890 
1891  return SCIP_OKAY;
1892 }
1893 
1894 /** applies one round of separation on the given primal solution or on the LP solution */
1896  BMS_BLKMEM* blkmem, /**< block memory buffers */
1897  SCIP_SET* set, /**< global SCIP settings */
1898  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1899  SCIP_STAT* stat, /**< dynamic problem statistics */
1900  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1901  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1902  SCIP_PROB* prob, /**< transformed problem after presolve */
1903  SCIP_PRIMAL* primal, /**< primal data */
1904  SCIP_TREE* tree, /**< branch and bound tree */
1905  SCIP_LP* lp, /**< LP data */
1906  SCIP_SEPASTORE* sepastore, /**< separation storage */
1907  SCIP_SOL* sol, /**< primal solution that should be separated, or NULL for LP solution */
1908  int actdepth, /**< current depth in the tree */
1909  SCIP_Bool allowlocal, /**< should the separator be asked to separate local cuts */
1910  SCIP_Bool onlydelayed, /**< should only delayed separators be called? */
1911  SCIP_Bool* delayed, /**< pointer to store whether a separator was delayed */
1912  SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
1913  )
1914 {
1915  SCIP_Bool enoughcuts;
1916 
1917  assert(delayed != NULL);
1918  assert(cutoff != NULL);
1919 
1920  *delayed = FALSE;
1921  *cutoff = FALSE;
1922  enoughcuts = FALSE;
1923 
1924  if( sol == NULL )
1925  {
1926  SCIP_Bool lperror;
1927  SCIP_Bool mustsepa;
1928  SCIP_Bool mustprice;
1929 
1930  /* apply a separation round on the LP solution */
1931  lperror = FALSE;
1932  mustsepa = FALSE;
1933  mustprice = FALSE;
1934  SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, sepastore, \
1935  actdepth, 0.0, allowlocal, onlydelayed, delayed, &enoughcuts, cutoff, \
1936  &lperror, &mustsepa, &mustprice) );
1937  }
1938  else
1939  {
1940  /* apply a separation round on the given primal solution */
1941  SCIP_CALL( separationRoundSol(blkmem, set, stat, sepastore, sol, actdepth, allowlocal, onlydelayed, delayed, &enoughcuts, cutoff) );
1942  }
1943 
1944  return SCIP_OKAY;
1945 }
1946 
1947 /** solves the current LP completely with pricing in new variables */
1949  BMS_BLKMEM* blkmem, /**< block memory buffers */
1950  SCIP_SET* set, /**< global SCIP settings */
1951  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1952  SCIP_STAT* stat, /**< dynamic problem statistics */
1953  SCIP_PROB* transprob, /**< transformed problem */
1954  SCIP_PROB* origprob, /**< original problem */
1955  SCIP_PRIMAL* primal, /**< primal data */
1956  SCIP_TREE* tree, /**< branch and bound tree */
1957  SCIP_REOPT* reopt, /**< reoptimization data structure */
1958  SCIP_LP* lp, /**< LP data */
1959  SCIP_PRICESTORE* pricestore, /**< pricing storage */
1960  SCIP_SEPASTORE* sepastore, /**< separation storage */
1961  SCIP_CUTPOOL* cutpool, /**< global cutpool */
1962  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1963  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1964  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1965  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1966  SCIP_Bool pretendroot, /**< should the pricers be called as if we are at the root node? */
1967  SCIP_Bool displayinfo, /**< should info lines be displayed after each pricing round? */
1968  int maxpricerounds, /**< maximal number of pricing rounds (-1: no limit);
1969  * a finite limit means that the LP might not be solved to optimality! */
1970  int* npricedcolvars, /**< pointer to store number of column variables after problem vars were priced */
1971  SCIP_Bool* mustsepa, /**< pointer to store TRUE if a separation round should follow */
1972  SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
1973  SCIP_Bool* aborted /**< pointer to store whether the pricing was aborted and the lower bound must
1974  * not be used */
1975  )
1976 {
1977  SCIP_NODE* currentnode;
1978  int npricerounds;
1979  SCIP_Bool mustprice;
1980  SCIP_Bool cutoff;
1981  SCIP_Bool unbounded;
1982 
1983  assert(transprob != NULL);
1984  assert(lp != NULL);
1985  assert(lp->flushed);
1986  assert(lp->solved);
1987  assert(npricedcolvars != NULL);
1988  assert(mustsepa != NULL);
1989  assert(lperror != NULL);
1990  assert(aborted != NULL);
1991 
1992  currentnode = SCIPtreeGetCurrentNode(tree);
1993  assert(currentnode == SCIPtreeGetFocusNode(tree) || SCIPtreeProbing(tree));
1994  *npricedcolvars = transprob->ncolvars;
1995  *lperror = FALSE;
1996  *aborted = FALSE;
1997 
1998  /* if the LP is unbounded, we don't need to price */
1999  mustprice = (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL
2002 
2003  /* if all the variables are already in the LP, we don't need to price */
2004  mustprice = mustprice && !SCIPprobAllColsInLP(transprob, set, lp);
2005 
2006  /* check if infinite number of pricing rounds should be used */
2007  if( maxpricerounds == -1 )
2008  maxpricerounds = INT_MAX;
2009 
2010  /* pricing (has to be done completely to get a valid lower bound) */
2011  npricerounds = 0;
2012  while( !(*lperror) && mustprice && npricerounds < maxpricerounds )
2013  {
2014  SCIP_Bool enoughvars;
2015  SCIP_RESULT result;
2016  SCIP_Real lb;
2017  SCIP_Bool foundsol;
2018  SCIP_Bool stopearly;
2019  SCIP_Bool stoppricing;
2020  int p;
2021 
2022  assert(lp->flushed);
2023  assert(lp->solved);
2025 
2026  /* check if pricing loop should be aborted */
2027  if( SCIPsolveIsStopped(set, stat, FALSE) )
2028  {
2029  /* do not print the warning message if we stopped because the problem is solved */
2030  if( !SCIPsetIsLE(set, SCIPgetUpperbound(set->scip), SCIPgetLowerbound(set->scip)) )
2031  SCIPmessagePrintWarning(messagehdlr, "pricing has been interrupted -- LP of current node is invalid\n");
2032 
2033  *aborted = TRUE;
2034  break;
2035  }
2036 
2037  /* call primal heuristics which are callable during pricing */
2038  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, SCIP_HEURTIMING_DURINGPRICINGLOOP,
2039  FALSE, &foundsol, &unbounded) );
2040 
2041  /* price problem variables */
2042  SCIPsetDebugMsg(set, "problem variable pricing\n");
2043  assert(SCIPpricestoreGetNVars(pricestore) == 0);
2044  assert(SCIPpricestoreGetNBoundResets(pricestore) == 0);
2045  SCIP_CALL( SCIPpricestoreAddProbVars(pricestore, blkmem, set, stat, transprob, tree, lp, branchcand, eventqueue) );
2046  *npricedcolvars = transprob->ncolvars;
2047 
2048  /* call external pricers to create additional problem variables */
2049  SCIPsetDebugMsg(set, "external variable pricing\n");
2050 
2051  /* sort pricer algorithms by priority */
2052  SCIPsetSortPricers(set);
2053 
2054  /* call external pricer algorithms, that are active for the current problem */
2055  enoughvars = (SCIPsetGetPriceMaxvars(set, pretendroot) == INT_MAX ?
2056  FALSE : SCIPpricestoreGetNVars(pricestore) >= SCIPsetGetPriceMaxvars(set, pretendroot) + 1);
2057  stoppricing = FALSE;
2058  for( p = 0; p < set->nactivepricers && !enoughvars; ++p )
2059  {
2060  SCIP_CALL( SCIPpricerExec(set->pricers[p], set, transprob, lp, pricestore, &lb, &stopearly, &result) );
2061  assert(result == SCIP_DIDNOTRUN || result == SCIP_SUCCESS);
2062  SCIPsetDebugMsg(set, "pricing: pricer %s returned result = %s, lowerbound = %f\n",
2063  SCIPpricerGetName(set->pricers[p]), (result == SCIP_DIDNOTRUN ? "didnotrun" : "success"), lb);
2064  enoughvars = enoughvars || (SCIPsetGetPriceMaxvars(set, pretendroot) == INT_MAX ?
2065  FALSE : SCIPpricestoreGetNVars(pricestore) >= SCIPsetGetPriceMaxvars(set, pretendroot) + 1);
2066  *aborted = ( (*aborted) || (result == SCIP_DIDNOTRUN) );
2067 
2068  /* set stoppricing to TRUE, of the first pricer wants to stop pricing */
2069  if( p == 0 && stopearly )
2070  stoppricing = TRUE;
2071 
2072  /* stoppricing only remains TRUE, if all other pricers want to stop pricing as well */
2073  if( stoppricing && !stopearly )
2074  stoppricing = FALSE;
2075 
2076  /* update lower bound w.r.t. the lower bound given by the pricer */
2077  SCIPnodeUpdateLowerbound(currentnode, stat, set, tree, transprob, origprob, lb);
2078  SCIPsetDebugMsg(set, " -> new lower bound given by pricer %s: %g\n", SCIPpricerGetName(set->pricers[p]), lb);
2079  }
2080 
2081  /* apply the priced variables to the LP */
2082  SCIP_CALL( SCIPpricestoreApplyVars(pricestore, blkmem, set, stat, eventqueue, transprob, tree, lp) );
2083  assert(SCIPpricestoreGetNVars(pricestore) == 0);
2084  assert(!lp->flushed || lp->solved);
2085  mustprice = !lp->flushed || (transprob->ncolvars != *npricedcolvars);
2086  *mustsepa = *mustsepa || !lp->flushed;
2087 
2088  /* after adding columns, the LP should be primal feasible such that the primal simplex is applicable;
2089  * if LP was infeasible, we have to use dual simplex
2090  */
2091  SCIPsetDebugMsg(set, "pricing: solve LP\n");
2092  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, TRUE, FALSE, lperror) );
2093  assert(lp->flushed);
2094  assert(lp->solved || *lperror);
2095 
2096  /* reset bounds temporarily set by pricer to their original values */
2097  SCIPsetDebugMsg(set, "pricing: reset bounds\n");
2098  SCIP_CALL( SCIPpricestoreResetBounds(pricestore, blkmem, set, stat, lp, branchcand, eventqueue) );
2099  assert(SCIPpricestoreGetNVars(pricestore) == 0);
2100  assert(SCIPpricestoreGetNBoundResets(pricestore) == 0);
2101  assert(!lp->flushed || lp->solved || *lperror);
2102 
2103  /* put all initial constraints into the LP */
2104  SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
2105  eventfilter, cliquetable, FALSE, FALSE, &cutoff) );
2106  assert(cutoff == FALSE);
2107 
2108  mustprice = mustprice || !lp->flushed || (transprob->ncolvars != *npricedcolvars);
2109  *mustsepa = *mustsepa || !lp->flushed;
2110 
2111  /* if all pricers wanted to stop pricing, do not do another pricing round (LP value is no valid dual bound in this case) */
2112  if( stoppricing )
2113  {
2114  SCIPsetDebugMsg(set, "pricing: stop pricing and perform early branching\n");
2115  mustprice = FALSE;
2116  *aborted = TRUE;
2117  }
2118 
2119  /* solve LP again after resetting bounds and adding new initial constraints (with dual simplex) */
2120  SCIPsetDebugMsg(set, "pricing: solve LP after resetting bounds and adding new initial constraints\n");
2121  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, FALSE, lperror) );
2122  assert(lp->flushed);
2123  assert(lp->solved || *lperror);
2124 
2125  /* remove previous primal ray, store new one if LP is unbounded */
2126  SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2127 
2128  /* increase pricing round counter */
2129  stat->npricerounds++;
2130  npricerounds++;
2131 
2132  /* display node information line */
2133  if( displayinfo && mustprice )
2134  {
2135  if( (SCIP_VERBLEVEL)set->disp_verblevel >= SCIP_VERBLEVEL_FULL
2136  || ((SCIP_VERBLEVEL)set->disp_verblevel >= SCIP_VERBLEVEL_HIGH && npricerounds % 100 == 1) )
2137  {
2138  SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, TRUE, TRUE) );
2139  }
2140  }
2141 
2142  /* if the LP is unbounded, we can stop pricing */
2143  mustprice = mustprice &&
2147 
2148  /* if the lower bound is already higher than the cutoff bound, we can stop pricing */
2149  mustprice = mustprice && SCIPsetIsLT(set, SCIPnodeGetLowerbound(currentnode), primal->cutoffbound);
2150  }
2151  assert(lp->flushed);
2152  assert(lp->solved || *lperror);
2153 
2154  *aborted = ( (*aborted) || (*lperror) || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_NOTSOLVED
2155  || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_ERROR || npricerounds == maxpricerounds );
2156 
2157  /* set information, whether the current lp is a valid relaxation of the current problem */
2158  SCIPlpSetIsRelax(lp, !(*aborted));
2159 
2160  return SCIP_OKAY;
2161 }
2162 
2163 /** separates cuts of the cut pool */
2164 static
2166  SCIP_CUTPOOL* cutpool, /**< cut pool */
2167  BMS_BLKMEM* blkmem, /**< block memory */
2168  SCIP_SET* set, /**< global SCIP settings */
2169  SCIP_STAT* stat, /**< problem statistics data */
2170  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2171  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
2172  SCIP_LP* lp, /**< current LP data */
2173  SCIP_SEPASTORE* sepastore, /**< separation storage */
2174  SCIP_Bool cutpoolisdelayed, /**< is the cutpool delayed (count cuts found)? */
2175  SCIP_Bool root, /**< are we at the root node? */
2176  int actdepth, /**< the depth of the focus node */
2177  SCIP_Bool* enoughcuts, /**< pointer to store if enough cuts were found in current separation round */
2178  SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
2179  )
2180 {
2181  if( (set->sepa_poolfreq == 0 && actdepth == 0)
2182  || (set->sepa_poolfreq > 0 && actdepth % set->sepa_poolfreq == 0) )
2183  {
2184  SCIP_RESULT result;
2185 
2186  SCIP_CALL( SCIPcutpoolSeparate(cutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, NULL, cutpoolisdelayed, root, &result) );
2187  *cutoff = *cutoff || (result == SCIP_CUTOFF);
2188  *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= 2 * (SCIP_Longint)SCIPsetGetSepaMaxcuts(set, root)) || (result == SCIP_NEWROUND);
2189  }
2190 
2191  return SCIP_OKAY;
2192 }
2193 
2194 /** solve the current LP of a node with a price-and-cut loop */
2195 static
2197  BMS_BLKMEM* blkmem, /**< block memory buffers */
2198  SCIP_SET* set, /**< global SCIP settings */
2199  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2200  SCIP_STAT* stat, /**< dynamic problem statistics */
2201  SCIP_MEM* mem, /**< block memory pools */
2202  SCIP_PROB* transprob, /**< transformed problem */
2203  SCIP_PROB* origprob, /**< original problem */
2204  SCIP_PRIMAL* primal, /**< primal data */
2205  SCIP_TREE* tree, /**< branch and bound tree */
2206  SCIP_REOPT* reopt, /**< reoptimization data structure */
2207  SCIP_LP* lp, /**< LP data */
2208  SCIP_PRICESTORE* pricestore, /**< pricing storage */
2209  SCIP_SEPASTORE* sepastore, /**< separation storage */
2210  SCIP_CUTPOOL* cutpool, /**< global cut pool */
2211  SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
2212  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2213  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2214  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
2215  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
2216  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2217  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2218  SCIP_Bool fullseparation, /**< are we in the first prop-and-cut-and-price loop? */
2219  SCIP_Bool* propagateagain, /**< pointer to store whether we want to propagate again */
2220  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
2221  SCIP_Bool* unbounded, /**< pointer to store whether an unbounded ray was found in the LP */
2222  SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
2223  SCIP_Bool* pricingaborted /**< pointer to store whether the pricing was aborted and the lower bound must
2224  * not be used */
2225  )
2226 {
2227  SCIP_NODE* focusnode;
2228  /* cppcheck-suppress unassignedVariable */
2229  SCIP_EVENT event;
2230  SCIP_LPSOLSTAT stalllpsolstat;
2231  SCIP_Real loclowerbound;
2232  SCIP_Real glblowerbound;
2233  SCIP_Real bounddist;
2234  SCIP_Real stalllpobjval;
2235  SCIP_Bool separate;
2236  SCIP_Bool mustprice;
2237  SCIP_Bool mustsepa;
2238  SCIP_Bool delayedsepa;
2239  SCIP_Bool root;
2240  SCIP_Bool allowlocal;
2241  int maxseparounds;
2242  int maxincseparounds;
2243  int nsepastallrounds;
2244  int maxnsepastallrounds;
2245  int stallnfracs;
2246  int actdepth;
2247  int npricedcolvars;
2248 
2249  assert(set != NULL);
2250  assert(blkmem != NULL);
2251  assert(stat != NULL);
2252  assert(transprob != NULL);
2253  assert(tree != NULL);
2254  assert(lp != NULL);
2255  assert(pricestore != NULL);
2256  assert(sepastore != NULL);
2257  assert(cutpool != NULL);
2258  assert(delayedcutpool != NULL);
2259  assert(primal != NULL);
2260  assert(cutoff != NULL);
2261  assert(unbounded != NULL);
2262  assert(lperror != NULL);
2263 
2264  focusnode = SCIPtreeGetFocusNode(tree);
2265  assert(focusnode != NULL);
2266  assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
2267  actdepth = SCIPnodeGetDepth(focusnode);
2268  root = (actdepth == 0);
2269 
2270  /* check, if we want to separate at this node */
2271  loclowerbound = SCIPnodeGetLowerbound(focusnode);
2272  glblowerbound = SCIPtreeGetLowerbound(tree, set);
2273  assert(primal->cutoffbound > glblowerbound);
2274  bounddist = (loclowerbound - glblowerbound)/(primal->cutoffbound - glblowerbound);
2275  allowlocal = SCIPsetIsLE(set, bounddist, set->sepa_maxlocalbounddist);
2276  separate = (set->sepa_maxruns == -1 || stat->nruns <= set->sepa_maxruns);
2277 
2278  /* get maximal number of separation rounds */
2279  maxseparounds = (root ? set->sepa_maxroundsroot : set->sepa_maxrounds);
2280  if( maxseparounds == -1 )
2281  maxseparounds = INT_MAX;
2282  if( stat->nruns > 1 && root && set->sepa_maxroundsrootsubrun >= 0 )
2283  maxseparounds = MIN(maxseparounds, set->sepa_maxroundsrootsubrun);
2284  if( !fullseparation && set->sepa_maxaddrounds >= 0 )
2285  maxseparounds = MIN(maxseparounds, stat->nseparounds + set->sepa_maxaddrounds);
2286  maxnsepastallrounds = root ? set->sepa_maxstallroundsroot : set->sepa_maxstallrounds;
2287  if( maxnsepastallrounds == -1 )
2288  maxnsepastallrounds = INT_MAX;
2289  maxincseparounds = set->sepa_maxincrounds;
2290  if( maxincseparounds == -1 )
2291  maxincseparounds = INT_MAX;
2292 
2293  /* solve initial LP of price-and-cut loop */
2294  /* @todo check if LP is always already solved, because of calling solveNodeInitialLP() in solveNodeLP()? */
2295  SCIPsetDebugMsg(set, "node: solve LP with price and cut\n");
2296  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2297  set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2298  assert(lp->flushed);
2299  assert(lp->solved || *lperror);
2300 
2301  /* remove previous primal ray, store new one if LP is unbounded */
2302  SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2303 
2304  /* price-and-cut loop */
2305  npricedcolvars = transprob->ncolvars;
2306  mustprice = TRUE;
2307  mustsepa = separate;
2308  delayedsepa = FALSE;
2309  *cutoff = FALSE;
2310  *unbounded = (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
2311  nsepastallrounds = 0;
2312  stalllpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2313  stalllpobjval = SCIP_REAL_MIN;
2314  stallnfracs = INT_MAX;
2315  lp->installing = FALSE;
2316  while( !(*cutoff) && !(*unbounded) && !(*lperror) && (mustprice || mustsepa || delayedsepa) )
2317  {
2318  SCIPsetDebugMsg(set, "-------- node solving loop --------\n");
2319  assert(lp->flushed);
2320  assert(lp->solved);
2321 
2322  /* solve the LP with pricing in new variables */
2323  while( mustprice && !(*lperror) )
2324  {
2325  SCIP_CALL( SCIPpriceLoop(blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
2326  pricestore, sepastore, cutpool, branchcand, eventqueue, eventfilter, cliquetable, root, root, -1, &npricedcolvars,
2327  &mustsepa, lperror, pricingaborted) );
2328 
2329  mustprice = FALSE;
2330 
2331  assert(lp->flushed);
2332  assert(lp->solved || *lperror);
2333 
2334  /* update lower bound w.r.t. the LP solution */
2335  if( !(*lperror) && !(*pricingaborted) && SCIPlpIsRelax(lp) )
2336  {
2337  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2338  SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2339  SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2340 
2341  /* update node estimate */
2342  SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2343 
2344  if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2345  SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2346  }
2347  else
2348  {
2349  SCIPsetDebugMsg(set, " -> error solving LP or pricing aborted. keeping old bound: %g\n", SCIPnodeGetLowerbound(focusnode));
2350  }
2351 
2352  /* display node information line for root node */
2353  if( root && (SCIP_VERBLEVEL)set->disp_verblevel >= SCIP_VERBLEVEL_HIGH )
2354  {
2355  SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, TRUE, TRUE) );
2356  }
2357 
2358  if( !(*lperror) )
2359  {
2360  /* call propagators that are applicable during LP solving loop only if the node is not cut off */
2361  if( SCIPsetIsLT(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound) )
2362  {
2363  SCIP_Longint oldnboundchgs;
2364  SCIP_Longint oldninitconssadded;
2365  SCIP_Bool postpone;
2366 
2367  oldnboundchgs = stat->nboundchgs;
2368  oldninitconssadded = stat->ninitconssadded;
2369 
2370  SCIPsetDebugMsg(set, " -> LP solved: call propagators that are applicable during LP solving loop\n");
2371 
2372  SCIP_CALL( propagateDomains(blkmem, set, stat, primal, tree, SCIPtreeGetCurrentDepth(tree), 0, FALSE,
2373  SCIP_PROPTIMING_DURINGLPLOOP, cutoff, &postpone) );
2374  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2375  assert(!postpone);
2376 
2377  if( stat->ninitconssadded != oldninitconssadded )
2378  {
2379  SCIPsetDebugMsg(set, "new initial constraints added during propagation: old=%" SCIP_LONGINT_FORMAT ", new=%" SCIP_LONGINT_FORMAT "\n", oldninitconssadded, stat->ninitconssadded);
2380 
2381  SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp,
2382  branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE, cutoff) );
2383  }
2384 
2385  if( !(*cutoff) && !(*unbounded) )
2386  {
2387  /* if we found something, solve LP again */
2388  if( !lp->flushed )
2389  {
2390  SCIPsetDebugMsg(set, " -> found reduction: resolve LP\n");
2391 
2392  /* in the root node, remove redundant rows permanently from the LP */
2393  if( root )
2394  {
2395  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
2396  SCIP_CALL( SCIPlpRemoveRedundantRows(lp, blkmem, set, stat, eventqueue, eventfilter) );
2397  }
2398 
2399  /* resolve LP */
2400  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2401  set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2402  assert(lp->flushed);
2403  assert(lp->solved || *lperror);
2404 
2405  /* remove previous primal ray, store new one if LP is unbounded */
2406  SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2407 
2408  mustprice = TRUE;
2409  *propagateagain = TRUE;
2410  }
2411  /* propagation might have changed the best bound of loose variables, thereby changing the loose objective
2412  * value which is added to the LP value; because of the loose status, the LP might not be reoptimized,
2413  * but the lower bound of the node needs to be updated
2414  */
2415  else if( stat->nboundchgs > oldnboundchgs )
2416  {
2417  *propagateagain = TRUE;
2418 
2419  if( lp->solved && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
2420  {
2421  assert(lp->flushed);
2422  assert(lp->solved);
2423 
2424  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2425  SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2426  SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2427 
2428  /* update node estimate */
2429  SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2430 
2431  if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2432  SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2433  }
2434  }
2435  }
2436  }
2437  }
2438 
2439  /* call primal heuristics that are applicable during node LP solving loop */
2440  if( !*cutoff && !(*unbounded) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2441  {
2442  SCIP_Bool foundsol;
2443 
2444  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, SCIP_HEURTIMING_DURINGLPLOOP,
2445  FALSE, &foundsol, unbounded) );
2446  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2447 
2448  *lperror = *lperror || lp->resolvelperror;
2449  }
2450  }
2451  assert(lp->flushed || *cutoff || *unbounded);
2452  assert(lp->solved || *lperror || *cutoff || *unbounded);
2453 
2454  /* check, if we exceeded the separation round limit */
2455  mustsepa = mustsepa
2456  && stat->nseparounds < maxseparounds
2457  && stat->nincseparounds < maxincseparounds
2458  && nsepastallrounds < maxnsepastallrounds
2459  && !(*cutoff);
2460 
2461  /* if separators were delayed, we want to apply a final separation round with the delayed separators */
2462  delayedsepa = delayedsepa && !mustsepa && !(*cutoff); /* if regular separation applies, we ignore delayed separators */
2463  mustsepa = mustsepa || delayedsepa;
2464 
2465  if( mustsepa )
2466  {
2467  /* if the LP is infeasible, unbounded, exceeded the objective limit or a global performance limit was reached,
2468  * we don't need to separate cuts
2469  * (the global limits are only checked at the root node in order to not query system time too often)
2470  */
2471  if( !separate || (*cutoff) || (*unbounded)
2473  || SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound)
2474  || (root && SCIPsolveIsStopped(set, stat, FALSE)) )
2475  {
2476  mustsepa = FALSE;
2477  delayedsepa = FALSE;
2478  }
2479  else
2480  assert(!(*lperror));
2481  }
2482 
2483  /* separation (needs not to be done completely, because we just want to increase the lower bound) */
2484  if( mustsepa )
2485  {
2486  SCIP_Longint olddomchgcount;
2487  SCIP_Longint oldninitconssadded;
2488  int oldnlprows;
2489  SCIP_Bool enoughcuts;
2490 
2491  assert(lp->flushed);
2492  assert(lp->solved);
2494 
2495  olddomchgcount = stat->domchgcount;
2496  oldninitconssadded = stat->ninitconssadded;
2497 
2498  mustsepa = FALSE;
2499  enoughcuts = (SCIPsetGetSepaMaxcuts(set, root) == 0);
2500  oldnlprows = lp->nrows;
2501 
2502  /* global cut pool separation */
2503  if( !enoughcuts && !delayedsepa )
2504  {
2505  SCIP_CALL( cutpoolSeparate(cutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, FALSE, root,
2506  actdepth, &enoughcuts, cutoff) );
2507 
2508  if( *cutoff )
2509  {
2510  SCIPsetDebugMsg(set, " -> global cut pool detected cutoff\n");
2511  }
2512  }
2513  assert(lp->flushed);
2514  assert(lp->solved);
2516 
2517  /* constraint separation */
2518  SCIPsetDebugMsg(set, "constraint separation\n");
2519 
2520  /* separate constraints and LP */
2521  if( !(*cutoff) && !(*lperror) && !enoughcuts && lp->solved )
2522  {
2523  /* apply a separation round */
2524  SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal, tree,
2525  lp, sepastore, actdepth, bounddist, allowlocal, delayedsepa,
2526  &delayedsepa, &enoughcuts, cutoff, lperror, &mustsepa, &mustprice) );
2527  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2528 
2529  /* if we are close to the stall round limit, also call the delayed separators */
2530  if( !(*cutoff) && !(*lperror) && !enoughcuts && lp->solved
2532  && nsepastallrounds >= maxnsepastallrounds-1 && delayedsepa )
2533  {
2534  SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal,
2535  tree, lp, sepastore, actdepth, bounddist, allowlocal, delayedsepa,
2536  &delayedsepa, &enoughcuts, cutoff, lperror, &mustsepa, &mustprice) );
2537  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2538  }
2539  }
2540 
2541  /* call global cut pool separation again since separators may add cuts to the pool instead of the sepastore */
2542  if( !(*cutoff) && !(*lperror) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && !enoughcuts && lp->solved )
2543  {
2544  SCIP_CALL( cutpoolSeparate(cutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, FALSE, root,
2545  actdepth, &enoughcuts, cutoff) );
2546 
2547  if( *cutoff )
2548  {
2549  SCIPsetDebugMsg(set, " -> global cut pool detected cutoff\n");
2550  }
2551  }
2552 
2553  /* delayed global cut pool separation */
2554  if( !(*cutoff) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && SCIPsepastoreGetNCuts(sepastore) == 0 )
2555  {
2556  assert( !(*lperror) );
2557 
2558  SCIP_CALL( cutpoolSeparate(delayedcutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, TRUE,
2559  root, actdepth, &enoughcuts, cutoff) );
2560 
2561  if( *cutoff )
2562  {
2563  SCIPsetDebugMsg(set, " -> delayed global cut pool detected cutoff\n");
2564  }
2566  assert(lp->flushed);
2567  assert(lp->solved);
2568  }
2569 
2570  assert(*cutoff || *lperror || SCIPlpIsSolved(lp));
2571  assert(!SCIPlpIsSolved(lp)
2578 
2579  if( *cutoff || *lperror
2582  {
2583  /* the found cuts are of no use, because the node is infeasible anyway (or we have an error in the LP) */
2584  SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
2585  }
2586  else
2587  {
2588  /* apply found cuts */
2589  SCIP_CALL( SCIPsepastoreApplyCuts(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
2590  branchcand, eventqueue, eventfilter, cliquetable, root, SCIP_EFFICIACYCHOICE_LP, cutoff) );
2591 
2592  if( !(*cutoff) )
2593  {
2594  mustprice = mustprice || !lp->flushed || (transprob->ncolvars != npricedcolvars);
2595  mustsepa = mustsepa || !lp->flushed;
2596 
2597  /* if a new bound change (e.g. a cut with only one column) was found, propagate domains again */
2598  if( stat->domchgcount != olddomchgcount )
2599  {
2600  SCIPsetDebugMsg(set, " -> separation changed bound: propagate again\n");
2601 
2602  *propagateagain = TRUE;
2603 
2604  /* in the root node, remove redundant rows permanently from the LP */
2605  if( root )
2606  {
2607  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
2608  SCIP_CALL( SCIPlpRemoveRedundantRows(lp, blkmem, set, stat, eventqueue, eventfilter) );
2609  }
2610  }
2611 
2612  if( stat->ninitconssadded != oldninitconssadded )
2613  {
2614  SCIPsetDebugMsg(set, "new initial constraints added during propagation: old=%" SCIP_LONGINT_FORMAT ", new=%" SCIP_LONGINT_FORMAT "\n",
2615  oldninitconssadded, stat->ninitconssadded);
2616 
2617  SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp,
2618  branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE, cutoff) );
2619  }
2620 
2621  if( !(*cutoff) )
2622  {
2623  SCIP_Real lpobjval;
2624 
2625  /* solve LP (with dual simplex) */
2626  SCIPsetDebugMsg(set, "separation: solve LP\n");
2627  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2628  set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2629  assert(lp->flushed);
2630  assert(lp->solved || *lperror);
2631 
2632  /* remove previous primal ray, store new one if LP is unbounded */
2633  SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2634 
2635  if( !(*lperror) )
2636  {
2637  SCIP_Bool stalling;
2638 
2639  /* propagation might have changed the best bound of loose variables, thereby changing the loose objective value
2640  * which is added to the LP value; because of the loose status, the LP might not be reoptimized, but the lower
2641  * bound of the node needs to be updated
2642  */
2643  if( stat->domchgcount != olddomchgcount && (!mustprice || mustsepa) && !(*cutoff)
2644  && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
2645  {
2646  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2647  SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2648  SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2649 
2650  /* update node estimate */
2651  SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2652 
2653  if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2654  SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2655  }
2656 
2657  /* check if we are stalling
2658  * If we have an LP solution, then we are stalling if
2659  * we had an LP solution before and
2660  * the LP value did not improve and
2661  * the number of fractional variables did not decrease.
2662  * If we do not have an LP solution, then we are stalling if the solution status of the LP did not change.
2663  */
2665  {
2666  SCIP_Real objreldiff;
2667  int nfracs;
2668 
2669  SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nfracs, NULL,
2670  NULL) );
2671  lpobjval = SCIPlpGetObjval(lp, set, transprob);
2672 
2673  objreldiff = SCIPrelDiff(lpobjval, stalllpobjval);
2674  SCIPsetDebugMsg(set, " -> LP bound moved from %g to %g (reldiff: %g)\n",
2675  stalllpobjval, lpobjval, objreldiff);
2676 
2677  stalling = (stalllpsolstat == SCIP_LPSOLSTAT_OPTIMAL &&
2678  objreldiff <= 1e-04 &&
2679  nfracs >= (0.9 - 0.1 * nsepastallrounds) * stallnfracs);
2680 
2681  stalllpobjval = lpobjval;
2682  stallnfracs = nfracs;
2683  }
2684  else
2685  {
2686  stalling = (stalllpsolstat == SCIPlpGetSolstat(lp));
2687  }
2688 
2689  if( !stalling )
2690  {
2691  nsepastallrounds = 0;
2692  lp->installing = FALSE;
2693  }
2694  else
2695  {
2696  nsepastallrounds++;
2697  }
2698  stalllpsolstat = SCIPlpGetSolstat(lp);
2699 
2700  /* tell LP that we are (close to) stalling */
2701  if( nsepastallrounds >= maxnsepastallrounds-2 )
2702  lp->installing = TRUE;
2703  SCIPsetDebugMsg(set, " -> nsepastallrounds=%d/%d\n", nsepastallrounds, maxnsepastallrounds);
2704  }
2705  }
2706  }
2707  }
2708  assert(*cutoff || *lperror || (lp->flushed && lp->solved)); /* cutoff: LP may be unsolved due to bound changes */
2709 
2710  SCIPsetDebugMsg(set, "separation round %d/%d finished (%d/%d stall rounds): mustprice=%u, mustsepa=%u, delayedsepa=%u, propagateagain=%u\n",
2711  stat->nseparounds, maxseparounds, nsepastallrounds, maxnsepastallrounds, mustprice, mustsepa, delayedsepa, *propagateagain);
2712 
2713  /* increase separation round counter */
2714  stat->nseparounds++;
2715 
2716  /* if size of lp relaxation increased also count this round separately */
2717  if( lp->nrows > oldnlprows )
2718  ++stat->nincseparounds;
2719  else if( lp->nrows < oldnlprows )
2720  stat->nincseparounds = 0;
2721  }
2722  }
2723 
2724  if( root && nsepastallrounds >= maxnsepastallrounds )
2725  {
2726  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
2727  "Truncate separation round because of stalling (%d stall rounds).\n", maxnsepastallrounds);
2728  }
2729 
2730  if( !*lperror )
2731  {
2732  /* update pseudo cost values for continuous variables, if it should be delayed */
2733  SCIP_CALL( updatePseudocost(set, stat, transprob, tree, lp, FALSE, set->branch_delaypscost) );
2734  }
2735 
2736  /* update lower bound w.r.t. the LP solution */
2737  if( *cutoff )
2738  {
2739  SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, SCIPsetInfinity(set));
2740  }
2741  else if( !(*lperror) )
2742  {
2743  assert(lp->flushed);
2744  assert(lp->solved);
2745 
2746  if( SCIPlpIsRelax(lp) )
2747  {
2748  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2749  }
2750 
2751  /* update node estimate */
2752  SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2753 
2754  /* issue LPSOLVED event */
2756  {
2758  SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
2759  SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
2760  }
2761 
2762  /* if the LP is a relaxation and we are not solving exactly, then we may analyze an infeasible or bound exceeding
2763  * LP (not necessary in the root node) and cut off the current node
2764  */
2765  if( !set->misc_exactsolve && !root && SCIPlpIsRelax(lp) && SCIPprobAllColsInLP(transprob, set, lp)
2767  {
2768  SCIP_CALL( SCIPconflictAnalyzeLP(conflict, conflictstore, blkmem, set, stat, transprob, origprob, tree, reopt,
2769  lp, branchcand, eventqueue, cliquetable, NULL) );
2770  *cutoff = TRUE;
2771  }
2772  }
2773  /* check for unboundedness */
2774  if( !(*lperror) )
2775  {
2776  *unbounded = (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
2777  /* 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 */
2778  }
2779 
2780  lp->installing = FALSE;
2781 
2782  SCIPsetDebugMsg(set, " -> final lower bound: %g (LP status: %d, LP obj: %g)\n",
2783  SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp),
2784  (*cutoff || *unbounded) ? SCIPsetInfinity(set) : *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
2785 
2786  return SCIP_OKAY;
2787 }
2788 
2789 /** updates the current lower bound with the pseudo objective value, cuts off node by bounding, and applies conflict
2790  * analysis if the pseudo objective lead to the cutoff
2791  */
2792 static
2794  BMS_BLKMEM* blkmem, /**< block memory buffers */
2795  SCIP_SET* set, /**< global SCIP settings */
2796  SCIP_STAT* stat, /**< dynamic problem statistics */
2797  SCIP_PROB* transprob, /**< tranformed problem after presolve */
2798  SCIP_PROB* origprob, /**< original problem */
2799  SCIP_PRIMAL* primal, /**< primal data */
2800  SCIP_TREE* tree, /**< branch and bound tree */
2801  SCIP_REOPT* reopt, /**< reoptimization data structure */
2802  SCIP_LP* lp, /**< LP data */
2803  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2804  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2805  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2806  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2807  SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
2808  )
2809 {
2810  assert(transprob != NULL);
2811  assert(origprob != NULL);
2812  assert(primal != NULL);
2813  assert(cutoff != NULL);
2814 
2815  if( !(*cutoff) )
2816  {
2817  SCIP_NODE* focusnode;
2818  SCIP_Real pseudoobjval;
2819 
2820  /* get current focus node */
2821  focusnode = SCIPtreeGetFocusNode(tree);
2822 
2823  /* update lower bound w.r.t. the pseudo solution */
2824  pseudoobjval = SCIPlpGetPseudoObjval(lp, set, transprob);
2825  SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, pseudoobjval);
2826  SCIPsetDebugMsg(set, " -> lower bound: %g [%g] (pseudoobj: %g [%g]), cutoff bound: %g [%g]\n",
2827  SCIPnodeGetLowerbound(focusnode), SCIPprobExternObjval(transprob, origprob, set, SCIPnodeGetLowerbound(focusnode)) + SCIPgetOrigObjoffset(set->scip),
2828  pseudoobjval, SCIPprobExternObjval(transprob, origprob, set, pseudoobjval) + SCIPgetOrigObjoffset(set->scip),
2829  primal->cutoffbound, SCIPprobExternObjval(transprob, origprob, set, primal->cutoffbound) + SCIPgetOrigObjoffset(set->scip));
2830 
2831  /* check for infeasible node by bounding */
2832  if( (set->misc_exactsolve && SCIPnodeGetLowerbound(focusnode) >= primal->cutoffbound)
2833  || (!set->misc_exactsolve && SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound)) )
2834  {
2835  SCIPsetDebugMsg(set, "node is cut off by bounding (lower=%g, upper=%g)\n",
2836  SCIPnodeGetLowerbound(focusnode), primal->cutoffbound);
2837  SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, SCIPsetInfinity(set));
2838  *cutoff = TRUE;
2839 
2840  /* call pseudo conflict analysis, if the node is cut off due to the pseudo objective value */
2841  if( pseudoobjval >= primal->cutoffbound && !SCIPsetIsInfinity(set, primal->cutoffbound) && !SCIPsetIsInfinity(set, -pseudoobjval) )
2842  {
2843  SCIP_CALL( SCIPconflictAnalyzePseudo(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cliquetable, NULL) );
2844  }
2845  }
2846  }
2847 
2848  return SCIP_OKAY;
2849 }
2850 
2851 /** marks all relaxators to be unsolved */
2852 static
2854  SCIP_SET* set, /**< global SCIP settings */
2855  SCIP_RELAXATION* relaxation /**< global relaxation data */
2856  )
2857 {
2858  int r;
2859 
2860  assert(set != NULL);
2861  assert(relaxation != NULL);
2862 
2863  SCIPrelaxationSetSolValid(relaxation, FALSE, FALSE);
2864 
2865  for( r = 0; r < set->nrelaxs; ++r )
2866  SCIPrelaxMarkUnsolved(set->relaxs[r]);
2867 }
2868 
2869 /** solves the current node's LP in a price-and-cut loop */
2870 static
2872  BMS_BLKMEM* blkmem, /**< block memory buffers */
2873  SCIP_SET* set, /**< global SCIP settings */
2874  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2875  SCIP_STAT* stat, /**< dynamic problem statistics */
2876  SCIP_MEM* mem, /**< block memory pools */
2877  SCIP_PROB* origprob, /**< original problem */
2878  SCIP_PROB* transprob, /**< transformed problem after presolve */
2879  SCIP_PRIMAL* primal, /**< primal data */
2880  SCIP_TREE* tree, /**< branch and bound tree */
2881  SCIP_REOPT* reopt, /**< reoptimization data structure */
2882  SCIP_LP* lp, /**< LP data */
2883  SCIP_RELAXATION* relaxation, /**< relaxators */
2884  SCIP_PRICESTORE* pricestore, /**< pricing storage */
2885  SCIP_SEPASTORE* sepastore, /**< separation storage */
2886  SCIP_CUTPOOL* cutpool, /**< global cut pool */
2887  SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
2888  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2889  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2890  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
2891  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
2892  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2893  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2894  SCIP_Bool initiallpsolved, /**< was the initial LP already solved? */
2895  SCIP_Bool fullseparation, /**< are we in the first prop-and-cut-and-price loop? */
2896  SCIP_Bool newinitconss, /**< do we have to add new initial constraints? */
2897  SCIP_Bool* propagateagain, /**< pointer to store whether we want to propagate again */
2898  SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called again */
2899  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
2900  SCIP_Bool* unbounded, /**< pointer to store TRUE, if an unbounded ray was found in the LP */
2901  SCIP_Bool* lperror, /**< pointer to store TRUE, if an unresolved error in LP solving occured */
2902  SCIP_Bool* pricingaborted /**< pointer to store TRUE, if the pricing was aborted and the lower bound
2903  * must not be used */
2904  )
2905 {
2906  SCIP_Longint nlpiterations;
2907  SCIP_Longint nlps;
2908 
2909  assert(stat != NULL);
2910  assert(tree != NULL);
2911  assert(SCIPtreeHasFocusNodeLP(tree));
2912  assert(cutoff != NULL);
2913  assert(unbounded != NULL);
2914  assert(lperror != NULL);
2915  assert(*cutoff == FALSE);
2916  assert(*unbounded == FALSE);
2917  assert(*lperror == FALSE);
2918 
2919  nlps = stat->nlps;
2920  nlpiterations = stat->nlpiterations;
2921 
2922  if( !initiallpsolved )
2923  {
2924  /* load and solve the initial LP of the node */
2925  SCIP_CALL( solveNodeInitialLP(blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
2926  pricestore, sepastore, cutpool, branchcand, eventfilter, eventqueue, cliquetable, newinitconss, cutoff, lperror) );
2927 
2928  assert(*cutoff || *lperror || (lp->flushed && lp->solved));
2929  SCIPsetDebugMsg(set, "price-and-cut-loop: initial LP status: %d, LP obj: %g\n",
2930  SCIPlpGetSolstat(lp),
2931  *cutoff ? SCIPsetInfinity(set) : *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
2932 
2933  /* update initial LP iteration counter */
2934  stat->ninitlps += stat->nlps - nlps;
2935  stat->ninitlpiterations += stat->nlpiterations - nlpiterations;
2936 
2937  /* In the root node, we try if the initial LP solution is feasible to avoid expensive setup of data structures in
2938  * separators; in case the root LP is aborted, e.g., by hitting the time limit, we do not check the LP solution
2939  * since the corresponding data structures have not been updated.
2940  */
2941  if( SCIPtreeGetCurrentDepth(tree) == 0 && !(*cutoff) && !(*lperror)
2943  && !SCIPsolveIsStopped(set, stat, FALSE) )
2944  {
2945  SCIP_Bool checklprows;
2946  SCIP_Bool stored;
2947  SCIP_SOL* sol;
2948  SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
2949 
2950  SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
2951 
2953  checklprows = FALSE;
2954  else
2955  checklprows = TRUE;
2956 
2957 #ifndef NDEBUG
2958  /* in the debug mode we want to explicitly check if the solution is feasible if it was stored */
2959  SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
2960  eventqueue, eventfilter, sol, FALSE, FALSE, TRUE, TRUE, checklprows, &stored) );
2961 
2962  if( stored )
2963  {
2964  SCIP_Bool feasible;
2965 
2966  SCIP_CALL( SCIPsolCheck(sol, set, messagehdlr, blkmem, stat, transprob, FALSE, FALSE, TRUE, TRUE,
2967  checklprows, &feasible) );
2968  assert(feasible);
2969  }
2970 
2971  SCIP_CALL( SCIPsolFree(&sol, blkmem, primal) );
2972 #else
2973  SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
2974  eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, checklprows, &stored) );
2975 #endif
2976  if( stored )
2977  {
2978  stat->nlpsolsfound++;
2979 
2980  if( primal->nbestsolsfound != oldnbestsolsfound )
2981  {
2982  stat->nlpbestsolsfound++;
2983  SCIPstoreSolutionGap(set->scip);
2984  }
2985 
2986  if( set->reopt_enable )
2987  {
2988  assert(reopt != NULL);
2989  SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, tree->focusnode, SCIP_EVENTTYPE_NODEFEASIBLE, lp,
2990  SCIPlpGetSolstat(lp), tree->root == tree->focusnode, TRUE, tree->focusnode->lowerbound,
2991  tree->effectiverootdepth) );
2992  }
2993  }
2994 
2996  *unbounded = TRUE;
2997  }
2998  }
2999  else
3000  {
3001  SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob,
3002  origprob, tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE,
3003  cutoff) );
3004  }
3005  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3006 
3007  /* check for infeasible node by bounding */
3008  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
3009 #ifdef SCIP_DEBUG
3010  if( *cutoff )
3011  {
3012  if( SCIPtreeGetCurrentDepth(tree) == 0 )
3013  {
3014  SCIPsetDebugMsg(set, "solution cuts off root node, stop solution process\n");
3015  }
3016  else
3017  {
3018  SCIPsetDebugMsg(set, "solution cuts off node\n");
3019  }
3020  }
3021 #endif
3022 
3023  if( !(*cutoff) && !(*lperror) )
3024  {
3025  SCIP_Longint oldninitconssadded;
3026  SCIP_Longint oldnboundchgs;
3027  SCIP_Longint olddomchgcount;
3028  int oldnpricedvars;
3029  int oldncutsapplied;
3030 
3031  oldnpricedvars = transprob->ncolvars;
3032  oldninitconssadded = stat->ninitconssadded;
3033  oldncutsapplied = SCIPsepastoreGetNCutsApplied(sepastore);
3034  oldnboundchgs = stat->nboundchgs;
3035  olddomchgcount = stat->domchgcount;
3036 
3037  /* solve the LP with price-and-cut*/
3038  SCIP_CALL( priceAndCutLoop(blkmem, set, messagehdlr, stat, mem, transprob, origprob, primal, tree, reopt, lp,
3039  pricestore, sepastore, cutpool, delayedcutpool, branchcand, conflict, conflictstore, eventfilter,
3040  eventqueue, cliquetable, fullseparation, propagateagain, cutoff, unbounded, lperror, pricingaborted) );
3041 
3042  /* check if the problem was changed and the relaxation needs to be resolved */
3043  if( (transprob->ncolvars != oldnpricedvars) || (stat->ninitconssadded != oldninitconssadded) ||
3044  (SCIPsepastoreGetNCutsApplied(sepastore) != oldncutsapplied) || (stat->nboundchgs != oldnboundchgs) ||
3045  (stat->domchgcount != olddomchgcount) )
3046  {
3047  *solverelaxagain = TRUE;
3048  markRelaxsUnsolved(set, relaxation);
3049  }
3050 
3051  }
3052  assert(*cutoff || *lperror || (lp->flushed && lp->solved));
3053 
3054  /* if there is no LP error, then *unbounded should be TRUE, iff the LP solution status is unboundedray */
3055  assert(*lperror || ((SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY) == *unbounded));
3056 
3057  /* 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,
3058  * 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
3059  * is not a feasible lower bound for the solutions in the current subtree.
3060  * In this case, the LP has to be solved to optimality by temporarily removing the cutoff bound.
3061  */
3062  if( (*pricingaborted) && (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_ITERLIMIT)
3063  && !(*cutoff) )
3064  {
3065  SCIP_Real tmpcutoff;
3066 
3067  /* temporarily disable cutoffbound, which also disables the objective limit */
3068  tmpcutoff = lp->cutoffbound;
3070 
3071  lp->solved = FALSE;
3072  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, FALSE, lperror) );
3073 
3074  /* reinstall old cutoff bound */
3075  lp->cutoffbound = tmpcutoff;
3076 
3077  SCIPsetDebugMsg(set, "re-optimized LP without cutoff bound: LP status: %d, LP obj: %g\n",
3078  SCIPlpGetSolstat(lp), *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
3079 
3080  /* lp solstat should not be objlimit, since the cutoff bound was removed temporarily */
3082  /* lp solstat should not be unboundedray, since the lp was dual feasible */
3084  /* there should be no primal ray, since the lp was dual feasible */
3085  assert(primal->primalray == NULL);
3087  {
3088  *cutoff = TRUE;
3089  }
3090  }
3091 
3092  assert(!(*pricingaborted) || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL /* cppcheck-suppress assertWithSideEffect */
3093  || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_NOTSOLVED || SCIPsolveIsStopped(set, stat, FALSE) || (*cutoff));
3094 
3095  assert(*cutoff || *lperror || (lp->flushed && lp->solved));
3096 
3097  /* update node's LP iteration counter */
3098  stat->nnodelps += stat->nlps - nlps;
3099  stat->nnodelpiterations += stat->nlpiterations - nlpiterations;
3100 
3101  /* update number of root node LPs and iterations if the root node was processed */
3102  if( SCIPnodeGetDepth(tree->focusnode) == 0 )
3103  {
3104  stat->nrootlps += stat->nlps - nlps;
3105  stat->nrootlpiterations += stat->nlpiterations - nlpiterations;
3106  }
3107 
3108  return SCIP_OKAY;
3109 }
3110 
3111 /** calls relaxators */
3112 static
3114  SCIP_SET* set, /**< global SCIP settings */
3115  SCIP_STAT* stat, /**< dynamic problem statistics */
3116  SCIP_TREE* tree, /**< branch and bound tree */
3117  SCIP_RELAXATION* relaxation, /**< relaxators */
3118  SCIP_PROB* transprob, /**< transformed problem */
3119  SCIP_PROB* origprob, /**< original problem */
3120  int depth, /**< depth of current node */
3121  SCIP_Bool beforelp, /**< should the relaxators with non-negative or negative priority be called? */
3122  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3123  SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3124  SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3125  SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called
3126  * again */
3127  SCIP_Bool* relaxcalled /**< pointer to store TRUE, if at least one relaxator was called (unmodified
3128  * otherwise) */
3129  )
3130 {
3131  SCIP_RESULT result;
3132  SCIP_Real lowerbound;
3133  int r;
3134 
3135  assert(set != NULL);
3136  assert(relaxation != NULL);
3137  assert(cutoff != NULL);
3138  assert(solvelpagain != NULL);
3139  assert(propagateagain != NULL);
3140  assert(solverelaxagain != NULL);
3141  assert(relaxcalled != NULL);
3142  assert(!(*cutoff));
3143 
3144  /* sort by priority */
3145  SCIPsetSortRelaxs(set);
3146 
3147  for( r = 0; r < set->nrelaxs && !(*cutoff); ++r )
3148  {
3149  if( beforelp != (SCIPrelaxGetPriority(set->relaxs[r]) >= 0) )
3150  continue;
3151 
3152  *relaxcalled = TRUE;
3153 
3154  lowerbound = -SCIPsetInfinity(set);
3155 
3156  SCIP_CALL( SCIPrelaxExec(set->relaxs[r], set, stat, depth, &lowerbound, &result) );
3157 
3158  switch( result )
3159  {
3160  case SCIP_CUTOFF:
3161  *cutoff = TRUE;
3162  SCIPsetDebugMsg(set, " -> relaxator <%s> detected cutoff\n", SCIPrelaxGetName(set->relaxs[r]));
3163  /* @todo does it make sense to proceed if the node is proven to be infeasible? */
3164  return SCIP_OKAY;
3165 
3166  case SCIP_CONSADDED:
3167  *solvelpagain = TRUE; /* the separation for new constraints should be called */
3168  *propagateagain = TRUE; /* the propagation for new constraints should be called */
3169  break;
3170 
3171  case SCIP_REDUCEDDOM:
3172  *solvelpagain = TRUE;
3173  *propagateagain = TRUE;
3174  break;
3175 
3176  case SCIP_SEPARATED:
3177  *solvelpagain = TRUE;
3178  break;
3179 
3180  case SCIP_SUSPENDED:
3181  *solverelaxagain = TRUE;
3182  break;
3183 
3184  case SCIP_SUCCESS:
3185  case SCIP_DIDNOTRUN:
3186  break;
3187 
3188  default:
3189  SCIPerrorMessage("invalid result code <%d> of relaxator <%s>\n", result, SCIPrelaxGetName(set->relaxs[r]));
3190  return SCIP_INVALIDRESULT;
3191  } /*lint !e788*/
3192 
3193  if( result != SCIP_CUTOFF && result != SCIP_DIDNOTRUN && result != SCIP_SUSPENDED )
3194  {
3195  SCIP_NODE* focusnode;
3196 
3197  focusnode = SCIPtreeGetFocusNode(tree);
3198  assert(focusnode != NULL);
3199  assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
3200 
3201  /* update lower bound w.r.t. the lower bound given by the relaxator */
3202  SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, lowerbound);
3203  SCIPsetDebugMsg(set, " -> new lower bound given by relaxator %s: %g\n",
3204  SCIPrelaxGetName(set->relaxs[r]), lowerbound);
3205  }
3206  }
3207 
3208  return SCIP_OKAY;
3209 }
3210 
3211 /** enforces constraints by branching, separation, or domain reduction */
3212 static
3214  BMS_BLKMEM* blkmem, /**< block memory buffers */
3215  SCIP_SET* set, /**< global SCIP settings */
3216  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3217  SCIP_STAT* stat, /**< dynamic problem statistics */
3218  SCIP_PROB* prob, /**< transformed problem after presolve */
3219  SCIP_PRIMAL* primal, /**< primal data */
3220  SCIP_TREE* tree, /**< branch and bound tree */
3221  SCIP_LP* lp, /**< LP data */
3222  SCIP_RELAXATION* relaxation, /**< global relaxation data */
3223  SCIP_SEPASTORE* sepastore, /**< separation storage */
3224  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3225  SCIP_Bool* branched, /**< pointer to store whether a branching was created */
3226  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3227  SCIP_Bool* infeasible, /**< pointer to store TRUE, if the LP/pseudo solution is infeasible */
3228  SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3229  SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3230  SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called again */
3231  SCIP_Bool forced /**< should enforcement of pseudo solution be forced? */
3232  )
3233 {
3234  SCIP_RESULT result;
3235  SCIP_SOL* relaxsol = NULL;
3236  SCIP_Real pseudoobjval;
3237  SCIP_Bool resolved;
3238  SCIP_Bool objinfeasible;
3239  SCIP_Bool enforcerelaxsol;
3240  int h;
3241 
3242  assert(set != NULL);
3243  assert(stat != NULL);
3244  assert(tree != NULL);
3245  assert(SCIPtreeGetFocusNode(tree) != NULL);
3246  assert(branched != NULL);
3247  assert(cutoff != NULL);
3248  assert(infeasible != NULL);
3249  assert(propagateagain != NULL);
3250  assert(solvelpagain != NULL);
3251  assert(solverelaxagain != NULL);
3252  assert(!(*cutoff));
3253  assert(!(*propagateagain));
3254  assert(!(*solvelpagain));
3255  assert(!(*solverelaxagain));
3256 
3257  *branched = FALSE;
3258  /**@todo avoid checking the same pseudosolution twice */
3259 
3260 
3261  /* enforce (best) relaxation solution if the LP has a worse objective value */
3262  enforcerelaxsol = SCIPrelaxationIsSolValid(relaxation) && SCIPrelaxationIsLpIncludedForSol(relaxation) && (!SCIPtreeHasFocusNodeLP(tree)
3263  || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, prob)));
3264 
3265  /* check if all constraint handlers implement the enforelax callback, otherwise enforce the LP solution */
3266  for( h = 0; h < set->nconshdlrs && enforcerelaxsol; ++h )
3267  {
3268  if( set->conshdlrs_enfo[h]->consenforelax == NULL && ((! set->conshdlrs_enfo[h]->needscons) ||
3269  (set->conshdlrs_enfo[h]->nconss > 0)) )
3270  {
3271  SCIP_VERBLEVEL verblevel;
3272 
3273  enforcerelaxsol = FALSE;
3274 
3275  verblevel = SCIP_VERBLEVEL_FULL;
3276 
3277  if( !stat->disableenforelaxmsg && set->disp_verblevel == SCIP_VERBLEVEL_HIGH )
3278  {
3279  verblevel = SCIP_VERBLEVEL_HIGH;
3280 
3281  /* remember that the disable relaxation enforcement message was posted and only post it again if the
3282  * verblevel is SCIP_VERBLEVEL_FULL
3283  */
3284  stat->disableenforelaxmsg = TRUE;
3285  }
3286  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, verblevel, "Disable enforcement of relaxation solutions"
3287  " since constraint handler %s does not implement enforelax-callback\n",
3288  SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3289  }
3290  }
3291 
3292  /* enforce constraints by branching, applying additional cutting planes (if LP is being processed),
3293  * introducing new constraints, or tighten the domains
3294  */
3295 #ifndef SCIP_NDEBUG
3296  if( enforcerelaxsol )
3297  {
3298  SCIPsetDebugMsg(set, "enforcing constraints on relaxation solution\n");
3299  }
3300  else
3301  {
3302  SCIPsetDebugMsg(set, "enforcing constraints on %s solution\n", SCIPtreeHasFocusNodeLP(tree) ? "LP" : "pseudo");
3303  }
3304 #endif
3305 
3306  /* check, if the solution is infeasible anyway due to it's objective value */
3307  if( SCIPtreeHasFocusNodeLP(tree) || enforcerelaxsol )
3308  objinfeasible = FALSE;
3309  else
3310  {
3311  pseudoobjval = SCIPlpGetPseudoObjval(lp, set, prob);
3312  objinfeasible = SCIPsetIsFeasLT(set, pseudoobjval, SCIPnodeGetLowerbound(SCIPtreeGetFocusNode(tree)));
3313  }
3314 
3315  /* during constraint enforcement, generated cuts should enter the LP in any case; otherwise, a constraint handler
3316  * would fail to enforce its constraints if it relies on the modification of the LP relaxation
3317  */
3318  SCIPsepastoreStartForceCuts(sepastore);
3319 
3320  /* enforce constraints until a handler resolved an infeasibility with cutting off the node, branching,
3321  * reducing a domain, or separating a cut
3322  * if a constraint handler introduced new constraints to enforce his constraints, the newly added constraints
3323  * have to be enforced themselves
3324  */
3325  resolved = FALSE;
3326 
3327  /* in case the relaxation solution should be enforced, we need to create the corresponding solution for the enforelax callbacks */
3328  if( enforcerelaxsol )
3329  {
3330  SCIP_CALL( SCIPsolCreateRelaxSol(&relaxsol, blkmem, set, stat, primal, tree, relaxation, NULL) );
3331  }
3332 
3333  for( h = 0; h < set->nconshdlrs && !resolved; ++h )
3334  {
3335  assert(SCIPsepastoreGetNCuts(sepastore) == 0); /* otherwise, the LP should have been resolved first */
3336 
3337  /* enforce LP, pseudo, or relaxation solution */
3338  if( enforcerelaxsol )
3339  {
3340  SCIPsetDebugMsg(set, "enforce relaxation solution with value %g\n", SCIPrelaxationGetSolObj(relaxation));
3341 
3342  SCIP_CALL( SCIPconshdlrEnforceRelaxSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, sepastore,
3343  relaxsol, *infeasible, &result) );
3344  }
3345  else if( SCIPtreeHasFocusNodeLP(tree) )
3346  {
3347 
3348  SCIPsetDebugMsg(set, "enforce LP solution with value %g\n", SCIPlpGetObjval(lp, set, prob));
3349 
3350  assert(lp->flushed);
3351  assert(lp->solved);
3353  SCIP_CALL( SCIPconshdlrEnforceLPSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, sepastore, *infeasible,
3354  &result) );
3355  }
3356  else
3357  {
3358  SCIP_CALL( SCIPconshdlrEnforcePseudoSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, branchcand, *infeasible,
3359  objinfeasible, forced, &result) );
3360  if( SCIPsepastoreGetNCuts(sepastore) != 0 )
3361  {
3362  SCIPerrorMessage("pseudo enforcing method of constraint handler <%s> separated cuts\n",
3363  SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3364  return SCIP_INVALIDRESULT;
3365  }
3366  }
3367  SCIPsetDebugMsg(set, "enforcing of <%s> returned result %d\n", SCIPconshdlrGetName(set->conshdlrs_enfo[h]), result);
3368 
3369  switch( result )
3370  {
3371  case SCIP_CUTOFF:
3372  assert(tree->nchildren == 0);
3373  *cutoff = TRUE;
3374  *infeasible = TRUE;
3375  resolved = TRUE;
3376  SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in enforcement\n",
3377  SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3378  break;
3379 
3380  case SCIP_CONSADDED:
3381  assert(tree->nchildren == 0);
3382  *infeasible = TRUE;
3383  *propagateagain = TRUE; /* the propagation for new constraints should be called */
3384  *solvelpagain = TRUE; /* the separation for new constraints should be called */
3385  *solverelaxagain = TRUE;
3386  markRelaxsUnsolved(set, relaxation);
3387  resolved = TRUE;
3388  break;
3389 
3390  case SCIP_REDUCEDDOM:
3391  assert(tree->nchildren == 0);
3392  *infeasible = TRUE;
3393  *propagateagain = TRUE;
3394  *solvelpagain = TRUE;
3395  *solverelaxagain = TRUE;
3396  markRelaxsUnsolved(set, relaxation);
3397  resolved = TRUE;
3398  break;
3399 
3400  case SCIP_SEPARATED:
3401  assert(tree->nchildren == 0);
3402  assert(SCIPsepastoreGetNCuts(sepastore) > 0);
3403  *infeasible = TRUE;
3404  *solvelpagain = TRUE;
3405  *solverelaxagain = TRUE;
3406  markRelaxsUnsolved(set, relaxation);
3407  resolved = TRUE;
3408  break;
3409 
3410  case SCIP_BRANCHED:
3411  assert(tree->nchildren >= 1);
3412  assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3413  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3414  *infeasible = TRUE;
3415  *branched = TRUE;
3416  resolved = TRUE;
3417 
3418  /* increase the number of internal nodes */
3419  stat->ninternalnodes++;
3420  stat->ntotalinternalnodes++;
3421  break;
3422 
3423  case SCIP_SOLVELP:
3424  assert(!SCIPtreeHasFocusNodeLP(tree));
3425  assert(tree->nchildren == 0);
3426  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3427  *infeasible = TRUE;
3428  *solvelpagain = TRUE;
3429  resolved = TRUE;
3430  SCIPtreeSetFocusNodeLP(tree, TRUE); /* the node's LP must be solved */
3431  break;
3432 
3433  case SCIP_INFEASIBLE:
3434  assert(tree->nchildren == 0);
3435  assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3436  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3437  *infeasible = TRUE;
3438  break;
3439 
3440  case SCIP_FEASIBLE:
3441  assert(tree->nchildren == 0);
3442  assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3443  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3444  break;
3445 
3446  case SCIP_DIDNOTRUN:
3447  assert(tree->nchildren == 0);
3448  assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3449  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3450  assert(objinfeasible);
3451  *infeasible = TRUE;
3452  break;
3453 
3454  default:
3455  SCIPerrorMessage("invalid result code <%d> from enforcing method of constraint handler <%s>\n",
3456  result, SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3457  return SCIP_INVALIDRESULT;
3458  } /*lint !e788*/
3459 
3460  /* the enforcement method may add a primal solution, after which the LP status could be set to
3461  * objective limit reached
3462  */
3464  {
3465  *cutoff = TRUE;
3466  *infeasible = TRUE;
3467  resolved = TRUE;
3468  SCIPsetDebugMsg(set, " -> LP exceeded objective limit\n");
3469 
3470  /* If we used the probing mode during branching, it might happen that we added a constraint or global bound
3471  * and returned SCIP_CONSADDED or SCIP_REDUCEDDOM, but when reoptimizing the LP after ending the probing mode,
3472  * this leads to hitting the objective limit. In this case, we do not need to propagate or solve the LP again.
3473  */
3474  *propagateagain = FALSE;
3475  *solvelpagain = FALSE;
3476  }
3477 
3478  assert(!(*branched) || (resolved && !(*cutoff) && *infeasible && !(*propagateagain) && !(*solvelpagain)));
3479  assert(!(*cutoff) || (resolved && !(*branched) && *infeasible && !(*propagateagain) && !(*solvelpagain)));
3480  assert(*infeasible || (!resolved && !(*branched) && !(*cutoff) && !(*propagateagain) && !(*solvelpagain)));
3481  assert(!(*propagateagain) || (resolved && !(*branched) && !(*cutoff) && *infeasible));
3482  assert(!(*solvelpagain) || (resolved && !(*branched) && !(*cutoff) && *infeasible));
3483  }
3484  assert(!objinfeasible || *infeasible);
3485  assert(resolved == (*branched || *cutoff || *propagateagain || *solvelpagain));
3486  assert(*cutoff || *solvelpagain || SCIPsepastoreGetNCuts(sepastore) == 0);
3487 
3488  /* in case the relaxation solution was enforced, free the created solution */
3489  if( enforcerelaxsol )
3490  {
3491  SCIP_CALL( SCIPsolFree(&relaxsol, blkmem, primal) );
3492  }
3493 
3494  /* deactivate the cut forcing of the constraint enforcement */
3495  SCIPsepastoreEndForceCuts(sepastore);
3496 
3497  SCIPsetDebugMsg(set, " -> enforcing result: branched=%u, cutoff=%u, infeasible=%u, propagateagain=%u, solvelpagain=%u, resolved=%u\n",
3498  *branched, *cutoff, *infeasible, *propagateagain, *solvelpagain, resolved);
3499 
3500  return SCIP_OKAY;
3501 }
3502 
3503 /** applies the cuts stored in the separation store, or clears the store if the node can be cut off */
3504 static
3506  BMS_BLKMEM* blkmem, /**< block memory buffers */
3507  SCIP_SET* set, /**< global SCIP settings */
3508  SCIP_STAT* stat, /**< dynamic problem statistics */
3509  SCIP_PROB* transprob, /**< transformed problem */
3510  SCIP_PROB* origprob, /**< original problem */
3511  SCIP_TREE* tree, /**< branch and bound tree */
3512  SCIP_REOPT* reopt, /**< reotimization data structure */
3513  SCIP_LP* lp, /**< LP data */
3514  SCIP_RELAXATION* relaxation, /**< relaxators */
3515  SCIP_SEPASTORE* sepastore, /**< separation storage */
3516  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3517  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3518  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
3519  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3520  SCIP_Bool root, /**< is this the initial root LP? */
3521  SCIP_EFFICIACYCHOICE efficiacychoice, /**< type of solution to base efficiacy computation on */
3522  SCIP_Bool* cutoff, /**< pointer to whether the node can be cut off */
3523  SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3524  SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3525  SCIP_Bool* solverelaxagain /**< pointer to store TRUE, if the node's relaxation has to be solved again */
3526  )
3527 {
3528  assert(stat != NULL);
3529  assert(cutoff != NULL);
3530  assert(propagateagain != NULL);
3531  assert(solvelpagain != NULL);
3532 
3533  if( *cutoff )
3534  {
3535  /* the found cuts are of no use, because the node is infeasible anyway (or we have an error in the LP) */
3536  SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
3537  }
3538  else if( SCIPsepastoreGetNCuts(sepastore) > 0 )
3539  {
3540  SCIP_Longint olddomchgcount;
3541  int oldncutsapplied;
3542 
3543  olddomchgcount = stat->domchgcount;
3544  oldncutsapplied = SCIPsepastoreGetNCutsApplied(sepastore);
3545  SCIP_CALL( SCIPsepastoreApplyCuts(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
3546  eventqueue, eventfilter, cliquetable, root, efficiacychoice, cutoff) );
3547  *propagateagain = *propagateagain || (stat->domchgcount != olddomchgcount);
3548  *solvelpagain = TRUE;
3549  if( (stat->domchgcount != olddomchgcount) || (SCIPsepastoreGetNCutsApplied(sepastore) != oldncutsapplied) )
3550  {
3551  *solverelaxagain = TRUE;
3552  markRelaxsUnsolved(set, relaxation);
3553  }
3554  }
3555 
3556  return SCIP_OKAY;
3557 }
3558 
3559 /** updates the cutoff, propagateagain, and solverelaxagain status of the current solving loop */
3560 static
3562  SCIP_SET* set, /**< global SCIP settings */
3563  SCIP_STAT* stat, /**< dynamic problem statistics */
3564  SCIP_TREE* tree, /**< branch and bound tree */
3565  int depth, /**< depth of current node */
3566  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3567  SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3568  SCIP_Bool* solverelaxagain /**< pointer to store TRUE, if at least one relaxator should be called again */
3569  )
3570 {
3571  SCIP_NODE* focusnode;
3572  int r;
3573 
3574  assert(set != NULL);
3575  assert(stat != NULL);
3576  assert(cutoff != NULL);
3577  assert(propagateagain != NULL);
3578  assert(solverelaxagain != NULL);
3579 
3580  /* check, if the path was cutoff */
3581  *cutoff = *cutoff || (tree->cutoffdepth <= depth);
3582 
3583  /* check if branching was already performed */
3584  if( tree->nchildren == 0 )
3585  {
3586  /* check, if the focus node should be repropagated */
3587  focusnode = SCIPtreeGetFocusNode(tree);
3588  *propagateagain = *propagateagain || SCIPnodeIsPropagatedAgain(focusnode);
3589 
3590  /* check, if one of the external relaxations should be solved again */
3591  for( r = 0; r < set->nrelaxs && !(*solverelaxagain); ++r )
3592  *solverelaxagain = *solverelaxagain || ( !SCIPrelaxIsSolved(set->relaxs[r], stat) );
3593  }
3594  else
3595  {
3596  /* if branching was performed, avoid another node loop iteration */
3597  *propagateagain = FALSE;
3598  *solverelaxagain = FALSE;
3599  }
3600 }
3601 
3602 /** propagate domains and solve relaxation and lp */
3603 static
3605  BMS_BLKMEM* blkmem, /**< block memory buffers */
3606  SCIP_SET* set, /**< global SCIP settings */
3607  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3608  SCIP_STAT* stat, /**< dynamic problem statistics */
3609  SCIP_MEM* mem, /**< block memory pools */
3610  SCIP_PROB* origprob, /**< original problem */
3611  SCIP_PROB* transprob, /**< transformed problem after presolve */
3612  SCIP_PRIMAL* primal, /**< primal data */
3613  SCIP_TREE* tree, /**< branch and bound tree */
3614  SCIP_REOPT* reopt, /**< reoptimization data structure */
3615  SCIP_LP* lp, /**< LP data */
3616  SCIP_RELAXATION* relaxation, /**< global relaxation data */
3617  SCIP_PRICESTORE* pricestore, /**< pricing storage */
3618  SCIP_SEPASTORE* sepastore, /**< separation storage */
3619  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3620  SCIP_CUTPOOL* cutpool, /**< global cut pool */
3621  SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
3622  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3623  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
3624  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3625  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3626  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3627  SCIP_NODE* focusnode, /**< focused node */
3628  int actdepth, /**< depth in the b&b tree */
3629  SCIP_Bool propagate, /**< should we propagate */
3630  SCIP_Bool solvelp, /**< should we solve the lp */
3631  SCIP_Bool solverelax, /**< should we solve the relaxation */
3632  SCIP_Bool forcedlpsolve, /**< is there a need for a solve lp */
3633  SCIP_Bool initiallpsolved, /**< was the initial LP already solved? */
3634  SCIP_Bool fullseparation, /**< are we in the first prop-and-cut-and-price loop? */
3635  SCIP_Longint* afterlpproplps, /**< pointer to store the last LP count for which AFTERLP propagation was performed */
3636  SCIP_HEURTIMING* heurtiming, /**< timing for running heuristics after propagation call */
3637  int* nlperrors, /**< pointer to store the number of lp errors */
3638  SCIP_Bool* fullpropagation, /**< pointer to store whether we want to do a fullpropagation next time */
3639  SCIP_Bool* propagateagain, /**< pointer to store whether we want to propagate again */
3640  SCIP_Bool* lpsolved, /**< pointer to store whether the lp was solved */
3641  SCIP_Bool* relaxcalled, /**< pointer to store whether a relaxator was called; initialized with last loop's result */
3642  SCIP_Bool* solvelpagain, /**< pointer to store whether we want to solve the lp again */
3643  SCIP_Bool* solverelaxagain, /**< pointer to store whether we want to solve the relaxation again */
3644  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
3645  SCIP_Bool* postpone, /**< pointer to store whether the node should be postponed */
3646  SCIP_Bool* unbounded, /**< pointer to store whether the focus node is unbounded */
3647  SCIP_Bool* stopped, /**< pointer to store whether solving was interrupted */
3648  SCIP_Bool* lperror, /**< pointer to store TRUE, if an unresolved error in LP solving occured */
3649  SCIP_Bool* pricingaborted, /**< pointer to store TRUE, if the pricing was aborted and the lower bound must not be used */
3650  SCIP_Bool* forcedenforcement /**< pointer to store whether the enforcement of pseudo solution should be forced */
3651  )
3652 {
3653  SCIP_Bool newinitconss;
3654 
3655  assert(set != NULL);
3656  assert(stat != NULL);
3657  assert(origprob != NULL);
3658  assert(transprob != NULL);
3659  assert(tree != NULL);
3660  assert(lp != NULL);
3661  assert(primal != NULL);
3662  assert(pricestore != NULL);
3663  assert(sepastore != NULL);
3664  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3665  assert(branchcand != NULL);
3666  assert(cutpool != NULL);
3667  assert(delayedcutpool != NULL);
3668  assert(conflict != NULL);
3669  assert(SCIPconflictGetNConflicts(conflict) == 0);
3670  assert(eventfilter != NULL);
3671  assert(eventqueue != NULL);
3672  assert(focusnode != NULL);
3673  assert(heurtiming != NULL);
3674  assert(nlperrors != NULL);
3675  assert(fullpropagation != NULL);
3676  assert(propagateagain != NULL);
3677  assert(afterlpproplps != NULL);
3678  assert(lpsolved != NULL);
3679  assert(solvelpagain != NULL);
3680  assert(solverelaxagain != NULL);
3681  assert(cutoff != NULL);
3682  assert(postpone != NULL);
3683  assert(unbounded != NULL);
3684  assert(lperror != NULL);
3685  assert(pricingaborted != NULL);
3686  assert(forcedenforcement != NULL);
3687 
3688  newinitconss = FALSE;
3689 
3690  if( !(*cutoff) && !(*postpone) )
3691  {
3692  SCIP_Longint oldninitconssadded;
3693  SCIP_Longint oldnboundchgs;
3694  SCIP_Bool lpwasflushed;
3695 
3696  lpwasflushed = lp->flushed;
3697  oldnboundchgs = stat->nboundchgs;
3698  oldninitconssadded = stat->ninitconssadded;
3699 
3700  /* call after LP propagators */
3701  if( ((*afterlpproplps) < stat->nnodelps && (*lpsolved)) || (*relaxcalled) )
3702  {
3703  SCIP_CALL( propagateDomains(blkmem, set, stat, primal, tree, SCIPtreeGetCurrentDepth(tree), 0, *fullpropagation,
3704  SCIP_PROPTIMING_AFTERLPLOOP, cutoff, postpone) );
3705  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3706 
3707  /* check, if the path was cutoff */
3708  *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3709  *afterlpproplps = stat->nnodelps;
3710  propagate = propagate || (stat->nboundchgs > oldnboundchgs);
3711  }
3712 
3713  /* call before LP propagators */
3714  if( propagate && !(*cutoff) )
3715  {
3716  SCIP_CALL( propagateDomains(blkmem, set, stat, primal, tree, SCIPtreeGetCurrentDepth(tree), 0, *fullpropagation,
3717  SCIP_PROPTIMING_BEFORELP, cutoff, postpone) );
3718  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3719  }
3720 
3721  newinitconss = (stat->ninitconssadded != oldninitconssadded);
3722  *fullpropagation = FALSE;
3723 
3724  /* check, if the path was cutoff */
3725  *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3726 
3727  /* if the LP was flushed and is now no longer flushed, a bound change occurred, and the LP has to be resolved;
3728  * we also have to solve the LP if new intial constraints were added which need to be added to the LP
3729  */
3730  solvelp = solvelp || (lpwasflushed && (!lp->flushed || newinitconss));
3731  solverelax = solverelax || newinitconss;
3732 
3733  /* the number of bound changes was increased by the propagation call, thus the relaxation should be solved again */
3734  if( stat->nboundchgs > oldnboundchgs )
3735  {
3736  /* propagation might have changed the best bound of loose variables, thereby changing the loose objective value
3737  * which is added to the LP value; because of the loose status, the LP might not be reoptimized, but the lower
3738  * bound of the node needs to be updated
3739  */
3740  if( !solvelp && lp->flushed && lp->solved && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
3741  {
3742  SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
3743  SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
3744  SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
3745 
3746  if( SCIPtreeHasFocusNodeLP(tree) )
3747  {
3748  /* update node estimate */
3749  SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
3750 
3751  if( actdepth == 0 && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
3752  SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
3753  }
3754  }
3755 
3756  solverelax = TRUE;
3757  markRelaxsUnsolved(set, relaxation);
3758  }
3759 
3760  /* update lower bound with the pseudo objective value, and cut off node by bounding */
3761  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
3762  conflict, cliquetable, cutoff) );
3763  }
3764  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3765 
3766  if( *postpone )
3767  return SCIP_OKAY;
3768 
3769  /* call primal heuristics that are applicable after propagation loop before lp solve;
3770  * the first time we go here, we call the before node heuristics instead
3771  */
3772  if( !(*cutoff) && !SCIPtreeProbing(tree) )
3773  {
3774  /* if the heuristics find a new incumbent solution, propagate again */
3775  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, *heurtiming,
3776  FALSE, propagateagain, unbounded) );
3777  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3778 
3779  *heurtiming = SCIP_HEURTIMING_AFTERPROPLOOP;
3780 
3781  /* check if primal heuristics found a solution and we therefore reached a solution limit */
3782  if( SCIPsolveIsStopped(set, stat, FALSE) )
3783  {
3784  /* cppcheck-suppress unassignedVariable */
3785  SCIP_NODE* node;
3786 
3787  /* we reached a solution limit and do not want to continue the processing of the current node, but in order to
3788  * allow restarting the optimization process later, we need to create a "branching" with only one child node that
3789  * is a copy of the focusnode
3790  */
3792  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, 1.0, focusnode->estimate) );
3793  assert(tree->nchildren >= 1);
3794  *stopped = TRUE;
3795  return SCIP_OKAY;
3796  }
3797 
3798  /* if diving produced an LP error, switch back to non-LP node */
3799  if( lp->resolvelperror )
3800  {
3802  lp->resolvelperror = FALSE;
3803  }
3804 
3805  if( *propagateagain )
3806  {
3807  *solvelpagain = solvelp;
3808  *solverelaxagain = solverelax;
3809 
3810  return SCIP_OKAY;
3811  }
3812  }
3813 
3814  /* solve external relaxations with non-negative priority */
3815  *relaxcalled = FALSE;
3816  if( solverelax && !(*cutoff) )
3817  {
3818 
3819  /* clear the storage of external branching candidates */
3820  SCIPbranchcandClearExternCands(branchcand);
3821 
3822  SCIP_CALL( solveNodeRelax(set, stat, tree, relaxation, transprob, origprob, actdepth, TRUE,
3823  cutoff, propagateagain, solvelpagain, solverelaxagain, relaxcalled) );
3824  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3825 
3826  /* check, if the path was cutoff */
3827  *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3828 
3829  /* apply found cuts */
3830  SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
3831  eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_RELAX, cutoff, propagateagain,
3832  solvelpagain, solverelaxagain) );
3833 
3834  /* update lower bound with the pseudo objective value, and cut off node by bounding */
3835  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
3836  }
3837  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3838 
3839  /* check, if we want to solve the LP at this node */
3840  if( solvelp && !(*cutoff) && SCIPtreeHasFocusNodeLP(tree) )
3841  {
3842  *lperror = FALSE;
3843  *unbounded = FALSE;
3844 
3845  /* solve the node's LP */
3846  SCIP_CALL( solveNodeLP(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp, relaxation, pricestore,
3847  sepastore, cutpool, delayedcutpool, branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable,
3848  initiallpsolved, fullseparation, newinitconss, propagateagain, solverelaxagain, cutoff, unbounded, lperror, pricingaborted) );
3849 
3850  *lpsolved = TRUE;
3851  *solvelpagain = FALSE;
3852  SCIPsetDebugMsg(set, " -> LP status: %d, LP obj: %g, iter: %" SCIP_LONGINT_FORMAT ", count: %" SCIP_LONGINT_FORMAT "\n",
3853  SCIPlpGetSolstat(lp),
3854  *cutoff ? SCIPsetInfinity(set) : (*lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob)),
3855  stat->nlpiterations, stat->lpcount);
3856 
3857  /* check, if the path was cutoff */
3858  *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3859 
3860  /* if an error occured during LP solving, switch to pseudo solution */
3861  if( *lperror )
3862  {
3863  if( forcedlpsolve )
3864  {
3865  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
3866  stat->nnodes, stat->nlps);
3867  return SCIP_LPERROR;
3868  }
3870  ++(*nlperrors);
3871  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, actdepth == 0 ? SCIP_VERBLEVEL_HIGH : SCIP_VERBLEVEL_FULL,
3872  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
3873  stat->nnodes, stat->nlps, *nlperrors);
3874  }
3875 
3877  {
3879  *forcedenforcement = TRUE;
3880 
3881  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, actdepth == 0 ? SCIP_VERBLEVEL_HIGH : SCIP_VERBLEVEL_FULL,
3882  "(node %" SCIP_LONGINT_FORMAT ") LP solver hit %s limit in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead\n",
3883  stat->nnodes, SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_TIMELIMIT ? "time" : "iteration", stat->nlps);
3884  }
3885 
3887  {
3888  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
3889  "(node %" SCIP_LONGINT_FORMAT ") LP relaxation is unbounded (LP %" SCIP_LONGINT_FORMAT ")\n", stat->nnodes, stat->nlps);
3890  }
3891 
3892  /* if we solve exactly, the LP claims to be infeasible but the infeasibility could not be proved,
3893  * we have to forget about the LP and use the pseudo solution instead
3894  */
3895  if( !(*cutoff) && !(*lperror) && (set->misc_exactsolve || *pricingaborted) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_INFEASIBLE
3896  && SCIPnodeGetLowerbound(focusnode) < primal->cutoffbound )
3897  {
3898  if( SCIPbranchcandGetNPseudoCands(branchcand) == 0 && transprob->ncontvars > 0 )
3899  {
3900  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",
3901  stat->nnodes, stat->nlps, set->misc_exactsolve, *pricingaborted, transprob->ncontvars);
3902  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") -> have to call PerPlex() (feature not yet implemented)\n", stat->nnodes);
3903  /**@todo call PerPlex */
3904  return SCIP_LPERROR;
3905  }
3906  else
3907  {
3909  *forcedenforcement = TRUE;
3910 
3911  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
3912  "(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",
3913  stat->nnodes, stat->nlps, set->misc_exactsolve, *pricingaborted, SCIPbranchcandGetNPseudoCands(branchcand));
3914  }
3915  }
3916 
3917  /* update lower bound with the pseudo objective value, and cut off node by bounding */
3918  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict,
3919  cliquetable, cutoff) );
3920  }
3921  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3922  assert(*cutoff || !SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3923 
3924  /* reset solverelaxagain if no relaxations were solved up to this point (the LP-changes are already included in
3925  * relaxators called after the LP)
3926  */
3927  *solverelaxagain = *solverelaxagain && *relaxcalled;
3928 
3929  /* solve external relaxations with negative priority */
3930  if( solverelax && !(*cutoff) )
3931  {
3932  SCIP_CALL( solveNodeRelax(set, stat, tree, relaxation, transprob, origprob, actdepth, FALSE, cutoff,
3933  propagateagain, solvelpagain, solverelaxagain, relaxcalled) );
3934  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3935 
3936  /* check, if the path was cutoff */
3937  *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3938 
3939  /* apply found cuts */
3940  SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
3941  eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_RELAX, cutoff, propagateagain,
3942  solvelpagain, solverelaxagain) );
3943 
3944  /* update lower bound with the pseudo objective value, and cut off node by bounding */
3945  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict,
3946  cliquetable, cutoff) );
3947  }
3948  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3949 
3950  return SCIP_OKAY;
3951 }
3952 
3953 /** check if a restart can be performed */
3954 #ifndef NDEBUG
3955 static
3957  SCIP_SET* set, /**< global SCIP settings */
3958  SCIP_STAT* stat /**< dynamic problem statistics */
3959  )
3960 {
3961  assert(set != NULL);
3962  assert(stat != NULL);
3963 
3964  return (set->nactivepricers == 0 && !set->reopt_enable
3965  && (set->presol_maxrestarts == -1 || stat->nruns <= set->presol_maxrestarts)
3966  && (set->limit_restarts == -1 || stat->nruns <= set->limit_restarts));
3967 }
3968 #else
3969 #define restartAllowed(set,stat) ((set)->nactivepricers == 0 && !set->reopt_enable && ((set)->presol_maxrestarts == -1 || (stat)->nruns <= (set)->presol_maxrestarts) \
3970  && (set->limit_restarts == -1 || stat->nruns <= set->limit_restarts))
3971 #endif
3972 
3973 /** solves the focus node */
3974 static
3976  BMS_BLKMEM* blkmem, /**< block memory buffers */
3977  SCIP_SET* set, /**< global SCIP settings */
3978  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3979  SCIP_STAT* stat, /**< dynamic problem statistics */
3980  SCIP_MEM* mem, /**< block memory pools */
3981  SCIP_PROB* origprob, /**< original problem */
3982  SCIP_PROB* transprob, /**< transformed problem after presolve */
3983  SCIP_PRIMAL* primal, /**< primal data */
3984  SCIP_TREE* tree, /**< branch and bound tree */
3985  SCIP_REOPT* reopt, /**< reoptimization data structure */
3986  SCIP_LP* lp, /**< LP data */
3987  SCIP_RELAXATION* relaxation, /**< global relaxation data */
3988  SCIP_PRICESTORE* pricestore, /**< pricing storage */
3989  SCIP_SEPASTORE* sepastore, /**< separation storage */
3990  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3991  SCIP_CUTPOOL* cutpool, /**< global cut pool */
3992  SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
3993  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3994  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
3995  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3996  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3997  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3998  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
3999  SCIP_Bool* postpone, /**< pointer to store whether the node should be postponed */
4000  SCIP_Bool* unbounded, /**< pointer to store whether the focus node is unbounded */
4001  SCIP_Bool* infeasible, /**< pointer to store whether the focus node's solution is infeasible */
4002  SCIP_Bool* restart, /**< should solving process be started again with presolving? */
4003  SCIP_Bool* afternodeheur, /**< pointer to store whether AFTERNODE heuristics were already called */
4004  SCIP_Bool* stopped /**< pointer to store whether solving was interrupted */
4005  )
4006 {
4007  SCIP_NODE* focusnode;
4008  SCIP_Longint lastdomchgcount;
4009  SCIP_Longint afterlpproplps;
4010  SCIP_Real restartfac;
4011  SCIP_Longint lastlpcount;
4012  SCIP_HEURTIMING heurtiming;
4013  int actdepth;
4014  int nlperrors;
4015  int nloops;
4016  SCIP_Bool foundsol = FALSE;
4017  SCIP_Bool focusnodehaslp;
4018  SCIP_Bool lpsolved;
4019  SCIP_Bool initiallpsolved;
4020  SCIP_Bool fullseparation;
4021  SCIP_Bool solverelaxagain;
4022  SCIP_Bool solvelpagain;
4023  SCIP_Bool propagateagain;
4024  SCIP_Bool fullpropagation;
4025  SCIP_Bool branched;
4026  SCIP_Bool forcedlpsolve;
4027  SCIP_Bool wasforcedlpsolve;
4028  SCIP_Bool pricingaborted;
4029 
4030  assert(set != NULL);
4031  assert(stat != NULL);
4032  assert(origprob != NULL);
4033  assert(transprob != NULL);
4034  assert(tree != NULL);
4035  assert(primal != NULL);
4036  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4037  assert(SCIPconflictGetNConflicts(conflict) == 0);
4038  assert(cutoff != NULL);
4039  assert(postpone != NULL);
4040  assert(unbounded != NULL);
4041  assert(infeasible != NULL);
4042  assert(restart != NULL);
4043  assert(afternodeheur != NULL);
4044 
4045  *cutoff = FALSE;
4046  *postpone = FALSE;
4047  *unbounded = FALSE;
4048  *infeasible = FALSE;
4049  *restart = FALSE;
4050  *afternodeheur = FALSE;
4051  *stopped = FALSE;
4052  pricingaborted = FALSE;
4053 
4054  focusnode = SCIPtreeGetFocusNode(tree);
4055  assert(focusnode != NULL);
4056  assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
4057  actdepth = SCIPnodeGetDepth(focusnode);
4058 
4059  /* invalidate relaxation solution */
4060  SCIPrelaxationSetSolValid(relaxation, FALSE, FALSE);
4061 
4062  /* clear the storage of external branching candidates */
4063  SCIPbranchcandClearExternCands(branchcand);
4064 
4065  SCIPsetDebugMsg(set, "Processing node %" SCIP_LONGINT_FORMAT " in depth %d, %d siblings\n",
4066  stat->nnodes, actdepth, tree->nsiblings);
4067  SCIPsetDebugMsg(set, "current pseudosolution: obj=%g\n", SCIPlpGetPseudoObjval(lp, set, transprob));
4068  /*debug(SCIPprobPrintPseudoSol(transprob, set));*/
4069 
4070  /* check, if we want to solve the LP at the selected node:
4071  * - solve the LP, if the lp solve depth and frequency demand solving
4072  * - solve the root LP, if the LP solve frequency is set to 0
4073  * - solve the root LP, if there are continuous variables present
4074  * - don't solve the node if its cut off by the pseudo objective value anyway
4075  */
4076  focusnodehaslp = (set->lp_solvedepth == -1 || actdepth <= set->lp_solvedepth);
4077  focusnodehaslp = focusnodehaslp && (set->lp_solvefreq >= 1 && actdepth % set->lp_solvefreq == 0);
4078  focusnodehaslp = focusnodehaslp || (actdepth == 0 && set->lp_solvefreq == 0);
4079  focusnodehaslp = focusnodehaslp && SCIPsetIsLT(set, SCIPlpGetPseudoObjval(lp, set, transprob), primal->cutoffbound);
4080  focusnodehaslp = set->reopt_enable ? focusnodehaslp && SCIPreoptGetSolveLP(reopt, set, focusnode) : focusnodehaslp;
4081  SCIPtreeSetFocusNodeLP(tree, focusnodehaslp);
4082 
4083  /* external node solving loop:
4084  * - propagate domains
4085  * - solve SCIP_LP
4086  * - enforce constraints
4087  * if a constraint handler adds constraints to enforce its own constraints, both, propagation and LP solving
4088  * is applied again (if applicable on current node); however, if the new constraints don't have the enforce flag set,
4089  * it is possible, that the current infeasible solution is not cut off; in this case, we have to declare the solution
4090  * infeasible and perform a branching
4091  */
4092  lastdomchgcount = stat->domchgcount;
4093  lastlpcount = stat->lpcount;
4094  initiallpsolved = FALSE;
4095  fullseparation = TRUE;
4096  heurtiming = SCIP_HEURTIMING_BEFORENODE;
4097  nlperrors = 0;
4098  stat->npricerounds = 0;
4099  stat->nseparounds = 0;
4100  stat->nincseparounds = 0;
4101  solverelaxagain = TRUE;
4102  solvelpagain = TRUE;
4103  propagateagain = TRUE;
4104  fullpropagation = TRUE;
4105  forcedlpsolve = FALSE;
4106  nloops = 0;
4107 
4108  while( !(*cutoff) && !(*postpone) && (solverelaxagain || solvelpagain || propagateagain) && nlperrors < MAXNLPERRORS && !(*restart) )
4109  {
4110  SCIP_Bool lperror;
4111  SCIP_Bool solverelax;
4112  SCIP_Bool solvelp;
4113  SCIP_Bool propagate;
4114  SCIP_Bool forcedenforcement;
4115  SCIP_Bool relaxcalled;
4116 
4117  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4118 
4119  *unbounded = FALSE;
4120  *infeasible = FALSE;
4121  foundsol = FALSE;
4122 
4123  nloops++;
4124  lperror = FALSE;
4125  lpsolved = FALSE;
4126  relaxcalled = FALSE;
4127  forcedenforcement = FALSE;
4128  afterlpproplps = -1L;
4129 
4130  while( !lperror && !(*cutoff) && (propagateagain || solvelpagain || solverelaxagain
4131  || (afterlpproplps < stat->nnodelps && lpsolved) || relaxcalled) )
4132  {
4133  solverelax = solverelaxagain;
4134  solverelaxagain = FALSE;
4135  solvelp = solvelpagain;
4136  solvelpagain = FALSE;
4137  propagate = propagateagain;
4138  propagateagain = FALSE;
4139 
4140  /* update lower bound with the pseudo objective value, and cut off node by bounding */
4141  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
4142  conflict, cliquetable, cutoff) );
4143 
4144  /* propagate domains before lp solving and solve relaxation and lp */
4145  SCIPsetDebugMsg(set, " -> node solving loop: call propagators that are applicable before%s LP is solved\n",
4146  lpsolved ? " and after" : "");
4147  SCIP_CALL( propAndSolve(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp,
4148  relaxation, pricestore, sepastore, branchcand, cutpool, delayedcutpool, conflict, conflictstore, eventfilter,
4149  eventqueue, cliquetable, focusnode, actdepth, propagate, solvelp, solverelax, forcedlpsolve, initiallpsolved,
4150  fullseparation, &afterlpproplps, &heurtiming, &nlperrors, &fullpropagation, &propagateagain, &lpsolved, &relaxcalled,
4151  &solvelpagain, &solverelaxagain, cutoff, postpone, unbounded, stopped, &lperror, &pricingaborted, &forcedenforcement) );
4152  initiallpsolved |= lpsolved;
4153 
4154  /* time or solution limit was hit and we already created a dummy child node to terminate fast */
4155  if( *stopped )
4156  return SCIP_OKAY;
4157 
4158  }
4159  fullseparation = FALSE;
4160 
4161  /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4162  updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4163 
4164  /* call primal heuristics that should be applied after the LP relaxation of the node was solved;
4165  * if this is the first loop of the root node, call also AFTERNODE heuristics already here, since they might help
4166  * to improve the primal bound, thereby producing additional reduced cost strengthenings and strong branching
4167  * bound fixings which also might lead to a restart
4168  */
4169  if( !(*postpone) && (!(*cutoff) || SCIPtreeGetNNodes(tree) > 0) )
4170  {
4171  if( actdepth == 0 && !(*afternodeheur) )
4172  {
4173  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL,
4174  SCIP_HEURTIMING_AFTERLPLOOP | SCIP_HEURTIMING_AFTERNODE, *cutoff, &foundsol, unbounded) );
4175  *afternodeheur = TRUE; /* the AFTERNODE heuristics should not be called again after the node */
4176  }
4177  else if( lpsolved || SCIPrelaxationIsSolValid(relaxation) )
4178  {
4179  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, SCIP_HEURTIMING_AFTERLPLOOP,
4180  *cutoff, &foundsol, unbounded) );
4181  }
4182  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4183 
4184  /* heuristics might have found a solution or set the cutoff bound such that the current node is cut off */
4185  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4186  }
4187 
4188  /* check if heuristics leave us with an invalid LP */
4189  if( lp->resolvelperror )
4190  {
4191  if( forcedlpsolve )
4192  {
4193  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
4194  stat->nnodes, stat->nlps);
4195  return SCIP_LPERROR;
4196  }
4198  lp->resolvelperror = FALSE;
4199  nlperrors++;
4200  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4201  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
4202  stat->nnodes, stat->nlps, nlperrors);
4203  }
4204 
4205  if( pricingaborted && !(*cutoff) && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL )
4206  {
4207 
4209 
4210  /* if we just ran into the time limit this is not really a numerical trouble;
4211  * however, if this is not the case, we print messages about numerical troubles in the current LP
4212  */
4213  if( !SCIPsolveIsStopped(set, stat, FALSE) )
4214  {
4215  if( forcedlpsolve )
4216  {
4217  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
4218  stat->nnodes, stat->nlps);
4219  return SCIP_LPERROR;
4220  }
4221  nlperrors++;
4222  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4223  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
4224  stat->nnodes, stat->nlps, nlperrors);
4225  }
4226  }
4227 
4228  /* if an improved solution was found, propagate and solve the relaxations again */
4229  if( foundsol )
4230  {
4231  propagateagain = TRUE;
4232  solvelpagain = TRUE;
4233  solverelaxagain = TRUE;
4234  markRelaxsUnsolved(set, relaxation);
4235  }
4236 
4237  /* enforce constraints */
4238  branched = FALSE;
4239  if( !(*postpone) && !(*cutoff) && !solverelaxagain && !solvelpagain && !propagateagain )
4240  {
4241  /* if the solution changed since the last enforcement, we have to completely reenforce it; otherwise, we
4242  * only have to enforce the additional constraints added in the last enforcement, but keep the infeasible
4243  * flag TRUE in order to not declare the infeasible solution feasible due to disregarding the already
4244  * enforced constraints
4245  */
4246  if( lastdomchgcount != stat->domchgcount || lastlpcount != stat->lpcount )
4247  {
4248  lastdomchgcount = stat->domchgcount;
4249  lastlpcount = stat->lpcount;
4250  *infeasible = FALSE;
4251  }
4252 
4253  /* call constraint enforcement */
4254  SCIP_CALL( enforceConstraints(blkmem, set, messagehdlr, stat, transprob, primal, tree, lp, relaxation, sepastore,
4255  branchcand, &branched, cutoff, infeasible, &propagateagain, &solvelpagain, &solverelaxagain,
4256  forcedenforcement) );
4257  assert(branched == (tree->nchildren > 0));
4258  assert(!branched || (!(*cutoff) && *infeasible && !propagateagain && !solvelpagain));
4259  assert(!(*cutoff) || (!branched && *infeasible && !propagateagain && !solvelpagain));
4260  assert(*infeasible || (!branched && !(*cutoff) && !propagateagain && !solvelpagain));
4261  assert(!propagateagain || (!branched && !(*cutoff) && *infeasible));
4262  assert(!solvelpagain || (!branched && !(*cutoff) && *infeasible));
4263 
4264  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4265 
4266  /* apply found cuts */
4267  SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4268  eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_LP, cutoff, &propagateagain,
4269  &solvelpagain, &solverelaxagain) );
4270 
4271  /* update lower bound with the pseudo objective value, and cut off node by bounding */
4272  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4273 
4274  /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4275  updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4276  }
4277  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4278 
4279  /* The enforcement detected no infeasibility, so, no branching was performed,
4280  * but the pricing was aborted and the current feasible solution does not have to be the
4281  * best solution in the current subtree --> we have to do a pseudo branching,
4282  * so we set infeasible TRUE and add the current solution to the solution pool
4283  */
4284  if( pricingaborted && !(*infeasible) && !(*cutoff) && !(*postpone) )
4285  {
4286  SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
4287  SCIP_SOL* sol;
4288  SCIP_Bool stored;
4289 
4290  /* in case the relaxation was enforced add this solution, otherwise decide between LP and pseudosol */
4291  if( SCIPrelaxationIsSolValid(relaxation) && SCIPrelaxationIsLpIncludedForSol(relaxation) && (!SCIPtreeHasFocusNodeLP(tree)
4292  || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
4293  {
4294  SCIP_SOL* relaxsol;
4295 
4296  SCIP_CALL( SCIPsolCreateRelaxSol(&relaxsol, blkmem, set, stat, primal, tree, relaxation, NULL) );
4297 
4298  SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4299  eventqueue, eventfilter, relaxsol, FALSE, FALSE, TRUE, TRUE, TRUE,
4300  &stored) );
4301 
4302  SCIP_CALL( SCIPsolFree(&relaxsol, blkmem, primal) );
4303 
4304  if( stored )
4305  {
4306  stat->nrelaxsolsfound++;
4307 
4308  if( primal->nbestsolsfound != oldnbestsolsfound )
4309  {
4310  stat->nrelaxbestsolsfound++;
4311  SCIPstoreSolutionGap(set->scip);
4312  }
4313  }
4314  }
4315  else
4316  {
4317  SCIP_CALL( SCIPsolCreateCurrentSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4318  SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4319  eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
4320 
4321  if( stored )
4322  {
4323  stat->nlpsolsfound++;
4324 
4325  if( primal->nbestsolsfound != oldnbestsolsfound )
4326  {
4327  stat->nlpbestsolsfound++;
4328  SCIPstoreSolutionGap(set->scip);
4329  }
4330  }
4331  }
4332 
4333  *infeasible = TRUE;
4334  }
4335 
4336  /* if the node is infeasible, but no constraint handler could resolve the infeasibility
4337  * -> branch on LP, external candidates, or the pseudo solution
4338  * -> e.g. select non-fixed binary or integer variable x with value x', create three
4339  * sons: x <= x'-1, x = x', and x >= x'+1.
4340  * In the left and right branch, the current solution is cut off. In the middle
4341  * branch, the constraints can hopefully reduce domains of other variables to cut
4342  * off the current solution.
4343  * In LP branching, we cannot allow adding constraints, because this does not necessary change the LP and can
4344  * therefore lead to an infinite loop.
4345  */
4346  wasforcedlpsolve = forcedlpsolve;
4347  forcedlpsolve = FALSE;
4348  if( (*infeasible) && !(*cutoff) && !(*postpone)
4349  && (!(*unbounded) || SCIPbranchcandGetNExternCands(branchcand) > 0 || SCIPbranchcandGetNPseudoCands(branchcand) > 0)
4350  && !solverelaxagain && !solvelpagain && !propagateagain && !branched )
4351  {
4352  SCIP_RESULT result = SCIP_DIDNOTRUN;
4353  int nlpcands = 0;
4354 
4355  if( SCIPtreeHasFocusNodeLP(tree) )
4356  {
4357  SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nlpcands, NULL, NULL) );
4358  }
4359 
4360  if ( nlpcands > 0 || SCIPbranchcandGetNExternCands(branchcand) > 0 )
4361  {
4362  /* If there are LP candidates and their maximal priority is at least the maximal priority of the external
4363  * candidates, then branch on the LP candidates. Note that due to implicit integer variables,
4364  * SCIPbranchcandGetLPMaxPrio(branchcand) might be finite and SCIPbranchcandGetNPrioLPCands(branchcand) > 0,
4365  * but nlpcands == 0. */
4366  if ( SCIPbranchcandGetLPMaxPrio(branchcand) >= SCIPbranchcandGetExternMaxPrio(branchcand) && nlpcands > 0 )
4367  {
4368  assert( SCIPbranchcandGetNPrioLPCands(branchcand) > 0 );
4369  assert( nlpcands > 0 );
4370 
4371  /* branch on LP solution */
4372  SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on LP solution with %d fractionals\n",
4373  SCIPnodeGetDepth(focusnode), nlpcands);
4374  SCIP_CALL( SCIPbranchExecLP(blkmem, set, stat, transprob, origprob, tree, reopt, lp, sepastore, branchcand,
4375  eventqueue, primal->cutoffbound, FALSE, &result) );
4376  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4377  assert(result != SCIP_DIDNOTRUN && result != SCIP_DIDNOTFIND);
4378  }
4379  else
4380  {
4381  assert( SCIPbranchcandGetNPrioExternCands(branchcand) > 0 );
4382  assert( SCIPbranchcandGetNExternCands(branchcand) > 0 );
4383 
4384  /* branch on external candidates */
4385  SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on %d external branching candidates.\n",
4386  SCIPnodeGetDepth(focusnode), SCIPbranchcandGetNExternCands(branchcand));
4387  SCIP_CALL( SCIPbranchExecExtern(blkmem, set, stat, transprob, origprob, tree, reopt, lp, sepastore, branchcand,
4388  eventqueue, primal->cutoffbound, TRUE, &result) );
4389  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4390  }
4391  }
4392 
4393  if( result == SCIP_DIDNOTRUN || result == SCIP_DIDNOTFIND )
4394  {
4395  /* branch on pseudo solution */
4396  SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on pseudo solution with %d unfixed integers\n",
4397  SCIPnodeGetDepth(focusnode), SCIPbranchcandGetNPseudoCands(branchcand));
4398  SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
4399  primal->cutoffbound, TRUE, &result) );
4400  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4401  }
4402 
4403  /* SCIP cannot guarantee convergence if it is necessary to branch on unbounded variables */
4404  if( result == SCIP_BRANCHED )
4405  {
4406  SCIP_VAR* var = stat->lastbranchvar;
4407 
4408  if( var != NULL && !stat->branchedunbdvar && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS
4410  {
4411  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_NORMAL,
4412  "Starting spatial branch-and-bound on unbounded variable <%s> ([%g,%g]) - cannot guarantee finite termination.\n",
4414  stat->branchedunbdvar = TRUE;
4415  }
4416  }
4417 
4418  switch( result )
4419  {
4420  case SCIP_CUTOFF:
4421  assert(tree->nchildren == 0);
4422  *cutoff = TRUE;
4423  SCIPsetDebugMsg(set, " -> branching rule detected cutoff\n");
4424  break;
4425  case SCIP_CONSADDED:
4426  assert(tree->nchildren == 0);
4427  if( nlpcands > 0 )
4428  {
4429  SCIPerrorMessage("LP branching rule added constraint, which was not allowed this time\n");
4430  return SCIP_INVALIDRESULT;
4431  }
4432  propagateagain = TRUE;
4433  solvelpagain = TRUE;
4434  solverelaxagain = TRUE;
4435  markRelaxsUnsolved(set, relaxation);
4436  break;
4437  case SCIP_REDUCEDDOM:
4438  assert(tree->nchildren == 0);
4439  propagateagain = TRUE;
4440  solvelpagain = TRUE;
4441  solverelaxagain = TRUE;
4442  markRelaxsUnsolved(set, relaxation);
4443  break;
4444  case SCIP_SEPARATED:
4445  assert(tree->nchildren == 0);
4446  assert(SCIPsepastoreGetNCuts(sepastore) > 0);
4447  solvelpagain = TRUE;
4448  solverelaxagain = TRUE;
4449  markRelaxsUnsolved(set, relaxation);
4450  break;
4451  case SCIP_BRANCHED:
4452  assert(tree->nchildren >= 1);
4453  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4454  branched = TRUE;
4455 
4456  /* increase the number of internal nodes */
4457  stat->ninternalnodes++;
4458  stat->ntotalinternalnodes++;
4459  break;
4460  case SCIP_DIDNOTFIND: /*lint -fallthrough*/
4461  case SCIP_DIDNOTRUN:
4462  /* all integer variables in the infeasible solution are fixed,
4463  * - if no continuous variables exist and all variables are known, the infeasible pseudo solution is completely
4464  * fixed, and the node can be cut off
4465  * - if at least one continuous variable exists or we do not know all variables due to external pricers, we
4466  * cannot resolve the infeasibility by branching -> solve LP (and maybe price in additional variables)
4467  */
4468  assert(tree->nchildren == 0);
4469  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4470  assert(SCIPbranchcandGetNPseudoCands(branchcand) == 0);
4471 
4472  if( transprob->ncontvars == 0 && set->nactivepricers == 0 )
4473  {
4474  *cutoff = TRUE;
4475  SCIPsetDebugMsg(set, " -> cutoff because all variables are fixed in current node\n");
4476  }
4477  else
4478  {
4479  /* feasible LP solutions with all integers fixed must be feasible
4480  * if also no external branching candidates were available
4481  */
4482  assert(!SCIPtreeHasFocusNodeLP(tree) || pricingaborted);
4483 
4485  {
4486  SCIP_NODE* node;
4487 
4488  /* as we hit the time or iteration limit or another interrupt (e.g., gap limit), we do not want to solve the LP again.
4489  * in order to terminate correctly, we create a "branching" with only one child node
4490  * that is a copy of the focusnode
4491  */
4492  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, 1.0, focusnode->estimate) );
4493  assert(tree->nchildren >= 1);
4494  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4495  branched = TRUE;
4496  }
4497  else
4498  {
4499  SCIP_VERBLEVEL verblevel;
4500 
4501  if( pricingaborted )
4502  {
4503  SCIPerrorMessage("pricing was aborted, but no branching could be created!\n");
4504  return SCIP_INVALIDRESULT;
4505  }
4506 
4507  if( wasforcedlpsolve )
4508  {
4509  assert(SCIPtreeHasFocusNodeLP(tree));
4510  SCIPerrorMessage("LP was solved, all integers fixed, some constraint still infeasible, but no branching could be created!\n");
4511  return SCIP_INVALIDRESULT;
4512  }
4513 
4514  verblevel = SCIP_VERBLEVEL_FULL;
4515 
4516  if( !tree->forcinglpmessage && set->disp_verblevel == SCIP_VERBLEVEL_HIGH )
4517  {
4518  verblevel = SCIP_VERBLEVEL_HIGH;
4519 
4520  /* remember that the forcing LP solving message was posted and do only post it again if the
4521  * verblevel is SCIP_VERBLEVEL_FULL
4522  */
4523  tree->forcinglpmessage = TRUE;
4524  }
4525 
4526  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, verblevel,
4527  "(node %" SCIP_LONGINT_FORMAT ") forcing the solution of an LP (last LP %" SCIP_LONGINT_FORMAT ")...\n", stat->nnodes, stat->nlps);
4528 
4529  /* solve the LP in the next loop */
4531  solvelpagain = TRUE;
4532  forcedlpsolve = TRUE; /* this LP must be solved without error - otherwise we have to abort */
4533  }
4534  }
4535  break;
4536  default:
4537  SCIPerrorMessage("invalid result code <%d> from SCIPbranchLP(), SCIPbranchExt() or SCIPbranchPseudo()\n", result);
4538  return SCIP_INVALIDRESULT;
4539  } /*lint !e788*/
4540  assert(*cutoff || solvelpagain || propagateagain || branched); /* something must have been done */
4541  assert(!(*cutoff) || (!solvelpagain && !propagateagain && !branched));
4542  assert(!solvelpagain || (!(*cutoff) && !branched));
4543  assert(!propagateagain || (!(*cutoff) && !branched));
4544  assert(!branched || (!solvelpagain && !propagateagain));
4545  assert(branched == (tree->nchildren > 0));
4546 
4547  /* apply found cuts */
4548  SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4549  eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_LP, cutoff, &propagateagain,
4550  &solvelpagain, &solverelaxagain) );
4551 
4552  /* update lower bound with the pseudo objective value, and cut off node by bounding */
4553  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4554 
4555  /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4556  updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4557  }
4558 
4559  /* check for immediate restart */
4560  *restart = *restart || (actdepth == 0 && restartAllowed(set, stat) && (stat->userrestart
4561  || (stat->nrootintfixingsrun > set->presol_immrestartfac * (transprob->nvars - transprob->ncontvars)
4562  && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars))) );
4563 
4564  SCIPsetDebugMsg(set, "node solving iteration %d finished: cutoff=%u, postpone=%u, propagateagain=%u, solverelaxagain=%u, solvelpagain=%u, nlperrors=%d, restart=%u\n",
4565  nloops, *cutoff, *postpone, propagateagain, solverelaxagain, solvelpagain, nlperrors, *restart);
4566  }
4567  assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4568  assert(*cutoff || SCIPconflictGetNConflicts(conflict) == 0);
4569 
4570  /* flush the conflict set storage */
4571  SCIP_CALL( SCIPconflictFlushConss(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cliquetable) );
4572 
4573  /* check for too many LP errors */
4574  if( nlperrors >= MAXNLPERRORS )
4575  {
4576  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- aborting\n", stat->nnodes, stat->nlps);
4577  return SCIP_LPERROR;
4578  }
4579 
4580  /* check for final restart */
4581  restartfac = set->presol_subrestartfac;
4582  if( actdepth == 0 )
4583  restartfac = MIN(restartfac, set->presol_restartfac);
4584  *restart = *restart || (restartAllowed(set, stat) && (stat->userrestart
4585  || (stat->nrootintfixingsrun > restartfac * (transprob->nvars - transprob->ncontvars)
4586  && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars))) );
4587 
4588  /* remember the last root LP solution */
4589  if( actdepth == 0 && !(*cutoff) && !(*unbounded) && !(*postpone) )
4590  {
4591  /* the root pseudo objective value and pseudo objective value should be equal in the root node */
4592  assert(SCIPsetIsFeasEQ(set, SCIPlpGetGlobalPseudoObjval(lp, set, transprob), SCIPlpGetPseudoObjval(lp, set, transprob)));
4593 
4594  SCIPprobStoreRootSol(transprob, set, stat, lp, SCIPtreeHasFocusNodeLP(tree));
4595  }
4596 
4597  /* check for cutoff */
4598  if( *cutoff )
4599  {
4600  SCIPsetDebugMsg(set, "node is cut off\n");
4601 
4602  SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, SCIPsetInfinity(set));
4603  *infeasible = TRUE;
4604  SCIP_CALL( SCIPdebugRemoveNode(blkmem, set, focusnode) ); /*lint !e506 !e774*/
4605  }
4606  else if( !(*unbounded) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && lp->looseobjvalinf == 0 )
4607  {
4608  /* update the regression statistic nlpbranchcands and LP objective value */
4609  int nlpbranchcands;
4610  SCIP_Real lpobjval;
4611 
4612  /* get number of LP candidate variables */
4613  SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nlpbranchcands, NULL, NULL) );
4614 
4615  /* get LP objective value */
4616  lpobjval = SCIPlpGetObjval(lp, set, transprob);
4617  assert(lpobjval != SCIP_INVALID); /*lint !e777*/
4618 
4619  /* add the observation to the regression */
4620  SCIPregressionAddObservation(stat->regressioncandsobjval, (SCIP_Real)nlpbranchcands, lpobjval);
4621  }
4622 
4623  return SCIP_OKAY;
4624 }
4625 
4626 /** if feasible, adds current solution to the solution storage */
4627 static
4629  BMS_BLKMEM* blkmem, /**< block memory buffers */
4630  SCIP_SET* set, /**< global SCIP settings */
4631  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4632  SCIP_STAT* stat, /**< dynamic problem statistics */
4633  SCIP_PROB* origprob, /**< original problem */
4634  SCIP_PROB* transprob, /**< transformed problem after presolve */
4635  SCIP_PRIMAL* primal, /**< primal data */
4636  SCIP_RELAXATION* relaxation, /**< global relaxation data */
4637  SCIP_TREE* tree, /**< branch and bound tree */
4638  SCIP_REOPT* reopt, /**< reoptimization data structure */
4639  SCIP_LP* lp, /**< LP data */
4640  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4641  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4642  SCIP_Bool checksol /**< should the solution be checked? */
4643  )
4644 {
4645  SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
4646  SCIP_SOL* sol;
4647  SCIP_Bool foundsol;
4648 
4649  /* found a feasible solution */
4650  if( SCIPrelaxationIsSolValid(relaxation) && SCIPrelaxationIsLpIncludedForSol(relaxation) && (!SCIPtreeHasFocusNodeLP(tree)
4651  || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
4652  {
4653  /* start clock for relaxation solutions */
4654  SCIPclockStart(stat->relaxsoltime, set);
4655 
4656  SCIP_CALL( SCIPsolCreateRelaxSol(&sol, blkmem, set, stat, primal, tree, relaxation, NULL) );
4657 
4658  SCIPsetDebugMsg(set, "found relaxation solution with objective %f\n", SCIPsolGetObj(sol, set, transprob, origprob));
4659 
4660  if( checksol || set->misc_exactsolve )
4661  {
4662  /* if we want to solve exactly, we have to check the solution exactly again */
4663  SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4664  eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &foundsol) );
4665  }
4666  else
4667  {
4668  SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4669  eventqueue, eventfilter, &sol, &foundsol) );
4670  }
4671 
4672  if( foundsol )
4673  {
4674  stat->nrelaxsolsfound++;
4675 
4676  if( primal->nbestsolsfound != oldnbestsolsfound )
4677  {
4678  stat->nrelaxbestsolsfound++;
4679  SCIPstoreSolutionGap(set->scip);
4680  }
4681  }
4682 
4683  /* stop clock for relaxation solutions */
4684  SCIPclockStop(stat->relaxsoltime, set);
4685 
4686  }
4687  else if( SCIPtreeHasFocusNodeLP(tree) )
4688  {
4689  assert(lp->primalfeasible);
4690 
4691  /* start clock for LP solutions */
4692  SCIPclockStart(stat->lpsoltime, set);
4693 
4694  /* add solution to storage */
4695  SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4696 
4697  SCIPsetDebugMsg(set, "found lp solution with objective %f\n", SCIPsolGetObj(sol, set, transprob, origprob));
4698 
4699  if( checksol || set->misc_exactsolve )
4700  {
4701  /* if we want to solve exactly, we have to check the solution exactly again */
4702  SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4703  eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &foundsol) );
4704  }
4705  else
4706  {
4707  SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4708  eventqueue, eventfilter, &sol, &foundsol) );
4709  }
4710 
4711  if( foundsol )
4712  {
4713  stat->nlpsolsfound++;
4714 
4715  if( primal->nbestsolsfound != oldnbestsolsfound )
4716  {
4717  stat->nlpbestsolsfound++;
4718  SCIPstoreSolutionGap(set->scip);
4719  }
4720  }
4721 
4722  /* stop clock for LP solutions */
4723  SCIPclockStop(stat->lpsoltime, set);
4724  }
4725  else
4726  {
4727  /* start clock for pseudo solutions */
4728  SCIPclockStart(stat->pseudosoltime, set);
4729 
4730  /* add solution to storage */
4731  SCIP_CALL( SCIPsolCreatePseudoSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4732 
4733  SCIPsetDebugMsg(set, "found pseudo solution with objective %f\n", SCIPsolGetObj(sol, set, transprob, origprob));
4734 
4735  if( checksol || set->misc_exactsolve )
4736  {
4737  /* if we want to solve exactly, we have to check the solution exactly again */
4738  SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4739  eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &foundsol) );
4740  }
4741  else
4742  {
4743  SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4744  eventqueue, eventfilter, &sol, &foundsol) );
4745  }
4746 
4747  /* stop clock for pseudo solutions */
4748  SCIPclockStop(stat->pseudosoltime, set);
4749 
4750  if( foundsol )
4751  {
4752  stat->npssolsfound++;
4753 
4754  if( primal->nbestsolsfound != oldnbestsolsfound )
4755  {
4756  stat->npsbestsolsfound++;
4757  SCIPstoreSolutionGap(set->scip);
4758  }
4759  }
4760  }
4761 
4762  return SCIP_OKAY;
4763 }
4764 
4765 /** main solving loop */
4767  BMS_BLKMEM* blkmem, /**< block memory buffers */
4768  SCIP_SET* set, /**< global SCIP settings */
4769  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4770  SCIP_STAT* stat, /**< dynamic problem statistics */
4771  SCIP_MEM* mem, /**< block memory pools */
4772  SCIP_PROB* origprob, /**< original problem */
4773  SCIP_PROB* transprob, /**< transformed problem after presolve */
4774  SCIP_PRIMAL* primal, /**< primal data */
4775  SCIP_TREE* tree, /**< branch and bound tree */
4776  SCIP_REOPT* reopt, /**< reoptimization data structure */
4777  SCIP_LP* lp, /**< LP data */
4778  SCIP_RELAXATION* relaxation, /**< global relaxation data */
4779  SCIP_PRICESTORE* pricestore, /**< pricing storage */
4780  SCIP_SEPASTORE* sepastore, /**< separation storage */
4781  SCIP_CUTPOOL* cutpool, /**< global cut pool */
4782  SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
4783  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4784  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4785  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
4786  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4787  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4788  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4789  SCIP_Bool* restart /**< should solving process be started again with presolving? */
4790  )
4791 {
4792  SCIP_NODESEL* nodesel;
4793  SCIP_NODE* focusnode;
4794  SCIP_NODE* nextnode;
4795  SCIP_EVENT event;
4796  SCIP_Real restartfac;
4797  SCIP_Real restartconfnum;
4798  int nnodes;
4799  int depth;
4800  SCIP_Bool cutoff;
4801  SCIP_Bool postpone;
4802  SCIP_Bool unbounded;
4803  SCIP_Bool infeasible;
4804  SCIP_Bool foundsol;
4805 
4806  assert(set != NULL);
4807  assert(blkmem != NULL);
4808  assert(stat != NULL);
4809  assert(transprob != NULL);
4810  assert(tree != NULL);
4811  assert(lp != NULL);
4812  assert(pricestore != NULL);
4813  assert(sepastore != NULL);
4814  assert(branchcand != NULL);
4815  assert(cutpool != NULL);
4816  assert(delayedcutpool != NULL);
4817  assert(primal != NULL);
4818  assert(eventfilter != NULL);
4819  assert(eventqueue != NULL);
4820  assert(restart != NULL);
4821 
4822  /* check for immediate restart (if problem solving marked to be restarted was aborted) */
4823  restartfac = set->presol_subrestartfac;
4824  if( SCIPtreeGetCurrentDepth(tree) == 0 )
4825  restartfac = MIN(restartfac, set->presol_restartfac);
4826  *restart = restartAllowed(set, stat) && (stat->userrestart
4827  || (stat->nrootintfixingsrun > restartfac * (transprob->nvars - transprob->ncontvars)
4828  && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars)) );
4829 
4830  /* calculate the number of successful conflict analysis calls that should trigger a restart */
4831  if( set->conf_restartnum > 0 )
4832  {
4833  int i;
4834 
4835  restartconfnum = (SCIP_Real)set->conf_restartnum;
4836  for( i = 0; i < stat->nconfrestarts; ++i )
4837  restartconfnum *= set->conf_restartfac;
4838  }
4839  else
4840  restartconfnum = SCIP_REAL_MAX;
4841  assert(restartconfnum >= 0.0);
4842 
4843  /* switch status to UNKNOWN */
4844  stat->status = SCIP_STATUS_UNKNOWN;
4845 
4846  focusnode = NULL;
4847  nextnode = NULL;
4848  unbounded = FALSE;
4849  postpone = FALSE;
4850 
4851  while( !SCIPsolveIsStopped(set, stat, TRUE) && !(*restart) )
4852  {
4853  SCIP_Longint nsuccessconflicts;
4854  SCIP_Bool afternodeheur;
4855  SCIP_Bool stopped;
4856  SCIP_Bool branched;
4857 
4858  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4859 
4860  foundsol = FALSE;
4861  infeasible = FALSE;
4862 
4863  do
4864  {
4865  /* update the memory saving flag, switch algorithms respectively */
4866  SCIPstatUpdateMemsaveMode(stat, set, messagehdlr, mem);
4867 
4868  /* get the current node selector */
4869  nodesel = SCIPsetGetNodesel(set, stat);
4870 
4871  /* inform tree about the current node selector */
4872  SCIP_CALL( SCIPtreeSetNodesel(tree, set, messagehdlr, stat, nodesel) );
4873 
4874  /* the next node was usually already selected in the previous solving loop before the primal heuristics were
4875  * called, because they need to know, if the next node will be a child/sibling (plunging) or not;
4876  * if the heuristics found a new best solution that cut off some of the nodes, the node selector must be called
4877  * again, because the selected next node may be invalid due to cut off
4878  */
4879  if( nextnode == NULL )
4880  {
4881  /* select next node to process */
4882  SCIP_CALL( SCIPnodeselSelect(nodesel, set, &nextnode) );
4883  }
4884  focusnode = nextnode;
4885  nextnode = NULL;
4886  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4887 
4888  /* start node activation timer */
4889  SCIPclockStart(stat->nodeactivationtime, set);
4890 
4891  /* focus selected node */
4892  SCIP_CALL( SCIPnodeFocus(&focusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt,
4893  lp, branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, FALSE, FALSE) );
4894  if( cutoff )
4895  stat->ndelayedcutoffs++;
4896 
4897  /* stop node activation timer */
4898  SCIPclockStop(stat->nodeactivationtime, set);
4899 
4900  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4901  }
4902  while( cutoff ); /* select new node, if the current one was located in a cut off subtree */
4903 
4904  assert(SCIPtreeGetCurrentNode(tree) == focusnode);
4905  assert(SCIPtreeGetFocusNode(tree) == focusnode);
4906 
4907  /* if no more node was selected, we finished optimization */
4908  if( focusnode == NULL )
4909  {
4910  assert(SCIPtreeGetNNodes(tree) == 0);
4911  break;
4912  }
4913 
4914  /* update maxdepth and node count statistics */
4915  depth = SCIPnodeGetDepth(focusnode);
4916  stat->maxdepth = MAX(stat->maxdepth, depth);
4917  stat->maxtotaldepth = MAX(stat->maxtotaldepth, depth);
4918  stat->nnodes++;
4919  stat->ntotalnodes++;
4920 
4921  /* update reference bound statistic, if available */
4922  if( SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), stat->referencebound) )
4923  stat->nnodesaboverefbound++;
4924 
4925  /* issue NODEFOCUSED event */
4927  SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
4928  SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
4929 
4930  /* solve focus node */
4931  SCIP_CALL( solveNode(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp, relaxation,
4932  pricestore, sepastore, branchcand, cutpool, delayedcutpool, conflict, conflictstore, eventfilter, eventqueue,
4933  cliquetable, &cutoff, &postpone, &unbounded, &infeasible, restart, &afternodeheur, &stopped) );
4934  assert(!cutoff || infeasible);
4935  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4936  assert(SCIPtreeGetCurrentNode(tree) == focusnode);
4937  assert(SCIPtreeGetFocusNode(tree) == focusnode);
4938 
4939  branched = (tree->nchildren > 0);
4940 
4941  if( stopped )
4942  break;
4943 
4944  /* check for restart */
4945  if( !(*restart) && !postpone )
4946  {
4947  /* change color of node in visualization */
4948  SCIPvisualSolvedNode(stat->visual, set, stat, focusnode);
4949 
4950  /* check, if the current solution is feasible */
4951  if( !infeasible )
4952  {
4953  SCIP_Bool feasible;
4954 
4955  assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
4956  assert(!cutoff);
4957 
4958  /* in the unbounded case, we check the solution w.r.t. the original problem, because we do not want to rely
4959  * on the LP feasibility and integrality is not checked for unbounded solutions, anyway
4960  */
4961  if( unbounded )
4962  {
4963  SCIP_SOL* sol;
4964 
4965  if( SCIPrelaxationIsSolValid(relaxation) && SCIPrelaxationIsLpIncludedForSol(relaxation) && (!SCIPtreeHasFocusNodeLP(tree)
4966  || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
4967  {
4968  SCIP_CALL( SCIPsolCreateRelaxSol(&sol, blkmem, set, stat, primal, tree, relaxation, NULL) );
4969  }
4970  else if( SCIPtreeHasFocusNodeLP(tree) )
4971  {
4972  SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4973  }
4974  else
4975  {
4976  SCIP_CALL( SCIPsolCreatePseudoSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4977  }
4978  SCIP_CALL( SCIPcheckSolOrig(set->scip, sol, &feasible, FALSE, FALSE) );
4979 
4980  SCIP_CALL( SCIPsolFree(&sol, blkmem, primal) );
4981  }
4982  else
4983  feasible = TRUE;
4984 
4985  /* node solution is feasible: add it to the solution store */
4986  if( feasible )
4987  {
4988  SCIP_CALL( addCurrentSolution(blkmem, set, messagehdlr, stat, origprob, transprob, primal, relaxation, tree, reopt,
4989  lp, eventqueue, eventfilter, FALSE) );
4990 
4991  /* update the cutoff pointer if the new solution made the cutoff bound equal to the lower bound */
4992  SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, &cutoff) );
4993 
4994 
4995  /* increment number of feasible leaf nodes */
4996  stat->nfeasleaves++;
4997 
4998  /* issue NODEFEASIBLE event */
5000  SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
5001  SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
5002 
5003  if( set->reopt_enable )
5004  {
5005  assert(reopt != NULL);
5006  SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEFEASIBLE, lp,
5007  SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
5008  focusnode->lowerbound, tree->effectiverootdepth) );
5009  }
5010  }
5011  }
5012  else if( !unbounded )
5013  {
5014  /* node solution is not feasible */
5015  if( !branched )
5016  {
5017  assert(tree->nchildren == 0);
5018 
5019  /* change color of node in visualization output */
5020  SCIPvisualCutoffNode(stat->visual, set, stat, focusnode, TRUE);
5021 
5022  /* issue NODEINFEASIBLE event */
5024 
5025  /* we only increase the number of objective leaf nodes if we hit the LP objective limit; we might have also
5026  * hit the objective limit at a node that is actually infeasible, or a dual reduction led to an infeasibility prior
5027  * to LP solving such that the node will be marked as infeasible */
5029  stat->nobjleaves++;
5030  else
5031  stat->ninfeasleaves++;
5032 
5033  if( set->reopt_enable )
5034  {
5035  assert(reopt != NULL);
5036  SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEINFEASIBLE, lp,
5037  SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
5038  focusnode->lowerbound, tree->effectiverootdepth) );
5039  }
5040 
5041  /* increase the cutoff counter of the branching variable */
5042  if( stat->lastbranchvar != NULL )
5043  {
5044  SCIP_CALL( SCIPvarIncCutoffSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
5045  }
5046  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
5047  }
5048  else
5049  {
5050  assert(tree->nchildren > 0);
5051 
5052  /* issue NODEBRANCHED event */
5054 
5055  if( set->reopt_enable )
5056  {
5057  assert(reopt != NULL);
5058  SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEBRANCHED, lp,
5059  SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
5060  focusnode->lowerbound, tree->effectiverootdepth) );
5061  }
5062  }
5063  SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
5064  SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
5065  }
5066  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5067 
5068  /* if no branching was created, the node was not cut off, but its lower bound is still smaller than
5069  * the cutoff bound, we have to branch on a non-fixed variable;
5070  * this can happen, if we want to solve exactly, the current solution was declared feasible by the
5071  * constraint enforcement, but in exact solution checking it was found out to be infeasible;
5072  * in this case, no branching would have been generated by the enforcement of constraints, but we
5073  * have to further investigate the current sub tree;
5074  * note that we must noch check tree->nchildren > 0 here to determine whether we branched, we rather
5075  * check it directly after solveNode() and store the result, because an event handler might impose a
5076  * new cutoff bound (as is the case in ParaSCIP)
5077  */
5078  if( !cutoff && !unbounded && !branched && SCIPnodeGetLowerbound(focusnode) < primal->cutoffbound )
5079  {
5080  SCIP_RESULT result;
5081 
5082  assert(set->misc_exactsolve);
5083 
5084  do
5085  {
5086  result = SCIP_DIDNOTRUN;
5087  if( SCIPbranchcandGetNPseudoCands(branchcand) == 0 )
5088  {
5089  if( transprob->ncontvars > 0 )
5090  {
5091  /**@todo call PerPlex */
5092  SCIPerrorMessage("cannot branch on all-fixed LP -- have to call PerPlex instead\n");
5093  }
5094  }
5095  else
5096  {
5097  SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
5098  eventqueue, primal->cutoffbound, FALSE, &result) );
5099  assert(result != SCIP_DIDNOTRUN && result != SCIP_DIDNOTFIND);
5100  }
5101  }
5102  while( result == SCIP_REDUCEDDOM );
5103  }
5104  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5105 
5106  /* select node to process in next solving loop; the primal heuristics need to know whether a child/sibling
5107  * (plunging) will be selected as next node or not
5108  */
5109  SCIP_CALL( SCIPnodeselSelect(nodesel, set, &nextnode) );
5110  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5111 
5112  /* call primal heuristics that should be applied after the node was solved */
5113  nnodes = SCIPtreeGetNNodes(tree);
5114  stopped = SCIPsolveIsStopped(set, stat, FALSE);
5115  if( !afternodeheur && (!cutoff || nnodes > 0) && !stopped )
5116  {
5117  SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, nextnode, SCIP_HEURTIMING_AFTERNODE,
5118  cutoff, &foundsol, &unbounded) );
5119  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5120 
5121  stopped = SCIPsolveIsStopped(set, stat, FALSE);
5122  }
5123 
5124  /* if the heuristics found a new best solution that cut off some of the nodes, the node selector must be called
5125  * again, because the selected next node may be invalid due to cut off
5126  */
5127  assert(!tree->cutoffdelayed);
5128 
5129  if( nnodes != SCIPtreeGetNNodes(tree) || stopped )
5130  nextnode = NULL;
5131  }
5132  else if( !infeasible && !postpone )
5133  {
5134  /* The current solution was not proven to be infeasible, but due to the restart, this does not mean that it is
5135  * feasible, we might just have skipped the check. Thus, we try to add it to the solution store, but check it
5136  * again.
5137  */
5138  SCIP_CALL( addCurrentSolution(blkmem, set, messagehdlr, stat, origprob, transprob, primal, relaxation, tree, reopt, lp,
5139  eventqueue, eventfilter, TRUE) );
5140 
5141  if( set->reopt_enable )
5142  {
5143  assert(reopt != NULL);
5144  SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEFEASIBLE, lp,
5145  SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode, focusnode->lowerbound,
5146  tree->effectiverootdepth) );
5147  }
5148  }
5149  /* we want to put the focusnode back into the leaf queue if it was postponed */
5150  else if( postpone )
5151  {
5152  SCIP_NODE* newfocusnode = NULL;
5153 
5154  /* @todo should we re-install the old focus node in order to somehow set the forks more clever? */
5155  SCIP_CALL( SCIPnodeFocus(&newfocusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
5156  branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, TRUE, FALSE) );
5157  }
5158  /* compute number of successfully applied conflicts */
5159  nsuccessconflicts = SCIPconflictGetNPropSuccess(conflict) + SCIPconflictGetNInfeasibleLPSuccess(conflict)
5161  + SCIPconflictGetNPseudoSuccess(conflict);
5162 
5163  /* trigger restart due to conflicts and the restart parameters allow another restart */
5164  if( nsuccessconflicts >= restartconfnum && restartAllowed(set, stat) )
5165  {
5166  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
5167  "(run %d, node %" SCIP_LONGINT_FORMAT ") restarting after %" SCIP_LONGINT_FORMAT " successful conflict analysis calls\n",
5168  stat->nruns, stat->nnodes, nsuccessconflicts);
5169  *restart = TRUE;
5170 
5171  stat->nconfrestarts++;
5172  }
5173 
5174  /* restart if the userrestart was set to true, we have still some nodes left and the restart parameters allow
5175  * another restart
5176  */
5177  *restart = *restart || (stat->userrestart && SCIPtreeGetNNodes(tree) > 0 && restartAllowed(set, stat));
5178  if( restartAllowed(set, stat) && set->limit_autorestartnodes == stat->nnodes && stat->ntotalnodes - stat->nruns + 1 == set->limit_autorestartnodes )
5179  {
5180  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
5181  "(run %d, node %" SCIP_LONGINT_FORMAT ") restarting: triggering parameter controlled restart)\n",
5182  stat->nruns, stat->nnodes);
5183  *restart = TRUE;
5184  }
5185  /* if restart limit was exceeded, change the status; if status is different from unknown, ie some other limit was
5186  * hit, leave it unchanged
5187  */
5188  if( *restart && stat->status == SCIP_STATUS_UNKNOWN && set->limit_restarts >= 0 && stat->nruns > set->limit_restarts )
5189  {
5190  *restart = FALSE;
5192  }
5193 
5194  /* display node information line */
5195  SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, (SCIPnodeGetDepth(focusnode) == 0) && infeasible && !foundsol, TRUE) );
5196 
5197  SCIPsetDebugMsg(set, "Processing of node %" SCIP_LONGINT_FORMAT " in depth %d finished. %d siblings, %d children, %d leaves left\n",
5198  stat->nnodes, SCIPnodeGetDepth(focusnode), tree->nsiblings, tree->nchildren, SCIPtreeGetNLeaves(tree));
5199  SCIPsetDebugMsg(set, "**********************************************************************\n");
5200  }
5201 
5202  /* update the primal-dual integral if node or time limits were hit or an interruption signal was called */
5203  if( SCIPsolveIsStopped(set, stat, TRUE) )
5204  {
5205  SCIPstatUpdatePrimalDualIntegral(stat, set, transprob, origprob, SCIPsetInfinity(set), -SCIPsetInfinity(set));
5206  }
5207 
5208  assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5209 
5210  SCIPsetDebugMsg(set, "Problem solving finished with status %u (restart=%u, userrestart=%u)\n", stat->status, *restart, stat->userrestart);
5211 
5212  /* cuts off nodes with lower bound is not better than given cutoff bound, manually; this necessary to ensure that
5213  * SCIP terminates with a proper solve stage
5214  */
5215  SCIP_CALL( SCIPtreeCutoff(tree, reopt, blkmem, set, stat, eventqueue, lp, primal->cutoffbound) );
5216 
5217  /* if the current node is the only remaining node, and if its lower bound exceeds the upper bound, we have
5218  * to delete it manually in order to get to the SOLVED stage instead of thinking, that only the gap limit
5219  * was reached (this may happen, if the current node is the one defining the global lower bound and a
5220  * feasible solution with the same value was found at this node)
5221  */
5222  if( tree->focusnode != NULL && SCIPtreeGetNNodes(tree) == 0
5223  && SCIPsetIsGE(set, tree->focusnode->lowerbound, primal->cutoffbound) )
5224  {
5225  if( set->reopt_enable )
5226  {
5227  assert(reopt != NULL);
5229  SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode, tree->focusnode->lowerbound,
5230  tree->effectiverootdepth) );
5231  }
5232 
5233  focusnode = NULL;
5234  SCIP_CALL( SCIPnodeFocus(&focusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
5235  branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, FALSE, FALSE) );
5236  }
5237 
5238  /* check whether we finished solving */
5239  if( SCIPtreeGetNNodes(tree) == 0 && SCIPtreeGetCurrentNode(tree) == NULL )
5240  {
5241  /* no restart necessary */
5242  *restart = FALSE;
5243 
5244  /* set the solution status */
5245  if( unbounded )
5246  {
5247  if( primal->nsols > 0 )
5248  {
5249  /* switch status to UNBOUNDED */
5250  stat->status = SCIP_STATUS_UNBOUNDED;
5251  }
5252  else
5253  {
5254  /* switch status to INFORUNB */
5255  stat->status = SCIP_STATUS_INFORUNBD;
5256  }
5257  }
5258  else if( primal->nlimsolsfound == 0 )
5259  {
5260  assert(primal->nsols == 0 || SCIPsetIsGT(set, SCIPsolGetObj(primal->sols[0], set, transprob, origprob),
5261  SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(transprob, set))));
5262 
5263  /* switch status to INFEASIBLE */
5265  }
5266  else
5267  {
5268  /* switch status to OPTIMAL */
5269  stat->status = SCIP_STATUS_OPTIMAL;
5270  }
5271  }
5272 
5273  return SCIP_OKAY;
5274 }
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:8613
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:15713
void SCIPpricestoreEndInitialLP(SCIP_PRICESTORE *pricestore)
Definition: pricestore.c:158
SCIP_SOL * primalray
Definition: struct_primal.h:52
SCIP_RETCODE SCIPsolCreateRelaxSol(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_RELAXATION *relaxation, SCIP_HEUR *heur)
Definition: sol.c:614
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:1374
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5776
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:7982
#define SCIP_EVENTTYPE_LPSOLVED
Definition: type_event.h:84
SCIP_Real firstlpdualbound
Definition: struct_stat.h:116
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:2793
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:2871
SCIP_Longint nnodelpiterations
Definition: struct_stat.h:63
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 allowlocal, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *cutoff)
Definition: solve.c:1895
static void markRelaxsUnsolved(SCIP_SET *set, SCIP_RELAXATION *relaxation)
Definition: solve.c:2853
int SCIPheurGetPriority(SCIP_HEUR *heur)
Definition: heur.c:1259
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:87
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:980
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 allowlocal, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *enoughcuts, SCIP_Bool *cutoff, SCIP_Bool *lperror, SCIP_Bool *mustsepa, SCIP_Bool *mustprice)
Definition: solve.c:1538
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:5834
SCIP_Longint nlpsolsfound
Definition: struct_stat.h:90
internal methods for storing primal CIP solutions
SCIP_Bool SCIPtreeHasFocusNodeLP(SCIP_TREE *tree)
Definition: tree.c:8242
SCIP_STATUS status
Definition: struct_stat.h:167
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:16989
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:17676
#define SCIPdebugRemoveNode(blkmem, set, node)
Definition: debug.h:254
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:7686
void SCIPlpSetIsRelax(SCIP_LP *lp, SCIP_Bool relax)
Definition: lp.c:16926
SCIP_Longint externmemestim
Definition: struct_stat.h:114
SCIP_Real SCIPrelaxationGetSolObj(SCIP_RELAXATION *relaxation)
Definition: relax.c:680
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:8252
SCIP_Longint SCIPconflictGetNPropSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:5467
int nremovablecols
Definition: struct_lp.h:312
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:1307
SCIP_Bool primalfeasible
Definition: struct_lp.h:349
enum SCIP_Efficiacychoice SCIP_EFFICIACYCHOICE
int SCIPgetNConcurrentSolvers(SCIP *scip)
Definition: concurrent.c:107
unsigned int boundchgtype
Definition: struct_var.h:114
BMS_BUFMEM * buffer
Definition: struct_mem.h:41
int npricerounds
Definition: struct_stat.h:213
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:8477
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:6174
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:7360
SCIP_Longint nlps
Definition: struct_stat.h:173
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
int * pathnlprows
Definition: struct_tree.h:197
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:5019
SCIP_RETCODE SCIPeventChgType(SCIP_EVENT *event, SCIP_EVENTTYPE eventtype)
Definition: event.c:969
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16863
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:1437
internal methods for clocks and timing issues
void SCIPstatUpdateMemsaveMode(SCIP_STAT *stat, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_MEM *mem)
Definition: stat.c:591
SCIP_Longint ntotalnodes
Definition: struct_stat.h:76
int SCIPbranchcandGetNPseudoCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:853
unsigned int SCIP_HEURTIMING
Definition: type_timing.h:97
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:125
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:17332
int SCIPpropGetPriority(SCIP_PROP *prop)
Definition: prop.c:907
SCIP_Longint SCIPconflictGetNInfeasibleLPSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:8149
#define SCIP_HEURTIMING_BEFORENODE
Definition: type_timing.h:70
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:168
void SCIPsepastoreStartForceCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:139
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:5636
SCIP_Real SCIPlpGetGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:12779
int SCIPbranchcandGetNPrioExternCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:516
int nclockskipsleft
Definition: struct_stat.h:256
SCIP_SOL ** sols
Definition: struct_primal.h:48
unsigned int nboundchgs
Definition: struct_var.h:123
SCIP_RETCODE SCIPsepaExecSol(SCIP_SEPA *sepa, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, int depth, SCIP_Bool allowlocal, SCIP_Bool execdelayed, SCIP_RESULT *result)
Definition: sepa.c:449
int SCIPsepastoreGetNCutsApplied(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1267
#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:4325
#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:17688
SCIP_NODESEL * SCIPsetGetNodesel(SCIP_SET *set, SCIP_STAT *stat)
Definition: set.c:4523
SCIP_Bool solved
Definition: struct_lp.h:348
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:10289
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:2678
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:280
SCIP_Longint nrootlps
Definition: struct_stat.h:174
void SCIPresetInterrupted(void)
Definition: interrupt.c:155
SCIP_Bool SCIPreoptGetSolveLP(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node)
Definition: reopt.c:7819
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:233
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:1008
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
Definition: sepa.c:646
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:3469
#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:2091
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1877
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:8300
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16969
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:698
#define SCIP_HEURTIMING_AFTERLPLOOP
Definition: type_timing.h:72
SCIP_Real estimate
Definition: struct_tree.h:134
SCIP_FORK * fork
Definition: struct_tree.h:143
SCIP_NODE * SCIPtreeGetFocusNode(SCIP_TREE *tree)
Definition: tree.c:8208
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:218
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:12045
SCIP_Real SCIPlpGetPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:12811
#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
void SCIPrelaxationSetSolValid(SCIP_RELAXATION *relaxation, SCIP_Bool isvalid, SCIP_Bool includeslp)
Definition: relax.c:636
SCIP_Longint nnodesaboverefbound
Definition: struct_stat.h:84
SCIP_Bool SCIPrelaxationIsSolValid(SCIP_RELAXATION *relaxation)
Definition: relax.c:649
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7350
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:13783
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1884
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:3561
static SCIP_RETCODE enforceConstraints(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, 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:3213
int maxdepth
Definition: struct_stat.h:217
int looseobjvalinf
Definition: struct_lp.h:318
int SCIPbranchcandGetExternMaxPrio(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:496
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:12612
SCIP_VISUAL * visual
Definition: struct_stat.h:165
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:2196
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:251
internal methods for LP management
SCIP_Real lpobjval
Definition: struct_tree.h:101
SCIP_Bool SCIPtreeIsFocusNodeLPConstructed(SCIP_TREE *tree)
Definition: tree.c:8263
void SCIPpricestoreStartInitialLP(SCIP_PRICESTORE *pricestore)
Definition: pricestore.c:146
int SCIPconshdlrGetSepaPriority(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4969
int nremovablerows
Definition: struct_lp.h:316
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
int SCIPsetGetSepaMaxcuts(SCIP_SET *set, SCIP_Bool root)
Definition: set.c:5504
SCIP_RETCODE SCIPnodeselSelect(SCIP_NODESEL *nodesel, SCIP_SET *set, SCIP_NODE **selnode)
Definition: nodesel.c:960
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:16744
#define SAFETYFACTOR
Definition: solve.c:66
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5870
internal methods for propagators
#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:8225
#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:2445
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:17708
SCIP_Real SCIPprobGetObjlim(SCIP_PROB *prob, SCIP_SET *set)
Definition: prob.c:2274
int SCIPbranchcandGetNExternCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:506
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:8685
int nconfrestarts
Definition: struct_stat.h:201
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:4766
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5816
SCIP_Real SCIPclockGetLastTime(SCIP_CLOCK *clck)
Definition: clock.c:508
SCIP_DOMCHG * domchg
Definition: struct_tree.h:148
SCIP_Bool forcinglpmessage
Definition: struct_tree.h:231
SCIP_Bool SCIPtreeProbing(SCIP_TREE *tree)
Definition: tree.c:8182
int nsiblings
Definition: struct_tree.h:212
BMS_BUFMEM * SCIPbuffer(SCIP *scip)
Definition: scip.c:46740
int cutoffdepth
Definition: struct_tree.h:218
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:2299
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13881
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:1492
SCIP_Longint npssolsfound
Definition: struct_stat.h:92
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1198
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:1507
SCIP_RETCODE SCIPsepaExecLP(SCIP_SEPA *sepa, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, int depth, SCIP_Real bounddist, SCIP_Bool allowlocal, SCIP_Bool execdelayed, SCIP_RESULT *result)
Definition: sepa.c:339
SCIP_Bool installing
Definition: struct_lp.h:357
int prevrunnvars
Definition: struct_stat.h:206
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:45944
SCIP_Longint lpcount
Definition: struct_stat.h:171
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:4236
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:657
SCIP_CLOCK * pseudosoltime
Definition: struct_stat.h:155
void SCIPnodeMarkPropagated(SCIP_NODE *node, SCIP_TREE *tree)
Definition: tree.c:1232
SCIP_Longint nrelaxbestsolsfound
Definition: struct_stat.h:95
SCIP_NODE ** path
Definition: struct_tree.h:177
#define MAXNCLOCKSKIPS
Definition: solve.c:64
SCIP_NODE * focuslpstatefork
Definition: struct_tree.h:185
SCIP_RETCODE SCIPsolSetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_VAR *var, SCIP_Real val)
Definition: sol.c:1027
int SCIPrelaxGetPriority(SCIP_RELAX *relax)
Definition: relax.c:464
SCIP_Longint ninitlpiterations
Definition: struct_stat.h:64
int SCIPsepastoreGetNCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1237
SCIP_RETCODE SCIPcheckSolOrig(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *feasible, SCIP_Bool printreason, SCIP_Bool completely)
Definition: scip.c:41031
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:16662
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:428
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:4628
SCIP_Bool SCIPnodeIsPropagatedAgain(SCIP_NODE *node)
Definition: tree.c:8105
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:417
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1881
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:274
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:3341
int SCIPbranchcandGetNPrioLPCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:486
int nseparounds
Definition: struct_stat.h:214
SCIP_Bool userinterrupt
Definition: struct_stat.h:258
#define REALABS(x)
Definition: def.h:173
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17650
internal methods for node selectors and node priority queues
internal methods for variable pricers
int correctlpdepth
Definition: struct_tree.h:217
const char * SCIPrelaxGetName(SCIP_RELAX *relax)
Definition: relax.c:444
#define SCIP_PROPTIMING_AFTERLPLOOP
Definition: type_timing.h:58
void SCIPsetSortProps(SCIP_SET *set)
Definition: set.c:4105
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:350
#define NINITCALLS
Definition: solve.c:65
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:43271
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:16764
void SCIPrelaxMarkUnsolved(SCIP_RELAX *relax)
Definition: relax.c:562
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:8850
SCIP_Bool resolvelperror
Definition: struct_lp.h:364
#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:5798
SCIP_LPI * SCIPlpGetLPI(SCIP_LP *lp)
Definition: lp.c:16916
SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:12628
internal methods for storing separated cuts
int SCIPbranchcandGetLPMaxPrio(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:476
#define MAXNLPERRORS
Definition: solve.c:63
void SCIPsetSortRelaxs(SCIP_SET *set)
Definition: set.c:3954
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:2391
SCIP_Bool SCIPsepaWasLPDelayed(SCIP_SEPA *sepa)
Definition: sepa.c:883
SCIP_Bool userrestart
Definition: struct_stat.h:259
SCIP_Longint nisstoppedcalls
Definition: struct_stat.h:195
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:3113
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:15021
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:90
#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:5926
unsigned int boundtype
Definition: struct_var.h:92
SCIP_Bool SCIPrelaxIsSolved(SCIP_RELAX *relax, SCIP_STAT *stat)
Definition: relax.c:550
int ncontvars
Definition: struct_prob.h:65
SCIP_Bool SCIPconshdlrWasPropagationDelayed(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5089
unsigned int depth
Definition: struct_tree.h:149
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
SCIP_RETCODE SCIPprintRay(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip.c:39741
SCIP_SYNCSTORE * SCIPgetSyncstore(SCIP *scip)
Definition: scip.c:42011
SCIP_Bool branchedunbdvar
Definition: struct_stat.h:263
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:43530
SCIP_Bool SCIPheurShouldBeExecuted(SCIP_HEUR *heur, int depth, int lpstateforkdepth, SCIP_HEURTIMING heurtiming, SCIP_Bool *delayed)
Definition: heur.c:946
#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:3956
#define SCIPsetDebugMsg
Definition: set.h:1913
#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:108
SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
Definition: prob.c:2262
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_Bool SCIPtreeHasCurrentNodeLP(SCIP_TREE *tree)
Definition: tree.c:8317
int SCIPconflictGetNConflicts(SCIP_CONFLICT *conflict)
Definition: conflict.c:3488
#define SCIP_PROPTIMING_BEFORELP
Definition: type_timing.h:56
internal methods for storing cuts in a cut pool
void SCIPsepastoreEndInitialLP(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:127
SCIP_Bool cutoffdelayed
Definition: struct_tree.h:225
SCIP_RETCODE SCIPlpRemoveRedundantRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:15151
#define SCIP_EVENTTYPE_FIRSTLPSOLVED
Definition: type_event.h:83
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6196
SCIP_ROW ** rows
Definition: struct_lp.h:289
SCIP_CLOCK * relaxsoltime
Definition: struct_stat.h:154
void SCIPsepastoreStartInitialLP(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:115
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:3975
int nincseparounds
Definition: struct_stat.h:215
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:887
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:17696
#define SCIP_REAL_MAX
Definition: def.h:150
SCIP_Longint nrootlpiterations
Definition: struct_stat.h:54
SCIP_Real newbound
Definition: struct_var.h:84
#define SCIP_REAL_MIN
Definition: def.h:151
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:153
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:1213
SCIP_Bool SCIPsepaWasSolDelayed(SCIP_SEPA *sepa)
Definition: sepa.c:893
SCIP_Bool SCIPpropWasDelayed(SCIP_PROP *prop)
Definition: prop.c:1092
SCIP_Longint SCIPconflictGetNBoundexceedingLPSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:8229
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:1948
internal methods for main solving loop and node processing
size_t BMSgetNUsedBufferMemory(BMS_BUFMEM *buffer)
Definition: memory.c:3088
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:570
SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
Definition: tree.c:8283
SCIP_CLOCK * solvingtime
Definition: struct_stat.h:142
SCIP_Bool flushed
Definition: struct_lp.h:347
SCIP_PROPTIMING SCIPpropGetTimingmask(SCIP_PROP *prop)
Definition: prop.c:1222
unsigned int pseudocostflag
Definition: struct_var.h:275
int nrows
Definition: struct_lp.h:315
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:978
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:133
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5852
SCIP_Longint nboundchgs
Definition: struct_stat.h:104
#define SCIP_HEURTIMING_AFTERPSEUDONODE
Definition: type_timing.h:76
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:7330
SCIP_Longint SCIPgetNBestSolsFound(SCIP *scip)
Definition: scip.c:43667
#define SCIP_Real
Definition: def.h:149
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:398
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:2165
SCIP_Bool SCIPlpIsSolved(SCIP_LP *lp)
Definition: lp.c:16949
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
SCIP_Real referencebound
Definition: struct_stat.h:138
void SCIPsetSortPricers(SCIP_SET *set)
Definition: set.c:3572
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:3279
SCIP_Longint ntotalinternalnodes
Definition: struct_stat.h:77
int effectiverootdepth
Definition: struct_tree.h:215
#define SCIP_INVALID
Definition: def.h:169
internal methods for constraints and constraint handlers
SCIP_Bool SCIPlpIsRelax(SCIP_LP *lp)
Definition: lp.c:16939
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:3604
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:814
SCIP_Bool SCIPsyncstoreSolveIsStopped(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:227
SCIP_Real SCIPgetOrigObjoffset(SCIP *scip)
Definition: scip.c:11137
SCIP_Bool SCIPnodeIsActive(SCIP_NODE *node)
Definition: tree.c:8095
#define SCIP_Longint
Definition: def.h:134
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:164
SCIP_RETCODE SCIPlpGetPrimalRay(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *ray)
Definition: lp.c:14326
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:2339
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16827
SCIP_Bool disableenforelaxmsg
Definition: struct_stat.h:264
SCIP_CLOCK * nodeactivationtime
Definition: struct_stat.h:157
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:43640
int nchildren
Definition: struct_tree.h:210
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:109
SCIP_Real SCIPprobExternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:2069
#define nnodes
Definition: gastrans.c:65
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17342
SCIP_Real SCIPtreeGetLowerbound(SCIP_TREE *tree, SCIP_SET *set)
Definition: tree.c:7153
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:5047
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:43420
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:636
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:112
SCIP_Longint nnodelps
Definition: struct_stat.h:185
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:205
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:419
int SCIPtreeGetNLeaves(SCIP_TREE *tree)
Definition: tree.c:8145
SCIP_NODE * root
Definition: struct_tree.h:175
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:1114
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:3505
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:2547
int SCIPtreeGetNNodes(SCIP_TREE *tree)
Definition: tree.c:8155
#define SCIPABORT()
Definition: def.h:322
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:4028
static SCIP_RETCODE separationRoundSol(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, int actdepth, SCIP_Bool allowlocal, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *enoughcuts, SCIP_Bool *cutoff)
Definition: solve.c:1752
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:1593
union SCIP_Node::@10 data
void SCIPsepastoreEndForceCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:150
SCIP_RETCODE SCIPrelaxExec(SCIP_RELAX *relax, SCIP_SET *set, SCIP_STAT *stat, int depth, SCIP_Real *lowerbound, SCIP_RESULT *result)
Definition: relax.c:293
unsigned int local
Definition: struct_lp.h:249
SCIP_RETCODE SCIPsepastoreAddCut(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool root, SCIP_Bool *infeasible)
Definition: sepastore.c:394
int SCIPsepaGetPriority(SCIP_SEPA *sepa)
Definition: sepa.c:666
SCIP_Longint ninitlps
Definition: struct_stat.h:186
int age
Definition: struct_lp.h:238
SCIP_Bool SCIPrelaxationIsLpIncludedForSol(SCIP_RELAXATION *relaxation)
Definition: relax.c:659
#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:1497
SCIP_Longint ndelayedcutoffs
Definition: struct_stat.h:86
SCIP_CLOCK * lpsoltime
Definition: struct_stat.h:153
SCIP_NODE * focusnode
Definition: struct_tree.h:180
SCIP_RETCODE SCIPsolFree(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_PRIMAL *primal)
Definition: sol.c:751
int SCIPsetGetPriceMaxvars(SCIP_SET *set, SCIP_Bool root)
Definition: set.c:5490
internal methods for displaying runtime statistics