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