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