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