Scippy

SCIP

Solving Constraint Integer Programs

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