Scippy

SCIP

Solving Constraint Integer Programs

solve.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2024 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file solve.c
26 * @ingroup OTHER_CFILES
27 * @brief main solving loop and node processing
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Marc Pfetsch
31 * @author Gerald Gamrath
32 */
33
34/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35#include <assert.h>
36
37#include "lpi/lpi.h"
38#include "scip/branch.h"
39#include "scip/clock.h"
40#include "scip/concurrent.h"
41#include "scip/conflict.h"
42#include "scip/cons.h"
43#include "scip/cutpool.h"
44#include "scip/disp.h"
45#include "scip/event.h"
46#include "scip/heur.h"
47#include "scip/interrupt.h"
48#include "scip/lp.h"
49#include "scip/nodesel.h"
50#include "scip/pricer.h"
51#include "scip/pricestore.h"
52#include "scip/primal.h"
53#include "scip/prob.h"
54#include "scip/prop.h"
55#include "scip/pub_cons.h"
56#include "scip/pub_heur.h"
57#include "scip/pub_message.h"
58#include "scip/pub_misc.h"
59#include "scip/pub_pricer.h"
60#include "scip/pub_prop.h"
61#include "scip/pub_relax.h"
62#include "scip/pub_sepa.h"
63#include "scip/pub_tree.h"
64#include "scip/pub_var.h"
65#include "scip/relax.h"
66#include "scip/reopt.h"
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( (result == SCIP_FOUNDSOL && lowerbound > primal->cutoffbound) || SCIPsolveIsStopped(set, stat, FALSE) )
382 break;
383
384 /* check if the problem is proven to be unbounded, currently this happens only in reoptimization */
385 if( result == SCIP_UNBOUNDED )
386 {
387 *unbounded = TRUE;
388 break;
389 }
390
391 /* make sure that heuristic did not change probing or diving status */
392 assert(tree == NULL || inprobing == SCIPtreeProbing(tree));
393 assert(lp == NULL || indiving == SCIPlpDiving(lp));
394 }
395 assert(0 <= ndelayedheurs && ndelayedheurs <= set->nheurs);
396
397 *foundsol = (primal->nbestsolsfound > oldnbestsolsfound);
398
399 return SCIP_OKAY;
400}
401
402/** applies one round of propagation */
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 assert(lp->nremovablecols == 0);
1214 assert(lp->nremovablerows == 0);
1215
1216 /* store number of variables for later */
1217 oldnvars = transprob->nvars;
1218
1219 /* inform pricing storage, that LP is now filled with initial data */
1220 SCIPpricestoreStartInitialLP(pricestore);
1221
1222 /* add all initial variables to LP */
1223 SCIPsetDebugMsg(set, "init LP: initial columns\n");
1224 for( v = 0; v < transprob->nvars && !(*cutoff); ++v )
1225 {
1226 var = transprob->vars[v];
1227 assert(SCIPvarGetProbindex(var) >= 0);
1228
1229 if( SCIPvarIsInitial(var) )
1230 {
1231 SCIP_CALL( SCIPpricestoreAddVar(pricestore, blkmem, set, eventqueue, lp, var, 0.0, TRUE) );
1232 }
1233
1234 /* check for empty domains (necessary if no presolving was performed) */
1236 *cutoff = TRUE;
1237 }
1238 assert(lp->nremovablecols == 0);
1239 SCIP_CALL( SCIPpricestoreApplyVars(pricestore, blkmem, set, stat, eventqueue, transprob, tree, lp) );
1240
1241 /* inform pricing storage, that initial LP setup is now finished */
1242 SCIPpricestoreEndInitialLP(pricestore);
1243 }
1244
1245 if( *cutoff )
1246 return SCIP_OKAY;
1247
1248 /* put all initial constraints into the LP */
1249 /* @todo check whether we jumped through the tree */
1250 SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
1251 eventfilter, cliquetable, root, TRUE, cutoff) );
1252
1253 /* putting all initial constraints into the LP might have added new variables */
1254 if( root && !(*cutoff) && transprob->nvars > oldnvars )
1255 {
1256 /* inform pricing storage, that LP is now filled with initial data */
1257 SCIPpricestoreStartInitialLP(pricestore);
1258
1259 /* check all initial variables */
1260 for( v = 0; v < transprob->nvars && !(*cutoff); ++v )
1261 {
1262 var = transprob->vars[v];
1263 assert(SCIPvarGetProbindex(var) >= 0);
1264
1266 {
1267 SCIP_CALL( SCIPpricestoreAddVar(pricestore, blkmem, set, eventqueue, lp, var, 0.0, TRUE) );
1268 }
1269
1270 /* check for empty domains (necessary if no presolving was performed) */
1272 *cutoff = TRUE;
1273 }
1274 assert(lp->nremovablecols == 0);
1275 SCIP_CALL( SCIPpricestoreApplyVars(pricestore, blkmem, set, stat, eventqueue, transprob, tree, lp) );
1276
1277 /* inform pricing storage, that initial LP setup is now finished */
1278 SCIPpricestoreEndInitialLP(pricestore);
1279 }
1280
1281 return SCIP_OKAY;
1282}
1283
1284/** constructs the LP of the current node, but does not load the LP state and warmstart information */
1286 BMS_BLKMEM* blkmem, /**< block memory buffers */
1287 SCIP_SET* set, /**< global SCIP settings */
1288 SCIP_STAT* stat, /**< dynamic problem statistics */
1289 SCIP_PROB* transprob, /**< transformed problem */
1290 SCIP_PROB* origprob, /**< original problem */
1291 SCIP_TREE* tree, /**< branch and bound tree */
1292 SCIP_REOPT* reopt, /**< reoptimization data structure */
1293 SCIP_LP* lp, /**< LP data */
1294 SCIP_PRICESTORE* pricestore, /**< pricing storage */
1295 SCIP_SEPASTORE* sepastore, /**< separation storage */
1296 SCIP_CUTPOOL* cutpool, /**< global cutpool */
1297 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1298 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1299 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1300 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1301 SCIP_Bool newinitconss, /**< do we have to add new initial constraints? */
1302 SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
1303 )
1304{
1305 SCIP_Bool initroot = FALSE;
1306
1307 assert(tree != NULL);
1308 assert(cutoff != NULL);
1309
1310 *cutoff = FALSE;
1311
1313 {
1314 /* inform separation storage, that LP is now filled with initial data */
1315 SCIPsepastoreStartInitialLP(sepastore);
1316
1317 if( tree->correctlpdepth >= 0 )
1318 {
1319 int i;
1320
1321 for( i = tree->pathnlprows[tree->correctlpdepth]; i < lp->nrows; ++i )
1322 {
1323 /* keep all active global cuts that where applied in the previous node in the lp */
1324 if( !lp->rows[i]->local && lp->rows[i]->age == 0 )
1325 {
1326 lp->rows[i]->fromcutpool = TRUE; /* this has no effect inside initial LP, but is set for consistency */
1327 SCIP_CALL( SCIPsepastoreAddCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, lp->rows[i],
1328 TRUE, (SCIPtreeGetCurrentDepth(tree) == 0), cutoff) );
1329 }
1330 }
1331 }
1332
1333 if( !(*cutoff) )
1334 {
1335 /* load the LP into the solver and load the LP state */
1336 SCIPsetDebugMsg(set, "loading LP\n");
1337 SCIP_CALL( SCIPtreeLoadLP(tree, blkmem, set, eventqueue, eventfilter, lp, &initroot) );
1338 assert(initroot || SCIPnodeGetDepth(SCIPtreeGetFocusNode(tree)) > 0);
1340
1341 /* apply cuts */
1342 SCIP_CALL( SCIPsepastoreApplyCuts(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
1343 eventqueue, eventfilter, cliquetable, (SCIPtreeGetCurrentDepth(tree) == 0), SCIP_EFFICIACYCHOICE_LP, cutoff) );
1344 }
1345 else
1346 {
1347 /* the current node will be cut off; we clear the sepastore */
1348 SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
1349 }
1350
1351 /* inform separation storage, that initial LP setup is now finished */
1352 SCIPsepastoreEndInitialLP(sepastore);
1353
1354 if( !(*cutoff) )
1355 {
1356 /* setup initial LP relaxation of node */
1357 SCIP_CALL( initLP(blkmem, set, stat, transprob, origprob, tree, reopt, lp, pricestore, sepastore, cutpool, branchcand,
1358 eventqueue, eventfilter, cliquetable, initroot, cutoff) );
1359 }
1360 }
1361 else if( newinitconss )
1362 {
1363 SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob,
1364 origprob, tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE,
1365 cutoff) );
1366 }
1367
1368 return SCIP_OKAY;
1369}
1370
1371/** updates the primal ray stored in primal data
1372 * clears previously stored primal ray, if existing and there was no LP error
1373 * stores current primal ray, if LP is unbounded and there has been no error
1374 */
1375static
1377 BMS_BLKMEM* blkmem, /**< block memory buffers */
1378 SCIP_SET* set, /**< global SCIP settings */
1379 SCIP_STAT* stat, /**< dynamic problem statistics */
1380 SCIP_PROB* prob, /**< transformed problem after presolve */
1381 SCIP_PRIMAL* primal, /**< primal data */
1382 SCIP_TREE* tree, /**< branch and bound tree */
1383 SCIP_LP* lp, /**< LP data */
1384 SCIP_Bool lperror /**< has there been an LP error? */
1385 )
1386{
1387 assert(blkmem != NULL);
1388 assert(set != NULL);
1389 assert(stat != NULL);
1390 assert(prob != NULL);
1391 assert(primal != NULL);
1392 assert(tree != NULL);
1393 assert(lp != NULL);
1394
1395 if( lperror )
1396 return SCIP_OKAY;
1397
1398 /* clear previously stored primal ray, if any */
1399 if( primal->primalray != NULL )
1400 {
1401 SCIP_CALL( SCIPsolFree(&primal->primalray, blkmem, primal) );
1402 }
1403
1404 /* store unbounded ray, if LP is unbounded */
1406 {
1407 SCIP_VAR** vars;
1408 SCIP_Real* ray;
1409 int nvars;
1410 int i;
1411
1412 SCIPsetDebugMsg(set, "LP is unbounded, store primal ray\n");
1413
1414 vars = prob->vars;
1415 nvars = prob->nvars;
1416
1417 /* get buffer memory for storing the ray and load the ray values into it */
1418 SCIP_CALL( SCIPsetAllocBufferArray(set, &ray, nvars) );
1419 BMSclearMemoryArray(ray, nvars);
1420 SCIP_CALL( SCIPlpGetPrimalRay(lp, set, ray) );
1421
1422 /* create solution to store the primal ray in */
1423 assert(primal->primalray == NULL);
1424 SCIP_CALL( SCIPsolCreate(&primal->primalray, blkmem, set, stat, primal, tree, NULL) );
1425
1426 /* set values of all active variable in the solution that represents the primal ray */
1427 for( i = 0; i < nvars; i++ )
1428 {
1429 SCIP_CALL( SCIPsolSetVal(primal->primalray, set, stat, tree, vars[i], ray[i]) );
1430 }
1431
1432 SCIPdebug( SCIP_CALL( SCIPprintRay(set->scip, primal->primalray, NULL, FALSE) ) );
1433
1434 /* free memory for buffering the ray values */
1436 }
1437
1438 return SCIP_OKAY;
1439}
1440
1441/** load and solve the initial LP of a node */
1442static
1444 BMS_BLKMEM* blkmem, /**< block memory buffers */
1445 SCIP_SET* set, /**< global SCIP settings */
1446 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1447 SCIP_STAT* stat, /**< dynamic problem statistics */
1448 SCIP_PROB* transprob, /**< transformed problem after presolve */
1449 SCIP_PROB* origprob, /**< original problem */
1450 SCIP_PRIMAL* primal, /**< primal data */
1451 SCIP_TREE* tree, /**< branch and bound tree */
1452 SCIP_REOPT* reopt, /**< reoptimization data structure */
1453 SCIP_LP* lp, /**< LP data */
1454 SCIP_PRICESTORE* pricestore, /**< pricing storage */
1455 SCIP_SEPASTORE* sepastore, /**< separation storage */
1456 SCIP_CUTPOOL* cutpool, /**< global cutpool */
1457 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1458 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1459 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1460 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1461 SCIP_Bool newinitconss, /**< do we have to add new initial constraints? */
1462 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
1463 SCIP_Bool* lperror /**< pointer to store whether an unresolved error in LP solving occured */
1464 )
1465{
1466 /* initializing variables for compiler warnings, which are not correct */
1467 SCIP_Real starttime = 0.0;
1468 SCIP_Longint nlpiterations = 0;
1469 SCIP_NODE* focusnode;
1470
1471 assert(stat != NULL);
1472 assert(tree != NULL);
1473 assert(lp != NULL);
1474 assert(cutoff != NULL);
1475 assert(lperror != NULL);
1476 assert(SCIPtreeGetFocusNode(tree) != NULL);
1478
1479 *cutoff = FALSE;
1480 *lperror = FALSE;
1481
1482 /* load the LP into the solver */
1483 SCIP_CALL( SCIPconstructCurrentLP(blkmem, set, stat, transprob, origprob, tree, reopt, lp, pricestore, sepastore, cutpool,
1484 branchcand, eventqueue, eventfilter, cliquetable, newinitconss, cutoff) );
1485
1486 if( *cutoff )
1487 return SCIP_OKAY;
1488
1489 /* load the LP state */
1490 SCIP_CALL( SCIPtreeLoadLPState(tree, blkmem, set, transprob, stat, eventqueue, lp) );
1491
1492 focusnode = SCIPtreeGetFocusNode(tree);
1493
1494 /* store current LP iteration count and solving time if we are at the root node */
1495 if( focusnode->depth == 0 )
1496 {
1497 nlpiterations = stat->nlpiterations;
1498 starttime = SCIPclockGetTime(stat->solvingtime);
1499 }
1500
1501 /* solve initial LP */
1502 SCIPsetDebugMsg(set, "node: solve initial LP\n");
1503 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
1504 SCIPnodeGetDepth(SCIPtreeGetFocusNode(tree)) == 0 ? set->lp_rootiterlim : set->lp_iterlim, TRUE, TRUE, FALSE, lperror) );
1505 assert(lp->flushed);
1506 assert(lp->solved || *lperror);
1507
1508 /* save time for very first LP in root node */
1509 if ( stat->nnodelps == 0 && focusnode->depth == 0 )
1510 {
1511 stat->firstlptime = SCIPclockGetTime(stat->solvingtime) - starttime;
1512 }
1513
1514 /* remove previous primal ray, store new one if LP is unbounded */
1515 SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
1516
1517 if( !(*lperror) )
1518 {
1519 /* cppcheck-suppress unassignedVariable */
1520 SCIP_EVENT event;
1521
1523 {
1524 /* issue FIRSTLPSOLVED event */
1527 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
1528 }
1529
1530 /* update pseudo cost values for integer variables (always) and for continuous variables (if not delayed) */
1531 SCIP_CALL( updatePseudocost(set, stat, transprob, tree, lp, TRUE, !set->branch_delaypscost) );
1532
1533 /* update lower bound of current node w.r.t. initial lp */
1534 assert(!(*cutoff));
1537 && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
1538 {
1539 SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
1540
1541 /* if this is the first LP solved at the root, store its iteration count and solution value */
1542 if( stat->nnodelps == 0 && focusnode->depth == 0 )
1543 {
1544 SCIP_Real lowerbound;
1545
1546 assert(stat->nrootfirstlpiterations == 0);
1547 stat->nrootfirstlpiterations = stat->nlpiterations - nlpiterations;
1548
1549 if( set->misc_exactsolve )
1550 {
1551 SCIP_CALL( SCIPlpGetProvedLowerbound(lp, set, &lowerbound) );
1552 }
1553 else
1554 lowerbound = SCIPlpGetObjval(lp, set, transprob);
1555
1556 stat->firstlpdualbound = SCIPprobExternObjval(transprob, origprob, set, lowerbound);
1557 }
1558 }
1559 }
1560
1561 return SCIP_OKAY;
1562}
1563
1564/** makes sure the LP is flushed and solved */
1565static
1567 BMS_BLKMEM* blkmem, /**< block memory buffers */
1568 SCIP_SET* set, /**< global SCIP settings */
1569 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1570 SCIP_STAT* stat, /**< dynamic problem statistics */
1571 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1572 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1573 SCIP_PROB* prob, /**< transformed problem after presolve */
1574 SCIP_PRIMAL* primal, /**< primal data */
1575 SCIP_TREE* tree, /**< branch and bound tree */
1576 SCIP_LP* lp, /**< LP data */
1577 SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
1578 SCIP_Bool* mustsepa, /**< pointer to store TRUE if additional separation rounds should be performed */
1579 SCIP_Bool* mustprice /**< pointer to store TRUE if additional pricing rounds should be performed */
1580 )
1581{
1582 assert(lp != NULL);
1583 assert(lperror != NULL);
1584 assert(mustsepa != NULL);
1585 assert(mustprice != NULL);
1586
1587 /* if bound changes were applied in the separation round, we have to resolve the LP */
1588 if( !lp->flushed )
1589 {
1590 /* solve LP (with dual simplex) */
1591 SCIPsetDebugMsg(set, "separation: resolve LP\n");
1592 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, prob, set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
1593 assert(lp->flushed);
1594 assert(lp->solved || *lperror);
1595 *mustsepa = TRUE;
1596 *mustprice = TRUE;
1597
1598 /* remove previous primal ray, store new one if LP is unbounded */
1599 SCIP_CALL( updatePrimalRay(blkmem, set, stat, prob, primal, tree, lp, *lperror) );
1600 }
1601
1602 return SCIP_OKAY;
1603}
1604
1605/** applies one round of LP separation */
1606static
1608 BMS_BLKMEM* blkmem, /**< block memory buffers */
1609 SCIP_SET* set, /**< global SCIP settings */
1610 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1611 SCIP_STAT* stat, /**< dynamic problem statistics */
1612 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1613 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1614 SCIP_PROB* prob, /**< transformed problem after presolve */
1615 SCIP_PRIMAL* primal, /**< primal data */
1616 SCIP_TREE* tree, /**< branch and bound tree */
1617 SCIP_LP* lp, /**< LP data */
1618 SCIP_SEPASTORE* sepastore, /**< separation storage */
1619 int actdepth, /**< current depth in the tree */
1620 SCIP_Real bounddist, /**< current relative distance of local dual bound to global dual bound */
1621 SCIP_Bool allowlocal, /**< should the separators be asked to separate local cuts */
1622 SCIP_Bool onlydelayed, /**< should only delayed separators be called? */
1623 SCIP_Bool* delayed, /**< pointer to store whether a separator was delayed */
1624 SCIP_Bool* enoughcuts, /**< pointer to store whether enough cuts have been found this round */
1625 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
1626 SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
1627 SCIP_Bool* mustsepa, /**< pointer to store TRUE if additional separation rounds should be performed */
1628 SCIP_Bool* mustprice /**< pointer to store TRUE if additional pricing rounds should be performed */
1629 )
1630{
1631 SCIP_RESULT result;
1632 int i;
1633 SCIP_Bool consadded;
1634 SCIP_Bool root;
1635
1636 assert(set != NULL);
1637 assert(lp != NULL);
1638 assert(set->conshdlrs_sepa != NULL);
1639 assert(delayed != NULL);
1640 assert(enoughcuts != NULL);
1641 assert(cutoff != NULL);
1642 assert(lperror != NULL);
1643
1644 root = (actdepth == 0);
1645 *delayed = FALSE;
1647 *enoughcuts = TRUE;
1649 *enoughcuts = FALSE;
1650 else
1651 *enoughcuts = (SCIPsepastoreGetNCuts(sepastore) >= (SCIP_Longint)SCIPsetCeil(set,
1653 *lperror = FALSE;
1654 consadded = FALSE;
1655
1656 SCIPsetDebugMsg(set, "calling separators on LP solution in depth %d (onlydelayed: %u)\n", actdepth, onlydelayed);
1657
1658 /* sort separators by priority */
1660
1661 /* call LP separators with nonnegative priority */
1662 for( i = 0; i < set->nsepas && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1664 ++i )
1665 {
1666#ifndef NDEBUG
1667 size_t nusedbuffer = BMSgetNUsedBufferMemory(SCIPbuffer(set->scip));
1668#endif
1669
1670 if( SCIPsepaGetPriority(set->sepas[i]) < 0 )
1671 continue;
1672
1673 if( onlydelayed && !SCIPsepaWasLPDelayed(set->sepas[i]) )
1674 continue;
1675
1676 SCIPsetDebugMsg(set, " -> executing separator <%s> with priority %d\n",
1677 SCIPsepaGetName(set->sepas[i]), SCIPsepaGetPriority(set->sepas[i]));
1678 SCIP_CALL( SCIPsepaExecLP(set->sepas[i], set, stat, sepastore, actdepth, bounddist, allowlocal, onlydelayed, &result) );
1679#ifndef NDEBUG
1680 if( BMSgetNUsedBufferMemory(SCIPbuffer(set->scip)) > nusedbuffer )
1681 {
1682 SCIPerrorMessage("Buffer not completely freed after executing separator <%s>\n", SCIPsepaGetName(set->sepas[i]));
1683 SCIPABORT();
1684 }
1685#endif
1686 *cutoff = *cutoff || (result == SCIP_CUTOFF);
1687 consadded = consadded || (result == SCIP_CONSADDED);
1689 *enoughcuts = TRUE;
1691 *enoughcuts = *enoughcuts || (result == SCIP_NEWROUND);
1692 else
1693 {
1694 *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= (SCIP_Longint)SCIPsetCeil(set,
1696 || (result == SCIP_NEWROUND);
1697 }
1698 *delayed = *delayed || (result == SCIP_DELAYED);
1699
1700 if( !(*cutoff) )
1701 {
1702 /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1703 SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1704 }
1705 else
1706 {
1707 SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1708 }
1709
1710 /* if we work off the delayed separators, we stop immediately if a cut was found */
1711 if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1712 {
1713 SCIPsetDebugMsg(set, " -> delayed separator <%s> found a cut\n", SCIPsepaGetName(set->sepas[i]));
1714 *delayed = TRUE;
1715 return SCIP_OKAY;
1716 }
1717 }
1718
1719 /* try separating constraints of the constraint handlers */
1720 for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1722 ++i )
1723 {
1724 if( onlydelayed && !SCIPconshdlrWasLPSeparationDelayed(set->conshdlrs_sepa[i]) )
1725 continue;
1726
1727 SCIPsetDebugMsg(set, " -> executing separation of constraint handler <%s> with priority %d\n",
1728 SCIPconshdlrGetName(set->conshdlrs_sepa[i]), SCIPconshdlrGetSepaPriority(set->conshdlrs_sepa[i]));
1729 SCIP_CALL( SCIPconshdlrSeparateLP(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, actdepth, onlydelayed,
1730 &result) );
1731
1732 *cutoff = *cutoff || (result == SCIP_CUTOFF);
1733 consadded = consadded || (result == SCIP_CONSADDED);
1735 *enoughcuts = TRUE;
1737 *enoughcuts = *enoughcuts || (result == SCIP_NEWROUND);
1738 else
1739 {
1740 *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= (SCIP_Longint)SCIPsetCeil(set,
1742 || (result == SCIP_NEWROUND);
1743 }
1744 *delayed = *delayed || (result == SCIP_DELAYED);
1745
1746 if( !(*cutoff) )
1747 {
1748 /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1749 SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1750 }
1751 else
1752 {
1753 SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n", SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1754 }
1755
1756 /* if we work off the delayed separators, we stop immediately if a cut was found */
1757 if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1758 {
1759 SCIPsetDebugMsg(set, " -> delayed constraint handler <%s> found a cut\n",
1760 SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1761 *delayed = TRUE;
1762 return SCIP_OKAY;
1763 }
1764 }
1765
1766 /* call LP separators with negative priority */
1767 for( i = 0; i < set->nsepas && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1769 ++i )
1770 {
1771 if( SCIPsepaGetPriority(set->sepas[i]) >= 0 )
1772 continue;
1773
1774 if( onlydelayed && !SCIPsepaWasLPDelayed(set->sepas[i]) )
1775 continue;
1776
1777 SCIPsetDebugMsg(set, " -> executing separator <%s> with priority %d\n",
1778 SCIPsepaGetName(set->sepas[i]), SCIPsepaGetPriority(set->sepas[i]));
1779 SCIP_CALL( SCIPsepaExecLP(set->sepas[i], set, stat, sepastore, actdepth, bounddist, allowlocal, onlydelayed, &result) );
1780
1781 *cutoff = *cutoff || (result == SCIP_CUTOFF);
1782 consadded = consadded || (result == SCIP_CONSADDED);
1784 *enoughcuts = TRUE;
1786 *enoughcuts = *enoughcuts || (result == SCIP_NEWROUND);
1787 else
1788 {
1789 *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= (SCIP_Longint)SCIPsetCeil(set,
1791 || (result == SCIP_NEWROUND);
1792 }
1793 *delayed = *delayed || (result == SCIP_DELAYED);
1794
1795 if( !(*cutoff) )
1796 {
1797 /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1798 SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1799 }
1800 else
1801 {
1802 SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1803 }
1804
1805 /* if we work off the delayed separators, we stop immediately if a cut was found */
1806 if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1807 {
1808 SCIPsetDebugMsg(set, " -> delayed separator <%s> found a cut\n", SCIPsepaGetName(set->sepas[i]));
1809 *delayed = TRUE;
1810 return SCIP_OKAY;
1811 }
1812 }
1813
1814 /* process the constraints that were added during this separation round */
1815 while( consadded )
1816 {
1817 assert(!onlydelayed);
1818 consadded = FALSE;
1819
1820 for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*lperror) && !(*enoughcuts) && lp->flushed && lp->solved
1822 ++i )
1823 {
1824 SCIPsetDebugMsg(set, " -> executing separation of constraint handler <%s> with priority %d\n",
1825 SCIPconshdlrGetName(set->conshdlrs_sepa[i]), SCIPconshdlrGetSepaPriority(set->conshdlrs_sepa[i]));
1826 SCIP_CALL( SCIPconshdlrSeparateLP(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, actdepth, onlydelayed,
1827 &result) );
1828
1829 *cutoff = *cutoff || (result == SCIP_CUTOFF);
1830 consadded = consadded || (result == SCIP_CONSADDED);
1832 *enoughcuts = TRUE;
1834 *enoughcuts = *enoughcuts || (result == SCIP_NEWROUND);
1835 else
1836 {
1837 *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= (SCIP_Longint)SCIPsetCeil(set,
1839 || (result == SCIP_NEWROUND);
1840 }
1841 *delayed = *delayed || (result == SCIP_DELAYED);
1842
1843 if( !(*cutoff) )
1844 {
1845 /* make sure the LP is solved (after adding bound changes, LP has to be flushed and resolved) */
1846 SCIP_CALL( separationRoundResolveLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, lperror, mustsepa, mustprice) );
1847 }
1848 else
1849 {
1850 SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n", SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1851 }
1852 }
1853 }
1854
1855 SCIPsetDebugMsg(set, " -> separation round finished: delayed=%u, enoughcuts=%u, lpflushed=%u, cutoff=%u\n",
1856 *delayed, *enoughcuts, lp->flushed, *cutoff);
1857
1858 return SCIP_OKAY;
1859}
1860
1861/** applies one round of separation on the given primal solution */
1862static
1864 BMS_BLKMEM* blkmem, /**< block memory buffers */
1865 SCIP_SET* set, /**< global SCIP settings */
1866 SCIP_STAT* stat, /**< dynamic problem statistics */
1867 SCIP_SEPASTORE* sepastore, /**< separation storage */
1868 SCIP_SOL* sol, /**< primal solution that should be separated, or NULL for LP solution */
1869 int actdepth, /**< current depth in the tree */
1870 SCIP_Bool allowlocal, /**< should the separator be asked to separate local cuts */
1871 SCIP_Bool onlydelayed, /**< should only delayed separators be called? */
1872 SCIP_Bool* delayed, /**< pointer to store whether a separator was delayed */
1873 SCIP_Bool* enoughcuts, /**< pointer to store whether enough cuts have been found this round */
1874 SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
1875 )
1876{
1877 SCIP_RESULT result;
1878 int i;
1879 SCIP_Bool consadded;
1880 SCIP_Bool root;
1881
1882 assert(set != NULL);
1883 assert(set->conshdlrs_sepa != NULL);
1884 assert(delayed != NULL);
1885 assert(enoughcuts != NULL);
1886 assert(cutoff != NULL);
1887
1888 *delayed = FALSE;
1889 *enoughcuts = FALSE;
1890 consadded = FALSE;
1891 root = (actdepth == 0);
1892
1893 SCIPsetDebugMsg(set, "calling separators on primal solution in depth %d (onlydelayed: %u)\n", actdepth, onlydelayed);
1894
1895 /* sort separators by priority */
1897
1898 /* call separators with nonnegative priority */
1899 for( i = 0; i < set->nsepas && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
1900 {
1901 if( SCIPsepaGetPriority(set->sepas[i]) < 0 )
1902 continue;
1903
1904 if( onlydelayed && !SCIPsepaWasSolDelayed(set->sepas[i]) )
1905 continue;
1906
1907 SCIP_CALL( SCIPsepaExecSol(set->sepas[i], set, stat, sepastore, sol, actdepth, allowlocal, onlydelayed, &result) );
1908 *cutoff = *cutoff || (result == SCIP_CUTOFF);
1909 consadded = consadded || (result == SCIP_CONSADDED);
1911 *enoughcuts = TRUE;
1913 *enoughcuts = *enoughcuts || (result == SCIP_NEWROUND);
1914 else
1915 {
1916 *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= (SCIP_Longint)SCIPsetCeil(set,
1918 || (result == SCIP_NEWROUND);
1919 }
1920 *delayed = *delayed || (result == SCIP_DELAYED);
1921 if( *cutoff )
1922 {
1923 SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1924 }
1925
1926 /* if we work off the delayed separators, we stop immediately if a cut was found */
1927 if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1928 {
1929 *delayed = TRUE;
1930 return SCIP_OKAY;
1931 }
1932 }
1933
1934 /* try separating constraints of the constraint handlers */
1935 for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
1936 {
1937 if( onlydelayed && !SCIPconshdlrWasSolSeparationDelayed(set->conshdlrs_sepa[i]) )
1938 continue;
1939
1940 SCIP_CALL( SCIPconshdlrSeparateSol(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, sol, actdepth, onlydelayed,
1941 &result) );
1942 *cutoff = *cutoff || (result == SCIP_CUTOFF);
1943 consadded = consadded || (result == SCIP_CONSADDED);
1945 *enoughcuts = TRUE;
1947 *enoughcuts = *enoughcuts || (result == SCIP_NEWROUND);
1948 else
1949 {
1950 *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= (SCIP_Longint)SCIPsetCeil(set,
1952 || (result == SCIP_NEWROUND);
1953 }
1954 *delayed = *delayed || (result == SCIP_DELAYED);
1955 if( *cutoff )
1956 {
1957 SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n",
1958 SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
1959 }
1960
1961 /* if we work off the delayed separators, we stop immediately if a cut was found */
1962 if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1963 {
1964 *delayed = TRUE;
1965 return SCIP_OKAY;
1966 }
1967 }
1968
1969 /* call separators with negative priority */
1970 for( i = 0; i < set->nsepas && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
1971 {
1972 if( SCIPsepaGetPriority(set->sepas[i]) >= 0 )
1973 continue;
1974
1975 if( onlydelayed && !SCIPsepaWasSolDelayed(set->sepas[i]) )
1976 continue;
1977
1978 SCIP_CALL( SCIPsepaExecSol(set->sepas[i], set, stat, sepastore, sol, actdepth, allowlocal, onlydelayed, &result) );
1979 *cutoff = *cutoff || (result == SCIP_CUTOFF);
1980 consadded = consadded || (result == SCIP_CONSADDED);
1982 *enoughcuts = TRUE;
1984 *enoughcuts = *enoughcuts || (result == SCIP_NEWROUND);
1985 else
1986 {
1987 *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= (SCIP_Longint)SCIPsetCeil(set,
1989 || (result == SCIP_NEWROUND);
1990 }
1991 *delayed = *delayed || (result == SCIP_DELAYED);
1992 if( *cutoff )
1993 {
1994 SCIPsetDebugMsg(set, " -> separator <%s> detected cutoff\n", SCIPsepaGetName(set->sepas[i]));
1995 }
1996
1997 /* if we work off the delayed separators, we stop immediately if a cut was found */
1998 if( onlydelayed && (result == SCIP_CONSADDED || result == SCIP_REDUCEDDOM || result == SCIP_SEPARATED || result == SCIP_NEWROUND) )
1999 {
2000 *delayed = TRUE;
2001 return SCIP_OKAY;
2002 }
2003 }
2004
2005 /* process the constraints that were added during this separation round */
2006 while( consadded )
2007 {
2008 assert(!onlydelayed);
2009 consadded = FALSE;
2010
2011 for( i = 0; i < set->nconshdlrs && !(*cutoff) && !(*enoughcuts) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
2012 {
2013 SCIP_CALL( SCIPconshdlrSeparateSol(set->conshdlrs_sepa[i], blkmem, set, stat, sepastore, sol, actdepth, onlydelayed, &result) );
2014 *cutoff = *cutoff || (result == SCIP_CUTOFF);
2015 consadded = consadded || (result == SCIP_CONSADDED);
2017 *enoughcuts = TRUE;
2019 *enoughcuts = *enoughcuts || (result == SCIP_NEWROUND);
2020 else
2021 {
2022 *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= (SCIP_Longint)SCIPsetCeil(set,
2024 || (result == SCIP_NEWROUND);
2025 }
2026 *delayed = *delayed || (result == SCIP_DELAYED);
2027 if( *cutoff )
2028 {
2029 SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in separation\n",
2030 SCIPconshdlrGetName(set->conshdlrs_sepa[i]));
2031 }
2032 }
2033 }
2034
2035 SCIPsetDebugMsg(set, " -> separation round finished: delayed=%u, enoughcuts=%u, cutoff=%u\n",
2036 *delayed, *enoughcuts, *cutoff);
2037
2038 return SCIP_OKAY;
2039}
2040
2041/** applies one round of separation on the given primal solution or on the LP solution */
2043 BMS_BLKMEM* blkmem, /**< block memory buffers */
2044 SCIP_SET* set, /**< global SCIP settings */
2045 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2046 SCIP_STAT* stat, /**< dynamic problem statistics */
2047 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2048 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
2049 SCIP_PROB* prob, /**< transformed problem after presolve */
2050 SCIP_PRIMAL* primal, /**< primal data */
2051 SCIP_TREE* tree, /**< branch and bound tree */
2052 SCIP_LP* lp, /**< LP data */
2053 SCIP_SEPASTORE* sepastore, /**< separation storage */
2054 SCIP_SOL* sol, /**< primal solution that should be separated, or NULL for LP solution */
2055 int actdepth, /**< current depth in the tree */
2056 SCIP_Bool allowlocal, /**< should the separator be asked to separate local cuts */
2057 SCIP_Bool onlydelayed, /**< should only delayed separators be called? */
2058 SCIP_Bool* delayed, /**< pointer to store whether a separator was delayed */
2059 SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
2060 )
2061{
2062 SCIP_Bool enoughcuts;
2063
2064 assert(delayed != NULL);
2065 assert(cutoff != NULL);
2066
2067 *delayed = FALSE;
2068 *cutoff = FALSE;
2069 enoughcuts = FALSE;
2070
2071 if( sol == NULL )
2072 {
2073 SCIP_Bool lperror;
2074 SCIP_Bool mustsepa;
2075 SCIP_Bool mustprice;
2076
2077 /* apply a separation round on the LP solution */
2078 lperror = FALSE;
2079 mustsepa = FALSE;
2080 mustprice = FALSE;
2081 SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, prob, primal, tree, lp, sepastore, \
2082 actdepth, 0.0, allowlocal, onlydelayed, delayed, &enoughcuts, cutoff, \
2083 &lperror, &mustsepa, &mustprice) );
2084 }
2085 else
2086 {
2087 /* apply a separation round on the given primal solution */
2088 SCIP_CALL( separationRoundSol(blkmem, set, stat, sepastore, sol, actdepth, allowlocal, onlydelayed, delayed, &enoughcuts, cutoff) );
2089 }
2090
2091 return SCIP_OKAY;
2092}
2093
2094/** solves the current LP completely with pricing in new variables */
2096 BMS_BLKMEM* blkmem, /**< block memory buffers */
2097 SCIP_SET* set, /**< global SCIP settings */
2098 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2099 SCIP_STAT* stat, /**< dynamic problem statistics */
2100 SCIP_PROB* transprob, /**< transformed problem */
2101 SCIP_PROB* origprob, /**< original problem */
2102 SCIP_PRIMAL* primal, /**< primal data */
2103 SCIP_TREE* tree, /**< branch and bound tree */
2104 SCIP_REOPT* reopt, /**< reoptimization data structure */
2105 SCIP_LP* lp, /**< LP data */
2106 SCIP_PRICESTORE* pricestore, /**< pricing storage */
2107 SCIP_SEPASTORE* sepastore, /**< separation storage */
2108 SCIP_CUTPOOL* cutpool, /**< global cutpool */
2109 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2110 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2111 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
2112 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2113 SCIP_Bool pretendroot, /**< should the pricers be called as if we are at the root node? */
2114 SCIP_Bool displayinfo, /**< should info lines be displayed after each pricing round? */
2115 int maxpricerounds, /**< maximal number of pricing rounds (-1: no limit);
2116 * a finite limit means that the LP might not be solved to optimality! */
2117 int* npricedcolvars, /**< pointer to store number of column variables after problem vars were priced */
2118 SCIP_Bool* mustsepa, /**< pointer to store TRUE if a separation round should follow */
2119 SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
2120 SCIP_Bool* aborted /**< pointer to store whether the pricing was aborted and the lower bound must
2121 * not be used */
2122 )
2123{
2124 SCIP_NODE* currentnode;
2125 int npricerounds;
2126 SCIP_Bool mustprice;
2127 SCIP_Bool cutoff;
2128 SCIP_Bool unbounded;
2129
2130 assert(transprob != NULL);
2131 assert(lp != NULL);
2132 assert(lp->flushed);
2133 assert(lp->solved);
2134 assert(npricedcolvars != NULL);
2135 assert(mustsepa != NULL);
2136 assert(lperror != NULL);
2137 assert(aborted != NULL);
2138
2139 currentnode = SCIPtreeGetCurrentNode(tree);
2140 assert(currentnode == SCIPtreeGetFocusNode(tree) || SCIPtreeProbing(tree));
2141 *npricedcolvars = transprob->ncolvars;
2142 *lperror = FALSE;
2143 *aborted = FALSE;
2144
2145 /* if the LP is unbounded, we don't need to price */
2146 mustprice = (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL
2149
2150 /* if all the variables are already in the LP, we don't need to price */
2151 mustprice = mustprice && !SCIPprobAllColsInLP(transprob, set, lp);
2152
2153 /* check if infinite number of pricing rounds should be used */
2154 if( maxpricerounds == -1 )
2155 maxpricerounds = INT_MAX;
2156
2157 /* pricing (has to be done completely to get a valid lower bound) */
2158 npricerounds = 0;
2159 while( !(*lperror) && mustprice && npricerounds < maxpricerounds )
2160 {
2161 SCIP_Bool enoughvars;
2162 SCIP_RESULT result;
2163 SCIP_Real lb;
2164 SCIP_Bool foundsol;
2165 SCIP_Bool stopearly;
2166 SCIP_Bool stoppricing;
2167 int p;
2168
2169 assert(lp->flushed);
2170 assert(lp->solved);
2172
2173 /* check if pricing loop should be aborted */
2174 if( SCIPsolveIsStopped(set, stat, FALSE) )
2175 {
2176 /* do not print the warning message if we stopped because the problem is solved */
2178 SCIPmessagePrintWarning(messagehdlr, "pricing has been interrupted -- LP of current node is invalid\n");
2179
2180 *aborted = TRUE;
2181 break;
2182 }
2183
2184 /* call primal heuristics which are callable during pricing */
2185 SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, SCIP_HEURTIMING_DURINGPRICINGLOOP,
2186 FALSE, &foundsol, &unbounded) );
2187
2188 /* price problem variables */
2189 SCIPsetDebugMsg(set, "problem variable pricing\n");
2190 assert(SCIPpricestoreGetNVars(pricestore) == 0);
2191 assert(SCIPpricestoreGetNBoundResets(pricestore) == 0);
2192 SCIP_CALL( SCIPpricestoreAddProbVars(pricestore, blkmem, set, stat, transprob, tree, lp, branchcand, eventqueue) );
2193 *npricedcolvars = transprob->ncolvars;
2194
2195 /* call external pricers to create additional problem variables */
2196 SCIPsetDebugMsg(set, "external variable pricing\n");
2197
2198 /* sort pricer algorithms by priority */
2200
2201 /* call external pricer algorithms, that are active for the current problem */
2202 enoughvars = (SCIPsetGetPriceMaxvars(set, pretendroot) == INT_MAX ?
2203 FALSE : SCIPpricestoreGetNVars(pricestore) >= SCIPsetGetPriceMaxvars(set, pretendroot) + 1);
2204 stoppricing = FALSE;
2205 for( p = 0; p < set->nactivepricers && !enoughvars; ++p )
2206 {
2207 SCIP_CALL( SCIPpricerExec(set->pricers[p], set, transprob, lp, pricestore, &lb, &stopearly, &result) );
2208 assert(result == SCIP_DIDNOTRUN || result == SCIP_SUCCESS);
2209 SCIPsetDebugMsg(set, "pricing: pricer %s returned result = %s, lowerbound = %f\n",
2210 SCIPpricerGetName(set->pricers[p]), (result == SCIP_DIDNOTRUN ? "didnotrun" : "success"), lb);
2211 enoughvars = enoughvars || (SCIPsetGetPriceMaxvars(set, pretendroot) == INT_MAX ?
2212 FALSE : SCIPpricestoreGetNVars(pricestore) >= SCIPsetGetPriceMaxvars(set, pretendroot) + 1);
2213 *aborted = ( (*aborted) || (result == SCIP_DIDNOTRUN) );
2214
2215 /* set stoppricing to TRUE, if the first pricer wants to stop pricing */
2216 if( p == 0 && stopearly )
2217 stoppricing = TRUE;
2218
2219 /* stoppricing only remains TRUE, if all other pricers want to stop pricing as well */
2220 if( stoppricing && !stopearly )
2221 stoppricing = FALSE;
2222
2223 /* update lower bound w.r.t. the lower bound given by the pricer */
2224 SCIPnodeUpdateLowerbound(currentnode, stat, set, tree, transprob, origprob, lb);
2225 SCIPsetDebugMsg(set, " -> new lower bound given by pricer %s: %g\n", SCIPpricerGetName(set->pricers[p]), lb);
2226 }
2227
2228 /* apply the priced variables to the LP */
2229 SCIP_CALL( SCIPpricestoreApplyVars(pricestore, blkmem, set, stat, eventqueue, transprob, tree, lp) );
2230 assert(SCIPpricestoreGetNVars(pricestore) == 0);
2231 assert(!lp->flushed || lp->solved);
2232 mustprice = !lp->flushed || (transprob->ncolvars != *npricedcolvars);
2233 *mustsepa = *mustsepa || !lp->flushed;
2234
2235 /* after adding columns, the LP should be primal feasible such that the primal simplex is applicable;
2236 * if LP was infeasible, we have to use dual simplex
2237 */
2238 SCIPsetDebugMsg(set, "pricing: solve LP\n");
2239 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, TRUE, FALSE, lperror) );
2240 assert(lp->flushed);
2241 assert(lp->solved || *lperror);
2242
2243 /* reset bounds temporarily set by pricer to their original values */
2244 SCIPsetDebugMsg(set, "pricing: reset bounds\n");
2245 SCIP_CALL( SCIPpricestoreResetBounds(pricestore, blkmem, set, stat, lp, branchcand, eventqueue) );
2246 assert(SCIPpricestoreGetNVars(pricestore) == 0);
2247 assert(SCIPpricestoreGetNBoundResets(pricestore) == 0);
2248 assert(!lp->flushed || lp->solved || *lperror);
2249
2250 /* put all initial constraints into the LP */
2251 SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
2252 eventfilter, cliquetable, FALSE, FALSE, &cutoff) );
2253 assert(cutoff == FALSE);
2254
2255 mustprice = mustprice || !lp->flushed || (transprob->ncolvars != *npricedcolvars);
2256 *mustsepa = *mustsepa || !lp->flushed;
2257
2258 /* if all pricers wanted to stop pricing, do not do another pricing round (LP value is no valid dual bound in this case) */
2259 if( stoppricing )
2260 {
2261 SCIPsetDebugMsg(set, "pricing: stop pricing and perform early branching\n");
2262 mustprice = FALSE;
2263 *aborted = TRUE;
2264 }
2265
2266 /* solve LP again after resetting bounds and adding new initial constraints (with dual simplex) */
2267 SCIPsetDebugMsg(set, "pricing: solve LP after resetting bounds and adding new initial constraints\n");
2268 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, FALSE, lperror) );
2269 assert(lp->flushed);
2270 assert(lp->solved || *lperror);
2271
2272 /* remove previous primal ray, store new one if LP is unbounded */
2273 SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2274
2275 /* increase pricing round counter */
2276 stat->npricerounds++;
2277 npricerounds++;
2278
2279 /* display node information line */
2280 if( displayinfo && mustprice )
2281 {
2282 if( (SCIP_VERBLEVEL)set->disp_verblevel >= SCIP_VERBLEVEL_FULL
2283 || ((SCIP_VERBLEVEL)set->disp_verblevel >= SCIP_VERBLEVEL_HIGH && npricerounds % 100 == 1) )
2284 {
2285 SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, TRUE, TRUE) );
2286 }
2287 }
2288
2289 /* if the LP is unbounded, we can stop pricing */
2290 mustprice = mustprice &&
2294
2295 /* if the lower bound is already higher than the cutoff bound, we can stop pricing */
2296 mustprice = mustprice && SCIPsetIsLT(set, SCIPnodeGetLowerbound(currentnode), primal->cutoffbound);
2297 } /*lint !e438*/
2298 assert(lp->flushed);
2299 assert(lp->solved || *lperror);
2300
2301 *aborted = ( (*aborted) || (*lperror) || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_NOTSOLVED
2302 || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_ERROR || npricerounds == maxpricerounds );
2303
2304 /* set information, whether the current lp is a valid relaxation of the current problem */
2305 SCIPlpSetIsRelax(lp, !(*aborted));
2306
2307 return SCIP_OKAY; /*lint !e438*/
2308}
2309
2310/** separates cuts of the cut pool */
2311static
2313 SCIP_CUTPOOL* cutpool, /**< cut pool */
2314 BMS_BLKMEM* blkmem, /**< block memory */
2315 SCIP_SET* set, /**< global SCIP settings */
2316 SCIP_STAT* stat, /**< problem statistics data */
2317 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2318 SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
2319 SCIP_LP* lp, /**< current LP data */
2320 SCIP_SEPASTORE* sepastore, /**< separation storage */
2321 SCIP_Bool cutpoolisdelayed, /**< is the cutpool delayed (count cuts found)? */
2322 SCIP_Bool root, /**< are we at the root node? */
2323 int actdepth, /**< the depth of the focus node */
2324 SCIP_Bool* enoughcuts, /**< pointer to store if enough cuts were found in current separation round */
2325 SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
2326 )
2327{
2328 if( (set->sepa_poolfreq == 0 && actdepth == 0)
2329 || (set->sepa_poolfreq > 0 && actdepth % set->sepa_poolfreq == 0) )
2330 {
2331 SCIP_RESULT result;
2332
2333 SCIP_CALL( SCIPcutpoolSeparate(cutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, NULL, cutpoolisdelayed, root, &result) );
2334 *cutoff = *cutoff || (result == SCIP_CUTOFF);
2336 *enoughcuts = TRUE;
2338 *enoughcuts = *enoughcuts || (result == SCIP_NEWROUND);
2339 else
2340 {
2341 *enoughcuts = *enoughcuts || (SCIPsepastoreGetNCuts(sepastore) >= (SCIP_Longint)SCIPsetCeil(set,
2343 || (result == SCIP_NEWROUND);
2344 }
2345 }
2346
2347 return SCIP_OKAY;
2348}
2349
2350/** solve the current LP of a node with a price-and-cut loop */
2351static
2353 BMS_BLKMEM* blkmem, /**< block memory buffers */
2354 SCIP_SET* set, /**< global SCIP settings */
2355 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2356 SCIP_STAT* stat, /**< dynamic problem statistics */
2357 SCIP_MEM* mem, /**< block memory pools */
2358 SCIP_PROB* transprob, /**< transformed problem */
2359 SCIP_PROB* origprob, /**< original problem */
2360 SCIP_PRIMAL* primal, /**< primal data */
2361 SCIP_TREE* tree, /**< branch and bound tree */
2362 SCIP_REOPT* reopt, /**< reoptimization data structure */
2363 SCIP_LP* lp, /**< LP data */
2364 SCIP_PRICESTORE* pricestore, /**< pricing storage */
2365 SCIP_SEPASTORE* sepastore, /**< separation storage */
2366 SCIP_CUTPOOL* cutpool, /**< global cut pool */
2367 SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
2368 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2369 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2370 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
2371 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
2372 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2373 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2374 SCIP_Bool fullseparation, /**< are we in the first prop-and-cut-and-price loop? */
2375 SCIP_Bool* propagateagain, /**< pointer to store whether we want to propagate again */
2376 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
2377 SCIP_Bool* unbounded, /**< pointer to store whether an unbounded ray was found in the LP */
2378 SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
2379 SCIP_Bool* pricingaborted /**< pointer to store whether the pricing was aborted and the lower bound must
2380 * not be used */
2381 )
2382{
2383 SCIP_NODE* focusnode;
2384 /* cppcheck-suppress unassignedVariable */
2385 SCIP_EVENT event;
2386 SCIP_LPSOLSTAT stalllpsolstat;
2387 SCIP_Real loclowerbound;
2388 SCIP_Real glblowerbound;
2389 SCIP_Real bounddist;
2390 SCIP_Real stalllpobjval;
2391 SCIP_Bool separate;
2392 SCIP_Bool mustprice;
2393 SCIP_Bool mustsepa;
2394 SCIP_Bool delayedsepa;
2395 SCIP_Bool root;
2396 SCIP_Bool allowlocal;
2397 int maxseparounds;
2398 int nsepastallrounds;
2399 int maxnsepastallrounds;
2400 int stallnfracs;
2401 int actdepth;
2402 int npricedcolvars;
2403
2404 assert(set != NULL);
2405 assert(blkmem != NULL);
2406 assert(stat != NULL);
2407 assert(transprob != NULL);
2408 assert(tree != NULL);
2409 assert(lp != NULL);
2410 assert(pricestore != NULL);
2411 assert(sepastore != NULL);
2412 assert(cutpool != NULL);
2413 assert(delayedcutpool != NULL);
2414 assert(primal != NULL);
2415 assert(cutoff != NULL);
2416 assert(unbounded != NULL);
2417 assert(lperror != NULL);
2418
2419 focusnode = SCIPtreeGetFocusNode(tree);
2420 assert(focusnode != NULL);
2421 assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
2422 actdepth = SCIPnodeGetDepth(focusnode);
2423 root = (actdepth == 0);
2424
2425 /* check, if we want to separate at this node */
2426 loclowerbound = SCIPnodeGetLowerbound(focusnode);
2427 glblowerbound = SCIPtreeGetLowerbound(tree, set);
2428 assert(primal->cutoffbound > glblowerbound);
2429 bounddist = (loclowerbound - glblowerbound)/(primal->cutoffbound - glblowerbound);
2430 allowlocal = SCIPsetIsLE(set, bounddist, set->sepa_maxlocalbounddist);
2431 separate = (set->sepa_maxruns == -1 || stat->nruns < set->sepa_maxruns);
2432
2433 /* get maximal number of separation rounds */
2434 maxseparounds = (root ? set->sepa_maxroundsroot : set->sepa_maxrounds);
2435 if( maxseparounds == -1 )
2436 maxseparounds = INT_MAX;
2437 if( stat->nruns > 1 && root && set->sepa_maxroundsrootsubrun >= 0 )
2438 maxseparounds = MIN(maxseparounds, set->sepa_maxroundsrootsubrun);
2439 if( !fullseparation && set->sepa_maxaddrounds >= 0 )
2440 maxseparounds = MIN(maxseparounds, stat->nseparounds + set->sepa_maxaddrounds);
2441 maxnsepastallrounds = root ? set->sepa_maxstallroundsroot : set->sepa_maxstallrounds;
2442 if( maxnsepastallrounds == -1 )
2443 maxnsepastallrounds = INT_MAX;
2444
2445 /* solve initial LP of price-and-cut loop */
2446 SCIPsetDebugMsg(set, "node: solve LP with price and cut\n");
2447 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2448 set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2449 assert(lp->flushed);
2450 assert(lp->solved || *lperror);
2451
2452 /* remove previous primal ray, store new one if LP is unbounded */
2453 SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2454
2455 /* price-and-cut loop */
2456 npricedcolvars = transprob->ncolvars;
2457 mustprice = TRUE;
2458 mustsepa = separate;
2459 delayedsepa = FALSE;
2460 *cutoff = FALSE;
2461 *unbounded = (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
2462 nsepastallrounds = 0;
2463 stalllpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2464 stalllpobjval = SCIP_REAL_MIN;
2465 stallnfracs = INT_MAX;
2466 lp->installing = FALSE;
2467 while( !(*cutoff) && !(*unbounded) && !(*lperror) && (mustprice || mustsepa || delayedsepa) )
2468 {
2469 SCIPsetDebugMsg(set, "-------- node solving loop --------\n");
2470 assert(lp->flushed);
2471 assert(lp->solved);
2472
2473 /* solve the LP with pricing in new variables */
2474 while( mustprice && !(*lperror) )
2475 {
2476 SCIP_CALL( SCIPpriceLoop(blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
2477 pricestore, sepastore, cutpool, branchcand, eventqueue, eventfilter, cliquetable, root, root, -1, &npricedcolvars,
2478 &mustsepa, lperror, pricingaborted) );
2479
2480 mustprice = FALSE;
2481
2482 assert(lp->flushed);
2483 assert(lp->solved || *lperror);
2484
2485 /* update lower bound w.r.t. the LP solution */
2486 if( !(*lperror) && !(*pricingaborted) && SCIPlpIsRelax(lp) )
2487 {
2488 SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2489 SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2490 SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2491
2492 /* update node estimate */
2493 SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2494
2495 if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2496 SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2497 }
2498 else
2499 {
2500 SCIPsetDebugMsg(set, " -> error solving LP or pricing aborted. keeping old bound: %g\n", SCIPnodeGetLowerbound(focusnode));
2501 }
2502
2503 /* display node information line for root node */
2504 if( root && (SCIP_VERBLEVEL)set->disp_verblevel >= SCIP_VERBLEVEL_HIGH )
2505 {
2506 SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, TRUE, TRUE) );
2507 }
2508
2509 if( !(*lperror) )
2510 {
2511 /* call propagators that are applicable during LP solving loop only if the node is not cut off */
2512 if( SCIPsetIsLT(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound) )
2513 {
2514 SCIP_Longint oldnboundchgs;
2515 SCIP_Longint oldninitconssadded;
2516 SCIP_Bool postpone;
2517
2518 oldnboundchgs = stat->nboundchgs;
2519 oldninitconssadded = stat->ninitconssadded;
2520
2521 SCIPsetDebugMsg(set, " -> LP solved: call propagators that are applicable during LP solving loop\n");
2522
2523 SCIP_CALL( propagateDomains(blkmem, set, stat, tree, SCIPtreeGetCurrentDepth(tree), 0, FALSE,
2524 SCIP_PROPTIMING_DURINGLPLOOP, cutoff, &postpone) );
2525 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2526 assert(!postpone);
2527
2528 if( stat->ninitconssadded != oldninitconssadded )
2529 {
2530 SCIPsetDebugMsg(set, "new initial constraints added during propagation: old=%" SCIP_LONGINT_FORMAT ", new=%" SCIP_LONGINT_FORMAT "\n", oldninitconssadded, stat->ninitconssadded);
2531
2532 SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp,
2533 branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE, cutoff) );
2534 }
2535
2536 if( !(*cutoff) && !(*unbounded) )
2537 {
2538 /* if we found something, solve LP again */
2539 if( !lp->flushed )
2540 {
2541 SCIPsetDebugMsg(set, " -> found reduction: resolve LP\n");
2542
2543 /* in the root node, remove redundant rows permanently from the LP */
2544 if( root )
2545 {
2546 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, transprob, eventqueue) );
2547 SCIP_CALL( SCIPlpRemoveRedundantRows(lp, blkmem, set, stat, eventqueue, eventfilter) );
2548 }
2549
2550 /* resolve LP */
2551 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2552 set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2553 assert(lp->flushed);
2554 assert(lp->solved || *lperror);
2555
2556 /* remove previous primal ray, store new one if LP is unbounded */
2557 SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2558
2559 mustprice = TRUE;
2560 *propagateagain = TRUE;
2561 }
2562 /* propagation might have changed the best bound of loose variables, thereby changing the loose objective
2563 * value which is added to the LP value; because of the loose status, the LP might not be reoptimized,
2564 * but the lower bound of the node needs to be updated
2565 */
2566 else if( stat->nboundchgs > oldnboundchgs )
2567 {
2568 *propagateagain = TRUE;
2569
2570 if( lp->solved && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
2571 {
2572 assert(lp->flushed);
2573 assert(lp->solved);
2574
2575 SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2576 SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2577 SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2578
2579 /* update node estimate */
2580 SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2581
2582 if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2583 SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2584 }
2585 }
2586 }
2587 }
2588 }
2589
2590 /* call primal heuristics that are applicable during node LP solving loop */
2591 if( !*cutoff && !(*unbounded) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2592 {
2593 SCIP_Bool foundsol;
2594
2595 SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, SCIP_HEURTIMING_DURINGLPLOOP,
2596 FALSE, &foundsol, unbounded) );
2597 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2598
2599 *lperror = *lperror || lp->resolvelperror;
2600 } /*lint !e438*/
2601 }
2602 assert(lp->flushed || *cutoff || *unbounded);
2603 assert(lp->solved || *lperror || *cutoff || *unbounded);
2604
2605 /* check, if we exceeded the separation round limit */
2606 mustsepa = mustsepa
2607 && stat->nseparounds < maxseparounds
2608 && nsepastallrounds < maxnsepastallrounds
2609 && !(*cutoff);
2610
2611 /* if separators were delayed, we want to apply a final separation round with the delayed separators */
2612 delayedsepa = delayedsepa && !mustsepa && !(*cutoff); /* if regular separation applies, we ignore delayed separators */
2613 mustsepa = mustsepa || delayedsepa;
2614
2615 if( mustsepa )
2616 {
2617 /* if the LP is infeasible, unbounded, exceeded the objective limit or a global performance limit was reached,
2618 * we don't need to separate cuts
2619 * (the global limits are only checked at the root node in order to not query system time too often)
2620 */
2621 if( !separate || (*cutoff) || (*unbounded)
2623 || SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound)
2624 || (root && SCIPsolveIsStopped(set, stat, FALSE)) )
2625 {
2626 mustsepa = FALSE;
2627 delayedsepa = FALSE;
2628 }
2629 else
2630 assert(!(*lperror));
2631 }
2632
2633 /* separation (needs not to be done completely, because we just want to increase the lower bound) */
2634 if( mustsepa )
2635 {
2636 SCIP_Longint olddomchgcount;
2637 SCIP_Longint oldninitconssadded;
2638 SCIP_Bool enoughcuts;
2639
2640 assert(lp->flushed);
2641 assert(lp->solved);
2643 assert(!(*lperror));
2644 assert(!(*cutoff));
2645
2646 olddomchgcount = stat->domchgcount;
2647 oldninitconssadded = stat->ninitconssadded;
2648
2649 mustsepa = FALSE;
2651
2652 /* global cut pool separation */
2653 if( !enoughcuts && !delayedsepa )
2654 {
2655 SCIP_CALL( cutpoolSeparate(cutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, FALSE, root,
2656 actdepth, &enoughcuts, cutoff) );
2657
2658 if( *cutoff )
2659 {
2660 SCIPsetDebugMsg(set, " -> global cut pool detected cutoff\n");
2661 }
2662 }
2663 assert(lp->flushed);
2664 assert(lp->solved);
2666 assert(!(*lperror));
2667
2668 /* separate constraints and LP */
2669 if( !(*cutoff) && !enoughcuts )
2670 {
2671 /* constraint and LP separation */
2672 SCIPsetDebugMsg(set, "constraint and LP separation\n");
2673
2674 /* apply a separation round */
2675 SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal, tree,
2676 lp, sepastore, actdepth, bounddist, allowlocal, delayedsepa,
2677 &delayedsepa, &enoughcuts, cutoff, lperror, &mustsepa, &mustprice) );
2678 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2679
2680 /* if we are close to the stall round limit, also call the delayed separators */
2681 if( !(*cutoff) && !(*lperror) && !enoughcuts && lp->solved
2683 && nsepastallrounds >= maxnsepastallrounds-1 && delayedsepa )
2684 {
2685 SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal,
2686 tree, lp, sepastore, actdepth, bounddist, allowlocal, delayedsepa,
2687 &delayedsepa, &enoughcuts, cutoff, lperror, &mustsepa, &mustprice) );
2688 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2689 }
2690 }
2691
2692 /* call global cut pool separation again since separators may add cuts to the pool instead of the sepastore */
2693 if( !(*cutoff) && !(*lperror) && lp->solved && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && !enoughcuts )
2694 {
2695 SCIP_CALL( cutpoolSeparate(cutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, FALSE, root,
2696 actdepth, &enoughcuts, cutoff) );
2697
2698 if( *cutoff )
2699 {
2700 SCIPsetDebugMsg(set, " -> global cut pool detected cutoff\n");
2701 }
2702 }
2703
2704 /* delayed global cut pool separation */
2705 if( !(*cutoff) && !(*lperror) && lp->solved && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && SCIPsepastoreGetNCuts(sepastore) == 0 && !enoughcuts )
2706 {
2707 SCIP_CALL( cutpoolSeparate(delayedcutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, TRUE,
2708 root, actdepth, &enoughcuts, cutoff) );
2709
2710 if( *cutoff )
2711 {
2712 SCIPsetDebugMsg(set, " -> delayed global cut pool detected cutoff\n");
2713 }
2714 assert(lp->solved);
2716 assert(lp->flushed);
2717 }
2718
2719 /* delayed separation if no cuts where produced */
2720 if( !(*cutoff) && !(*lperror) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && SCIPsepastoreGetNCuts(sepastore) == 0 && delayedsepa )
2721 {
2722 SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal,
2723 tree, lp, sepastore, actdepth, bounddist, allowlocal, delayedsepa,
2724 &delayedsepa, &enoughcuts, cutoff, lperror, &mustsepa, &mustprice) );
2725 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2726
2727 /* call delayed cut pool separation again, since separators may add cuts to the pool instead of the sepastore */
2728 if( !(*cutoff) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2729 {
2730 assert( !(*lperror) );
2731
2732 SCIP_CALL( cutpoolSeparate(delayedcutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, TRUE,
2733 root, actdepth, &enoughcuts, cutoff) );
2734
2735 if( *cutoff )
2736 {
2737 SCIPsetDebugMsg(set, " -> delayed global cut pool detected cutoff\n");
2738 }
2740 assert(lp->flushed);
2741 assert(lp->solved);
2742 }
2743 }
2744
2745 assert(*cutoff || *lperror || SCIPlpIsSolved(lp));
2746 assert(!SCIPlpIsSolved(lp)
2753
2754 if( *cutoff || *lperror
2757 {
2758 /* the found cuts are of no use, because the node is infeasible anyway (or we have an error in the LP) */
2759 SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
2760 }
2761 else
2762 {
2763 /* apply found cuts */
2764 SCIP_CALL( SCIPsepastoreApplyCuts(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
2765 branchcand, eventqueue, eventfilter, cliquetable, root, SCIP_EFFICIACYCHOICE_LP, cutoff) );
2766
2767 if( !(*cutoff) )
2768 {
2769 mustprice = mustprice || !lp->flushed || (transprob->ncolvars != npricedcolvars);
2770 mustsepa = mustsepa || !lp->flushed;
2771
2772 /* if a new bound change (e.g. a cut with only one column) was found, propagate domains again */
2773 if( stat->domchgcount != olddomchgcount )
2774 {
2775 SCIPsetDebugMsg(set, " -> separation changed bound: propagate again\n");
2776
2777 *propagateagain = TRUE;
2778
2779 /* in the root node, remove redundant rows permanently from the LP */
2780 if( root )
2781 {
2782 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, transprob, eventqueue) );
2783 SCIP_CALL( SCIPlpRemoveRedundantRows(lp, blkmem, set, stat, eventqueue, eventfilter) );
2784 }
2785 }
2786
2787 if( stat->ninitconssadded != oldninitconssadded )
2788 {
2789 SCIPsetDebugMsg(set, "new initial constraints added during propagation: old=%" SCIP_LONGINT_FORMAT ", new=%" SCIP_LONGINT_FORMAT "\n",
2790 oldninitconssadded, stat->ninitconssadded);
2791
2792 SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp,
2793 branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE, cutoff) );
2794 }
2795
2796 if( !(*cutoff) )
2797 {
2798 SCIP_Real lpobjval;
2799
2800 /* solve LP (with dual simplex) */
2801 SCIPsetDebugMsg(set, "separation: solve LP\n");
2802 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2803 set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2804 assert(lp->flushed);
2805 assert(lp->solved || *lperror);
2806
2807 /* remove previous primal ray, store new one if LP is unbounded */
2808 SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2809
2810 if( !(*lperror) )
2811 {
2812 SCIP_Bool stalling;
2813
2814 /* propagation might have changed the best bound of loose variables, thereby changing the loose objective value
2815 * which is added to the LP value; because of the loose status, the LP might not be reoptimized, but the lower
2816 * bound of the node needs to be updated
2817 */
2818 if( stat->domchgcount != olddomchgcount && (!mustprice || mustsepa) && !(*cutoff)
2819 && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
2820 {
2821 SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2822 SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2823 SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2824
2825 /* update node estimate */
2826 SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2827
2828 if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2829 SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2830 }
2831
2832 /* check if we are stalling
2833 * If we have an LP solution, then we are stalling if
2834 * we had an LP solution before and
2835 * the LP value did not improve and
2836 * the number of fractional variables did not decrease.
2837 * If we do not have an LP solution, then we are stalling if the solution status of the LP did not change.
2838 */
2840 {
2841 SCIP_Real objreldiff;
2842 int nfracs;
2843
2844 SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nfracs, NULL,
2845 NULL) );
2846 lpobjval = SCIPlpGetObjval(lp, set, transprob);
2847
2848 objreldiff = SCIPrelDiff(lpobjval, stalllpobjval);
2849 SCIPsetDebugMsg(set, " -> LP bound moved from %g to %g (reldiff: %g)\n",
2850 stalllpobjval, lpobjval, objreldiff);
2851
2852 stalling = (stalllpsolstat == SCIP_LPSOLSTAT_OPTIMAL &&
2853 objreldiff <= 1e-04 &&
2854 nfracs >= (0.9 - 0.1 * nsepastallrounds) * stallnfracs);
2855
2856 stalllpobjval = lpobjval;
2857 stallnfracs = nfracs;
2858 } /*lint !e438*/
2859 else
2860 {
2861 stalling = (stalllpsolstat == SCIPlpGetSolstat(lp));
2862 }
2863
2864 if( !stalling )
2865 {
2866 nsepastallrounds = 0;
2867 lp->installing = FALSE;
2868 }
2869 else
2870 {
2871 nsepastallrounds++;
2872 }
2873 stalllpsolstat = SCIPlpGetSolstat(lp);
2874
2875 /* tell LP that we are (close to) stalling */
2876 if( nsepastallrounds >= maxnsepastallrounds-2 )
2877 lp->installing = TRUE;
2878 SCIPsetDebugMsg(set, " -> nsepastallrounds=%d/%d\n", nsepastallrounds, maxnsepastallrounds);
2879 }
2880 }
2881 }
2882 }
2883 assert(*cutoff || *lperror || (lp->flushed && lp->solved)); /* cutoff: LP may be unsolved due to bound changes */
2884
2885 SCIPsetDebugMsg(set, "separation round %d/%d finished (%d/%d stall rounds): mustprice=%u, mustsepa=%u, delayedsepa=%u, propagateagain=%u\n",
2886 stat->nseparounds, maxseparounds, nsepastallrounds, maxnsepastallrounds, mustprice, mustsepa, delayedsepa, *propagateagain);
2887
2888 /* increase separation round counter */
2889 stat->nseparounds++;
2890 }
2891 }
2892
2893 if( root && nsepastallrounds >= maxnsepastallrounds )
2894 {
2895 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
2896 "Truncate separation round because of stalling (%d stall rounds).\n", maxnsepastallrounds);
2897 }
2898
2899 if( !*lperror )
2900 {
2901 /* update pseudo cost values for continuous variables, if it should be delayed */
2902 SCIP_CALL( updatePseudocost(set, stat, transprob, tree, lp, FALSE, set->branch_delaypscost) );
2903 }
2904
2905 /* update lower bound w.r.t. the LP solution */
2906 if( *cutoff )
2907 {
2908 SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, SCIPsetInfinity(set));
2909 }
2910 else if( !(*lperror) )
2911 {
2912 assert(lp->flushed);
2913 assert(lp->solved);
2914
2915 if( SCIPlpIsRelax(lp) )
2916 {
2917 SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2918 }
2919
2920 /* update node estimate */
2921 SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2922
2923 /* issue LPSOLVED event */
2925 {
2927 SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
2928 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
2929 }
2930
2931 /* if the LP is a relaxation and we are not solving exactly, then we may analyze an infeasible or bound exceeding
2932 * LP (not necessary in the root node) and cut off the current node
2933 */
2934 if( !set->misc_exactsolve && !root && SCIPlpIsRelax(lp) && SCIPprobAllColsInLP(transprob, set, lp)
2936 {
2937 SCIP_CALL( SCIPconflictAnalyzeLP(conflict, conflictstore, blkmem, set, stat, transprob, origprob, tree, reopt,
2938 lp, branchcand, eventqueue, cliquetable, NULL) );
2939 *cutoff = TRUE;
2940 }
2941 }
2942 /* check for unboundedness */
2943 if( !(*lperror) )
2944 {
2945 *unbounded = (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
2946 /* assert(!(*unbounded) || root); */ /* unboundedness can only happen in the root node; no, of course it can also happens in the tree if a branching did not help to resolve unboundedness */
2947 }
2948
2949 lp->installing = FALSE;
2950
2951 SCIPsetDebugMsg(set, " -> final lower bound: %g (LP status: %d, LP obj: %g)\n",
2953 (*cutoff || *unbounded) ? SCIPsetInfinity(set) : *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
2954
2955 return SCIP_OKAY; /*lint !e438*/
2956}
2957
2958/** updates the current lower bound with the pseudo objective value, cuts off node by bounding, and applies conflict
2959 * analysis if the pseudo objective lead to the cutoff
2960 */
2961static
2963 BMS_BLKMEM* blkmem, /**< block memory buffers */
2964 SCIP_SET* set, /**< global SCIP settings */
2965 SCIP_STAT* stat, /**< dynamic problem statistics */
2966 SCIP_PROB* transprob, /**< tranformed problem after presolve */
2967 SCIP_PROB* origprob, /**< original problem */
2968 SCIP_PRIMAL* primal, /**< primal data */
2969 SCIP_TREE* tree, /**< branch and bound tree */
2970 SCIP_REOPT* reopt, /**< reoptimization data structure */
2971 SCIP_LP* lp, /**< LP data */
2972 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2973 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2974 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2975 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2976 SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
2977 )
2978{
2979 assert(transprob != NULL);
2980 assert(origprob != NULL);
2981 assert(primal != NULL);
2982 assert(cutoff != NULL);
2983
2984 if( !(*cutoff) )
2985 {
2986 SCIP_NODE* focusnode;
2987 SCIP_Real pseudoobjval;
2988
2989 /* get current focus node */
2990 focusnode = SCIPtreeGetFocusNode(tree);
2991
2992 /* update lower bound w.r.t. the pseudo solution */
2993 pseudoobjval = SCIPlpGetPseudoObjval(lp, set, transprob);
2994 SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, pseudoobjval);
2995 SCIPsetDebugMsg(set, " -> lower bound: %g [%g] (pseudoobj: %g [%g]), cutoff bound: %g [%g]\n",
2996 SCIPnodeGetLowerbound(focusnode), SCIPprobExternObjval(transprob, origprob, set, SCIPnodeGetLowerbound(focusnode)) + SCIPgetOrigObjoffset(set->scip),
2997 pseudoobjval, SCIPprobExternObjval(transprob, origprob, set, pseudoobjval) + SCIPgetOrigObjoffset(set->scip),
2998 primal->cutoffbound, SCIPprobExternObjval(transprob, origprob, set, primal->cutoffbound) + SCIPgetOrigObjoffset(set->scip));
2999
3000 /* check for infeasible node by bounding */
3001 if( (set->misc_exactsolve && SCIPnodeGetLowerbound(focusnode) >= primal->cutoffbound)
3002 || (!set->misc_exactsolve && SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound)) )
3003 {
3004 SCIPsetDebugMsg(set, "node is cut off by bounding (lower=%g, upper=%g)\n",
3005 SCIPnodeGetLowerbound(focusnode), primal->cutoffbound);
3006 SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, SCIPsetInfinity(set));
3007 *cutoff = TRUE;
3008
3009 /* call pseudo conflict analysis, if the node is cut off due to the pseudo objective value */
3010 if( pseudoobjval >= primal->cutoffbound && !SCIPsetIsInfinity(set, primal->cutoffbound) && !SCIPsetIsInfinity(set, -pseudoobjval) )
3011 {
3012 SCIP_CALL( SCIPconflictAnalyzePseudo(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cliquetable, NULL) );
3013 }
3014 }
3015 }
3016
3017 return SCIP_OKAY;
3018}
3019
3020/** marks all relaxators to be unsolved */
3021static
3023 SCIP_SET* set, /**< global SCIP settings */
3024 SCIP_RELAXATION* relaxation /**< global relaxation data */
3025 )
3026{
3027 int r;
3028
3029 assert(set != NULL);
3030 assert(relaxation != NULL);
3031
3033
3034 for( r = 0; r < set->nrelaxs; ++r )
3035 SCIPrelaxMarkUnsolved(set->relaxs[r]);
3036}
3037
3038/** solves the current node's LP in a price-and-cut loop */
3039static
3041 BMS_BLKMEM* blkmem, /**< block memory buffers */
3042 SCIP_SET* set, /**< global SCIP settings */
3043 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3044 SCIP_STAT* stat, /**< dynamic problem statistics */
3045 SCIP_MEM* mem, /**< block memory pools */
3046 SCIP_PROB* origprob, /**< original problem */
3047 SCIP_PROB* transprob, /**< transformed problem after presolve */
3048 SCIP_PRIMAL* primal, /**< primal data */
3049 SCIP_TREE* tree, /**< branch and bound tree */
3050 SCIP_REOPT* reopt, /**< reoptimization data structure */
3051 SCIP_LP* lp, /**< LP data */
3052 SCIP_RELAXATION* relaxation, /**< relaxators */
3053 SCIP_PRICESTORE* pricestore, /**< pricing storage */
3054 SCIP_SEPASTORE* sepastore, /**< separation storage */
3055 SCIP_CUTPOOL* cutpool, /**< global cut pool */
3056 SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
3057 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3058 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3059 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
3060 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3061 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3062 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3063 SCIP_Bool initiallpsolved, /**< was the initial LP already solved? */
3064 SCIP_Bool fullseparation, /**< are we in the first prop-and-cut-and-price loop? */
3065 SCIP_Bool newinitconss, /**< do we have to add new initial constraints? */
3066 SCIP_Bool* propagateagain, /**< pointer to store whether we want to propagate again */
3067 SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called again */
3068 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3069 SCIP_Bool* unbounded, /**< pointer to store TRUE, if an unbounded ray was found in the LP */
3070 SCIP_Bool* lperror, /**< pointer to store TRUE, if an unresolved error in LP solving occured */
3071 SCIP_Bool* pricingaborted /**< pointer to store TRUE, if the pricing was aborted and the lower bound
3072 * must not be used */
3073 )
3074{
3075 SCIP_Longint nlpiterations;
3076 SCIP_Longint nlps;
3077 SCIP_Longint nzeroitlps;
3078
3079 assert(stat != NULL);
3080 assert(tree != NULL);
3081 assert(SCIPtreeHasFocusNodeLP(tree));
3082 assert(cutoff != NULL);
3083 assert(unbounded != NULL);
3084 assert(lperror != NULL);
3085 assert(*cutoff == FALSE);
3086 assert(*unbounded == FALSE);
3087 assert(*lperror == FALSE);
3088
3089 nlps = stat->nlps;
3090 nzeroitlps = stat->ndualzeroitlps + stat->nprimalzeroitlps + stat->nbarrierzeroitlps;
3091 nlpiterations = stat->nlpiterations;
3092
3093 if( !initiallpsolved )
3094 {
3095 /* load and solve the initial LP of the node */
3096 SCIP_CALL( solveNodeInitialLP(blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
3097 pricestore, sepastore, cutpool, branchcand, eventfilter, eventqueue, cliquetable, newinitconss, cutoff, lperror) );
3098
3099 assert(*cutoff || *lperror || (lp->flushed && lp->solved));
3100 SCIPsetDebugMsg(set, "price-and-cut-loop: initial LP status: %d, LP obj: %g\n",
3101 SCIPlpGetSolstat(lp),
3102 *cutoff ? SCIPsetInfinity(set) : *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
3103
3104 /* update initial LP iteration counter */
3105 stat->ninitlps += stat->nlps - nlps;
3106 stat->ninitlpiterations += stat->nlpiterations - nlpiterations;
3107
3108 /* In the root node, we try if the initial LP solution is feasible to avoid expensive setup of data structures in
3109 * separators; in case the root LP is aborted, e.g., by hitting the time limit, we do not check the LP solution
3110 * since the corresponding data structures have not been updated.
3111 */
3112 if( SCIPtreeGetCurrentDepth(tree) == 0 && !(*cutoff) && !(*lperror)
3114 && !SCIPsolveIsStopped(set, stat, FALSE) )
3115 {
3116 SCIP_Bool checklprows;
3117 SCIP_Bool stored;
3118 SCIP_SOL* sol;
3119 SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
3120
3121 SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
3122
3124 checklprows = FALSE;
3125 else
3126 checklprows = TRUE;
3127
3128#ifndef NDEBUG
3129 /* in the debug mode we want to explicitly check if the solution is feasible if it was stored */
3130 SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
3131 eventqueue, eventfilter, sol, FALSE, FALSE, TRUE, TRUE, checklprows, &stored) );
3132
3133 if( stored )
3134 {
3135 SCIP_Bool feasible;
3136
3137 SCIP_CALL( SCIPsolCheck(sol, set, messagehdlr, blkmem, stat, transprob, FALSE, FALSE, TRUE, TRUE,
3138 checklprows, &feasible) );
3139 assert(feasible);
3140 }
3141
3142 SCIP_CALL( SCIPsolFree(&sol, blkmem, primal) );
3143#else
3144 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
3145 eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, checklprows, &stored) );
3146#endif
3147 if( stored )
3148 {
3149 stat->nlpsolsfound++;
3150
3151 if( primal->nbestsolsfound != oldnbestsolsfound )
3152 {
3153 stat->nlpbestsolsfound++;
3155 }
3156
3157 if( set->reopt_enable )
3158 {
3159 assert(reopt != NULL);
3161 SCIPlpGetSolstat(lp), tree->root == tree->focusnode, TRUE, tree->focusnode->lowerbound,
3162 tree->effectiverootdepth) );
3163 }
3164 }
3165
3167 *unbounded = TRUE;
3168 }
3169 }
3170 else
3171 {
3172 SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob,
3173 origprob, tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE,
3174 cutoff) );
3175 }
3176 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3177
3178 /* check for infeasible node by bounding */
3179 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
3180#ifdef SCIP_DEBUG
3181 if( *cutoff )
3182 {
3183 if( SCIPtreeGetCurrentDepth(tree) == 0 )
3184 {
3185 SCIPsetDebugMsg(set, "solution cuts off root node, stop solution process\n");
3186 }
3187 else
3188 {
3189 SCIPsetDebugMsg(set, "solution cuts off node\n");
3190 }
3191 }
3192#endif
3193
3194 if( !(*cutoff) && !(*lperror) )
3195 {
3196 SCIP_Longint oldninitconssadded;
3197 SCIP_Longint oldnboundchgs;
3198 SCIP_Longint olddomchgcount;
3199 int oldnpricedvars;
3200 int oldncutsapplied;
3201
3202 oldnpricedvars = transprob->ncolvars;
3203 oldninitconssadded = stat->ninitconssadded;
3204 oldncutsapplied = SCIPsepastoreGetNCutsApplied(sepastore);
3205 oldnboundchgs = stat->nboundchgs;
3206 olddomchgcount = stat->domchgcount;
3207
3208 /* solve the LP with price-and-cut*/
3209 SCIP_CALL( priceAndCutLoop(blkmem, set, messagehdlr, stat, mem, transprob, origprob, primal, tree, reopt, lp,
3210 pricestore, sepastore, cutpool, delayedcutpool, branchcand, conflict, conflictstore, eventfilter,
3211 eventqueue, cliquetable, fullseparation, propagateagain, cutoff, unbounded, lperror, pricingaborted) );
3212
3213 /* check if the problem was changed and the relaxation needs to be resolved */
3214 if( (transprob->ncolvars != oldnpricedvars) || (stat->ninitconssadded != oldninitconssadded) ||
3215 (SCIPsepastoreGetNCutsApplied(sepastore) != oldncutsapplied) || (stat->nboundchgs != oldnboundchgs) ||
3216 (stat->domchgcount != olddomchgcount) )
3217 {
3218 *solverelaxagain = TRUE;
3219 markRelaxsUnsolved(set, relaxation);
3220 }
3221 }
3222 assert(*cutoff || *lperror || (lp->flushed && lp->solved));
3223
3224 /* if there is no LP error, then *unbounded should be TRUE, iff the LP solution status is unboundedray */
3225 assert(*lperror || ((SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY) == *unbounded));
3226
3227 /* If pricing was aborted while solving the LP of the node and the node cannot be cut off due to the lower bound computed by the pricer,
3228 * the solving of the LP might be stopped due to the objective limit, but the node may not be cut off, since the LP objective
3229 * is not a feasible lower bound for the solutions in the current subtree.
3230 * In this case, the LP has to be solved to optimality by temporarily removing the cutoff bound.
3231 */
3232 if( (*pricingaborted) && (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_ITERLIMIT)
3233 && !(*cutoff) )
3234 {
3235 SCIP_Real tmpcutoff;
3236
3237 /* temporarily disable cutoffbound, which also disables the objective limit */
3238 tmpcutoff = lp->cutoffbound;
3240
3241 lp->solved = FALSE;
3242 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, FALSE, lperror) );
3243
3244 /* reinstall old cutoff bound */
3245 lp->cutoffbound = tmpcutoff;
3246
3247 SCIPsetDebugMsg(set, "re-optimized LP without cutoff bound: LP status: %d, LP obj: %g\n",
3248 SCIPlpGetSolstat(lp), *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
3249
3250 /* lp solstat should not be objlimit, since the cutoff bound was removed temporarily */
3252 /* lp solstat should not be unboundedray, since the lp was dual feasible */
3254 /* there should be no primal ray, since the lp was dual feasible */
3255 assert(primal->primalray == NULL);
3257 {
3258 *cutoff = TRUE;
3259 }
3260 }
3261
3262 assert(!(*pricingaborted) || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL /* cppcheck-suppress assertWithSideEffect */
3263 || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_NOTSOLVED || SCIPsolveIsStopped(set, stat, FALSE) || (*cutoff));
3264
3265 assert(*cutoff || *lperror || (lp->flushed && lp->solved));
3266
3267 /* update node's LP iteration counter */
3268 stat->nnodelps += stat->nlps - nlps;
3269 stat->nnodezeroitlps += stat->ndualzeroitlps + stat->nprimalzeroitlps + stat->nbarrierzeroitlps - nzeroitlps;
3270 stat->nnodelpiterations += stat->nlpiterations - nlpiterations;
3271
3272 /* update number of root node LPs and iterations if the root node was processed */
3273 if( SCIPnodeGetDepth(tree->focusnode) == 0 )
3274 {
3275 stat->nrootlps += stat->nlps - nlps;
3276 stat->nrootlpiterations += stat->nlpiterations - nlpiterations;
3277 }
3278
3279 return SCIP_OKAY;
3280}
3281
3282/** calls relaxators */
3283static
3285 SCIP_SET* set, /**< global SCIP settings */
3286 SCIP_STAT* stat, /**< dynamic problem statistics */
3287 SCIP_TREE* tree, /**< branch and bound tree */
3288 SCIP_RELAXATION* relaxation, /**< relaxators */
3289 SCIP_PROB* transprob, /**< transformed problem */
3290 SCIP_PROB* origprob, /**< original problem */
3291 int depth, /**< depth of current node */
3292 SCIP_Bool beforelp, /**< should the relaxators with non-negative or negative priority be called? */
3293 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3294 SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3295 SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3296 SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called
3297 * again */
3298 SCIP_Bool* relaxcalled /**< pointer to store TRUE, if at least one relaxator was called (unmodified
3299 * otherwise) */
3300 )
3301{
3302 SCIP_RESULT result;
3303 SCIP_Real lowerbound;
3304 int r;
3305
3306 assert(set != NULL);
3307 assert(relaxation != NULL);
3308 assert(cutoff != NULL);
3309 assert(solvelpagain != NULL);
3310 assert(propagateagain != NULL);
3311 assert(solverelaxagain != NULL);
3312 assert(relaxcalled != NULL);
3313 assert(!(*cutoff));
3314
3315 /* sort by priority */
3317
3318 for( r = 0; r < set->nrelaxs && !(*cutoff); ++r )
3319 {
3320 if( beforelp != (SCIPrelaxGetPriority(set->relaxs[r]) >= 0) )
3321 continue;
3322
3323 *relaxcalled = TRUE;
3324
3325 lowerbound = -SCIPsetInfinity(set);
3326
3327 SCIP_CALL( SCIPrelaxExec(set->relaxs[r], set, tree, stat, depth, &lowerbound, &result) );
3328
3329 switch( result )
3330 {
3331 case SCIP_CUTOFF:
3332 *cutoff = TRUE;
3333 SCIPsetDebugMsg(set, " -> relaxator <%s> detected cutoff\n", SCIPrelaxGetName(set->relaxs[r]));
3334 /* @todo does it make sense to proceed if the node is proven to be infeasible? */
3335 return SCIP_OKAY;
3336
3337 case SCIP_CONSADDED:
3338 *solvelpagain = TRUE; /* the separation for new constraints should be called */
3339 *propagateagain = TRUE; /* the propagation for new constraints should be called */
3340 break;
3341
3342 case SCIP_REDUCEDDOM:
3343 *solvelpagain = TRUE;
3344 *propagateagain = TRUE;
3345 break;
3346
3347 case SCIP_SEPARATED:
3348 *solvelpagain = TRUE;
3349 break;
3350
3351 case SCIP_SUSPENDED:
3352 *solverelaxagain = TRUE;
3353 break;
3354
3355 case SCIP_SUCCESS:
3356 case SCIP_DIDNOTRUN:
3357 break;
3358
3359 default:
3360 SCIPerrorMessage("invalid result code <%d> of relaxator <%s>\n", result, SCIPrelaxGetName(set->relaxs[r]));
3361 return SCIP_INVALIDRESULT;
3362 } /*lint !e788*/
3363
3364 if( result != SCIP_CUTOFF && result != SCIP_DIDNOTRUN && result != SCIP_SUSPENDED )
3365 {
3366 SCIP_NODE* focusnode;
3367
3368 focusnode = SCIPtreeGetFocusNode(tree);
3369 assert(focusnode != NULL);
3370 assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
3371
3372 /* update lower bound w.r.t. the lower bound given by the relaxator */
3373 SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, lowerbound);
3374 SCIPsetDebugMsg(set, " -> new lower bound given by relaxator %s: %g\n",
3375 SCIPrelaxGetName(set->relaxs[r]), lowerbound);
3376 }
3377 }
3378
3379 return SCIP_OKAY;
3380}
3381
3382/** enforces constraints by branching, separation, or domain reduction */
3383static
3385 BMS_BLKMEM* blkmem, /**< block memory buffers */
3386 SCIP_SET* set, /**< global SCIP settings */
3387 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3388 SCIP_STAT* stat, /**< dynamic problem statistics */
3389 SCIP_PROB* prob, /**< transformed problem after presolve */
3390 SCIP_PRIMAL* primal, /**< primal data */
3391 SCIP_TREE* tree, /**< branch and bound tree */
3392 SCIP_LP* lp, /**< LP data */
3393 SCIP_RELAXATION* relaxation, /**< global relaxation data */
3394 SCIP_SEPASTORE* sepastore, /**< separation storage */
3395 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3396 SCIP_Bool* branched, /**< pointer to store whether a branching was created */
3397 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3398 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the LP/pseudo solution is infeasible */
3399 SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3400 SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3401 SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called again */
3402 SCIP_Bool forced /**< should enforcement of pseudo solution be forced? */
3403 )
3404{
3405 SCIP_RESULT result;
3406 SCIP_SOL* relaxsol = NULL;
3407 SCIP_Real pseudoobjval;
3408 SCIP_Bool resolved;
3409 SCIP_Bool objinfeasible;
3410 SCIP_Bool enforcerelaxsol;
3411 int h;
3412
3413 assert(set != NULL);
3414 assert(stat != NULL);
3415 assert(tree != NULL);
3416 assert(SCIPtreeGetFocusNode(tree) != NULL);
3417 assert(branched != NULL);
3418 assert(cutoff != NULL);
3419 assert(infeasible != NULL);
3420 assert(propagateagain != NULL);
3421 assert(solvelpagain != NULL);
3422 assert(solverelaxagain != NULL);
3423 assert(!(*cutoff));
3424 assert(!(*propagateagain));
3425 assert(!(*solvelpagain));
3426 assert(!(*solverelaxagain));
3427
3428 *branched = FALSE;
3429 /**@todo avoid checking the same pseudosolution twice */
3430
3431 /* enforce (best) relaxation solution if the LP has a worse objective value */
3432 enforcerelaxsol = SCIPrelaxationIsSolValid(relaxation) && SCIPrelaxationIsLpIncludedForSol(relaxation) && (!SCIPtreeHasFocusNodeLP(tree)
3433 || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, prob)));
3434
3435 /* check if all constraint handlers implement the enforelax callback, otherwise enforce the LP solution */
3436 for( h = 0; h < set->nconshdlrs && enforcerelaxsol; ++h )
3437 {
3438 if( set->conshdlrs_enfo[h]->consenforelax == NULL && ((! set->conshdlrs_enfo[h]->needscons) ||
3439 (set->conshdlrs_enfo[h]->nconss > 0)) )
3440 {
3441 SCIP_VERBLEVEL verblevel;
3442
3443 enforcerelaxsol = FALSE;
3444
3445 verblevel = SCIP_VERBLEVEL_FULL;
3446
3447 if( !stat->disableenforelaxmsg && set->disp_verblevel == SCIP_VERBLEVEL_HIGH )
3448 {
3449 verblevel = SCIP_VERBLEVEL_HIGH;
3450
3451 /* remember that the disable relaxation enforcement message was posted and only post it again if the
3452 * verblevel is SCIP_VERBLEVEL_FULL
3453 */
3454 stat->disableenforelaxmsg = TRUE;
3455 }
3456 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, verblevel, "Disable enforcement of relaxation solutions"
3457 " since constraint handler %s does not implement enforelax-callback\n",
3458 SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3459 }
3460 }
3461
3462 /* enforce constraints by branching, applying additional cutting planes (if LP is being processed),
3463 * introducing new constraints, or tighten the domains
3464 */
3465#ifndef SCIP_NDEBUG
3466 if( enforcerelaxsol )
3467 {
3468 SCIPsetDebugMsg(set, "enforcing constraints on relaxation solution\n");
3469 }
3470 else
3471 {
3472 SCIPsetDebugMsg(set, "enforcing constraints on %s solution\n", SCIPtreeHasFocusNodeLP(tree) ? "LP" : "pseudo");
3473 }
3474#endif
3475
3476 /* check, if the solution is infeasible anyway due to it's objective value */
3477 if( SCIPtreeHasFocusNodeLP(tree) || enforcerelaxsol )
3478 objinfeasible = FALSE;
3479 else
3480 {
3481 pseudoobjval = SCIPlpGetPseudoObjval(lp, set, prob);
3482 objinfeasible = SCIPsetIsFeasLT(set, pseudoobjval, SCIPnodeGetLowerbound(SCIPtreeGetFocusNode(tree)));
3483 }
3484
3485 /* during constraint enforcement, generated cuts should enter the LP in any case; otherwise, a constraint handler
3486 * would fail to enforce its constraints if it relies on the modification of the LP relaxation
3487 */
3488 SCIPsepastoreStartForceCuts(sepastore);
3489
3490 /* enforce constraints until a handler resolved an infeasibility with cutting off the node, branching,
3491 * reducing a domain, or separating a cut
3492 * if a constraint handler introduced new constraints to enforce his constraints, the newly added constraints
3493 * have to be enforced themselves
3494 */
3495 resolved = FALSE;
3496
3497 /* in case the relaxation solution should be enforced, we need to create the corresponding solution for the enforelax callbacks */
3498 if( enforcerelaxsol )
3499 {
3500 SCIP_CALL( SCIPsolCreateRelaxSol(&relaxsol, blkmem, set, stat, primal, tree, relaxation, NULL) );
3501 }
3502
3503 for( h = 0; h < set->nconshdlrs && !resolved; ++h )
3504 {
3505 assert(SCIPsepastoreGetNCuts(sepastore) == 0); /* otherwise, the LP should have been resolved first */
3506
3507 /* enforce LP, pseudo, or relaxation solution */
3508 if( enforcerelaxsol )
3509 {
3510 SCIPsetDebugMsg(set, "enforce relaxation solution with value %g\n", SCIPrelaxationGetSolObj(relaxation));
3511
3512 SCIP_CALL( SCIPconshdlrEnforceRelaxSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, sepastore,
3513 relaxsol, *infeasible, &result) );
3514 }
3515 else if( SCIPtreeHasFocusNodeLP(tree) )
3516 {
3517 SCIPsetDebugMsg(set, "enforce LP solution with value %g\n", SCIPlpGetObjval(lp, set, prob));
3518
3519 assert(lp->flushed);
3520 assert(lp->solved);
3522 SCIP_CALL( SCIPconshdlrEnforceLPSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, sepastore, *infeasible,
3523 &result) );
3524 }
3525 else
3526 {
3527 SCIP_CALL( SCIPconshdlrEnforcePseudoSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, branchcand, *infeasible,
3528 objinfeasible, forced, &result) );
3529 if( SCIPsepastoreGetNCuts(sepastore) != 0 )
3530 {
3531 SCIPerrorMessage("pseudo enforcing method of constraint handler <%s> separated cuts\n",
3532 SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3533 return SCIP_INVALIDRESULT;
3534 }
3535 }
3536 SCIPsetDebugMsg(set, "enforcing of <%s> returned result %d\n", SCIPconshdlrGetName(set->conshdlrs_enfo[h]), result);
3537
3538 switch( result )
3539 {
3540 case SCIP_CUTOFF:
3541 assert(tree->nchildren == 0);
3542 *cutoff = TRUE;
3543 *infeasible = TRUE;
3544 resolved = TRUE;
3545 SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in enforcement\n",
3546 SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3547 break;
3548
3549 case SCIP_CONSADDED:
3550 assert(tree->nchildren == 0);
3551 *infeasible = TRUE;
3552 *propagateagain = TRUE; /* the propagation for new constraints should be called */
3553 *solvelpagain = TRUE; /* the separation for new constraints should be called */
3554 *solverelaxagain = TRUE;
3555 markRelaxsUnsolved(set, relaxation);
3556 resolved = TRUE;
3557 break;
3558
3559 case SCIP_REDUCEDDOM:
3560 assert(tree->nchildren == 0);
3561 *infeasible = TRUE;
3562 *propagateagain = TRUE;
3563 *solvelpagain = TRUE;
3564 *solverelaxagain = TRUE;
3565 markRelaxsUnsolved(set, relaxation);
3566 resolved = TRUE;
3567 break;
3568
3569 case SCIP_SEPARATED:
3570 assert(tree->nchildren == 0);
3571 assert(SCIPsepastoreGetNCuts(sepastore) > 0);
3572 *infeasible = TRUE;
3573 *solvelpagain = TRUE;
3574 *solverelaxagain = TRUE;
3575 markRelaxsUnsolved(set, relaxation);
3576 resolved = TRUE;
3577 break;
3578
3579 case SCIP_BRANCHED:
3580 assert(tree->nchildren >= 1);
3581 assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3582 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3583 *infeasible = TRUE;
3584 *branched = TRUE;
3585 resolved = TRUE;
3586
3587 /* increase the number of internal nodes */
3588 stat->ninternalnodes++;
3589 stat->ntotalinternalnodes++;
3590 break;
3591
3592 case SCIP_SOLVELP:
3593 /* either LP was not solved, or it is not solved anymore (e.g., because feastol has been tightened by some constraint handler) */
3594 assert(!SCIPtreeHasFocusNodeLP(tree) || !lp->solved);
3595 assert(tree->nchildren == 0);
3596 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3597 *infeasible = TRUE;
3598 *solvelpagain = TRUE;
3599 resolved = TRUE;
3600 SCIPtreeSetFocusNodeLP(tree, TRUE); /* the node's LP must be solved */
3601 break;
3602
3603 case SCIP_INFEASIBLE:
3604 assert(tree->nchildren == 0);
3605 assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3606 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3607 *infeasible = TRUE;
3608 break;
3609
3610 case SCIP_FEASIBLE:
3611 assert(tree->nchildren == 0);
3612 assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3613 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3614 break;
3615
3616 case SCIP_DIDNOTRUN:
3617 assert(tree->nchildren == 0);
3618 assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3619 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3620 assert(objinfeasible);
3621 *infeasible = TRUE;
3622 break;
3623
3624 default:
3625 SCIPerrorMessage("invalid result code <%d> from enforcing method of constraint handler <%s>\n",
3626 result, SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3627 return SCIP_INVALIDRESULT;
3628 } /*lint !e788*/
3629
3630 /* the enforcement method may add a primal solution, after which the LP status could be set to
3631 * objective limit reached
3632 */
3634 {
3635 *cutoff = TRUE;
3636 *infeasible = TRUE;
3637 resolved = TRUE;
3638 SCIPsetDebugMsg(set, " -> LP exceeded objective limit\n");
3639
3640 /* If we used the probing mode during branching, it might happen that we added a constraint or global bound
3641 * and returned SCIP_CONSADDED or SCIP_REDUCEDDOM, but when reoptimizing the LP after ending the probing mode,
3642 * this leads to hitting the objective limit. In this case, we do not need to propagate or solve the LP again.
3643 */
3644 *propagateagain = FALSE;
3645 *solvelpagain = FALSE;
3646 }
3647
3648 assert(!(*branched) || (resolved && !(*cutoff) && *infeasible && !(*propagateagain) && !(*solvelpagain)));
3649 assert(!(*cutoff) || (resolved && !(*branched) && *infeasible && !(*propagateagain) && !(*solvelpagain)));
3650 assert(*infeasible || (!resolved && !(*branched) && !(*cutoff) && !(*propagateagain) && !(*solvelpagain)));
3651 assert(!(*propagateagain) || (resolved && !(*branched) && !(*cutoff) && *infeasible));
3652 assert(!(*solvelpagain) || (resolved && !(*branched) && !(*cutoff) && *infeasible));
3653 }
3654 assert(!objinfeasible || *infeasible);
3655 assert(resolved == (*branched || *cutoff || *propagateagain || *solvelpagain));
3656 assert(*cutoff || *solvelpagain || SCIPsepastoreGetNCuts(sepastore) == 0);
3657
3658 /* in case the relaxation solution was enforced, free the created solution */
3659 if( enforcerelaxsol )
3660 {
3661 SCIP_CALL( SCIPsolFree(&relaxsol, blkmem, primal) );
3662 }
3663
3664 /* deactivate the cut forcing of the constraint enforcement */
3665 SCIPsepastoreEndForceCuts(sepastore);
3666
3667 SCIPsetDebugMsg(set, " -> enforcing result: branched=%u, cutoff=%u, infeasible=%u, propagateagain=%u, solvelpagain=%u, resolved=%u\n",
3668 *branched, *cutoff, *infeasible, *propagateagain, *solvelpagain, resolved);
3669
3670 return SCIP_OKAY;
3671}
3672
3673/** applies the cuts stored in the separation store, or clears the store if the node can be cut off */
3674static
3676 BMS_BLKMEM* blkmem, /**< block memory buffers */
3677 SCIP_SET* set, /**< global SCIP settings */
3678 SCIP_STAT* stat, /**< dynamic problem statistics */
3679 SCIP_PROB* transprob, /**< transformed problem */
3680 SCIP_PROB* origprob, /**< original problem */
3681 SCIP_TREE* tree, /**< branch and bound tree */
3682 SCIP_REOPT* reopt, /**< reotimization data structure */
3683 SCIP_LP* lp, /**< LP data */
3684 SCIP_RELAXATION* relaxation, /**< relaxators */
3685 SCIP_SEPASTORE* sepastore, /**< separation storage */
3686 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3687 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3688 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
3689 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3690 SCIP_Bool root, /**< is this the initial root LP? */
3691 SCIP_EFFICIACYCHOICE efficiacychoice, /**< type of solution to base efficiacy computation on */
3692 SCIP_Bool* cutoff, /**< pointer to whether the node can be cut off */
3693 SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3694 SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3695 SCIP_Bool* solverelaxagain /**< pointer to store TRUE, if the node's relaxation has to be solved again */
3696 )
3697{
3698 assert(stat != NULL);
3699 assert(cutoff != NULL);
3700 assert(propagateagain != NULL);
3701 assert(solvelpagain != NULL);
3702
3703 if( *cutoff )
3704 {
3705 /* the found cuts are of no use, because the node is infeasible anyway (or we have an error in the LP) */
3706 SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
3707 }
3708 else if( SCIPsepastoreGetNCuts(sepastore) > 0 )
3709 {
3710 SCIP_Longint olddomchgcount;
3711 int oldncutsapplied;
3712
3713 olddomchgcount = stat->domchgcount;
3714 oldncutsapplied = SCIPsepastoreGetNCutsApplied(sepastore);
3715 SCIP_CALL( SCIPsepastoreApplyCuts(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
3716 eventqueue, eventfilter, cliquetable, root, efficiacychoice, cutoff) );
3717 *propagateagain = *propagateagain || (stat->domchgcount != olddomchgcount);
3718 *solvelpagain = TRUE;
3719 if( (stat->domchgcount != olddomchgcount) || (SCIPsepastoreGetNCutsApplied(sepastore) != oldncutsapplied) )
3720 {
3721 *solverelaxagain = TRUE;
3722 markRelaxsUnsolved(set, relaxation);
3723 }
3724 }
3725
3726 return SCIP_OKAY;
3727}
3728
3729/** updates the cutoff, propagateagain, and solverelaxagain status of the current solving loop */
3730static
3732 SCIP_SET* set, /**< global SCIP settings */
3733 SCIP_STAT* stat, /**< dynamic problem statistics */
3734 SCIP_TREE* tree, /**< branch and bound tree */
3735 int depth, /**< depth of current node */
3736 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3737 SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3738 SCIP_Bool* solverelaxagain /**< pointer to store TRUE, if at least one relaxator should be called again */
3739 )
3740{
3741 SCIP_NODE* focusnode;
3742 int r;
3743
3744 assert(set != NULL);
3745 assert(stat != NULL);
3746 assert(cutoff != NULL);
3747 assert(propagateagain != NULL);
3748 assert(solverelaxagain != NULL);
3749
3750 /* check, if the path was cutoff */
3751 *cutoff = *cutoff || (tree->cutoffdepth <= depth);
3752
3753 /* check if branching was already performed */
3754 if( tree->nchildren == 0 )
3755 {
3756 /* check, if the focus node should be repropagated */
3757 focusnode = SCIPtreeGetFocusNode(tree);
3758 *propagateagain = *propagateagain || SCIPnodeIsPropagatedAgain(focusnode);
3759
3760 /* check, if one of the external relaxations should be solved again */
3761 for( r = 0; r < set->nrelaxs && !(*solverelaxagain); ++r )
3762 *solverelaxagain = *solverelaxagain || ( !SCIPrelaxIsSolved(set->relaxs[r], stat) );
3763 }
3764 else
3765 {
3766 /* if branching was performed, avoid another node loop iteration */
3767 *propagateagain = FALSE;
3768 *solverelaxagain = FALSE;
3769 }
3770}
3771
3772/** propagate domains and solve relaxation and lp */
3773static
3775 BMS_BLKMEM* blkmem, /**< block memory buffers */
3776 SCIP_SET* set, /**< global SCIP settings */
3777 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3778 SCIP_STAT* stat, /**< dynamic problem statistics */
3779 SCIP_MEM* mem, /**< block memory pools */
3780 SCIP_PROB* origprob, /**< original problem */
3781 SCIP_PROB* transprob, /**< transformed problem after presolve */
3782 SCIP_PRIMAL* primal, /**< primal data */
3783 SCIP_TREE* tree, /**< branch and bound tree */
3784 SCIP_REOPT* reopt, /**< reoptimization data structure */
3785 SCIP_LP* lp, /**< LP data */
3786 SCIP_RELAXATION* relaxation, /**< global relaxation data */
3787 SCIP_PRICESTORE* pricestore, /**< pricing storage */
3788 SCIP_SEPASTORE* sepastore, /**< separation storage */
3789 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3790 SCIP_CUTPOOL* cutpool, /**< global cut pool */
3791 SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
3792 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3793 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
3794 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3795 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3796 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3797 SCIP_NODE* focusnode, /**< focused node */
3798 int actdepth, /**< depth in the b&b tree */
3799 SCIP_Bool propagate, /**< should we propagate */
3800 SCIP_Bool solvelp, /**< should we solve the lp */
3801 SCIP_Bool solverelax, /**< should we solve the relaxation */
3802 SCIP_Bool forcedlpsolve, /**< is there a need for a solve lp */
3803 SCIP_Bool initiallpsolved, /**< was the initial LP already solved? */
3804 SCIP_Bool fullseparation, /**< are we in the first prop-and-cut-and-price loop? */
3805 SCIP_Longint* afterlpproplps, /**< pointer to store the last LP count for which AFTERLP propagation was performed */
3806 SCIP_HEURTIMING* heurtiming, /**< timing for running heuristics after propagation call */
3807 int* nlperrors, /**< pointer to store the number of lp errors */
3808 SCIP_Bool* fullpropagation, /**< pointer to store whether we want to do a fullpropagation next time */
3809 SCIP_Bool* propagateagain, /**< pointer to store whether we want to propagate again */
3810 SCIP_Bool* lpsolved, /**< pointer to store whether the lp was solved */
3811 SCIP_Bool* relaxcalled, /**< pointer to store whether a relaxator was called; initialized with last loop's result */
3812 SCIP_Bool* solvelpagain, /**< pointer to store whether we want to solve the lp again */
3813 SCIP_Bool* solverelaxagain, /**< pointer to store whether we want to solve the relaxation again */
3814 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
3815 SCIP_Bool* postpone, /**< pointer to store whether the node should be postponed */
3816 SCIP_Bool* unbounded, /**< pointer to store whether the focus node is unbounded */
3817 SCIP_Bool* stopped, /**< pointer to store whether solving was interrupted */
3818 SCIP_Bool* lperror, /**< pointer to store TRUE, if an unresolved error in LP solving occured */
3819 SCIP_Bool* pricingaborted, /**< pointer to store TRUE, if the pricing was aborted and the lower bound must not be used */
3820 SCIP_Bool* forcedenforcement /**< pointer to store whether the enforcement of pseudo solution should be forced */
3821 )
3822{
3823 SCIP_Bool newinitconss;
3824
3825 assert(set != NULL);
3826 assert(stat != NULL);
3827 assert(origprob != NULL);
3828 assert(transprob != NULL);
3829 assert(tree != NULL);
3830 assert(lp != NULL);
3831 assert(primal != NULL);
3832 assert(pricestore != NULL);
3833 assert(sepastore != NULL);
3834 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3835 assert(branchcand != NULL);
3836 assert(cutpool != NULL);
3837 assert(delayedcutpool != NULL);
3838 assert(conflict != NULL);
3839 assert(SCIPconflictGetNConflicts(conflict) == 0);
3840 assert(eventfilter != NULL);
3841 assert(eventqueue != NULL);
3842 assert(focusnode != NULL);
3843 assert(heurtiming != NULL);
3844 assert(nlperrors != NULL);
3845 assert(fullpropagation != NULL);
3846 assert(propagateagain != NULL);
3847 assert(afterlpproplps != NULL);
3848 assert(lpsolved != NULL);
3849 assert(solvelpagain != NULL);
3850 assert(solverelaxagain != NULL);
3851 assert(cutoff != NULL);
3852 assert(postpone != NULL);
3853 assert(unbounded != NULL);
3854 assert(lperror != NULL);
3855 assert(pricingaborted != NULL);
3856 assert(forcedenforcement != NULL);
3857
3858 newinitconss = FALSE;
3859
3860 if( !(*cutoff) && !(*postpone) )
3861 {
3862 SCIP_Longint oldninitconssadded;
3863 SCIP_Longint oldnboundchgs;
3864 SCIP_Bool lpwasflushed;
3865
3866 lpwasflushed = lp->flushed;
3867 oldnboundchgs = stat->nboundchgs;
3868 oldninitconssadded = stat->ninitconssadded;
3869
3870 /* call after LP propagators */
3871 if( ((*afterlpproplps) < stat->nnodelps && (*lpsolved)) || (*relaxcalled) )
3872 {
3873 SCIP_CALL( propagateDomains(blkmem, set, stat, tree, SCIPtreeGetCurrentDepth(tree), 0, *fullpropagation,
3874 SCIP_PROPTIMING_AFTERLPLOOP, cutoff, postpone) );
3875 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3876
3877 /* check, if the path was cutoff */
3878 *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3879 *afterlpproplps = stat->nnodelps;
3880 propagate = propagate || (stat->nboundchgs > oldnboundchgs);
3881 }
3882
3883 /* call before LP propagators */
3884 if( propagate && !(*cutoff) )
3885 {
3886 SCIP_CALL( propagateDomains(blkmem, set, stat, tree, SCIPtreeGetCurrentDepth(tree), 0, *fullpropagation,
3887 SCIP_PROPTIMING_BEFORELP, cutoff, postpone) );
3888 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3889 }
3890
3891 newinitconss = (stat->ninitconssadded != oldninitconssadded);
3892 *fullpropagation = FALSE;
3893
3894 /* check, if the path was cutoff */
3895 *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3896
3897 /* if the LP was flushed and is now no longer flushed, a bound change occurred, and the LP has to be resolved;
3898 * we also have to solve the LP if new intial constraints were added which need to be added to the LP
3899 */
3900 solvelp = solvelp || (lpwasflushed && (!lp->flushed || newinitconss));
3901 solverelax = solverelax || newinitconss;
3902
3903 /* the number of bound changes was increased by the propagation call, thus the relaxation should be solved again */
3904 if( stat->nboundchgs > oldnboundchgs )
3905 {
3906 /* propagation might have changed the best bound of loose variables, thereby changing the loose objective value
3907 * which is added to the LP value; because of the loose status, the LP might not be reoptimized, but the lower
3908 * bound of the node needs to be updated
3909 */
3910 if( !solvelp && lp->flushed && lp->solved && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
3911 {
3912 SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
3913 SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
3914 SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
3915
3916 if( SCIPtreeHasFocusNodeLP(tree) )
3917 {
3918 /* update node estimate */
3919 SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
3920
3921 if( actdepth == 0 && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
3922 SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
3923 }
3924 }
3925
3926 solverelax = TRUE;
3927 markRelaxsUnsolved(set, relaxation);
3928 }
3929
3930 /* update lower bound with the pseudo objective value, and cut off node by bounding */
3931 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
3932 conflict, cliquetable, cutoff) );
3933 }
3934 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3935
3936 if( *postpone )
3937 return SCIP_OKAY;
3938
3939 /* call primal heuristics that are applicable after propagation loop before lp solve;
3940 * the first time we go here, we call the before node heuristics instead
3941 */
3942 if( !(*cutoff) && !SCIPtreeProbing(tree) )
3943 {
3944 /* if the heuristics find a new incumbent solution, propagate again */
3945 SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, *heurtiming,
3946 FALSE, propagateagain, unbounded) );
3947 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3948
3949 *heurtiming = SCIP_HEURTIMING_AFTERPROPLOOP;
3950
3951 /* check if primal heuristics found a solution and we therefore reached a solution limit */
3952 if( SCIPsolveIsStopped(set, stat, FALSE) )
3953 {
3954 /* cppcheck-suppress unassignedVariable */
3955 SCIP_NODE* node;
3956
3957 /* we reached a solution limit and do not want to continue the processing of the current node, but in order to
3958 * allow restarting the optimization process later, we need to create a "branching" with only one child node that
3959 * is a copy of the focusnode
3960 */
3962 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, 1.0, focusnode->estimate) );
3963 assert(tree->nchildren >= 1);
3964 *stopped = TRUE;
3965 return SCIP_OKAY;
3966 }
3967
3968 /* if diving produced an LP error, switch back to non-LP node */
3969 if( lp->resolvelperror )
3970 {
3972 lp->resolvelperror = FALSE;
3973 }
3974
3975 if( *propagateagain )
3976 {
3977 *solvelpagain = solvelp;
3978 *solverelaxagain = solverelax;
3979
3980 return SCIP_OKAY;
3981 }
3982 }
3983
3984 /* solve external relaxations with non-negative priority */
3985 *relaxcalled = FALSE;
3986 if( solverelax && !(*cutoff) )
3987 {
3988 /* clear the storage of external branching candidates */
3990
3991 SCIP_CALL( solveNodeRelax(set, stat, tree, relaxation, transprob, origprob, actdepth, TRUE,
3992 cutoff, propagateagain, solvelpagain, solverelaxagain, relaxcalled) );
3993 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3994
3995 /* check, if the path was cutoff */
3996 *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3997
3998 /* apply found cuts */
3999 SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4000 eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_RELAX, cutoff, propagateagain,
4001 solvelpagain, solverelaxagain) );
4002
4003 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4004 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4005 }
4006 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4007
4008 /* check, if we want to solve the LP at this node */
4009 if( solvelp && !(*cutoff) && SCIPtreeHasFocusNodeLP(tree) )
4010 {
4011 *lperror = FALSE;
4012 *unbounded = FALSE;
4013
4014 /* solve the node's LP */
4015 SCIP_CALL( solveNodeLP(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp, relaxation, pricestore,
4016 sepastore, cutpool, delayedcutpool, branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable,
4017 initiallpsolved, fullseparation, newinitconss, propagateagain, solverelaxagain, cutoff, unbounded, lperror, pricingaborted) );
4018
4019 *lpsolved = TRUE;
4020 *solvelpagain = FALSE;
4021 SCIPsetDebugMsg(set, " -> LP status: %d, LP obj: %g, iter: %" SCIP_LONGINT_FORMAT ", count: %" SCIP_LONGINT_FORMAT "\n",
4022 SCIPlpGetSolstat(lp),
4023 *cutoff ? SCIPsetInfinity(set) : (*lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob)),
4024 stat->nlpiterations, stat->lpcount);
4025
4026 /* check, if the path was cutoff */
4027 *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
4028
4029 /* if an error occured during LP solving, switch to pseudo solution */
4030 if( *lperror )
4031 {
4032 if( forcedlpsolve )
4033 {
4034 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
4035 stat->nnodes, stat->nlps);
4036 return SCIP_LPERROR;
4037 }
4039 ++(*nlperrors);
4040 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, actdepth == 0 ? SCIP_VERBLEVEL_HIGH : SCIP_VERBLEVEL_FULL,
4041 "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
4042 stat->nnodes, stat->nlps, *nlperrors);
4043 }
4044
4046 {
4048 *forcedenforcement = TRUE;
4049
4050 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, actdepth == 0 ? SCIP_VERBLEVEL_HIGH : SCIP_VERBLEVEL_FULL,
4051 "(node %" SCIP_LONGINT_FORMAT ") LP solver hit %s limit in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead\n",
4052 stat->nnodes, SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_TIMELIMIT ? "time" : "iteration", stat->nlps);
4053 }
4054
4056 {
4057 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4058 "(node %" SCIP_LONGINT_FORMAT ") LP relaxation is unbounded (LP %" SCIP_LONGINT_FORMAT ")\n", stat->nnodes, stat->nlps);
4059 }
4060
4061 /* if we solve exactly, the LP claims to be infeasible but the infeasibility could not be proved,
4062 * we have to forget about the LP and use the pseudo solution instead
4063 */
4064 if( !(*cutoff) && !(*lperror) && (set->misc_exactsolve || *pricingaborted) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_INFEASIBLE
4065 && SCIPnodeGetLowerbound(focusnode) < primal->cutoffbound )
4066 {
4067 if( SCIPbranchcandGetNPseudoCands(branchcand) == 0 && transprob->ncontvars > 0 )
4068 {
4069 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") could not prove infeasibility of LP %" SCIP_LONGINT_FORMAT " (exactsolve=%u, pricingaborted=%u), all variables are fixed, %d continuous vars\n",
4070 stat->nnodes, stat->nlps, set->misc_exactsolve, *pricingaborted, transprob->ncontvars);
4071 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") -> have to call PerPlex() (feature not yet implemented)\n", stat->nnodes);
4072 /**@todo call PerPlex */
4073 return SCIP_LPERROR;
4074 }
4075 else
4076 {
4078 *forcedenforcement = TRUE;
4079
4080 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4081 "(node %" SCIP_LONGINT_FORMAT ") could not prove infeasibility of LP %" SCIP_LONGINT_FORMAT " (exactsolve=%u, pricingaborted=%u) -- using pseudo solution (%d unfixed vars) instead\n",
4082 stat->nnodes, stat->nlps, set->misc_exactsolve, *pricingaborted, SCIPbranchcandGetNPseudoCands(branchcand));
4083 }
4084 }
4085
4086 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4087 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict,
4088 cliquetable, cutoff) );
4089 }
4090 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4091 assert(*cutoff || !SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
4092
4093 /* reset solverelaxagain if no relaxations were solved up to this point (the LP-changes are already included in
4094 * relaxators called after the LP)
4095 */
4096 *solverelaxagain = *solverelaxagain && *relaxcalled;
4097
4098 /* solve external relaxations with negative priority */
4099 if( solverelax && !(*cutoff) )
4100 {
4101 SCIP_CALL( solveNodeRelax(set, stat, tree, relaxation, transprob, origprob, actdepth, FALSE, cutoff,
4102 propagateagain, solvelpagain, solverelaxagain, relaxcalled) );
4103 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4104
4105 /* check, if the path was cutoff */
4106 *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
4107
4108 /* apply found cuts */
4109 SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4110 eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_RELAX, cutoff, propagateagain,
4111 solvelpagain, solverelaxagain) );
4112
4113 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4114 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict,
4115 cliquetable, cutoff) );
4116 }
4117 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4118
4119 return SCIP_OKAY;
4120}
4121
4122/** check if a restart can be performed */
4123#ifndef NDEBUG
4124static
4126 SCIP_SET* set, /**< global SCIP settings */
4127 SCIP_STAT* stat /**< dynamic problem statistics */
4128 )
4129{
4130 assert(set != NULL);
4131 assert(stat != NULL);
4132
4133 return set->nactivepricers == 0 && !set->reopt_enable
4134 && ( set->presol_maxrestarts == -1 || stat->nruns <= set->presol_maxrestarts );
4135}
4136#else
4137#define restartAllowed(set,stat) ((set)->nactivepricers == 0 && !set->reopt_enable && ((set)->presol_maxrestarts == -1 || (stat)->nruns <= (set)->presol_maxrestarts))
4138#endif
4139
4140/** solves the focus node */
4141static
4143 BMS_BLKMEM* blkmem, /**< block memory buffers */
4144 SCIP_SET* set, /**< global SCIP settings */
4145 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4146 SCIP_STAT* stat, /**< dynamic problem statistics */
4147 SCIP_MEM* mem, /**< block memory pools */
4148 SCIP_PROB* origprob, /**< original problem */
4149 SCIP_PROB* transprob, /**< transformed problem after presolve */
4150 SCIP_PRIMAL* primal, /**< primal data */
4151 SCIP_TREE* tree, /**< branch and bound tree */
4152 SCIP_REOPT* reopt, /**< reoptimization data structure */
4153 SCIP_LP* lp, /**< LP data */
4154 SCIP_RELAXATION* relaxation, /**< global relaxation data */
4155 SCIP_PRICESTORE* pricestore, /**< pricing storage */
4156 SCIP_SEPASTORE* sepastore, /**< separation storage */
4157 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4158 SCIP_CUTPOOL* cutpool, /**< global cut pool */
4159 SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
4160 SCIP_CONFLICT* conflict, /**< conflict analysis data */
4161 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
4162 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4163 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4164 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4165 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4166 SCIP_Bool* postpone, /**< pointer to store whether the node should be postponed */
4167 SCIP_Bool* unbounded, /**< pointer to store whether the focus node is unbounded */
4168 SCIP_Bool* infeasible, /**< pointer to store whether the focus node's solution is infeasible */
4169 SCIP_Bool* restart, /**< should solving process be started again with presolving? */
4170 SCIP_Bool* afternodeheur, /**< pointer to store whether AFTERNODE heuristics were already called */
4171 SCIP_Bool* stopped /**< pointer to store whether solving was interrupted */
4172 )
4173{
4174 SCIP_NODE* focusnode;
4175 SCIP_Longint lastdomchgcount;
4176 SCIP_Longint afterlpproplps;
4177 SCIP_Real restartfac;
4178 SCIP_Longint lastlpcount;
4179 SCIP_HEURTIMING heurtiming;
4180 int actdepth;
4181 int nlperrors;
4182 int nloops;
4183 SCIP_Bool foundsol;
4184 SCIP_Bool focusnodehaslp;
4185 SCIP_Bool lpsolved;
4186 SCIP_Bool initiallpsolved;
4187 SCIP_Bool fullseparation;
4188 SCIP_Bool solverelaxagain;
4189 SCIP_Bool solvelpagain;
4190 SCIP_Bool propagateagain;
4191 SCIP_Bool fullpropagation;
4192 SCIP_Bool branched;
4193 SCIP_Bool forcedlpsolve;
4194 SCIP_Bool wasforcedlpsolve;
4195 SCIP_Bool pricingaborted;
4196
4197 assert(set != NULL);
4198 assert(stat != NULL);
4199 assert(origprob != NULL);
4200 assert(transprob != NULL);
4201 assert(tree != NULL);
4202 assert(primal != NULL);
4203 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4204 assert(SCIPconflictGetNConflicts(conflict) == 0);
4205 assert(cutoff != NULL);
4206 assert(postpone != NULL);
4207 assert(unbounded != NULL);
4208 assert(infeasible != NULL);
4209 assert(restart != NULL);
4210 assert(afternodeheur != NULL);
4211
4212 *cutoff = FALSE;
4213 *postpone = FALSE;
4214 *unbounded = FALSE;
4215 *infeasible = FALSE;
4216 *restart = FALSE;
4217 *afternodeheur = FALSE;
4218 *stopped = FALSE;
4219 pricingaborted = FALSE;
4220
4221 focusnode = SCIPtreeGetFocusNode(tree);
4222 assert(focusnode != NULL);
4223 assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
4224 actdepth = SCIPnodeGetDepth(focusnode);
4225
4226 /* invalidate relaxation solution */
4228
4229 /* clear the storage of external branching candidates */
4231
4232 SCIPsetDebugMsg(set, "Processing node %" SCIP_LONGINT_FORMAT " in depth %d, %d siblings\n",
4233 stat->nnodes, actdepth, tree->nsiblings);
4234 SCIPsetDebugMsg(set, "current pseudosolution: obj=%g\n", SCIPlpGetPseudoObjval(lp, set, transprob));
4235 /*debug(SCIPprobPrintPseudoSol(transprob, set));*/
4236
4237 /* check, if we want to solve the LP at the selected node:
4238 * - solve the LP, if the lp solve depth and frequency demand solving
4239 * - solve the root LP, if the LP solve frequency is set to 0
4240 * - solve the root LP, if there are continuous variables present
4241 * - don't solve the node if its cut off by the pseudo objective value anyway
4242 */
4243 focusnodehaslp = (set->lp_solvedepth == -1 || actdepth <= set->lp_solvedepth);
4244 focusnodehaslp = focusnodehaslp && (set->lp_solvefreq >= 1 && actdepth % set->lp_solvefreq == 0);
4245 focusnodehaslp = focusnodehaslp || (actdepth == 0 && set->lp_solvefreq == 0);
4246 focusnodehaslp = focusnodehaslp && SCIPsetIsLT(set, SCIPlpGetPseudoObjval(lp, set, transprob), primal->cutoffbound);
4247 focusnodehaslp = set->reopt_enable ? focusnodehaslp && SCIPreoptGetSolveLP(reopt, set, focusnode) : focusnodehaslp;
4248 SCIPtreeSetFocusNodeLP(tree, focusnodehaslp);
4249
4250 /* external node solving loop:
4251 * - propagate domains
4252 * - solve SCIP_LP
4253 * - enforce constraints
4254 * if a constraint handler adds constraints to enforce its own constraints, both, propagation and LP solving
4255 * is applied again (if applicable on current node); however, if the new constraints don't have the enforce flag set,
4256 * it is possible, that the current infeasible solution is not cut off; in this case, we have to declare the solution
4257 * infeasible and perform a branching
4258 */
4259 lastdomchgcount = stat->domchgcount;
4260 lastlpcount = stat->lpcount;
4261 initiallpsolved = FALSE;
4262 fullseparation = TRUE;
4263 heurtiming = SCIP_HEURTIMING_BEFORENODE;
4264 nlperrors = 0;
4265 stat->npricerounds = 0;
4266 stat->nseparounds = 0;
4267 solverelaxagain = TRUE;
4268 solvelpagain = TRUE;
4269 propagateagain = TRUE;
4270 fullpropagation = TRUE;
4271 forcedlpsolve = FALSE;
4272 nloops = 0;
4273
4274 while( !(*cutoff) && !(*postpone) && (solverelaxagain || solvelpagain || propagateagain) && nlperrors < MAXNLPERRORS && !(*restart) )
4275 {
4276 SCIP_Bool lperror;
4277 SCIP_Bool solverelax;
4278 SCIP_Bool solvelp;
4279 SCIP_Bool propagate;
4280 SCIP_Bool forcedenforcement;
4281 SCIP_Bool relaxcalled;
4282
4283 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4284
4285 *unbounded = FALSE;
4286 *infeasible = FALSE;
4287 foundsol = FALSE;
4288
4289 nloops++;
4290 lperror = FALSE;
4291 lpsolved = FALSE;
4292 relaxcalled = FALSE;
4293 forcedenforcement = FALSE;
4294 afterlpproplps = -1L;
4295
4296 while( !lperror && !(*cutoff) && (propagateagain || solvelpagain || solverelaxagain
4297 || (afterlpproplps < stat->nnodelps && lpsolved) || relaxcalled) )
4298 {
4299 solverelax = solverelaxagain;
4300 solverelaxagain = FALSE;
4301 solvelp = solvelpagain;
4302 solvelpagain = FALSE;
4303 propagate = propagateagain;
4304 propagateagain = FALSE;
4305
4306 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4307 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
4308 conflict, cliquetable, cutoff) );
4309
4310 /* propagate domains before lp solving and solve relaxation and lp */
4311 SCIPsetDebugMsg(set, " -> node solving loop: call propagators that are applicable before%s LP is solved\n",
4312 lpsolved ? " and after" : "");
4313 SCIP_CALL( propAndSolve(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp,
4314 relaxation, pricestore, sepastore, branchcand, cutpool, delayedcutpool, conflict, conflictstore, eventfilter,
4315 eventqueue, cliquetable, focusnode, actdepth, propagate, solvelp, solverelax, forcedlpsolve, initiallpsolved,
4316 fullseparation, &afterlpproplps, &heurtiming, &nlperrors, &fullpropagation, &propagateagain, &lpsolved, &relaxcalled,
4317 &solvelpagain, &solverelaxagain, cutoff, postpone, unbounded, stopped, &lperror, &pricingaborted, &forcedenforcement) );
4318 initiallpsolved |= lpsolved;
4319
4320 /* time or solution limit was hit and we already created a dummy child node to terminate fast */
4321 if( *stopped )
4322 {
4323 /* reset LP feastol to normal value, in case someone tightened it during node solving */
4325 return SCIP_OKAY;
4326 }
4327 }
4328 fullseparation = FALSE;
4329
4330 /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4331 updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4332
4333 /* call primal heuristics that should be applied after the LP relaxation of the node was solved;
4334 * if this is the first loop of the root node, call also AFTERNODE heuristics already here, since they might help
4335 * to improve the primal bound, thereby producing additional reduced cost strengthenings and strong branching
4336 * bound fixings which also might lead to a restart
4337 */
4338 if( !(*postpone) && (!(*cutoff) || SCIPtreeGetNNodes(tree) > 0) )
4339 {
4340 if( actdepth == 0 && !(*afternodeheur) )
4341 {
4342 SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL,
4343 SCIP_HEURTIMING_AFTERLPLOOP | SCIP_HEURTIMING_AFTERNODE, *cutoff, &foundsol, unbounded) );
4344 *afternodeheur = TRUE; /* the AFTERNODE heuristics should not be called again after the node */
4345 }
4346 else if( lpsolved || SCIPrelaxationIsSolValid(relaxation) )
4347 {
4348 SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, SCIP_HEURTIMING_AFTERLPLOOP,
4349 *cutoff, &foundsol, unbounded) );
4350 }
4351 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4352
4353 /* heuristics might have found a solution or set the cutoff bound such that the current node is cut off */
4354 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4355 }
4356
4357 /* check if heuristics leave us with an invalid LP */
4358 if( lp->resolvelperror )
4359 {
4360 if( forcedlpsolve )
4361 {
4362 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
4363 stat->nnodes, stat->nlps);
4364 return SCIP_LPERROR;
4365 }
4367 lp->resolvelperror = FALSE;
4368 nlperrors++;
4369 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4370 "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
4371 stat->nnodes, stat->nlps, nlperrors);
4372 }
4373
4374 if( pricingaborted && !(*cutoff) && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL )
4375 {
4377
4378 /* if we just ran into the time limit this is not really a numerical trouble;
4379 * however, if this is not the case, we print messages about numerical troubles in the current LP
4380 */
4381 if( !SCIPsolveIsStopped(set, stat, FALSE) )
4382 {
4383 if( forcedlpsolve )
4384 {
4385 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
4386 stat->nnodes, stat->nlps);
4387 return SCIP_LPERROR;
4388 }
4389 nlperrors++;
4390 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4391 "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
4392 stat->nnodes, stat->nlps, nlperrors);
4393 }
4394 }
4395
4396 /* if an improved solution was found, propagate and solve the relaxations again */
4397 if( foundsol && !(*cutoff) )
4398 {
4399 propagateagain = TRUE;
4400 solvelpagain = TRUE;
4401 solverelaxagain = TRUE;
4402 markRelaxsUnsolved(set, relaxation);
4403 }
4404
4405 /* check for immediate restart */
4406 *restart = *restart || (actdepth == 0 && restartAllowed(set, stat) && (stat->userrestart
4407 || (stat->nrootintfixingsrun > set->presol_immrestartfac * (transprob->nvars - transprob->ncontvars)
4408 && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars))) );
4409
4410 /* enforce constraints */
4411 branched = FALSE;
4412 if( !(*postpone) && !(*restart) && !(*cutoff) && !solverelaxagain && !solvelpagain && !propagateagain )
4413 {
4414 /* if the solution changed since the last enforcement, we have to completely reenforce it; otherwise, we
4415 * only have to enforce the additional constraints added in the last enforcement, but keep the infeasible
4416 * flag TRUE in order to not declare the infeasible solution feasible due to disregarding the already
4417 * enforced constraints
4418 */
4419 if( lastdomchgcount != stat->domchgcount || lastlpcount != stat->lpcount )
4420 {
4421 lastdomchgcount = stat->domchgcount;
4422 lastlpcount = stat->lpcount;
4423 *infeasible = FALSE;
4424 }
4425
4426 /* call constraint enforcement */
4427 SCIP_CALL( enforceConstraints(blkmem, set, messagehdlr, stat, transprob, primal, tree, lp, relaxation, sepastore,
4428 branchcand, &branched, cutoff, infeasible, &propagateagain, &solvelpagain, &solverelaxagain,
4429 forcedenforcement) );
4430 assert(branched == (tree->nchildren > 0));
4431 assert(!branched || (!(*cutoff) && *infeasible && !propagateagain && !solvelpagain));
4432 assert(!(*cutoff) || (!branched && *infeasible && !propagateagain && !solvelpagain));
4433 assert(*infeasible || (!branched && !(*cutoff) && !propagateagain && !solvelpagain));
4434 assert(!propagateagain || (!branched && !(*cutoff) && *infeasible));
4435 assert(!solvelpagain || (!branched && !(*cutoff) && *infeasible));
4436
4437 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4438
4439 /* apply found cuts */
4440 SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4441 eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_LP, cutoff, &propagateagain,
4442 &solvelpagain, &solverelaxagain) );
4443
4444 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4445 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4446
4447 /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4448 updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4449 }
4450 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4451
4452 /* The enforcement detected no infeasibility, so, no branching was performed,
4453 * but the pricing was aborted and the current feasible solution does not have to be the
4454 * best solution in the current subtree --> we have to do a pseudo branching,
4455 * so we set infeasible TRUE and add the current solution to the solution pool
4456 */
4457 if( pricingaborted && !(*infeasible) && !(*cutoff) && !(*postpone) && !(*restart) )
4458 {
4459 SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
4460 SCIP_SOL* sol;
4461 SCIP_Bool stored;
4462
4463 /* in case the relaxation was enforced add this solution, otherwise decide between LP and pseudosol */
4465 || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
4466 {
4467 SCIP_SOL* relaxsol;
4468
4469 SCIP_CALL( SCIPsolCreateRelaxSol(&relaxsol, blkmem, set, stat, primal, tree, relaxation, NULL) );
4470
4471 SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4472 eventqueue, eventfilter, relaxsol, FALSE, FALSE, TRUE, TRUE, TRUE,
4473 &stored) );
4474
4475 SCIP_CALL( SCIPsolFree(&relaxsol, blkmem, primal) );
4476
4477 if( stored )
4478 {
4479 stat->nrelaxsolsfound++;
4480
4481 if( primal->nbestsolsfound != oldnbestsolsfound )
4482 {
4483 stat->nrelaxbestsolsfound++;
4485 }
4486 }
4487 }
4488 else
4489 {
4490 SCIP_CALL( SCIPsolCreateCurrentSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4491 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4492 eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
4493
4494 if( stored )
4495 {
4496 stat->nlpsolsfound++;
4497
4498 if( primal->nbestsolsfound != oldnbestsolsfound )
4499 {
4500 stat->nlpbestsolsfound++;
4502 }
4503 }
4504 }
4505
4506 *infeasible = TRUE;
4507 }
4508
4509 /* if the node is infeasible, but no constraint handler could resolve the infeasibility
4510 * -> branch on LP, external candidates, or the pseudo solution
4511 * -> e.g. select non-fixed binary or integer variable x with value x', create three
4512 * sons: x <= x'-1, x = x', and x >= x'+1.
4513 * In the left and right branch, the current solution is cut off. In the middle
4514 * branch, the constraints can hopefully reduce domains of other variables to cut
4515 * off the current solution.
4516 * In LP branching, we cannot allow adding constraints, because this does not necessary change the LP and can
4517 * therefore lead to an infinite loop.
4518 */
4519 wasforcedlpsolve = forcedlpsolve;
4520 forcedlpsolve = FALSE;
4521 if( (*infeasible) && !(*cutoff) && !(*postpone) && !(*restart)
4522 && (!(*unbounded) || SCIPbranchcandGetNExternCands(branchcand) > 0 || SCIPbranchcandGetNPseudoCands(branchcand) > 0)
4523 && !solverelaxagain && !solvelpagain && !propagateagain && !branched )
4524 {
4525 SCIP_RESULT result = SCIP_DIDNOTRUN;
4526 int nlpcands = 0;
4527
4528 if( SCIPtreeHasFocusNodeLP(tree) )
4529 {
4530 SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nlpcands, NULL, NULL) );
4531 }
4532
4533 if ( nlpcands > 0 || SCIPbranchcandGetNExternCands(branchcand) > 0 )
4534 {
4535 /* If there are LP candidates and their maximal priority is at least the maximal priority of the external
4536 * candidates, then branch on the LP candidates. Note that due to implicit integer variables,
4537 * SCIPbranchcandGetLPMaxPrio(branchcand) might be finite and SCIPbranchcandGetNPrioLPCands(branchcand) > 0,
4538 * but nlpcands == 0. */
4539 if ( SCIPbranchcandGetLPMaxPrio(branchcand) >= SCIPbranchcandGetExternMaxPrio(branchcand) && nlpcands > 0 )
4540 {
4541 assert( SCIPbranchcandGetNPrioLPCands(branchcand) > 0 );
4542 assert( nlpcands > 0 );
4543
4544 /* branch on LP solution */
4545 SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on LP solution with %d fractionals\n",
4546 SCIPnodeGetDepth(focusnode), nlpcands);
4547 SCIP_CALL( SCIPbranchExecLP(blkmem, set, stat, transprob, origprob, tree, reopt, lp, sepastore, branchcand,
4548 eventqueue, primal->cutoffbound, FALSE, &result) );
4549 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4550 assert(result != SCIP_DIDNOTRUN && result != SCIP_DIDNOTFIND);
4551 }
4552 else
4553 {
4554 assert( SCIPbranchcandGetNPrioExternCands(branchcand) > 0 );
4555 assert( SCIPbranchcandGetNExternCands(branchcand) > 0 );
4556
4557 /* branch on external candidates */
4558 SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on %d external branching candidates.\n",
4559 SCIPnodeGetDepth(focusnode), SCIPbranchcandGetNExternCands(branchcand));
4560 SCIP_CALL( SCIPbranchExecExtern(blkmem, set, stat, transprob, origprob, tree, reopt, lp, sepastore, branchcand,
4561 eventqueue, primal->cutoffbound, TRUE, &result) );
4562 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4563 }
4564 }
4565
4566 if( result == SCIP_DIDNOTRUN || result == SCIP_DIDNOTFIND )
4567 {
4568 /* branch on pseudo solution */
4569 SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on pseudo solution with %d unfixed integers\n",
4570 SCIPnodeGetDepth(focusnode), SCIPbranchcandGetNPseudoCands(branchcand));
4571 SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
4572 primal->cutoffbound, TRUE, &result) );
4573 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4574 }
4575
4576 /* SCIP cannot guarantee convergence if it is necessary to branch on unbounded variables */
4577 if( result == SCIP_BRANCHED )
4578 {
4579 SCIP_VAR* var = stat->lastbranchvar;
4580
4581 if( var != NULL && !stat->branchedunbdvar && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS
4583 {
4584 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_NORMAL,
4585 "Starting spatial branch-and-bound on unbounded variable <%s> ([%g,%g]) - cannot guarantee finite termination.\n",
4587 stat->branchedunbdvar = TRUE;
4588 }
4589 }
4590
4591 switch( result )
4592 {
4593 case SCIP_CUTOFF:
4594 assert(tree->nchildren == 0);
4595 *cutoff = TRUE;
4596 SCIPsetDebugMsg(set, " -> branching rule detected cutoff\n");
4597 break;
4598 case SCIP_CONSADDED:
4599 assert(tree->nchildren == 0);
4600 if( nlpcands > 0 )
4601 {
4602 SCIPerrorMessage("LP branching rule added constraint, which was not allowed this time\n");
4603 return SCIP_INVALIDRESULT;
4604 }
4605 propagateagain = TRUE;
4606 solvelpagain = TRUE;
4607 solverelaxagain = TRUE;
4608 markRelaxsUnsolved(set, relaxation);
4609 break;
4610 case SCIP_REDUCEDDOM:
4611 assert(tree->nchildren == 0);
4612 propagateagain = TRUE;
4613 solvelpagain = TRUE;
4614 solverelaxagain = TRUE;
4615 markRelaxsUnsolved(set, relaxation);
4616 break;
4617 case SCIP_SEPARATED:
4618 assert(tree->nchildren == 0);
4619 assert(SCIPsepastoreGetNCuts(sepastore) > 0);
4620 solvelpagain = TRUE;
4621 solverelaxagain = TRUE;
4622 markRelaxsUnsolved(set, relaxation);
4623 break;
4624 case SCIP_BRANCHED:
4625 assert(tree->nchildren >= 1);
4626 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4627 branched = TRUE;
4628
4629 /* increase the number of internal nodes */
4630 stat->ninternalnodes++;
4631 stat->ntotalinternalnodes++;
4632 break;
4633 case SCIP_DIDNOTFIND: /*lint -fallthrough*/
4634 case SCIP_DIDNOTRUN:
4635 /* all integer variables in the infeasible solution are fixed,
4636 * - if no continuous variables exist and all variables are known, the infeasible pseudo solution is completely
4637 * fixed, and the node can be cut off
4638 * - if at least one continuous variable exists or we do not know all variables due to external pricers, we
4639 * cannot resolve the infeasibility by branching -> solve LP (and maybe price in additional variables)
4640 */
4641 assert(tree->nchildren == 0);
4642 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4643 assert(SCIPbranchcandGetNPseudoCands(branchcand) == 0);
4644
4645 if( transprob->ncontvars == 0 && set->nactivepricers == 0 )
4646 {
4647 *cutoff = TRUE;
4648 SCIPsetDebugMsg(set, " -> cutoff because all variables are fixed in current node\n");
4649 }
4650 else
4651 {
4652 /* feasible LP solutions with all integers fixed must be feasible
4653 * if also no external branching candidates were available
4654 */
4655 assert(!SCIPtreeHasFocusNodeLP(tree) || pricingaborted);
4656
4658 {
4659 SCIP_NODE* node;
4660
4661 /* as we hit the time or iteration limit or another interrupt (e.g., gap limit), we do not want to solve the LP again.
4662 * in order to terminate correctly, we create a "branching" with only one child node
4663 * that is a copy of the focusnode
4664 */
4665 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, 1.0, focusnode->estimate) );
4666 assert(tree->nchildren >= 1);
4667 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4668 branched = TRUE;
4669 }
4670 else
4671 {
4672 SCIP_VERBLEVEL verblevel;
4673
4674 if( pricingaborted )
4675 {
4676 SCIPerrorMessage("pricing was aborted, but no branching could be created!\n");
4677 return SCIP_INVALIDRESULT;
4678 }
4679
4680 if( wasforcedlpsolve )
4681 {
4682 assert(SCIPtreeHasFocusNodeLP(tree));
4683 SCIPerrorMessage("LP was solved, all integers fixed, some constraint still infeasible, but no branching could be created!\n");
4684 return SCIP_INVALIDRESULT;
4685 }
4686
4687 verblevel = SCIP_VERBLEVEL_FULL;
4688
4689 if( !tree->forcinglpmessage && set->disp_verblevel == SCIP_VERBLEVEL_HIGH )
4690 {
4691 verblevel = SCIP_VERBLEVEL_HIGH;
4692
4693 /* remember that the forcing LP solving message was posted and do only post it again if the
4694 * verblevel is SCIP_VERBLEVEL_FULL
4695 */
4696 tree->forcinglpmessage = TRUE;
4697 }
4698
4699 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, verblevel,
4700 "(node %" SCIP_LONGINT_FORMAT ") forcing the solution of an LP (last LP %" SCIP_LONGINT_FORMAT ")...\n", stat->nnodes, stat->nlps);
4701
4702 /* solve the LP in the next loop */
4704 solvelpagain = TRUE;
4705 forcedlpsolve = TRUE; /* this LP must be solved without error - otherwise we have to abort */
4706 }
4707 }
4708 break;
4709 default:
4710 SCIPerrorMessage("invalid result code <%d> from SCIPbranchLP(), SCIPbranchExt() or SCIPbranchPseudo()\n", result);
4711 return SCIP_INVALIDRESULT;
4712 } /*lint !e788*/
4713 assert(*cutoff || solvelpagain || propagateagain || branched); /* something must have been done */
4714 assert(!(*cutoff) || (!solvelpagain && !propagateagain && !branched));
4715 assert(!solvelpagain || (!(*cutoff) && !branched));
4716 assert(!propagateagain || (!(*cutoff) && !branched));
4717 assert(!branched || (!solvelpagain && !propagateagain));
4718 assert(branched == (tree->nchildren > 0));
4719
4720 /* apply found cuts */
4721 SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4722 eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_LP, cutoff, &propagateagain,
4723 &solvelpagain, &solverelaxagain) );
4724
4725 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4726 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4727
4728 /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4729 updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4730 }
4731
4732 /* check for immediate restart */
4733 *restart = *restart || (actdepth == 0 && restartAllowed(set, stat) && (stat->userrestart
4734 || (stat->nrootintfixingsrun > set->presol_immrestartfac * (transprob->nvars - transprob->ncontvars)
4735 && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars))) );
4736
4737 SCIPsetDebugMsg(set, "node solving iteration %d finished: cutoff=%u, postpone=%u, propagateagain=%u, solverelaxagain=%u, solvelpagain=%u, nlperrors=%d, restart=%u\n",
4738 nloops, *cutoff, *postpone, propagateagain, solverelaxagain, solvelpagain, nlperrors, *restart);
4739 }
4740 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4741 assert(*cutoff || SCIPconflictGetNConflicts(conflict) == 0);
4742
4743 /* flush the conflict set storage */
4744 SCIP_CALL( SCIPconflictFlushConss(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cliquetable) );
4745
4746 /* check for too many LP errors */
4747 if( nlperrors >= MAXNLPERRORS )
4748 {
4749 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- aborting\n", stat->nnodes, stat->nlps);
4750 return SCIP_LPERROR;
4751 }
4752
4753 /* check for final restart */
4754 restartfac = set->presol_subrestartfac;
4755 if( actdepth == 0 )
4756 restartfac = MIN(restartfac, set->presol_restartfac);
4757 *restart = *restart || (restartAllowed(set, stat) && (stat->userrestart
4758 || (stat->nrootintfixingsrun > restartfac * (transprob->nvars - transprob->ncontvars)
4759 && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars))) );
4760
4761 /* remember the last root LP solution */
4762 if( actdepth == 0 && !(*cutoff) && !(*unbounded) && !(*postpone) )
4763 {
4764 /* the root pseudo objective value and pseudo objective value should be equal in the root node */
4765 assert(SCIPsetIsFeasEQ(set, SCIPlpGetGlobalPseudoObjval(lp, set, transprob), SCIPlpGetPseudoObjval(lp, set, transprob)));
4766
4767 SCIPprobStoreRootSol(transprob, set, stat, lp, SCIPtreeHasFocusNodeLP(tree));
4768 }
4769
4770 /* check for cutoff */
4771 if( *cutoff )
4772 {
4773 SCIPsetDebugMsg(set, "node is cut off\n");
4774
4775 SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, SCIPsetInfinity(set));
4776 *infeasible = TRUE;
4777 SCIP_CALL( SCIPdebugRemoveNode(blkmem, set, focusnode) ); /*lint !e506 !e774*/
4778
4779 /* the LP might have been unbounded but not enforced, because the node is cut off anyway */
4780 *unbounded = FALSE;
4781 }
4782 else if( !(*unbounded) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && lp->looseobjvalinf == 0 )
4783 {
4784 /* update the regression statistic nlpbranchcands and LP objective value */
4785 int nlpbranchcands;
4786 SCIP_Real lpobjval;
4787
4788 /* get number of LP candidate variables */
4789 SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nlpbranchcands, NULL, NULL) );
4790
4791 /* get LP objective value */
4792 lpobjval = SCIPlpGetObjval(lp, set, transprob);
4793 assert(lpobjval != SCIP_INVALID); /*lint !e777*/
4794
4795 /* add the observation to the regression */
4796 SCIPregressionAddObservation(stat->regressioncandsobjval, (SCIP_Real)nlpbranchcands, lpobjval);
4797 }
4798
4799 /* reset LP feastol to normal value, in case someone tightened it during node solving */
4801
4802 return SCIP_OKAY;
4803}
4804
4805/** if feasible, adds current solution to the solution storage */
4806static
4808 BMS_BLKMEM* blkmem, /**< block memory buffers */
4809 SCIP_SET* set, /**< global SCIP settings */
4810 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4811 SCIP_STAT* stat, /**< dynamic problem statistics */
4812 SCIP_PROB* origprob, /**< original problem */
4813 SCIP_PROB* transprob, /**< transformed problem after presolve */
4814 SCIP_PRIMAL* primal, /**< primal data */
4815 SCIP_RELAXATION* relaxation, /**< global relaxation data */
4816 SCIP_TREE* tree, /**< branch and bound tree */
4817 SCIP_REOPT* reopt, /**< reoptimization data structure */
4818 SCIP_LP* lp, /**< LP data */
4819 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4820 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4821 SCIP_Bool checksol /**< should the solution be checked? */
4822 )
4823{
4824 SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
4825 SCIP_SOL* sol;
4826 SCIP_Bool foundsol;
4827
4828 /* found a feasible solution */
4830 || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
4831 {
4832 /* start clock for relaxation solutions */
4834
4835 SCIP_CALL( SCIPsolCreateRelaxSol(&sol, blkmem, set, stat, primal, tree, relaxation, NULL) );
4836
4837 SCIPsetDebugMsg(set, "found relaxation solution with objective %f\n", SCIPsolGetObj(sol, set, transprob, origprob));
4838
4839 if( checksol || set->misc_exactsolve )
4840 {
4841 /* if we want to solve exactly, we have to check the solution exactly again */
4842 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4843 eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &foundsol) );
4844 }
4845 else
4846 {
4847 SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4848 eventqueue, eventfilter, &sol, &foundsol) );
4849 }
4850
4851 if( foundsol )
4852 {
4853 stat->nrelaxsolsfound++;
4854
4855 if( primal->nbestsolsfound != oldnbestsolsfound )
4856 {
4857 stat->nrelaxbestsolsfound++;
4859 }
4860 }
4861
4862 /* stop clock for relaxation solutions */
4864 }
4865 else if( SCIPtreeHasFocusNodeLP(tree) )
4866 {
4867 assert(lp->primalfeasible);
4868
4869 /* start clock for LP solutions */
4871
4872 /* add solution to storage */
4873 SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4874
4875 SCIPsetDebugMsg(set, "found lp solution with objective %f\n", SCIPsolGetObj(sol, set, transprob, origprob));
4876
4877 if( checksol || set->misc_exactsolve )
4878 {
4879 /* if we want to solve exactly, we have to check the solution exactly again */
4880 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4881 eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &foundsol) );
4882 }
4883 else
4884 {
4885 SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4886 eventqueue, eventfilter, &sol, &foundsol) );
4887 }
4888
4889 if( foundsol )
4890 {
4891 stat->nlpsolsfound++;
4892
4893 if( primal->nbestsolsfound != oldnbestsolsfound )
4894 {
4895 stat->nlpbestsolsfound++;
4897 }
4898 }
4899
4900 /* stop clock for LP solutions */
4901 SCIPclockStop(stat->lpsoltime, set);
4902 }
4903 else
4904 {
4905 /* start clock for pseudo solutions */
4907
4908 /* add solution to storage */
4909 SCIP_CALL( SCIPsolCreatePseudoSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4910
4911 SCIPsetDebugMsg(set, "found pseudo solution with objective %f\n", SCIPsolGetObj(sol, set, transprob, origprob));
4912
4913 if( checksol || set->misc_exactsolve )
4914 {
4915 /* if we want to solve exactly, we have to check the solution exactly again */
4916 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4917 eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &foundsol) );
4918 }
4919 else
4920 {
4921 SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4922 eventqueue, eventfilter, &sol, &foundsol) );
4923 }
4924
4925 /* stop clock for pseudo solutions */
4927
4928 if( foundsol )
4929 {
4930 stat->npssolsfound++;
4931
4932 if( primal->nbestsolsfound != oldnbestsolsfound )
4933 {
4934 stat->npsbestsolsfound++;
4936 }
4937 }
4938 }
4939
4940 return SCIP_OKAY;
4941}
4942
4943/** main solving loop */
4945 BMS_BLKMEM* blkmem, /**< block memory buffers */
4946 SCIP_SET* set, /**< global SCIP settings */
4947 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4948 SCIP_STAT* stat, /**< dynamic problem statistics */
4949 SCIP_MEM* mem, /**< block memory pools */
4950 SCIP_PROB* origprob, /**< original problem */
4951 SCIP_PROB* transprob, /**< transformed problem after presolve */
4952 SCIP_PRIMAL* primal, /**< primal data */
4953 SCIP_TREE* tree, /**< branch and bound tree */
4954 SCIP_REOPT* reopt, /**< reoptimization data structure */
4955 SCIP_LP* lp, /**< LP data */
4956 SCIP_RELAXATION* relaxation, /**< global relaxation data */
4957 SCIP_PRICESTORE* pricestore, /**< pricing storage */
4958 SCIP_SEPASTORE* sepastore, /**< separation storage */
4959 SCIP_CUTPOOL* cutpool, /**< global cut pool */
4960 SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
4961 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4962 SCIP_CONFLICT* conflict, /**< conflict analysis data */
4963 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
4964 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4965 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4966 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4967 SCIP_Bool* restart /**< should solving process be started again with presolving? */
4968 )
4969{
4970 SCIP_NODESEL* nodesel;
4971 SCIP_NODE* focusnode;
4972 SCIP_NODE* nextnode;
4973 SCIP_EVENT event;
4974 SCIP_Real restartfac;
4975 SCIP_Real restartconfnum;
4976 int nnodes;
4977 int depth;
4978 SCIP_Bool cutoff;
4979 SCIP_Bool postpone;
4980 SCIP_Bool unbounded;
4981 SCIP_Bool infeasible;
4982 SCIP_Bool foundsol;
4983
4984 assert(set != NULL);
4985 assert(blkmem != NULL);
4986 assert(stat != NULL);
4987 assert(transprob != NULL);
4988 assert(tree != NULL);
4989 assert(lp != NULL);
4990 assert(pricestore != NULL);
4991 assert(sepastore != NULL);
4992 assert(branchcand != NULL);
4993 assert(cutpool != NULL);
4994 assert(delayedcutpool != NULL);
4995 assert(primal != NULL);
4996 assert(eventfilter != NULL);
4997 assert(eventqueue != NULL);
4998 assert(restart != NULL);
4999
5000 /* check for immediate restart (if problem solving marked to be restarted was aborted) */
5001 restartfac = set->presol_subrestartfac;
5002 if( SCIPtreeGetCurrentDepth(tree) == 0 )
5003 restartfac = MIN(restartfac, set->presol_restartfac);
5004 *restart = restartAllowed(set, stat) && (stat->userrestart
5005 || (stat->nrootintfixingsrun > restartfac * (transprob->nvars - transprob->ncontvars)
5006 && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars)) );
5007
5008 /* calculate the number of successful conflict analysis calls that should trigger a restart */
5009 if( set->conf_restartnum > 0 )
5010 {
5011 int i;
5012
5013 restartconfnum = (SCIP_Real)set->conf_restartnum;
5014 for( i = 0; i < stat->nconfrestarts; ++i )
5015 restartconfnum *= set->conf_restartfac;
5016 }
5017 else
5018 restartconfnum = SCIP_REAL_MAX;
5019 assert(restartconfnum >= 0.0);
5020
5021 /* switch status to UNKNOWN */
5023
5024 focusnode = NULL;
5025 nextnode = NULL;
5026 unbounded = FALSE;
5027 postpone = FALSE;
5028
5029 while( !SCIPsolveIsStopped(set, stat, TRUE) && !(*restart) )
5030 {
5031 SCIP_Longint nsuccessconflicts;
5032 SCIP_Bool afternodeheur;
5033 SCIP_Bool stopped;
5034 SCIP_Bool branched;
5035
5036 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5037
5038 foundsol = FALSE;
5039 infeasible = FALSE;
5040
5041 do
5042 {
5043 /* update the memory saving flag, switch algorithms respectively */
5044 SCIPstatUpdateMemsaveMode(stat, set, messagehdlr, mem);
5045
5046 /* get the current node selector */
5047 nodesel = SCIPsetGetNodesel(set, stat);
5048
5049 /* inform tree about the current node selector */
5050 SCIP_CALL( SCIPtreeSetNodesel(tree, set, messagehdlr, stat, nodesel) );
5051
5052 /* the next node was usually already selected in the previous solving loop before the primal heuristics were
5053 * called, because they need to know, if the next node will be a child/sibling (plunging) or not;
5054 * if the heuristics found a new best solution that cut off some of the nodes, the node selector must be called
5055 * again, because the selected next node may be invalid due to cut off
5056 */
5057 if( nextnode == NULL )
5058 {
5059 /* select next node to process */
5060 SCIP_CALL( SCIPnodeselSelect(nodesel, set, &nextnode) );
5061 }
5062 focusnode = nextnode;
5063 nextnode = NULL;
5064 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5065
5066 /* start node activation timer */
5068
5069 /* focus selected node */
5070 SCIP_CALL( SCIPnodeFocus(&focusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt,
5071 lp, branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, FALSE, FALSE) );
5072 if( cutoff )
5073 stat->ndelayedcutoffs++;
5074
5075 /* stop node activation timer */
5077
5078 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5079 }
5080 while( cutoff ); /* select new node, if the current one was located in a cut off subtree */
5081
5082 assert(SCIPtreeGetCurrentNode(tree) == focusnode);
5083 assert(SCIPtreeGetFocusNode(tree) == focusnode);
5084
5085 /* if no more node was selected, we finished optimization */
5086 if( focusnode == NULL )
5087 {
5088 assert(SCIPtreeGetNNodes(tree) == 0);
5089 break;
5090 }
5091
5092 /* update maxdepth and node count statistics */
5093 depth = SCIPnodeGetDepth(focusnode);
5094 stat->maxdepth = MAX(stat->maxdepth, depth);
5095 stat->maxtotaldepth = MAX(stat->maxtotaldepth, depth);
5096 stat->nnodes++;
5097 stat->ntotalnodes++;
5098
5099 /* update reference bound statistic, if available */
5100 if( SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), stat->referencebound) )
5101 stat->nnodesaboverefbound++;
5102
5103 /* issue NODEFOCUSED event */
5105 SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
5106 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
5107
5108 /* solve focus node */
5109 SCIP_CALL( solveNode(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp, relaxation,
5110 pricestore, sepastore, branchcand, cutpool, delayedcutpool, conflict, conflictstore, eventfilter, eventqueue,
5111 cliquetable, &cutoff, &postpone, &unbounded, &infeasible, restart, &afternodeheur, &stopped) );
5112 assert(!cutoff || infeasible);
5113 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5114 assert(SCIPtreeGetCurrentNode(tree) == focusnode);
5115 assert(SCIPtreeGetFocusNode(tree) == focusnode);
5116
5117 branched = (tree->nchildren > 0);
5118
5119 if( stopped )
5120 break;
5121
5122 /* check for restart */
5123 if( !(*restart) && !postpone )
5124 {
5125 /* change color of node in visualization */
5126 SCIPvisualSolvedNode(stat->visual, set, stat, focusnode);
5127
5128 /* check, if the current solution is feasible */
5129 if( !infeasible )
5130 {
5131 SCIP_Bool feasible;
5132
5133 assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
5134 assert(!cutoff);
5135
5136 /* in the unbounded case, we check the solution w.r.t. the original problem, because we do not want to rely
5137 * on the LP feasibility and integrality is not checked for unbounded solutions, anyway
5138 */
5139 if( unbounded )
5140 {
5141 SCIP_SOL* sol;
5142
5144 || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
5145 {
5146 SCIP_CALL( SCIPsolCreateRelaxSol(&sol, blkmem, set, stat, primal, tree, relaxation, NULL) );
5147 }
5148 else if( SCIPtreeHasFocusNodeLP(tree) )
5149 {
5150 SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
5151 }
5152 else
5153 {
5154 SCIP_CALL( SCIPsolCreatePseudoSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
5155 }
5156 SCIP_CALL( SCIPcheckSolOrig(set->scip, sol, &feasible, FALSE, FALSE) );
5157
5158 SCIP_CALL( SCIPsolFree(&sol, blkmem, primal) );
5159 }
5160 else
5161 feasible = TRUE;
5162
5163 /* node solution is feasible: add it to the solution store */
5164 if( feasible )
5165 {
5166 SCIP_CALL( addCurrentSolution(blkmem, set, messagehdlr, stat, origprob, transprob, primal, relaxation, tree, reopt,
5167 lp, eventqueue, eventfilter, FALSE) );
5168
5169 /* update the cutoff pointer if the new solution made the cutoff bound equal to the lower bound */
5170 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, &cutoff) );
5171
5172 /* increment number of feasible leaf nodes */
5173 stat->nfeasleaves++;
5174
5175 /* issue NODEFEASIBLE event */
5177 SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
5178 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
5179
5180 if( set->reopt_enable )
5181 {
5182 assert(reopt != NULL);
5183 SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEFEASIBLE, lp,
5184 SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
5185 focusnode->lowerbound, tree->effectiverootdepth) );
5186 }
5187 }
5188 }
5189 else if( !unbounded || branched )
5190 {
5191 /* node solution is not feasible */
5192 if( !branched )
5193 {
5194 assert(tree->nchildren == 0);
5195
5196 /* change color of node in visualization output */
5197 SCIPvisualCutoffNode(stat->visual, set, stat, focusnode, TRUE);
5198
5199 /* issue NODEINFEASIBLE event */
5201
5202 /* we only increase the number of objective leaf nodes if we hit the LP objective limit; we might have also
5203 * hit the objective limit at a node that is actually infeasible, or a dual reduction led to an infeasibility prior
5204 * to LP solving such that the node will be marked as infeasible */
5206 stat->nobjleaves++;
5207 else
5208 stat->ninfeasleaves++;
5209
5210 if( set->reopt_enable )
5211 {
5212 assert(reopt != NULL);
5213 SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEINFEASIBLE, lp,
5214 SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
5215 focusnode->lowerbound, tree->effectiverootdepth) );
5216 }
5217
5218 /* increase the cutoff counter of the branching variable */
5219 if( stat->lastbranchvar != NULL )
5220 {
5221 SCIP_CALL( SCIPvarIncCutoffSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
5222 }
5223 /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
5224 }
5225 else
5226 {
5227 assert(tree->nchildren > 0);
5228
5229 /* issue NODEBRANCHED event */
5231
5232 if( set->reopt_enable )
5233 {
5234 assert(reopt != NULL);
5235 SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEBRANCHED, lp,
5236 SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
5237 focusnode->lowerbound, tree->effectiverootdepth) );
5238 }
5239 }
5240 SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
5241 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
5242 }
5243 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5244
5245 /* if no branching was created, the node was not cut off, but its lower bound is still smaller than
5246 * the cutoff bound, we have to branch on a non-fixed variable;
5247 * this can happen, if we want to solve exactly, the current solution was declared feasible by the
5248 * constraint enforcement, but in exact solution checking it was found out to be infeasible;
5249 * in this case, no branching would have been generated by the enforcement of constraints, but we
5250 * have to further investigate the current sub tree;
5251 * note that we must not check tree->nchildren > 0 here to determine whether we branched, we rather
5252 * check it directly after solveNode() and store the result, because an event handler might impose a
5253 * new cutoff bound (as is the case in ParaSCIP)
5254 */
5255 if( !cutoff && !unbounded && !branched && SCIPnodeGetLowerbound(focusnode) < primal->cutoffbound )
5256 {
5257 SCIP_RESULT result;
5258
5259 assert(set->misc_exactsolve);
5260
5261 do
5262 {
5263 result = SCIP_DIDNOTRUN;
5264 if( SCIPbranchcandGetNPseudoCands(branchcand) == 0 )
5265 {
5266 if( transprob->ncontvars > 0 )
5267 {
5268 /**@todo call PerPlex */
5269 SCIPerrorMessage("cannot branch on all-fixed LP -- have to call PerPlex instead\n");
5270 }
5271 }
5272 else
5273 {
5274 SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
5275 eventqueue, primal->cutoffbound, FALSE, &result) );
5276 assert(result != SCIP_DIDNOTRUN && result != SCIP_DIDNOTFIND);
5277 }
5278 }
5279 while( result == SCIP_REDUCEDDOM );
5280 }
5281 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5282
5283 /* select node to process in next solving loop; the primal heuristics need to know whether a child/sibling
5284 * (plunging) will be selected as next node or not
5285 */
5286 SCIP_CALL( SCIPnodeselSelect(nodesel, set, &nextnode) );
5287 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5288
5289 /* call primal heuristics that should be applied after the node was solved */
5290 nnodes = SCIPtreeGetNNodes(tree);
5291 stopped = SCIPsolveIsStopped(set, stat, FALSE);
5292 if( !afternodeheur && (!cutoff || nnodes > 0) && !stopped )
5293 {
5294 SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, nextnode, SCIP_HEURTIMING_AFTERNODE,
5295 cutoff, &foundsol, &unbounded) );
5296 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5297
5298 stopped = SCIPsolveIsStopped(set, stat, FALSE);
5299 }
5300
5301 /* if the heuristics found a new best solution that cut off some of the nodes, the node selector must be called
5302 * again, because the selected next node may be invalid due to cut off
5303 */
5304 assert(!tree->cutoffdelayed);
5305
5306 if( nnodes != SCIPtreeGetNNodes(tree) || stopped )
5307 nextnode = NULL;
5308 }
5309 else if( !infeasible && !postpone )
5310 {
5311 /* The current solution was not proven to be infeasible, but due to the restart, this does not mean that it is
5312 * feasible, we might just have skipped the check. Thus, we try to add it to the solution store, but check it
5313 * again.
5314 */
5315 SCIP_CALL( addCurrentSolution(blkmem, set, messagehdlr, stat, origprob, transprob, primal, relaxation, tree, reopt, lp,
5316 eventqueue, eventfilter, TRUE) );
5317
5318 if( set->reopt_enable )
5319 {
5320 assert(reopt != NULL);
5321 SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEFEASIBLE, lp,
5322 SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode, focusnode->lowerbound,
5323 tree->effectiverootdepth) );
5324 }
5325 }
5326 /* we want to put the focusnode back into the leaf queue if it was postponed */
5327 else if( postpone )
5328 {
5329 SCIP_NODE* newfocusnode = NULL;
5330
5331 /* @todo should we re-install the old focus node in order to somehow set the forks more clever? */
5332 SCIP_CALL( SCIPnodeFocus(&newfocusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
5333 branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, TRUE, FALSE) );
5334 }
5335 /* compute number of successfully applied conflicts */
5336 nsuccessconflicts = SCIPconflictGetNPropSuccess(conflict) + SCIPconflictGetNInfeasibleLPSuccess(conflict)
5339
5340 /* trigger restart due to conflicts and the restart parameters allow another restart */
5341 if( nsuccessconflicts >= restartconfnum && restartAllowed(set, stat) )
5342 {
5343 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
5344 "(run %d, node %" SCIP_LONGINT_FORMAT ") restarting after %" SCIP_LONGINT_FORMAT " successful conflict analysis calls\n",
5345 stat->nruns, stat->nnodes, nsuccessconflicts);
5346 *restart = TRUE;
5347
5348 stat->nconfrestarts++;
5349 }
5350
5351 /* restart if the userrestart was set to true, we have still some nodes left and the restart parameters allow
5352 * another restart
5353 */
5354 *restart = *restart || (stat->userrestart && SCIPtreeGetNNodes(tree) > 0 && restartAllowed(set, stat));
5355 if( restartAllowed(set, stat) && set->limit_autorestartnodes == stat->nnodes && stat->ntotalnodes - stat->nruns + 1 == set->limit_autorestartnodes )
5356 {
5357 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
5358 "(run %d, node %" SCIP_LONGINT_FORMAT ") restarting: triggering parameter controlled restart)\n",
5359 stat->nruns, stat->nnodes);
5360 *restart = TRUE;
5361 }
5362 /* if restart limit was exceeded, change the status; if status is different from unknown, ie some other limit was
5363 * hit, leave it unchanged
5364 */
5365 if( *restart && stat->status == SCIP_STATUS_UNKNOWN && set->limit_restarts >= 0 && stat->nruns > set->limit_restarts )
5366 {
5367 *restart = FALSE;
5369 }
5370
5371 /* display node information line */
5372 SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, (SCIPnodeGetDepth(focusnode) == 0) && infeasible && !foundsol, TRUE) );
5373
5374 SCIPsetDebugMsg(set, "Processing of node %" SCIP_LONGINT_FORMAT " in depth %d finished. %d siblings, %d children, %d leaves left\n",
5375 stat->nnodes, SCIPnodeGetDepth(focusnode), tree->nsiblings, tree->nchildren, SCIPtreeGetNLeaves(tree));
5376 SCIPsetDebugMsg(set, "**********************************************************************\n");
5377 }
5378
5379 /* update the primal-dual integral if node or time limits were hit or an interruption signal was called */
5380 if( SCIPsolveIsStopped(set, stat, TRUE) )
5381 {
5383 }
5384
5385 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5386
5387 SCIPsetDebugMsg(set, "Problem solving finished with status %d (restart=%u, userrestart=%u)\n", stat->status, *restart, stat->userrestart);
5388
5389 /* cuts off nodes with lower bound is not better than given cutoff bound, manually; this necessary to ensure that
5390 * SCIP terminates with a proper solve stage
5391 */
5392 SCIP_CALL( SCIPtreeCutoff(tree, reopt, blkmem, set, stat, eventfilter, eventqueue, lp, primal->cutoffbound) );
5393
5394 /* if the current node is the only remaining node, and if its lower bound exceeds the upper bound, we have
5395 * to delete it manually in order to get to the SOLVED stage instead of thinking, that only the gap limit
5396 * was reached (this may happen, if the current node is the one defining the global lower bound and a
5397 * feasible solution with the same value was found at this node)
5398 */
5399 if( tree->focusnode != NULL && SCIPtreeGetNNodes(tree) == 0
5400 && SCIPsetIsGE(set, tree->focusnode->lowerbound, primal->cutoffbound) )
5401 {
5402 if( set->reopt_enable )
5403 {
5404 assert(reopt != NULL);
5406 SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode, tree->focusnode->lowerbound,
5407 tree->effectiverootdepth) );
5408 }
5409
5410 focusnode = NULL;
5411 SCIP_CALL( SCIPnodeFocus(&focusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
5412 branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, FALSE, FALSE) );
5413 }
5414
5415 /* check whether we finished solving */
5416 if( SCIPtreeGetNNodes(tree) == 0 && SCIPtreeGetCurrentNode(tree) == NULL )
5417 {
5418 /* no restart necessary */
5419 *restart = FALSE;
5420
5421 /* set the solution status */
5422 if( unbounded || SCIPsetIsInfinity(set, -SCIPgetUpperbound(set->scip)) )
5423 {
5424 if( primal->nsols > 0 )
5425 {
5426 /* switch status to UNBOUNDED */
5428 }
5429 else
5430 {
5431 /* switch status to INFORUNB */
5433 }
5434 }
5435 else if( primal->nlimsolsfound == 0 )
5436 {
5437 assert(primal->nsols == 0 || SCIPsetIsGT(set, SCIPsolGetObj(primal->sols[0], set, transprob, origprob),
5438 SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(transprob, set))));
5439
5440 /* switch status to INFEASIBLE */
5442 }
5443 else
5444 {
5445 /* switch status to OPTIMAL */
5447 }
5448 }
5449
5450 return SCIP_OKAY;
5451}
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:288
int SCIPgetNConcurrentSolvers(SCIP *scip)
Definition: concurrent.c:117
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:3351
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:3822
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:3556
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:835
internal methods for storing cuts in a cut pool
#define SCIPdebugRemoveNode(blkmem, set, node)
Definition: debug.h:288
#define NULL
Definition: def.h:267
#define SCIP_Longint
Definition: def.h:158
#define SCIP_REAL_MAX
Definition: def.h:174
#define SCIP_INVALID
Definition: def.h:193
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:243
#define SCIP_Real
Definition: def.h:173
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:239
#define SCIP_LONGINT_FORMAT
Definition: def.h:165
#define SCIPABORT()
Definition: def.h:346
#define SCIP_REAL_MIN
Definition: def.h:175
#define REALABS(x)
Definition: def.h:197
#define SCIP_CALL(x)
Definition: def.h:374
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:3919
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11184
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:17115
SCIP_PROPTIMING SCIPconshdlrGetPropTiming(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5250
SCIP_Bool SCIPconshdlrWasSolSeparationDelayed(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5210
int SCIPconshdlrGetSepaPriority(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5100
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4197
SCIP_Bool SCIPconshdlrWasLPSeparationDelayed(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5200
SCIP_Bool SCIPconshdlrWasPropagationDelayed(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5220
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:7483
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7513
SCIP_Bool SCIPnodeIsActive(SCIP_NODE *node)
Definition: tree.c:8247
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7503
SCIP_Bool SCIPnodeIsPropagatedAgain(SCIP_NODE *node)
Definition: tree.c:8257
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:3309
SCIP_RETCODE SCIPprintRay(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip_sol.c:2034
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:17620
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17789
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17538
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18144
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17584
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17768
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17419
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18452
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18134
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:18478
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:18510
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:18498
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:18490
void SCIPregressionAddObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:381
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:8671
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:13103
void SCIPlpSetIsRelax(SCIP_LP *lp, SCIP_Bool relax)
Definition: lp.c:17784
SCIP_Bool SCIPlpIsRelax(SCIP_LP *lp)
Definition: lp.c:17797
SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13119
SCIP_RETCODE SCIPlpGetProvedLowerbound(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *bound)
Definition: lp.c:16491
SCIP_LPI * SCIPlpGetLPI(SCIP_LP *lp)
Definition: lp.c:17774
SCIP_RETCODE SCIPlpRemoveRedundantRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:15929
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17847
SCIP_Bool SCIPlpIsSolved(SCIP_LP *lp)
Definition: lp.c:17807
SCIP_Real SCIPlpGetGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13270
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:17575
SCIP_RETCODE SCIPlpSolveAndEval(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_Longint itlim, SCIP_Bool limitresolveiters, SCIP_Bool aging, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:12413
void SCIPlpResetFeastol(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:10281
SCIP_RETCODE SCIPlpGetPrimalRay(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *ray)
Definition: lp.c:14991
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:17622
SCIP_Real SCIPlpGetPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13302
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:1012
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:2362
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:2350
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 SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6597
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
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6619
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:2312
static SCIP_RETCODE enforceConstraints(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_Bool *branched, SCIP_Bool *cutoff, SCIP_Bool *infeasible, SCIP_Bool *propagateagain, SCIP_Bool *solvelpagain, SCIP_Bool *solverelaxagain, SCIP_Bool forced)
Definition: solve.c:3384
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:2962
static SCIP_RETCODE solveNodeInitialLP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool newinitconss, SCIP_Bool *cutoff, SCIP_Bool *lperror)
Definition: solve.c:1443
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:4944
#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:1863
static void updateLoopStatus(SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, int depth, SCIP_Bool *cutoff, SCIP_Bool *propagateagain, SCIP_Bool *solverelaxagain)
Definition: solve.c:3731
static SCIP_RETCODE propAndSolve(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_MEM *mem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_CUTPOOL *cutpool, SCIP_CUTPOOL *delayedcutpool, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_NODE *focusnode, int actdepth, SCIP_Bool propagate, SCIP_Bool solvelp, SCIP_Bool solverelax, SCIP_Bool forcedlpsolve, SCIP_Bool initiallpsolved, SCIP_Bool fullseparation, SCIP_Longint *afterlpproplps, SCIP_HEURTIMING *heurtiming, int *nlperrors, SCIP_Bool *fullpropagation, SCIP_Bool *propagateagain, SCIP_Bool *lpsolved, SCIP_Bool *relaxcalled, SCIP_Bool *solvelpagain, SCIP_Bool *solverelaxagain, SCIP_Bool *cutoff, SCIP_Bool *postpone, SCIP_Bool *unbounded, SCIP_Bool *stopped, SCIP_Bool *lperror, SCIP_Bool *pricingaborted, SCIP_Bool *forcedenforcement)
Definition: solve.c:3774
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:1607
static SCIP_RETCODE solveNodeLP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_MEM *mem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_CUTPOOL *delayedcutpool, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool initiallpsolved, SCIP_Bool fullseparation, SCIP_Bool newinitconss, SCIP_Bool *propagateagain, SCIP_Bool *solverelaxagain, SCIP_Bool *cutoff, SCIP_Bool *unbounded, SCIP_Bool *lperror, SCIP_Bool *pricingaborted)
Definition: solve.c:3040
SCIP_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:3284
static SCIP_RETCODE applyCuts(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool root, SCIP_EFFICIACYCHOICE efficiacychoice, SCIP_Bool *cutoff, SCIP_Bool *propagateagain, SCIP_Bool *solvelpagain, SCIP_Bool *solverelaxagain)
Definition: solve.c:3675
static SCIP_RETCODE 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:2095
SCIP_RETCODE SCIPconstructCurrentLP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool newinitconss, SCIP_Bool *cutoff)
Definition: solve.c:1285
#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:4807
SCIP_Bool SCIPsolveIsStopped(SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool checknodelimits)
Definition: solve.c:102
static SCIP_RETCODE priceAndCutLoop(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_MEM *mem, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_CUTPOOL *delayedcutpool, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool fullseparation, SCIP_Bool *propagateagain, SCIP_Bool *cutoff, SCIP_Bool *unbounded, SCIP_Bool *lperror, SCIP_Bool *pricingaborted)
Definition: solve.c:2352
static SCIP_RETCODE solveNode(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_MEM *mem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_CUTPOOL *cutpool, SCIP_CUTPOOL *delayedcutpool, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff, SCIP_Bool *postpone, SCIP_Bool *unbounded, SCIP_Bool *infeasible, SCIP_Bool *restart, SCIP_Bool *afternodeheur, SCIP_Bool *stopped)
Definition: solve.c:4142
static SCIP_RETCODE updatePrimalRay(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_Bool lperror)
Definition: solve.c:1376
#define NINITCALLS
Definition: solve.c:96
static void markRelaxsUnsolved(SCIP_SET *set, SCIP_RELAXATION *relaxation)
Definition: solve.c:3022
SCIP_RETCODE SCIPseparationRound(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, int actdepth, SCIP_Bool allowlocal, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *cutoff)
Definition: solve.c:2042
static SCIP_Bool restartAllowed(SCIP_SET *set, SCIP_STAT *stat)
Definition: solve.c:4125
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:1566
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:239
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:2375
SCIP_Bool SCIPtreeIsFocusNodeLPConstructed(SCIP_TREE *tree)
Definition: tree.c:8415
SCIP_NODE * SCIPtreeGetFocusNode(SCIP_TREE *tree)
Definition: tree.c:8360
SCIP_Bool SCIPtreeProbing(SCIP_TREE *tree)
Definition: tree.c:8334
int SCIPtreeGetFocusDepth(SCIP_TREE *tree)
Definition: tree.c:8377
SCIP_RETCODE SCIPtreeSetNodesel(SCIP_TREE *tree, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_NODESEL *nodesel)
Definition: tree.c:5155
void SCIPnodeSetEstimate(SCIP_NODE *node, SCIP_SET *set, SCIP_Real newestimate)
Definition: tree.c:2471
SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
Definition: tree.c:8435
void SCIPnodeMarkPropagated(SCIP_NODE *node, SCIP_TREE *tree)
Definition: tree.c:1320
int SCIPtreeGetNLeaves(SCIP_TREE *tree)
Definition: tree.c:8297
SCIP_RETCODE SCIPnodeCreateChild(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: tree.c:1039
SCIP_Bool SCIPtreeHasCurrentNodeLP(SCIP_TREE *tree)
Definition: tree.c:8469
SCIP_Real SCIPtreeGetLowerbound(SCIP_TREE *tree, SCIP_SET *set)
Definition: tree.c:7306
void SCIPtreeSetFocusNodeLP(SCIP_TREE *tree, SCIP_Bool solvelp)
Definition: tree.c:8404
int SCIPtreeGetNNodes(SCIP_TREE *tree)
Definition: tree.c:8307
SCIP_Bool SCIPtreeHasFocusNodeLP(SCIP_TREE *tree)
Definition: tree.c:8394
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:4399
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:8452
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:2419
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:5183
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:3635
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:3507
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:14477
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:14379
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:15615
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)