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