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