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