Scippy

SCIP

Solving Constraint Integer Programs

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