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