Scippy

SCIP

Solving Constraint Integer Programs

solve.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2024 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file solve.c
26 * @ingroup OTHER_CFILES
27 * @brief main solving loop and node processing
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Marc Pfetsch
31 * @author Gerald Gamrath
32 */
33
34/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35#include <assert.h>
36
37#include "lpi/lpi.h"
38#include "scip/branch.h"
39#include "scip/clock.h"
40#include "scip/concurrent.h"
41#include "scip/conflict.h"
42#include "scip/cons.h"
43#include "scip/cutpool.h"
44#include "scip/disp.h"
45#include "scip/event.h"
46#include "scip/heur.h"
47#include "scip/interrupt.h"
48#include "scip/lp.h"
49#include "scip/nodesel.h"
50#include "scip/pricer.h"
51#include "scip/pricestore.h"
52#include "scip/primal.h"
53#include "scip/prob.h"
54#include "scip/prop.h"
55#include "scip/pub_cons.h"
56#include "scip/pub_heur.h"
57#include "scip/pub_message.h"
58#include "scip/pub_misc.h"
59#include "scip/pub_pricer.h"
60#include "scip/pub_prop.h"
61#include "scip/pub_relax.h"
62#include "scip/pub_sepa.h"
63#include "scip/pub_tree.h"
64#include "scip/pub_var.h"
65#include "scip/relax.h"
66#include "scip/reopt.h"
68#include "scip/scip_mem.h"
69#include "scip/scip_prob.h"
70#include "scip/scip_sol.h"
72#include "scip/sepa.h"
73#include "scip/sepastore.h"
74#include "scip/set.h"
75#include "scip/sol.h"
76#include "scip/solve.h"
77#include "scip/stat.h"
78#include "scip/struct_cons.h"
79#include "scip/struct_event.h"
80#include "scip/struct_lp.h"
81#include "scip/struct_mem.h"
82#include "scip/struct_primal.h"
83#include "scip/struct_prob.h"
84#include "scip/struct_set.h"
85#include "scip/struct_stat.h"
86#include "scip/struct_tree.h"
87#include "scip/struct_var.h"
88#include "scip/syncstore.h"
89#include "scip/tree.h"
90#include "scip/var.h"
91#include "scip/visual.h"
92
93
94#define MAXNLPERRORS 10 /**< maximal number of LP error loops in a single node */
95#define MAXNCLOCKSKIPS 64 /**< maximum number of SCIPsolveIsStopped() calls without checking the clock */
96#define NINITCALLS 1000L /**< minimum number of calls to SCIPsolveIsStopped() prior to dynamic clock skips */
97#define SAFETYFACTOR 1e-2 /**< the probability that SCIP skips the clock call after the time limit has already been reached */
98
99/** returns whether the solving process will be / was stopped before proving optimality;
100 * if the solving process was stopped, stores the reason as status in stat
101 */
103 SCIP_SET* set, /**< global SCIP settings */
104 SCIP_STAT* stat, /**< dynamic problem statistics */
105 SCIP_Bool checknodelimits /**< should the node limits be involved in the check? */
106 )
107{
108 assert(set != NULL);
109 assert(stat != NULL);
110
111 /* increase the number of calls to this method */
112 SCIPstatIncrement(stat, set, nisstoppedcalls);
113
114 /* in case lowerbound >= upperbound, we do not want to terminate with SCIP_STATUS_GAPLIMIT but with the ordinary
115 * SCIP_STATUS_OPTIMAL/INFEASIBLE/...
116 */
118 return TRUE;
119
120 /* if some limit has been changed since the last call, we reset the status */
121 if( set->limitchanged )
122 {
124 set->limitchanged = FALSE;
125 }
126
127 if( SCIPinterrupted() || stat->userinterrupt )
128 {
130 stat->userinterrupt = FALSE;
131
132 /* only reset the interrupted counter if this is the main SCIP catching CTRL-C */
133 if( set->misc_catchctrlc )
134 {
136 }
137 }
138 else if( SCIPterminated() )
139 {
141
142 return TRUE;
143 }
144 /* only measure the clock if a time limit is set */
145 else if( set->istimelimitfinite )
146 {
147 /* check if we have already called this function sufficiently often for a valid estimation of its average call interval */
148 if( stat->nclockskipsleft <= 0 || stat->nisstoppedcalls < NINITCALLS )
149 {
150 SCIP_Real currtime = SCIPclockGetTime(stat->solvingtime);
151
152 /* use the measured time to update the average time interval between two calls to this method */
153 if( set->time_rareclockcheck && stat->nisstoppedcalls >= NINITCALLS )
154 {
155 SCIP_Real avgisstoppedfreq;
156 int nclockskips = MAXNCLOCKSKIPS;
157
158 avgisstoppedfreq = currtime / stat->nisstoppedcalls;
159
160 /* if we are approaching the time limit, reset the number of clock skips to 0 */
161 if( (SAFETYFACTOR * (set->limit_time - currtime) / (avgisstoppedfreq + 1e-6)) < nclockskips )
162 nclockskips = 0;
163
164 stat->nclockskipsleft = nclockskips;
165 }
166 else
167 stat->nclockskipsleft = 0;
168
169 /* set the status if the time limit was hit */
170 if( currtime >= set->limit_time )
171 {
173 return TRUE;
174 }
175 }
176 else if( SCIPclockGetLastTime(stat->solvingtime) >= set->limit_time )
177 {
178 /* use information if clock has been updated more recently */
180 return TRUE;
181 }
182 else
183 --stat->nclockskipsleft;
184 }
185 if( SCIPgetConcurrentMemTotal(set->scip) >= set->limit_memory*1048576.0 - stat->externmemestim * (1.0 + SCIPgetNConcurrentSolvers(set->scip)) )
187 else if( SCIPgetNLimSolsFound(set->scip) > 0
188 && (SCIPsetIsLT(set, SCIPgetGap(set->scip), set->limit_gap)
189 || SCIPsetIsLT(set, (SCIPgetUpperbound(set->scip) - SCIPgetLowerbound(set->scip)) * SCIPgetTransObjscale(set->scip), set->limit_absgap )) )
191 else if( set->limit_primal != SCIP_INVALID && !SCIPsetIsPositive(set, (int)SCIPgetObjsense(set->scip) * (SCIPgetPrimalbound(set->scip) - set->limit_primal)) ) /*lint !e777*/
193 else if( set->limit_dual != SCIP_INVALID && !SCIPsetIsNegative(set, (int)SCIPgetObjsense(set->scip) * (SCIPgetDualbound(set->scip) - set->limit_dual)) ) /*lint !e777*/
195 else if( set->limit_solutions >= 0 && set->stage >= SCIP_STAGE_PRESOLVING
196 && SCIPgetNLimSolsFound(set->scip) >= set->limit_solutions )
198 else if( set->limit_bestsol >= 0 && set->stage >= SCIP_STAGE_PRESOLVING
199 && SCIPgetNBestSolsFound(set->scip) >= set->limit_bestsol )
201 else if( checknodelimits && set->limit_nodes >= 0 && stat->nnodes >= set->limit_nodes )
203 else if( checknodelimits && set->limit_totalnodes >= 0 && stat->ntotalnodes >= set->limit_totalnodes )
205 else if( checknodelimits && set->limit_stallnodes >= 0 && stat->nnodes >= stat->bestsolnode + set->limit_stallnodes )
207
208 /* If stat->status was initialized to SCIP_STATUS_NODELIMIT or SCIP_STATUS_STALLNODELIMIT due to a previous call to SCIPsolveIsStopped(,,TRUE),
209 * in the case of checknodelimits == FALSE, we do not want to report here that the solve will be stopped due to a nodelimit.
210 */
211 if( !checknodelimits )
213 else
215}
216
217/** calls primal heuristics */
219 SCIP_SET* set, /**< global SCIP settings */
220 SCIP_STAT* stat, /**< dynamic problem statistics */
221 SCIP_PROB* prob, /**< transformed problem after presolve */
222 SCIP_PRIMAL* primal, /**< primal data */
223 SCIP_TREE* tree, /**< branch and bound tree, or NULL if called during presolving */
224 SCIP_LP* lp, /**< LP data, or NULL if called during presolving or propagation */
225 SCIP_NODE* nextnode, /**< next node that will be processed, or NULL if no more nodes left
226 * (only needed when calling after node heuristics) */
227 SCIP_HEURTIMING heurtiming, /**< current point in the node solving process */
228 SCIP_Bool nodeinfeasible, /**< was the current node already detected to be infeasible? */
229 SCIP_Bool* foundsol, /**< pointer to store whether a solution has been found */
230 SCIP_Bool* unbounded /**< pointer to store whether an unbounded ray was found in the LP */
231 )
232{ /*lint --e{715}*/
233 SCIP_RESULT result;
234 SCIP_Longint oldnbestsolsfound;
235 SCIP_Real lowerbound;
236 int ndelayedheurs;
237 int depth;
238 int lpstateforkdepth;
239 int h;
240#ifndef NDEBUG
241 SCIP_Bool inprobing;
242 SCIP_Bool indiving;
243#endif
244
245 assert(set != NULL);
246 assert(primal != NULL);
247 assert(tree != NULL || heurtiming == SCIP_HEURTIMING_BEFOREPRESOL || heurtiming == SCIP_HEURTIMING_DURINGPRESOLLOOP);
248 assert(lp != NULL || heurtiming == SCIP_HEURTIMING_BEFOREPRESOL || heurtiming == SCIP_HEURTIMING_DURINGPRESOLLOOP
249 || heurtiming == SCIP_HEURTIMING_AFTERPROPLOOP);
250 assert(heurtiming == SCIP_HEURTIMING_BEFORENODE || heurtiming == SCIP_HEURTIMING_DURINGLPLOOP
251 || heurtiming == SCIP_HEURTIMING_AFTERLPLOOP || heurtiming == SCIP_HEURTIMING_AFTERNODE
255 assert(heurtiming != SCIP_HEURTIMING_AFTERNODE || (nextnode == NULL) == (SCIPtreeGetNNodes(tree) == 0));
256 assert(foundsol != NULL);
257
258 *foundsol = FALSE;
259
260 /* nothing to do, if no heuristics are available, or if the branch-and-bound process is finished */
261 if( set->nheurs == 0 || (heurtiming == SCIP_HEURTIMING_AFTERNODE && nextnode == NULL) )
262 return SCIP_OKAY;
263
264 /* do not continue if we reached a time limit */
265 if( SCIPsolveIsStopped(set, stat, FALSE) )
266 return SCIP_OKAY;
267
268 /* sort heuristics by priority, but move the delayed heuristics to the front */
270
271 /* specialize the AFTERNODE timing flag */
273 {
274 SCIP_Bool plunging;
275 SCIP_Bool pseudonode;
276
277 /* clear the AFTERNODE flags and replace them by the right ones */
278 heurtiming &= ~SCIP_HEURTIMING_AFTERNODE;
279
280 /* we are in plunging mode iff the next node is a sibling or a child, and no leaf */
281 assert(nextnode == NULL
284 || SCIPnodeGetType(nextnode) == SCIP_NODETYPE_LEAF);
285 plunging = (nextnode != NULL && SCIPnodeGetType(nextnode) != SCIP_NODETYPE_LEAF);
286 pseudonode = !SCIPtreeHasFocusNodeLP(tree);
287 if( plunging && SCIPtreeGetCurrentDepth(tree) > 0 ) /* call plunging heuristics also at root node */
288 {
289 if( !pseudonode )
290 heurtiming |= SCIP_HEURTIMING_AFTERLPNODE;
291 else
293 }
294 else
295 {
296 if( !pseudonode )
298 else
300 }
301 }
302
303 /* initialize the tree related data, if we are not in presolving */
304 if( heurtiming == SCIP_HEURTIMING_BEFOREPRESOL || heurtiming == SCIP_HEURTIMING_DURINGPRESOLLOOP )
305 {
306 depth = -1;
307 lpstateforkdepth = -1;
308
309 SCIPsetDebugMsg(set, "calling primal heuristics %s presolving\n",
310 heurtiming == SCIP_HEURTIMING_BEFOREPRESOL ? "before" : "during");
311 }
312 else
313 {
314 assert(tree != NULL); /* for lint */
315 depth = SCIPtreeGetFocusDepth(tree);
316 lpstateforkdepth = (tree->focuslpstatefork != NULL ? SCIPnodeGetDepth(tree->focuslpstatefork) : -1);
317
318 SCIPsetDebugMsg(set, "calling primal heuristics in depth %d (timing: %u)\n", depth, heurtiming);
319 }
320
321 /* call heuristics */
322 ndelayedheurs = 0;
323 oldnbestsolsfound = primal->nbestsolsfound;
324
325#ifndef NDEBUG
326 /* remember old probing and diving status */
327 inprobing = tree != NULL && SCIPtreeProbing(tree);
328 indiving = lp != NULL && SCIPlpDiving(lp);
329
330 /* heuristics should currently not be called in diving mode */
331 assert(!indiving);
332#endif
333
334 /* collect lower bound of current node */
335 if( tree != NULL )
336 {
337 assert(SCIPtreeGetFocusNode(tree) != NULL);
339 }
340 else if( lp != NULL )
341 lowerbound = SCIPlpGetPseudoObjval(lp, set, prob);
342 else
343 lowerbound = -SCIPsetInfinity(set);
344
345 for( h = 0; h < set->nheurs; ++h )
346 {
347#ifndef NDEBUG
348 size_t nusedbuffer = BMSgetNUsedBufferMemory(SCIPbuffer(set->scip));
349#endif
350 /* it might happen that a diving heuristic renders the previously solved node LP invalid
351 * such that additional calls to LP heuristics will fail; better abort the loop in this case
352 */
353 if( lp != NULL && lp->resolvelperror)
354 break;
355
356#ifdef SCIP_DEBUG
357 {
358 SCIP_Bool delayed;
359 if( SCIPheurShouldBeExecuted(set->heurs[h], depth, lpstateforkdepth, heurtiming, &delayed) )
360 {
361 SCIPsetDebugMsg(set, " -> executing heuristic <%s> with priority %d\n",
362 SCIPheurGetName(set->heurs[h]), SCIPheurGetPriority(set->heurs[h]));
363 }
364 }
365#endif
366
367 SCIP_CALL( SCIPheurExec(set->heurs[h], set, primal, depth, lpstateforkdepth, heurtiming, nodeinfeasible,
368 &ndelayedheurs, &result) );
369
370#ifndef NDEBUG
371 if( BMSgetNUsedBufferMemory(SCIPbuffer(set->scip)) > nusedbuffer )
372 {
373 SCIPerrorMessage("Buffer not completely freed after executing heuristic <%s>\n", SCIPheurGetName(set->heurs[h]));
374 SCIPABORT();
375 }
376#endif
377
378 /* if the new solution cuts off the current node due to a new primal solution (via the cutoff bound) interrupt
379 * calling the remaining heuristics
380 */
381 if( 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, 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, 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, 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, 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* propagateagain, /**< pointer to store whether we want to propagate again */
2385 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
2386 SCIP_Bool* unbounded, /**< pointer to store whether an unbounded ray was found in the LP */
2387 SCIP_Bool* lperror, /**< pointer to store whether an unresolved error in LP solving occured */
2388 SCIP_Bool* pricingaborted /**< pointer to store whether the pricing was aborted and the lower bound must
2389 * not be used */
2390 )
2391{
2392 SCIP_NODE* focusnode;
2393 /* cppcheck-suppress unassignedVariable */
2394 SCIP_EVENT event;
2395 SCIP_LPSOLSTAT stalllpsolstat;
2396 SCIP_Real loclowerbound;
2397 SCIP_Real glblowerbound;
2398 SCIP_Real bounddist;
2399 SCIP_Real stalllpobjval;
2400 SCIP_Bool separate;
2401 SCIP_Bool mustprice;
2402 SCIP_Bool mustsepa;
2403 SCIP_Bool delayedsepa;
2404 SCIP_Bool root;
2405 SCIP_Bool allowlocal;
2406 int maxseparounds;
2407 int nsepastallrounds;
2408 int maxnsepastallrounds;
2409 int stallnfracs;
2410 int actdepth;
2411 int npricedcolvars;
2412
2413 assert(set != NULL);
2414 assert(blkmem != NULL);
2415 assert(stat != NULL);
2416 assert(transprob != NULL);
2417 assert(tree != NULL);
2418 assert(lp != NULL);
2419 assert(pricestore != NULL);
2420 assert(sepastore != NULL);
2421 assert(cutpool != NULL);
2422 assert(delayedcutpool != NULL);
2423 assert(primal != NULL);
2424 assert(cutoff != NULL);
2425 assert(unbounded != NULL);
2426 assert(lperror != NULL);
2427
2428 focusnode = SCIPtreeGetFocusNode(tree);
2429 assert(focusnode != NULL);
2430 assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
2431 actdepth = SCIPnodeGetDepth(focusnode);
2432 root = (actdepth == 0);
2433
2434 /* check, if we want to separate at this node */
2435 loclowerbound = SCIPnodeGetLowerbound(focusnode);
2436 glblowerbound = SCIPtreeGetLowerbound(tree, set);
2437 assert(primal->cutoffbound > glblowerbound);
2438 bounddist = (loclowerbound - glblowerbound)/(primal->cutoffbound - glblowerbound);
2439 allowlocal = SCIPsetIsLE(set, bounddist, set->sepa_maxlocalbounddist);
2440 separate = (set->sepa_maxruns == -1 || stat->nruns < set->sepa_maxruns);
2441
2442 /* get maximal number of separation rounds */
2443 maxseparounds = (root ? set->sepa_maxroundsroot : set->sepa_maxrounds);
2444 if( maxseparounds == -1 )
2445 maxseparounds = INT_MAX;
2446 if( stat->nruns > 1 && root && set->sepa_maxroundsrootsubrun >= 0 )
2447 maxseparounds = MIN(maxseparounds, set->sepa_maxroundsrootsubrun);
2448 if( !fullseparation && set->sepa_maxaddrounds >= 0 )
2449 maxseparounds = MIN(maxseparounds, stat->nseparounds + set->sepa_maxaddrounds);
2450 maxnsepastallrounds = root ? set->sepa_maxstallroundsroot : set->sepa_maxstallrounds;
2451 if( maxnsepastallrounds == -1 )
2452 maxnsepastallrounds = INT_MAX;
2453
2454 /* solve initial LP of price-and-cut loop */
2455 SCIPsetDebugMsg(set, "node: solve LP with price and cut\n");
2456 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2457 set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2458 assert(lp->flushed);
2459 assert(lp->solved || *lperror);
2460
2461 /* remove previous primal ray, store new one if LP is unbounded */
2462 SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2463
2464 /* price-and-cut loop */
2465 npricedcolvars = transprob->ncolvars;
2466 mustprice = TRUE;
2467 mustsepa = separate;
2468 delayedsepa = FALSE;
2469 *cutoff = FALSE;
2470 *unbounded = (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
2471 nsepastallrounds = 0;
2472 stalllpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2473 stalllpobjval = SCIP_REAL_MIN;
2474 stallnfracs = INT_MAX;
2475 lp->installing = FALSE;
2476 while( !(*cutoff) && !(*unbounded) && !(*lperror) && (mustprice || mustsepa || delayedsepa) )
2477 {
2478 SCIPsetDebugMsg(set, "-------- node solving loop --------\n");
2479 assert(lp->flushed);
2480 assert(lp->solved);
2481
2482 /* solve the LP with pricing in new variables */
2483 while( mustprice && !(*lperror) )
2484 {
2485 SCIP_CALL( SCIPpriceLoop(blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
2486 pricestore, sepastore, cutpool, branchcand, eventqueue, eventfilter, cliquetable, root, root, -1, &npricedcolvars,
2487 &mustsepa, lperror, pricingaborted) );
2488
2489 mustprice = FALSE;
2490
2491 assert(lp->flushed);
2492 assert(lp->solved || *lperror);
2493
2494 /* update lower bound w.r.t. the LP solution */
2495 if( !(*lperror) && !(*pricingaborted) && SCIPlpIsRelax(lp) )
2496 {
2497 SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2498 SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2499 SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2500
2501 /* update node estimate */
2502 SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2503
2504 if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2505 SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2506 }
2507 else
2508 {
2509 SCIPsetDebugMsg(set, " -> error solving LP or pricing aborted. keeping old bound: %g\n", SCIPnodeGetLowerbound(focusnode));
2510 }
2511
2512 /* display node information line for root node */
2513 if( root && (SCIP_VERBLEVEL)set->disp_verblevel >= SCIP_VERBLEVEL_HIGH )
2514 {
2515 SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, TRUE, TRUE) );
2516 }
2517
2518 if( !(*lperror) )
2519 {
2520 /* call propagators that are applicable during LP solving loop only if the node is not cut off */
2521 if( SCIPsetIsLT(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound) )
2522 {
2523 SCIP_Longint oldnboundchgs;
2524 SCIP_Longint oldninitconssadded;
2525 SCIP_Bool postpone;
2526
2527 oldnboundchgs = stat->nboundchgs;
2528 oldninitconssadded = stat->ninitconssadded;
2529
2530 SCIPsetDebugMsg(set, " -> LP solved: call propagators that are applicable during LP solving loop\n");
2531
2532 SCIP_CALL( propagateDomains(blkmem, set, stat, tree, SCIPtreeGetCurrentDepth(tree), 0, FALSE,
2533 SCIP_PROPTIMING_DURINGLPLOOP, cutoff, &postpone) );
2534 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2535 assert(!postpone);
2536
2537 if( stat->ninitconssadded != oldninitconssadded )
2538 {
2539 SCIPsetDebugMsg(set, "new initial constraints added during propagation: old=%" SCIP_LONGINT_FORMAT ", new=%" SCIP_LONGINT_FORMAT "\n", oldninitconssadded, stat->ninitconssadded);
2540
2541 SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp,
2542 branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE, cutoff) );
2543 }
2544
2545 if( !(*cutoff) && !(*unbounded) )
2546 {
2547 /* if we found something, solve LP again */
2548 if( !lp->flushed )
2549 {
2550 SCIPsetDebugMsg(set, " -> found reduction: resolve LP\n");
2551
2552 /* in the root node, remove redundant rows permanently from the LP */
2553 if( root )
2554 {
2555 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, transprob, eventqueue) );
2556 SCIP_CALL( SCIPlpRemoveRedundantRows(lp, blkmem, set, stat, eventqueue, eventfilter) );
2557 }
2558
2559 /* resolve LP */
2560 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2561 set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2562 assert(lp->flushed);
2563 assert(lp->solved || *lperror);
2564
2565 /* remove previous primal ray, store new one if LP is unbounded */
2566 SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2567
2568 mustprice = TRUE;
2569 *propagateagain = TRUE;
2570 }
2571 /* propagation might have changed the best bound of loose variables, thereby changing the loose objective
2572 * value which is added to the LP value; because of the loose status, the LP might not be reoptimized,
2573 * but the lower bound of the node needs to be updated
2574 */
2575 else if( stat->nboundchgs > oldnboundchgs )
2576 {
2577 *propagateagain = TRUE;
2578
2579 if( lp->solved && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
2580 {
2581 assert(lp->flushed);
2582 assert(lp->solved);
2583
2584 SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2585 SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2586 SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2587
2588 /* update node estimate */
2589 SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2590
2591 if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2592 SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2593 }
2594 }
2595 }
2596 }
2597 }
2598
2599 /* call primal heuristics that are applicable during node LP solving loop */
2600 if( !*cutoff && !(*unbounded) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2601 {
2602 SCIP_Bool foundsol;
2603
2604 SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, SCIP_HEURTIMING_DURINGLPLOOP,
2605 FALSE, &foundsol, unbounded) );
2606 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2607
2608 *lperror = *lperror || lp->resolvelperror;
2609 } /*lint !e438*/
2610 }
2611 assert(lp->flushed || *cutoff || *unbounded);
2612 assert(lp->solved || *lperror || *cutoff || *unbounded);
2613
2614 /* check, if we exceeded the separation round limit */
2615 mustsepa = mustsepa
2616 && stat->nseparounds < maxseparounds
2617 && nsepastallrounds < maxnsepastallrounds
2618 && !(*cutoff);
2619
2620 /* if separators were delayed, we want to apply a final separation round with the delayed separators */
2621 delayedsepa = delayedsepa && !mustsepa && !(*cutoff); /* if regular separation applies, we ignore delayed separators */
2622 mustsepa = mustsepa || delayedsepa;
2623
2624 if( mustsepa )
2625 {
2626 /* if the LP is infeasible, unbounded, exceeded the objective limit or a global performance limit was reached,
2627 * we don't need to separate cuts
2628 * (the global limits are only checked at the root node in order to not query system time too often)
2629 */
2630 if( !separate || (*cutoff) || (*unbounded)
2632 || SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound)
2633 || (root && SCIPsolveIsStopped(set, stat, FALSE)) )
2634 {
2635 mustsepa = FALSE;
2636 delayedsepa = FALSE;
2637 }
2638 else
2639 assert(!(*lperror));
2640 }
2641
2642 /* separation (needs not to be done completely, because we just want to increase the lower bound) */
2643 if( mustsepa )
2644 {
2645 SCIP_Longint olddomchgcount;
2646 SCIP_Longint oldninitconssadded;
2647 SCIP_Bool enoughcuts;
2648
2649 assert(lp->flushed);
2650 assert(lp->solved);
2652 assert(!(*lperror));
2653 assert(!(*cutoff));
2654
2655 olddomchgcount = stat->domchgcount;
2656 oldninitconssadded = stat->ninitconssadded;
2657
2658 mustsepa = FALSE;
2660
2661 /* global cut pool separation */
2662 if( !enoughcuts && !delayedsepa )
2663 {
2664 SCIP_CALL( cutpoolSeparate(cutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, FALSE, root,
2665 actdepth, &enoughcuts, cutoff) );
2666
2667 if( *cutoff )
2668 {
2669 SCIPsetDebugMsg(set, " -> global cut pool detected cutoff\n");
2670 }
2671 }
2672 assert(lp->flushed);
2673 assert(lp->solved);
2675 assert(!(*lperror));
2676
2677 /* separate constraints and LP */
2678 if( !(*cutoff) && !enoughcuts )
2679 {
2680 /* constraint and LP separation */
2681 SCIPsetDebugMsg(set, "constraint and LP separation\n");
2682
2683 /* apply a separation round */
2684 SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal, tree,
2685 lp, sepastore, actdepth, bounddist, allowlocal, delayedsepa,
2686 &delayedsepa, &enoughcuts, cutoff, lperror, &mustsepa, &mustprice) );
2687 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2688
2689 /* if we are close to the stall round limit, also call the delayed separators */
2690 if( !(*cutoff) && !(*lperror) && !enoughcuts && lp->solved
2692 && nsepastallrounds >= maxnsepastallrounds-1 && delayedsepa )
2693 {
2694 SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal,
2695 tree, lp, sepastore, actdepth, bounddist, allowlocal, delayedsepa,
2696 &delayedsepa, &enoughcuts, cutoff, lperror, &mustsepa, &mustprice) );
2697 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2698 }
2699 }
2700
2701 /* call global cut pool separation again since separators may add cuts to the pool instead of the sepastore */
2702 if( !(*cutoff) && !(*lperror) && lp->solved && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && !enoughcuts )
2703 {
2704 SCIP_CALL( cutpoolSeparate(cutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, FALSE, root,
2705 actdepth, &enoughcuts, cutoff) );
2706
2707 if( *cutoff )
2708 {
2709 SCIPsetDebugMsg(set, " -> global cut pool detected cutoff\n");
2710 }
2711 }
2712
2713 /* delayed global cut pool separation */
2714 if( !(*cutoff) && !(*lperror) && lp->solved && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && SCIPsepastoreGetNCuts(sepastore) == 0 && !enoughcuts )
2715 {
2716 SCIP_CALL( cutpoolSeparate(delayedcutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, TRUE,
2717 root, actdepth, &enoughcuts, cutoff) );
2718
2719 if( *cutoff )
2720 {
2721 SCIPsetDebugMsg(set, " -> delayed global cut pool detected cutoff\n");
2722 }
2723 assert(lp->solved);
2725 assert(lp->flushed);
2726 }
2727
2728 /* delayed separation if no cuts where produced */
2729 if( !(*cutoff) && !(*lperror) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && SCIPsepastoreGetNCuts(sepastore) == 0 && delayedsepa )
2730 {
2731 SCIP_CALL( separationRoundLP(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, primal,
2732 tree, lp, sepastore, actdepth, bounddist, allowlocal, delayedsepa,
2733 &delayedsepa, &enoughcuts, cutoff, lperror, &mustsepa, &mustprice) );
2734 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
2735
2736 /* call delayed cut pool separation again, since separators may add cuts to the pool instead of the sepastore */
2737 if( !(*cutoff) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2738 {
2739 assert( !(*lperror) );
2740
2741 SCIP_CALL( cutpoolSeparate(delayedcutpool, blkmem, set, stat, eventqueue, eventfilter, lp, sepastore, TRUE,
2742 root, actdepth, &enoughcuts, cutoff) );
2743
2744 if( *cutoff )
2745 {
2746 SCIPsetDebugMsg(set, " -> delayed global cut pool detected cutoff\n");
2747 }
2749 assert(lp->flushed);
2750 assert(lp->solved);
2751 }
2752 }
2753
2754 assert(*cutoff || *lperror || SCIPlpIsSolved(lp));
2755 assert(!SCIPlpIsSolved(lp)
2762
2763 if( *cutoff || *lperror
2766 {
2767 /* the found cuts are of no use, because the node is infeasible anyway (or we have an error in the LP) */
2768 SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
2769 }
2770 else
2771 {
2772 /* apply found cuts */
2773 SCIP_CALL( SCIPsepastoreApplyCuts(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
2774 branchcand, eventqueue, eventfilter, cliquetable, root, SCIP_EFFICIACYCHOICE_LP, cutoff) );
2775
2776 if( !(*cutoff) )
2777 {
2778 mustprice = mustprice || !lp->flushed || (transprob->ncolvars != npricedcolvars);
2779 mustsepa = mustsepa || !lp->flushed;
2780
2781 /* if a new bound change (e.g. a cut with only one column) was found, propagate domains again */
2782 if( stat->domchgcount != olddomchgcount )
2783 {
2784 SCIPsetDebugMsg(set, " -> separation changed bound: propagate again\n");
2785
2786 *propagateagain = TRUE;
2787
2788 /* in the root node, remove redundant rows permanently from the LP */
2789 if( root )
2790 {
2791 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, transprob, eventqueue) );
2792 SCIP_CALL( SCIPlpRemoveRedundantRows(lp, blkmem, set, stat, eventqueue, eventfilter) );
2793 }
2794 }
2795
2796 if( stat->ninitconssadded != oldninitconssadded )
2797 {
2798 SCIPsetDebugMsg(set, "new initial constraints added during propagation: old=%" SCIP_LONGINT_FORMAT ", new=%" SCIP_LONGINT_FORMAT "\n",
2799 oldninitconssadded, stat->ninitconssadded);
2800
2801 SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob, origprob, tree, reopt, lp,
2802 branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE, cutoff) );
2803 }
2804
2805 if( !(*cutoff) )
2806 {
2807 SCIP_Real lpobjval;
2808
2809 /* solve LP (with dual simplex) */
2810 SCIPsetDebugMsg(set, "separation: solve LP\n");
2811 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob,
2812 set->lp_iterlim, FALSE, TRUE, FALSE, lperror) );
2813 assert(lp->flushed);
2814 assert(lp->solved || *lperror);
2815
2816 /* remove previous primal ray, store new one if LP is unbounded */
2817 SCIP_CALL( updatePrimalRay(blkmem, set, stat, transprob, primal, tree, lp, *lperror) );
2818
2819 if( !(*lperror) )
2820 {
2821 SCIP_Bool stalling;
2822
2823 /* propagation might have changed the best bound of loose variables, thereby changing the loose objective value
2824 * which is added to the LP value; because of the loose status, the LP might not be reoptimized, but the lower
2825 * bound of the node needs to be updated
2826 */
2827 if( stat->domchgcount != olddomchgcount && (!mustprice || mustsepa) && !(*cutoff)
2828 && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
2829 {
2830 SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2831 SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
2832 SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
2833
2834 /* update node estimate */
2835 SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2836
2837 if( root && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
2838 SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
2839 }
2840
2841 /* check if we are stalling
2842 * If we have an LP solution, then we are stalling if
2843 * we had an LP solution before and
2844 * the LP value did not improve and
2845 * the number of fractional variables did not decrease.
2846 * If we do not have an LP solution, then we are stalling if the solution status of the LP did not change.
2847 */
2849 {
2850 SCIP_Real objreldiff;
2851 int nfracs;
2852
2853 SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nfracs, NULL,
2854 NULL) );
2855 lpobjval = SCIPlpGetObjval(lp, set, transprob);
2856
2857 objreldiff = SCIPrelDiff(lpobjval, stalllpobjval);
2858 SCIPsetDebugMsg(set, " -> LP bound moved from %g to %g (reldiff: %g)\n",
2859 stalllpobjval, lpobjval, objreldiff);
2860
2861 stalling = (stalllpsolstat == SCIP_LPSOLSTAT_OPTIMAL &&
2862 objreldiff <= 1e-04 &&
2863 nfracs >= (0.9 - 0.1 * nsepastallrounds) * stallnfracs);
2864
2865 stalllpobjval = lpobjval;
2866 stallnfracs = nfracs;
2867 } /*lint !e438*/
2868 else
2869 {
2870 stalling = (stalllpsolstat == SCIPlpGetSolstat(lp));
2871 }
2872
2873 if( !stalling )
2874 {
2875 nsepastallrounds = 0;
2876 lp->installing = FALSE;
2877 }
2878 else
2879 {
2880 nsepastallrounds++;
2881 }
2882 stalllpsolstat = SCIPlpGetSolstat(lp);
2883
2884 /* tell LP that we are (close to) stalling */
2885 if( nsepastallrounds >= maxnsepastallrounds-2 )
2886 lp->installing = TRUE;
2887 SCIPsetDebugMsg(set, " -> nsepastallrounds=%d/%d\n", nsepastallrounds, maxnsepastallrounds);
2888 }
2889 }
2890 }
2891 }
2892 assert(*cutoff || *lperror || (lp->flushed && lp->solved)); /* cutoff: LP may be unsolved due to bound changes */
2893
2894 SCIPsetDebugMsg(set, "separation round %d/%d finished (%d/%d stall rounds): mustprice=%u, mustsepa=%u, delayedsepa=%u, propagateagain=%u\n",
2895 stat->nseparounds, maxseparounds, nsepastallrounds, maxnsepastallrounds, mustprice, mustsepa, delayedsepa, *propagateagain);
2896
2897 /* increase separation round counter */
2898 stat->nseparounds++;
2899 }
2900 }
2901
2902 if( root && nsepastallrounds >= maxnsepastallrounds )
2903 {
2904 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
2905 "Truncate separation round because of stalling (%d stall rounds).\n", maxnsepastallrounds);
2906 }
2907
2908 if( !*lperror )
2909 {
2910 /* update pseudo cost values for continuous variables, if it should be delayed */
2911 SCIP_CALL( updatePseudocost(set, stat, transprob, tree, lp, FALSE, set->branch_delaypscost) );
2912 }
2913
2914 /* update lower bound w.r.t. the LP solution */
2915 if( !(*cutoff) && !(*lperror) )
2916 {
2917 assert(lp->flushed);
2918 assert(lp->solved);
2919
2920 if( SCIPlpIsRelax(lp) )
2921 {
2922 SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
2923 }
2924
2925 /* update node estimate */
2926 SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
2927
2928 /* issue LPSOLVED event */
2930 {
2932 SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
2933 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
2934 }
2935
2936 /* if the LP is a relaxation and we are not solving exactly, then we may analyze an infeasible or bound exceeding
2937 * LP (not necessary in the root node) and cut off the current node
2938 */
2939 if( !set->misc_exactsolve && !root && SCIPlpIsRelax(lp) && SCIPprobAllColsInLP(transprob, set, lp)
2941 {
2942 SCIP_CALL( SCIPconflictAnalyzeLP(conflict, conflictstore, blkmem, set, stat, transprob, origprob, tree, reopt,
2943 lp, branchcand, eventqueue, cliquetable, NULL) );
2944 *cutoff = TRUE;
2945 }
2946 }
2947
2948 /* check for unboundedness */
2949 if( !(*lperror) )
2950 *unbounded = (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
2951
2952 lp->installing = FALSE;
2953
2954 /* check for cutoff */
2955 if( *cutoff )
2956 {
2957 SCIP_CALL( SCIPnodeCutoff(focusnode, set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
2958 }
2959
2960 SCIPsetDebugMsg(set, " -> final lower bound: %g (LP status: %d, LP obj: %g)\n",
2962 (*cutoff || *unbounded) ? SCIPsetInfinity(set) : *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
2963
2964 return SCIP_OKAY; /*lint !e438*/
2965}
2966
2967/** updates the current lower bound with the pseudo objective value, cuts off node by bounding, and applies conflict
2968 * analysis if the pseudo objective lead to the cutoff
2969 */
2970static
2972 BMS_BLKMEM* blkmem, /**< block memory buffers */
2973 SCIP_SET* set, /**< global SCIP settings */
2974 SCIP_STAT* stat, /**< dynamic problem statistics */
2975 SCIP_PROB* transprob, /**< tranformed problem after presolve */
2976 SCIP_PROB* origprob, /**< original problem */
2977 SCIP_PRIMAL* primal, /**< primal data */
2978 SCIP_TREE* tree, /**< branch and bound tree */
2979 SCIP_REOPT* reopt, /**< reoptimization data structure */
2980 SCIP_LP* lp, /**< LP data */
2981 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2982 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2983 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2984 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2985 SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
2986 )
2987{
2988 assert(transprob != NULL);
2989 assert(origprob != NULL);
2990 assert(primal != NULL);
2991 assert(cutoff != NULL);
2992
2993 if( !(*cutoff) )
2994 {
2995 SCIP_NODE* focusnode;
2996 SCIP_Real pseudoobjval;
2997
2998 /* get current focus node */
2999 focusnode = SCIPtreeGetFocusNode(tree);
3000
3001 /* update lower bound w.r.t. the pseudo solution */
3002 pseudoobjval = SCIPlpGetPseudoObjval(lp, set, transprob);
3003 SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, pseudoobjval);
3004 SCIPsetDebugMsg(set, " -> lower bound: %g [%g] (pseudoobj: %g [%g]), cutoff bound: %g [%g]\n",
3005 SCIPnodeGetLowerbound(focusnode), SCIPprobExternObjval(transprob, origprob, set, SCIPnodeGetLowerbound(focusnode)) + SCIPgetOrigObjoffset(set->scip),
3006 pseudoobjval, SCIPprobExternObjval(transprob, origprob, set, pseudoobjval) + SCIPgetOrigObjoffset(set->scip),
3007 primal->cutoffbound, SCIPprobExternObjval(transprob, origprob, set, primal->cutoffbound) + SCIPgetOrigObjoffset(set->scip));
3008
3009 /* check for infeasible node by bounding */
3010 if( (set->misc_exactsolve && SCIPnodeGetLowerbound(focusnode) >= primal->cutoffbound)
3011 || (!set->misc_exactsolve && SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), primal->cutoffbound)) )
3012 {
3013 /* call pseudo conflict analysis, if the node is cut off due to the pseudo objective value */
3014 if( !SCIPsetIsInfinity(set, -pseudoobjval) && !SCIPsetIsInfinity(set, primal->cutoffbound) && SCIPsetIsGE(set, pseudoobjval, primal->cutoffbound) )
3015 {
3016 SCIP_CALL( SCIPconflictAnalyzePseudo(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cliquetable, NULL) );
3017 }
3018
3019 *cutoff = TRUE;
3020 }
3021 }
3022
3023 return SCIP_OKAY;
3024}
3025
3026/** marks all relaxators to be unsolved */
3027static
3029 SCIP_SET* set, /**< global SCIP settings */
3030 SCIP_RELAXATION* relaxation /**< global relaxation data */
3031 )
3032{
3033 int r;
3034
3035 assert(set != NULL);
3036 assert(relaxation != NULL);
3037
3039
3040 for( r = 0; r < set->nrelaxs; ++r )
3041 SCIPrelaxMarkUnsolved(set->relaxs[r]);
3042}
3043
3044/** solves the current node's LP in a price-and-cut loop */
3045static
3047 BMS_BLKMEM* blkmem, /**< block memory buffers */
3048 SCIP_SET* set, /**< global SCIP settings */
3049 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3050 SCIP_STAT* stat, /**< dynamic problem statistics */
3051 SCIP_MEM* mem, /**< block memory pools */
3052 SCIP_PROB* origprob, /**< original problem */
3053 SCIP_PROB* transprob, /**< transformed problem after presolve */
3054 SCIP_PRIMAL* primal, /**< primal data */
3055 SCIP_TREE* tree, /**< branch and bound tree */
3056 SCIP_REOPT* reopt, /**< reoptimization data structure */
3057 SCIP_LP* lp, /**< LP data */
3058 SCIP_RELAXATION* relaxation, /**< relaxators */
3059 SCIP_PRICESTORE* pricestore, /**< pricing storage */
3060 SCIP_SEPASTORE* sepastore, /**< separation storage */
3061 SCIP_CUTPOOL* cutpool, /**< global cut pool */
3062 SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
3063 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3064 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3065 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
3066 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3067 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3068 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3069 SCIP_Bool initiallpsolved, /**< was the initial LP already solved? */
3070 SCIP_Bool fullseparation, /**< are we in the first prop-and-cut-and-price loop? */
3071 SCIP_Bool newinitconss, /**< do we have to add new initial constraints? */
3072 SCIP_Bool* propagateagain, /**< pointer to store whether we want to propagate again */
3073 SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called again */
3074 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3075 SCIP_Bool* unbounded, /**< pointer to store TRUE, if an unbounded ray was found in the LP */
3076 SCIP_Bool* lperror, /**< pointer to store TRUE, if an unresolved error in LP solving occured */
3077 SCIP_Bool* pricingaborted /**< pointer to store TRUE, if the pricing was aborted and the lower bound
3078 * must not be used */
3079 )
3080{
3081 SCIP_Longint nlpiterations;
3082 SCIP_Longint nlps;
3083 SCIP_Longint nzeroitlps;
3084
3085 assert(stat != NULL);
3086 assert(tree != NULL);
3087 assert(SCIPtreeHasFocusNodeLP(tree));
3088 assert(cutoff != NULL);
3089 assert(unbounded != NULL);
3090 assert(lperror != NULL);
3091 assert(*cutoff == FALSE);
3092 assert(*unbounded == FALSE);
3093 assert(*lperror == FALSE);
3094
3095 nlps = stat->nlps;
3096 nzeroitlps = stat->ndualzeroitlps + stat->nprimalzeroitlps + stat->nbarrierzeroitlps;
3097 nlpiterations = stat->nlpiterations;
3098
3099 if( !initiallpsolved )
3100 {
3101 /* load and solve the initial LP of the node */
3102 SCIP_CALL( solveNodeInitialLP(blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
3103 pricestore, sepastore, cutpool, branchcand, eventfilter, eventqueue, cliquetable, newinitconss, cutoff, lperror) );
3104
3105 assert(*cutoff || *lperror || (lp->flushed && lp->solved));
3106 SCIPsetDebugMsg(set, "price-and-cut-loop: initial LP status: %d, LP obj: %g\n",
3107 SCIPlpGetSolstat(lp),
3108 *cutoff ? SCIPsetInfinity(set) : *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
3109
3110 /* update initial LP iteration counter */
3111 stat->ninitlps += stat->nlps - nlps;
3112 stat->ninitlpiterations += stat->nlpiterations - nlpiterations;
3113
3114 /* In the root node, we try if the initial LP solution is feasible to avoid expensive setup of data structures in
3115 * separators; in case the root LP is aborted, e.g., by hitting the time limit, we do not check the LP solution
3116 * since the corresponding data structures have not been updated.
3117 */
3118 if( SCIPtreeGetCurrentDepth(tree) == 0 && !(*cutoff) && !(*lperror)
3120 && !SCIPsolveIsStopped(set, stat, FALSE) )
3121 {
3122 SCIP_Bool checklprows;
3123 SCIP_Bool stored;
3124 SCIP_SOL* sol;
3125 SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
3126
3127 SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
3128
3130 checklprows = FALSE;
3131 else
3132 checklprows = TRUE;
3133
3134#ifndef NDEBUG
3135 /* in the debug mode we want to explicitly check if the solution is feasible if it was stored */
3136 SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
3137 eventqueue, eventfilter, sol, FALSE, FALSE, TRUE, TRUE, checklprows, &stored) );
3138
3139 if( stored )
3140 {
3141 SCIP_Bool feasible;
3142
3143 SCIP_CALL( SCIPsolCheck(sol, set, messagehdlr, blkmem, stat, transprob, FALSE, FALSE, TRUE, TRUE,
3144 checklprows, &feasible) );
3145 assert(feasible);
3146 }
3147
3148 SCIP_CALL( SCIPsolFree(&sol, blkmem, primal) );
3149#else
3150 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
3151 eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, checklprows, &stored) );
3152#endif
3153 if( stored )
3154 {
3155 stat->nlpsolsfound++;
3156
3157 if( primal->nbestsolsfound != oldnbestsolsfound )
3158 {
3159 stat->nlpbestsolsfound++;
3161 }
3162
3163 if( set->reopt_enable )
3164 {
3165 assert(reopt != NULL);
3167 SCIPlpGetSolstat(lp), tree->root == tree->focusnode, TRUE, tree->focusnode->lowerbound,
3168 tree->effectiverootdepth) );
3169 }
3170 }
3171
3173 *unbounded = TRUE;
3174 }
3175 }
3176 else
3177 {
3178 SCIP_CALL( SCIPinitConssLP(blkmem, set, sepastore, cutpool, stat, transprob,
3179 origprob, tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, FALSE, FALSE,
3180 cutoff) );
3181 }
3182 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3183
3184 /* check for infeasible node by bounding */
3185 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
3186#ifdef SCIP_DEBUG
3187 if( *cutoff )
3188 {
3189 if( SCIPtreeGetCurrentDepth(tree) == 0 )
3190 {
3191 SCIPsetDebugMsg(set, "solution cuts off root node, stop solution process\n");
3192 }
3193 else
3194 {
3195 SCIPsetDebugMsg(set, "solution cuts off node\n");
3196 }
3197 }
3198#endif
3199
3200 if( !(*cutoff) && !(*lperror) )
3201 {
3202 SCIP_Longint oldninitconssadded;
3203 SCIP_Longint oldnboundchgs;
3204 SCIP_Longint olddomchgcount;
3205 int oldnpricedvars;
3206 int oldncutsapplied;
3207
3208 oldnpricedvars = transprob->ncolvars;
3209 oldninitconssadded = stat->ninitconssadded;
3210 oldncutsapplied = SCIPsepastoreGetNCutsApplied(sepastore);
3211 oldnboundchgs = stat->nboundchgs;
3212 olddomchgcount = stat->domchgcount;
3213
3214 /* solve the LP with price-and-cut*/
3215 SCIP_CALL( priceAndCutLoop(blkmem, set, messagehdlr, stat, mem, transprob, origprob, primal, tree, reopt, lp,
3216 pricestore, sepastore, cutpool, delayedcutpool, branchcand, conflict, conflictstore, eventfilter,
3217 eventqueue, cliquetable, fullseparation, propagateagain, cutoff, unbounded, lperror, pricingaborted) );
3218
3219 /* check if the problem was changed and the relaxation needs to be resolved */
3220 if( (transprob->ncolvars != oldnpricedvars) || (stat->ninitconssadded != oldninitconssadded) ||
3221 (SCIPsepastoreGetNCutsApplied(sepastore) != oldncutsapplied) || (stat->nboundchgs != oldnboundchgs) ||
3222 (stat->domchgcount != olddomchgcount) )
3223 {
3224 *solverelaxagain = TRUE;
3225 markRelaxsUnsolved(set, relaxation);
3226 }
3227 }
3228 assert(*cutoff || *lperror || (lp->flushed && lp->solved));
3229
3230 /* if there is no LP error, then *unbounded should be TRUE, iff the LP solution status is unboundedray */
3231 assert(*lperror || ((SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY) == *unbounded));
3232
3233 /* 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,
3234 * 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
3235 * is not a feasible lower bound for the solutions in the current subtree.
3236 * In this case, the LP has to be solved to optimality by temporarily removing the cutoff bound.
3237 */
3238 if( (*pricingaborted) && (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_ITERLIMIT)
3239 && !(*cutoff) )
3240 {
3241 SCIP_Real tmpcutoff;
3242
3243 /* temporarily disable cutoffbound, which also disables the objective limit */
3244 tmpcutoff = lp->cutoffbound;
3246
3247 lp->solved = FALSE;
3248 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, FALSE, lperror) );
3249
3250 /* reinstall old cutoff bound */
3251 lp->cutoffbound = tmpcutoff;
3252
3253 SCIPsetDebugMsg(set, "re-optimized LP without cutoff bound: LP status: %d, LP obj: %g\n",
3254 SCIPlpGetSolstat(lp), *lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob));
3255
3256 /* lp solstat should not be objlimit, since the cutoff bound was removed temporarily */
3258 /* lp solstat should not be unboundedray, since the lp was dual feasible */
3260 /* there should be no primal ray, since the lp was dual feasible */
3261 assert(primal->primalray == NULL);
3263 {
3264 *cutoff = TRUE;
3265 }
3266 }
3267
3268 assert(!(*pricingaborted) || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL /* cppcheck-suppress assertWithSideEffect */
3269 || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_NOTSOLVED || SCIPsolveIsStopped(set, stat, FALSE) || (*cutoff));
3270
3271 assert(*cutoff || *lperror || (lp->flushed && lp->solved));
3272
3273 /* update node's LP iteration counter */
3274 stat->nnodelps += stat->nlps - nlps;
3275 stat->nnodezeroitlps += stat->ndualzeroitlps + stat->nprimalzeroitlps + stat->nbarrierzeroitlps - nzeroitlps;
3276 stat->nnodelpiterations += stat->nlpiterations - nlpiterations;
3277
3278 /* update number of root node LPs and iterations if the root node was processed */
3279 if( SCIPnodeGetDepth(tree->focusnode) == 0 )
3280 {
3281 stat->nrootlps += stat->nlps - nlps;
3282 stat->nrootlpiterations += stat->nlpiterations - nlpiterations;
3283 }
3284
3285 return SCIP_OKAY;
3286}
3287
3288/** calls relaxators */
3289static
3291 SCIP_SET* set, /**< global SCIP settings */
3292 SCIP_STAT* stat, /**< dynamic problem statistics */
3293 SCIP_TREE* tree, /**< branch and bound tree */
3294 SCIP_RELAXATION* relaxation, /**< relaxators */
3295 SCIP_PROB* transprob, /**< transformed problem */
3296 SCIP_PROB* origprob, /**< original problem */
3297 int depth, /**< depth of current node */
3298 SCIP_Bool beforelp, /**< should the relaxators with non-negative or negative priority be called? */
3299 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3300 SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3301 SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3302 SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called
3303 * again */
3304 SCIP_Bool* relaxcalled /**< pointer to store TRUE, if at least one relaxator was called (unmodified
3305 * otherwise) */
3306 )
3307{
3308 SCIP_RESULT result;
3309 SCIP_Real lowerbound;
3310 int r;
3311
3312 assert(set != NULL);
3313 assert(relaxation != NULL);
3314 assert(cutoff != NULL);
3315 assert(solvelpagain != NULL);
3316 assert(propagateagain != NULL);
3317 assert(solverelaxagain != NULL);
3318 assert(relaxcalled != NULL);
3319 assert(!(*cutoff));
3320
3321 /* sort by priority */
3323
3324 for( r = 0; r < set->nrelaxs && !(*cutoff); ++r )
3325 {
3326 if( beforelp != (SCIPrelaxGetPriority(set->relaxs[r]) >= 0) )
3327 continue;
3328
3329 *relaxcalled = TRUE;
3330
3331 lowerbound = -SCIPsetInfinity(set);
3332
3333 SCIP_CALL( SCIPrelaxExec(set->relaxs[r], set, tree, stat, depth, &lowerbound, &result) );
3334
3335 switch( result )
3336 {
3337 case SCIP_CUTOFF:
3338 *cutoff = TRUE;
3339 SCIPsetDebugMsg(set, " -> relaxator <%s> detected cutoff\n", SCIPrelaxGetName(set->relaxs[r]));
3340 /* @todo does it make sense to proceed if the node is proven to be infeasible? */
3341 return SCIP_OKAY;
3342
3343 case SCIP_CONSADDED:
3344 *solvelpagain = TRUE; /* the separation for new constraints should be called */
3345 *propagateagain = TRUE; /* the propagation for new constraints should be called */
3346 break;
3347
3348 case SCIP_REDUCEDDOM:
3349 *solvelpagain = TRUE;
3350 *propagateagain = TRUE;
3351 break;
3352
3353 case SCIP_SEPARATED:
3354 *solvelpagain = TRUE;
3355 break;
3356
3357 case SCIP_SUSPENDED:
3358 *solverelaxagain = TRUE;
3359 break;
3360
3361 case SCIP_SUCCESS:
3362 case SCIP_DIDNOTRUN:
3363 break;
3364
3365 default:
3366 SCIPerrorMessage("invalid result code <%d> of relaxator <%s>\n", result, SCIPrelaxGetName(set->relaxs[r]));
3367 return SCIP_INVALIDRESULT;
3368 } /*lint !e788*/
3369
3370 if( result != SCIP_CUTOFF && result != SCIP_DIDNOTRUN && result != SCIP_SUSPENDED )
3371 {
3372 SCIP_NODE* focusnode;
3373
3374 focusnode = SCIPtreeGetFocusNode(tree);
3375 assert(focusnode != NULL);
3376 assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
3377
3378 /* update lower bound w.r.t. the lower bound given by the relaxator */
3379 SCIPnodeUpdateLowerbound(focusnode, stat, set, tree, transprob, origprob, lowerbound);
3380 SCIPsetDebugMsg(set, " -> new lower bound given by relaxator %s: %g\n",
3381 SCIPrelaxGetName(set->relaxs[r]), lowerbound);
3382 }
3383 }
3384
3385 return SCIP_OKAY;
3386}
3387
3388/** enforces constraints by branching, separation, or domain reduction */
3389static
3391 BMS_BLKMEM* blkmem, /**< block memory buffers */
3392 SCIP_SET* set, /**< global SCIP settings */
3393 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3394 SCIP_STAT* stat, /**< dynamic problem statistics */
3395 SCIP_PROB* prob, /**< transformed problem after presolve */
3396 SCIP_PRIMAL* primal, /**< primal data */
3397 SCIP_TREE* tree, /**< branch and bound tree */
3398 SCIP_LP* lp, /**< LP data */
3399 SCIP_RELAXATION* relaxation, /**< global relaxation data */
3400 SCIP_SEPASTORE* sepastore, /**< separation storage */
3401 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3402 SCIP_Bool* branched, /**< pointer to store whether a branching was created */
3403 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3404 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the LP/pseudo solution is infeasible */
3405 SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3406 SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3407 SCIP_Bool* solverelaxagain, /**< pointer to store TRUE, if the external relaxators should be called again */
3408 SCIP_Bool forced /**< should enforcement of pseudo solution be forced? */
3409 )
3410{
3411 SCIP_RESULT result;
3412 SCIP_SOL* relaxsol = NULL;
3413 SCIP_Real pseudoobjval;
3414 SCIP_Bool resolved;
3415 SCIP_Bool objinfeasible;
3416 SCIP_Bool enforcerelaxsol;
3417 int h;
3418
3419 assert(set != NULL);
3420 assert(stat != NULL);
3421 assert(tree != NULL);
3422 assert(SCIPtreeGetFocusNode(tree) != NULL);
3423 assert(branched != NULL);
3424 assert(cutoff != NULL);
3425 assert(infeasible != NULL);
3426 assert(propagateagain != NULL);
3427 assert(solvelpagain != NULL);
3428 assert(solverelaxagain != NULL);
3429 assert(!(*cutoff));
3430 assert(!(*propagateagain));
3431 assert(!(*solvelpagain));
3432 assert(!(*solverelaxagain));
3433
3434 *branched = FALSE;
3435 /**@todo avoid checking the same pseudosolution twice */
3436
3437 /* enforce (best) relaxation solution if the LP has a worse objective value */
3438 enforcerelaxsol = SCIPrelaxationIsSolValid(relaxation) && SCIPrelaxationIsLpIncludedForSol(relaxation) && (!SCIPtreeHasFocusNodeLP(tree)
3439 || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, prob)));
3440
3441 /* check if all constraint handlers implement the enforelax callback, otherwise enforce the LP solution */
3442 for( h = 0; h < set->nconshdlrs && enforcerelaxsol; ++h )
3443 {
3444 if( set->conshdlrs_enfo[h]->consenforelax == NULL && ((! set->conshdlrs_enfo[h]->needscons) ||
3445 (set->conshdlrs_enfo[h]->nconss > 0)) )
3446 {
3447 SCIP_VERBLEVEL verblevel;
3448
3449 enforcerelaxsol = FALSE;
3450
3451 verblevel = SCIP_VERBLEVEL_FULL;
3452
3453 if( !stat->disableenforelaxmsg && set->disp_verblevel == SCIP_VERBLEVEL_HIGH )
3454 {
3455 verblevel = SCIP_VERBLEVEL_HIGH;
3456
3457 /* remember that the disable relaxation enforcement message was posted and only post it again if the
3458 * verblevel is SCIP_VERBLEVEL_FULL
3459 */
3460 stat->disableenforelaxmsg = TRUE;
3461 }
3462 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, verblevel, "Disable enforcement of relaxation solutions"
3463 " since constraint handler %s does not implement enforelax-callback\n",
3464 SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3465 }
3466 }
3467
3468 /* enforce constraints by branching, applying additional cutting planes (if LP is being processed),
3469 * introducing new constraints, or tighten the domains
3470 */
3471#ifndef SCIP_NDEBUG
3472 if( enforcerelaxsol )
3473 {
3474 SCIPsetDebugMsg(set, "enforcing constraints on relaxation solution\n");
3475 }
3476 else
3477 {
3478 SCIPsetDebugMsg(set, "enforcing constraints on %s solution\n", SCIPtreeHasFocusNodeLP(tree) ? "LP" : "pseudo");
3479 }
3480#endif
3481
3482 /* check, if the solution is infeasible anyway due to it's objective value */
3483 if( SCIPtreeHasFocusNodeLP(tree) || enforcerelaxsol )
3484 objinfeasible = FALSE;
3485 else
3486 {
3487 pseudoobjval = SCIPlpGetPseudoObjval(lp, set, prob);
3488 objinfeasible = SCIPsetIsDualfeasLT(set, pseudoobjval, SCIPnodeGetLowerbound(SCIPtreeGetFocusNode(tree)));
3489 }
3490
3491 /* during constraint enforcement, generated cuts should enter the LP in any case; otherwise, a constraint handler
3492 * would fail to enforce its constraints if it relies on the modification of the LP relaxation
3493 */
3494 SCIPsepastoreStartForceCuts(sepastore);
3495
3496 /* enforce constraints until a handler resolved an infeasibility with cutting off the node, branching,
3497 * reducing a domain, or separating a cut
3498 * if a constraint handler introduced new constraints to enforce his constraints, the newly added constraints
3499 * have to be enforced themselves
3500 */
3501 resolved = FALSE;
3502
3503 /* in case the relaxation solution should be enforced, we need to create the corresponding solution for the enforelax callbacks */
3504 if( enforcerelaxsol )
3505 {
3506 SCIP_CALL( SCIPsolCreateRelaxSol(&relaxsol, blkmem, set, stat, primal, tree, relaxation, NULL) );
3507 }
3508
3509 for( h = 0; h < set->nconshdlrs && !resolved; ++h )
3510 {
3511 assert(SCIPsepastoreGetNCuts(sepastore) == 0); /* otherwise, the LP should have been resolved first */
3512
3513 /* enforce LP, pseudo, or relaxation solution */
3514 if( enforcerelaxsol )
3515 {
3516 SCIPsetDebugMsg(set, "enforce relaxation solution with value %g\n", SCIPrelaxationGetSolObj(relaxation));
3517
3518 SCIP_CALL( SCIPconshdlrEnforceRelaxSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, sepastore,
3519 relaxsol, *infeasible, &result) );
3520 }
3521 else if( SCIPtreeHasFocusNodeLP(tree) )
3522 {
3523 SCIPsetDebugMsg(set, "enforce LP solution with value %g\n", SCIPlpGetObjval(lp, set, prob));
3524
3525 assert(lp->flushed);
3526 assert(lp->solved);
3528 SCIP_CALL( SCIPconshdlrEnforceLPSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, sepastore, *infeasible,
3529 &result) );
3530 }
3531 else
3532 {
3533 SCIP_CALL( SCIPconshdlrEnforcePseudoSol(set->conshdlrs_enfo[h], blkmem, set, stat, tree, branchcand, *infeasible,
3534 objinfeasible, forced, &result) );
3535 if( SCIPsepastoreGetNCuts(sepastore) != 0 )
3536 {
3537 SCIPerrorMessage("pseudo enforcing method of constraint handler <%s> separated cuts\n",
3538 SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3539 return SCIP_INVALIDRESULT;
3540 }
3541 }
3542 SCIPsetDebugMsg(set, "enforcing of <%s> returned result %d\n", SCIPconshdlrGetName(set->conshdlrs_enfo[h]), result);
3543
3544 switch( result )
3545 {
3546 case SCIP_CUTOFF:
3547 assert(tree->nchildren == 0);
3548 *cutoff = TRUE;
3549 *infeasible = TRUE;
3550 resolved = TRUE;
3551 SCIPsetDebugMsg(set, " -> constraint handler <%s> detected cutoff in enforcement\n",
3552 SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3553 break;
3554
3555 case SCIP_CONSADDED:
3556 assert(tree->nchildren == 0);
3557 *infeasible = TRUE;
3558 *propagateagain = TRUE; /* the propagation for new constraints should be called */
3559 *solvelpagain = TRUE; /* the separation for new constraints should be called */
3560 *solverelaxagain = TRUE;
3561 markRelaxsUnsolved(set, relaxation);
3562 resolved = TRUE;
3563 break;
3564
3565 case SCIP_REDUCEDDOM:
3566 assert(tree->nchildren == 0);
3567 *infeasible = TRUE;
3568 *propagateagain = TRUE;
3569 *solvelpagain = TRUE;
3570 *solverelaxagain = TRUE;
3571 markRelaxsUnsolved(set, relaxation);
3572 resolved = TRUE;
3573 break;
3574
3575 case SCIP_SEPARATED:
3576 assert(tree->nchildren == 0);
3577 assert(SCIPsepastoreGetNCuts(sepastore) > 0);
3578 *infeasible = TRUE;
3579 *solvelpagain = TRUE;
3580 *solverelaxagain = TRUE;
3581 markRelaxsUnsolved(set, relaxation);
3582 resolved = TRUE;
3583 break;
3584
3585 case SCIP_BRANCHED:
3586 assert(tree->nchildren >= 1);
3587 assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3588 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3589 *infeasible = TRUE;
3590 *branched = TRUE;
3591 resolved = TRUE;
3592
3593 /* increase the number of internal nodes */
3594 stat->ninternalnodes++;
3595 stat->ntotalinternalnodes++;
3596 break;
3597
3598 case SCIP_SOLVELP:
3599 /* either LP was not solved, or it is not solved anymore (e.g., because feastol has been tightened by some constraint handler) */
3600 assert(!SCIPtreeHasFocusNodeLP(tree) || !lp->solved);
3601 assert(tree->nchildren == 0);
3602 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3603 *infeasible = TRUE;
3604 *solvelpagain = TRUE;
3605 resolved = TRUE;
3606 SCIPtreeSetFocusNodeLP(tree, TRUE); /* the node's LP must be solved */
3607 break;
3608
3609 case SCIP_INFEASIBLE:
3610 assert(tree->nchildren == 0);
3611 assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3612 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3613 *infeasible = TRUE;
3614 break;
3615
3616 case SCIP_FEASIBLE:
3617 assert(tree->nchildren == 0);
3618 assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3619 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3620 break;
3621
3622 case SCIP_DIDNOTRUN:
3623 assert(tree->nchildren == 0);
3624 assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
3625 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3626 assert(objinfeasible);
3627 *infeasible = TRUE;
3628 break;
3629
3630 default:
3631 SCIPerrorMessage("invalid result code <%d> from enforcing method of constraint handler <%s>\n",
3632 result, SCIPconshdlrGetName(set->conshdlrs_enfo[h]));
3633 return SCIP_INVALIDRESULT;
3634 } /*lint !e788*/
3635
3636 /* the enforcement method may add a primal solution, after which the LP status could be set to
3637 * objective limit reached
3638 */
3640 {
3641 *cutoff = TRUE;
3642 *infeasible = TRUE;
3643 resolved = TRUE;
3644 SCIPsetDebugMsg(set, " -> LP exceeded objective limit\n");
3645
3646 /* If we used the probing mode during branching, it might happen that we added a constraint or global bound
3647 * and returned SCIP_CONSADDED or SCIP_REDUCEDDOM, but when reoptimizing the LP after ending the probing mode,
3648 * this leads to hitting the objective limit. In this case, we do not need to propagate or solve the LP again.
3649 */
3650 *propagateagain = FALSE;
3651 *solvelpagain = FALSE;
3652 }
3653
3654 assert(!(*branched) || (resolved && !(*cutoff) && *infeasible && !(*propagateagain) && !(*solvelpagain)));
3655 assert(!(*cutoff) || (resolved && !(*branched) && *infeasible && !(*propagateagain) && !(*solvelpagain)));
3656 assert(*infeasible || (!resolved && !(*branched) && !(*cutoff) && !(*propagateagain) && !(*solvelpagain)));
3657 assert(!(*propagateagain) || (resolved && !(*branched) && !(*cutoff) && *infeasible));
3658 assert(!(*solvelpagain) || (resolved && !(*branched) && !(*cutoff) && *infeasible));
3659 }
3660 assert(!objinfeasible || *infeasible);
3661 assert(resolved == (*branched || *cutoff || *propagateagain || *solvelpagain));
3662 assert(*cutoff || *solvelpagain || SCIPsepastoreGetNCuts(sepastore) == 0);
3663
3664 /* in case the relaxation solution was enforced, free the created solution */
3665 if( enforcerelaxsol )
3666 {
3667 SCIP_CALL( SCIPsolFree(&relaxsol, blkmem, primal) );
3668 }
3669
3670 /* deactivate the cut forcing of the constraint enforcement */
3671 SCIPsepastoreEndForceCuts(sepastore);
3672
3673 SCIPsetDebugMsg(set, " -> enforcing result: branched=%u, cutoff=%u, infeasible=%u, propagateagain=%u, solvelpagain=%u, resolved=%u\n",
3674 *branched, *cutoff, *infeasible, *propagateagain, *solvelpagain, resolved);
3675
3676 return SCIP_OKAY;
3677}
3678
3679/** applies the cuts stored in the separation store, or clears the store if the node can be cut off */
3680static
3682 BMS_BLKMEM* blkmem, /**< block memory buffers */
3683 SCIP_SET* set, /**< global SCIP settings */
3684 SCIP_STAT* stat, /**< dynamic problem statistics */
3685 SCIP_PROB* transprob, /**< transformed problem */
3686 SCIP_PROB* origprob, /**< original problem */
3687 SCIP_TREE* tree, /**< branch and bound tree */
3688 SCIP_REOPT* reopt, /**< reotimization data structure */
3689 SCIP_LP* lp, /**< LP data */
3690 SCIP_RELAXATION* relaxation, /**< relaxators */
3691 SCIP_SEPASTORE* sepastore, /**< separation storage */
3692 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3693 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3694 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
3695 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3696 SCIP_Bool root, /**< is this the initial root LP? */
3697 SCIP_EFFICIACYCHOICE efficiacychoice, /**< type of solution to base efficiacy computation on */
3698 SCIP_Bool* cutoff, /**< pointer to whether the node can be cut off */
3699 SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3700 SCIP_Bool* solvelpagain, /**< pointer to store TRUE, if the node's LP has to be solved again */
3701 SCIP_Bool* solverelaxagain /**< pointer to store TRUE, if the node's relaxation has to be solved again */
3702 )
3703{
3704 assert(stat != NULL);
3705 assert(cutoff != NULL);
3706 assert(propagateagain != NULL);
3707 assert(solvelpagain != NULL);
3708
3709 if( *cutoff )
3710 {
3711 /* the found cuts are of no use, because the node is infeasible anyway (or we have an error in the LP) */
3712 SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
3713 }
3714 else if( SCIPsepastoreGetNCuts(sepastore) > 0 )
3715 {
3716 SCIP_Longint olddomchgcount;
3717 int oldncutsapplied;
3718
3719 olddomchgcount = stat->domchgcount;
3720 oldncutsapplied = SCIPsepastoreGetNCutsApplied(sepastore);
3721 SCIP_CALL( SCIPsepastoreApplyCuts(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
3722 eventqueue, eventfilter, cliquetable, root, efficiacychoice, cutoff) );
3723 *propagateagain = *propagateagain || (stat->domchgcount != olddomchgcount);
3724 *solvelpagain = TRUE;
3725 if( (stat->domchgcount != olddomchgcount) || (SCIPsepastoreGetNCutsApplied(sepastore) != oldncutsapplied) )
3726 {
3727 *solverelaxagain = TRUE;
3728 markRelaxsUnsolved(set, relaxation);
3729 }
3730 }
3731
3732 return SCIP_OKAY;
3733}
3734
3735/** updates the cutoff, propagateagain, and solverelaxagain status of the current solving loop */
3736static
3738 SCIP_SET* set, /**< global SCIP settings */
3739 SCIP_STAT* stat, /**< dynamic problem statistics */
3740 SCIP_TREE* tree, /**< branch and bound tree */
3741 int depth, /**< depth of current node */
3742 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
3743 SCIP_Bool* propagateagain, /**< pointer to store TRUE, if domain propagation should be applied again */
3744 SCIP_Bool* solverelaxagain /**< pointer to store TRUE, if at least one relaxator should be called again */
3745 )
3746{
3747 SCIP_NODE* focusnode;
3748 int r;
3749
3750 assert(set != NULL);
3751 assert(stat != NULL);
3752 assert(cutoff != NULL);
3753 assert(propagateagain != NULL);
3754 assert(solverelaxagain != NULL);
3755
3756 /* check, if the path was cutoff */
3757 *cutoff = *cutoff || (tree->cutoffdepth <= depth);
3758
3759 /* check if branching was already performed */
3760 if( tree->nchildren == 0 )
3761 {
3762 /* check, if the focus node should be repropagated */
3763 focusnode = SCIPtreeGetFocusNode(tree);
3764 *propagateagain = *propagateagain || SCIPnodeIsPropagatedAgain(focusnode);
3765
3766 /* check, if one of the external relaxations should be solved again */
3767 for( r = 0; r < set->nrelaxs && !(*solverelaxagain); ++r )
3768 *solverelaxagain = *solverelaxagain || ( !SCIPrelaxIsSolved(set->relaxs[r], stat) );
3769 }
3770 else
3771 {
3772 /* if branching was performed, avoid another node loop iteration */
3773 *propagateagain = FALSE;
3774 *solverelaxagain = FALSE;
3775 }
3776}
3777
3778/** propagate domains and solve relaxation and lp */
3779static
3781 BMS_BLKMEM* blkmem, /**< block memory buffers */
3782 SCIP_SET* set, /**< global SCIP settings */
3783 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3784 SCIP_STAT* stat, /**< dynamic problem statistics */
3785 SCIP_MEM* mem, /**< block memory pools */
3786 SCIP_PROB* origprob, /**< original problem */
3787 SCIP_PROB* transprob, /**< transformed problem after presolve */
3788 SCIP_PRIMAL* primal, /**< primal data */
3789 SCIP_TREE* tree, /**< branch and bound tree */
3790 SCIP_REOPT* reopt, /**< reoptimization data structure */
3791 SCIP_LP* lp, /**< LP data */
3792 SCIP_RELAXATION* relaxation, /**< global relaxation data */
3793 SCIP_PRICESTORE* pricestore, /**< pricing storage */
3794 SCIP_SEPASTORE* sepastore, /**< separation storage */
3795 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3796 SCIP_CUTPOOL* cutpool, /**< global cut pool */
3797 SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
3798 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3799 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
3800 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3801 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3802 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3803 SCIP_NODE* focusnode, /**< focused node */
3804 int actdepth, /**< depth in the b&b tree */
3805 SCIP_Bool propagate, /**< should we propagate */
3806 SCIP_Bool solvelp, /**< should we solve the lp */
3807 SCIP_Bool solverelax, /**< should we solve the relaxation */
3808 SCIP_Bool forcedlpsolve, /**< is there a need for a solve lp */
3809 SCIP_Bool initiallpsolved, /**< was the initial LP already solved? */
3810 SCIP_Bool fullseparation, /**< are we in the first prop-and-cut-and-price loop? */
3811 SCIP_Longint* afterlpproplps, /**< pointer to store the last LP count for which AFTERLP propagation was performed */
3812 SCIP_HEURTIMING* heurtiming, /**< timing for running heuristics after propagation call */
3813 int* nlperrors, /**< pointer to store the number of lp errors */
3814 SCIP_Bool* fullpropagation, /**< pointer to store whether we want to do a fullpropagation next time */
3815 SCIP_Bool* propagateagain, /**< pointer to store whether we want to propagate again */
3816 SCIP_Bool* lpsolved, /**< pointer to store whether the lp was solved */
3817 SCIP_Bool* relaxcalled, /**< pointer to store whether a relaxator was called; initialized with last loop's result */
3818 SCIP_Bool* solvelpagain, /**< pointer to store whether we want to solve the lp again */
3819 SCIP_Bool* solverelaxagain, /**< pointer to store whether we want to solve the relaxation again */
3820 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
3821 SCIP_Bool* postpone, /**< pointer to store whether the node should be postponed */
3822 SCIP_Bool* unbounded, /**< pointer to store whether the focus node is unbounded */
3823 SCIP_Bool* stopped, /**< pointer to store whether solving was interrupted */
3824 SCIP_Bool* lperror, /**< pointer to store TRUE, if an unresolved error in LP solving occured */
3825 SCIP_Bool* pricingaborted, /**< pointer to store TRUE, if the pricing was aborted and the lower bound must not be used */
3826 SCIP_Bool* forcedenforcement /**< pointer to store whether the enforcement of pseudo solution should be forced */
3827 )
3828{
3829 SCIP_Bool newinitconss;
3830
3831 assert(set != NULL);
3832 assert(stat != NULL);
3833 assert(origprob != NULL);
3834 assert(transprob != NULL);
3835 assert(tree != NULL);
3836 assert(lp != NULL);
3837 assert(primal != NULL);
3838 assert(pricestore != NULL);
3839 assert(sepastore != NULL);
3840 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3841 assert(branchcand != NULL);
3842 assert(cutpool != NULL);
3843 assert(delayedcutpool != NULL);
3844 assert(conflict != NULL);
3845 assert(SCIPconflictGetNConflicts(conflict) == 0);
3846 assert(eventfilter != NULL);
3847 assert(eventqueue != NULL);
3848 assert(focusnode != NULL);
3849 assert(heurtiming != NULL);
3850 assert(nlperrors != NULL);
3851 assert(fullpropagation != NULL);
3852 assert(propagateagain != NULL);
3853 assert(afterlpproplps != NULL);
3854 assert(lpsolved != NULL);
3855 assert(solvelpagain != NULL);
3856 assert(solverelaxagain != NULL);
3857 assert(cutoff != NULL);
3858 assert(postpone != NULL);
3859 assert(unbounded != NULL);
3860 assert(lperror != NULL);
3861 assert(pricingaborted != NULL);
3862 assert(forcedenforcement != NULL);
3863
3864 newinitconss = FALSE;
3865
3866 if( !(*cutoff) && !(*postpone) )
3867 {
3868 SCIP_Longint oldninitconssadded;
3869 SCIP_Longint oldnboundchgs;
3870 SCIP_Bool lpwasflushed;
3871
3872 lpwasflushed = lp->flushed;
3873 oldnboundchgs = stat->nboundchgs;
3874 oldninitconssadded = stat->ninitconssadded;
3875
3876 /* call after LP propagators */
3877 if( ((*afterlpproplps) < stat->nnodelps && (*lpsolved)) || (*relaxcalled) )
3878 {
3879 SCIP_CALL( propagateDomains(blkmem, set, stat, tree, SCIPtreeGetCurrentDepth(tree), 0, *fullpropagation,
3880 SCIP_PROPTIMING_AFTERLPLOOP, cutoff, postpone) );
3881 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3882
3883 /* check, if the path was cutoff */
3884 *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3885 *afterlpproplps = stat->nnodelps;
3886 propagate = propagate || (stat->nboundchgs > oldnboundchgs);
3887 }
3888
3889 /* call before LP propagators */
3890 if( propagate && !(*cutoff) )
3891 {
3892 SCIP_CALL( propagateDomains(blkmem, set, stat, tree, SCIPtreeGetCurrentDepth(tree), 0, *fullpropagation,
3893 SCIP_PROPTIMING_BEFORELP, cutoff, postpone) );
3894 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3895 }
3896
3897 newinitconss = (stat->ninitconssadded != oldninitconssadded);
3898 *fullpropagation = FALSE;
3899
3900 /* check, if the path was cutoff */
3901 *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
3902
3903 /* if the LP was flushed and is now no longer flushed, a bound change occurred, and the LP has to be resolved;
3904 * we also have to solve the LP if new intial constraints were added which need to be added to the LP
3905 */
3906 solvelp = solvelp || (lpwasflushed && (!lp->flushed || newinitconss));
3907 solverelax = solverelax || newinitconss;
3908
3909 /* the number of bound changes was increased by the propagation call, thus the relaxation should be solved again */
3910 if( stat->nboundchgs > oldnboundchgs )
3911 {
3912 /* propagation might have changed the best bound of loose variables, thereby changing the loose objective value
3913 * which is added to the LP value; because of the loose status, the LP might not be reoptimized, but the lower
3914 * bound of the node needs to be updated
3915 */
3916 if( !solvelp && lp->flushed && lp->solved && SCIPprobAllColsInLP(transprob, set, lp) && SCIPlpIsRelax(lp) )
3917 {
3918 SCIP_CALL( SCIPnodeUpdateLowerboundLP(focusnode, set, stat, tree, transprob, origprob, lp) );
3919 SCIPsetDebugMsg(set, " -> new lower bound: %g (LP status: %d, LP obj: %g)\n",
3920 SCIPnodeGetLowerbound(focusnode), SCIPlpGetSolstat(lp), SCIPlpGetObjval(lp, set, transprob));
3921
3922 if( SCIPtreeHasFocusNodeLP(tree) )
3923 {
3924 /* update node estimate */
3925 SCIP_CALL( updateEstimate(set, stat, tree, lp, branchcand) );
3926
3927 if( actdepth == 0 && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
3928 SCIPprobUpdateBestRootSol(transprob, set, stat, lp);
3929 }
3930 }
3931
3932 solverelax = TRUE;
3933 markRelaxsUnsolved(set, relaxation);
3934 }
3935
3936 /* update lower bound with the pseudo objective value, and cut off node by bounding */
3937 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
3938 conflict, cliquetable, cutoff) );
3939 }
3940 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
3941
3942 if( *postpone )
3943 return SCIP_OKAY;
3944
3945 /* call primal heuristics that are applicable after propagation loop before lp solve;
3946 * the first time we go here, we call the before node heuristics instead
3947 */
3948 if( !(*cutoff) && !SCIPtreeProbing(tree) )
3949 {
3950 /* if the heuristics find a new incumbent solution, propagate again */
3951 SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, *heurtiming,
3952 FALSE, propagateagain, unbounded) );
3953 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
3954
3955 *heurtiming = SCIP_HEURTIMING_AFTERPROPLOOP;
3956
3957 /* check if primal heuristics found a solution and we therefore reached a solution limit */
3958 if( SCIPsolveIsStopped(set, stat, FALSE) )
3959 {
3960 /* cppcheck-suppress unassignedVariable */
3961 SCIP_NODE* node;
3962
3963 /* we reached a solution limit and do not want to continue the processing of the current node, but in order to
3964 * allow restarting the optimization process later, we need to create a "branching" with only one child node that
3965 * is a copy of the focusnode
3966 */
3968 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, 1.0, focusnode->estimate) );
3969 assert(tree->nchildren >= 1);
3970 *stopped = TRUE;
3971 return SCIP_OKAY;
3972 }
3973
3974 /* if diving produced an LP error, switch back to non-LP node */
3975 if( lp->resolvelperror )
3976 {
3978 lp->resolvelperror = FALSE;
3979 }
3980
3981 if( *propagateagain )
3982 {
3983 *solvelpagain = solvelp;
3984 *solverelaxagain = solverelax;
3985
3986 return SCIP_OKAY;
3987 }
3988 }
3989
3990 /* solve external relaxations with non-negative priority */
3991 *relaxcalled = FALSE;
3992 if( solverelax && !(*cutoff) )
3993 {
3994 /* clear the storage of external branching candidates */
3996
3997 SCIP_CALL( solveNodeRelax(set, stat, tree, relaxation, transprob, origprob, actdepth, TRUE,
3998 cutoff, propagateagain, solvelpagain, solverelaxagain, relaxcalled) );
3999 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4000
4001 /* check, if the path was cutoff */
4002 *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
4003
4004 /* apply found cuts */
4005 SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4006 eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_RELAX, cutoff, propagateagain,
4007 solvelpagain, solverelaxagain) );
4008
4009 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4010 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4011 }
4012 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4013
4014 /* check, if we want to solve the LP at this node */
4015 if( solvelp && !(*cutoff) && SCIPtreeHasFocusNodeLP(tree) )
4016 {
4017 *lperror = FALSE;
4018 *unbounded = FALSE;
4019
4020 /* solve the node's LP */
4021 SCIP_CALL( solveNodeLP(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp, relaxation, pricestore,
4022 sepastore, cutpool, delayedcutpool, branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable,
4023 initiallpsolved, fullseparation, newinitconss, propagateagain, solverelaxagain, cutoff, unbounded, lperror, pricingaborted) );
4024
4025 *lpsolved = TRUE;
4026 *solvelpagain = FALSE;
4027 SCIPsetDebugMsg(set, " -> LP status: %d, LP obj: %g, iter: %" SCIP_LONGINT_FORMAT ", count: %" SCIP_LONGINT_FORMAT "\n",
4028 SCIPlpGetSolstat(lp),
4029 *cutoff ? SCIPsetInfinity(set) : (*lperror ? -SCIPsetInfinity(set) : SCIPlpGetObjval(lp, set, transprob)),
4030 stat->nlpiterations, stat->lpcount);
4031
4032 /* check, if the path was cutoff */
4033 *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
4034
4035 /* if an error occured during LP solving, switch to pseudo solution */
4036 if( *lperror )
4037 {
4038 if( forcedlpsolve )
4039 {
4040 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
4041 stat->nnodes, stat->nlps);
4042 return SCIP_LPERROR;
4043 }
4045 ++(*nlperrors);
4046 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, actdepth == 0 ? SCIP_VERBLEVEL_HIGH : SCIP_VERBLEVEL_FULL,
4047 "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
4048 stat->nnodes, stat->nlps, *nlperrors);
4049 }
4050
4052 {
4054 *forcedenforcement = TRUE;
4055
4056 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, actdepth == 0 ? SCIP_VERBLEVEL_HIGH : SCIP_VERBLEVEL_FULL,
4057 "(node %" SCIP_LONGINT_FORMAT ") LP solver hit %s limit in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead\n",
4058 stat->nnodes, SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_TIMELIMIT ? "time" : "iteration", stat->nlps);
4059 }
4060
4062 {
4063 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4064 "(node %" SCIP_LONGINT_FORMAT ") LP relaxation is unbounded (LP %" SCIP_LONGINT_FORMAT ")\n", stat->nnodes, stat->nlps);
4065 }
4066
4067 /* if we solve exactly, the LP claims to be infeasible but the infeasibility could not be proved,
4068 * we have to forget about the LP and use the pseudo solution instead
4069 */
4070 if( !(*cutoff) && !(*lperror) && (set->misc_exactsolve || *pricingaborted) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_INFEASIBLE
4071 && SCIPnodeGetLowerbound(focusnode) < primal->cutoffbound )
4072 {
4073 if( SCIPbranchcandGetNPseudoCands(branchcand) == 0 && transprob->ncontvars > 0 )
4074 {
4075 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",
4076 stat->nnodes, stat->nlps, set->misc_exactsolve, *pricingaborted, transprob->ncontvars);
4077 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") -> have to call PerPlex() (feature not yet implemented)\n", stat->nnodes);
4078 /**@todo call PerPlex */
4079 return SCIP_LPERROR;
4080 }
4081 else
4082 {
4084 *forcedenforcement = TRUE;
4085
4086 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4087 "(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",
4088 stat->nnodes, stat->nlps, set->misc_exactsolve, *pricingaborted, SCIPbranchcandGetNPseudoCands(branchcand));
4089 }
4090 }
4091
4092 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4093 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict,
4094 cliquetable, cutoff) );
4095 }
4096 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4097 assert(*cutoff || !SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
4098
4099 /* reset solverelaxagain if no relaxations were solved up to this point (the LP-changes are already included in
4100 * relaxators called after the LP)
4101 */
4102 *solverelaxagain = *solverelaxagain && *relaxcalled;
4103
4104 /* solve external relaxations with negative priority */
4105 if( solverelax && !(*cutoff) )
4106 {
4107 SCIP_CALL( solveNodeRelax(set, stat, tree, relaxation, transprob, origprob, actdepth, FALSE, cutoff,
4108 propagateagain, solvelpagain, solverelaxagain, relaxcalled) );
4109 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4110
4111 /* check, if the path was cutoff */
4112 *cutoff = *cutoff || (tree->cutoffdepth <= actdepth);
4113
4114 /* apply found cuts */
4115 SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4116 eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_RELAX, cutoff, propagateagain,
4117 solvelpagain, solverelaxagain) );
4118
4119 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4120 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict,
4121 cliquetable, cutoff) );
4122 }
4123 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4124
4125 return SCIP_OKAY;
4126}
4127
4128/** check if a restart can be performed */
4129#ifndef NDEBUG
4130static
4132 SCIP_SET* set, /**< global SCIP settings */
4133 SCIP_STAT* stat /**< dynamic problem statistics */
4134 )
4135{
4136 assert(set != NULL);
4137 assert(stat != NULL);
4138
4139 return set->nactivepricers == 0 && !set->reopt_enable
4140 && ( set->presol_maxrestarts == -1 || stat->nruns <= set->presol_maxrestarts );
4141}
4142#else
4143#define restartAllowed(set,stat) ((set)->nactivepricers == 0 && !set->reopt_enable && ((set)->presol_maxrestarts == -1 || (stat)->nruns <= (set)->presol_maxrestarts))
4144#endif
4145
4146/** solves the focus node */
4147static
4149 BMS_BLKMEM* blkmem, /**< block memory buffers */
4150 SCIP_SET* set, /**< global SCIP settings */
4151 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4152 SCIP_STAT* stat, /**< dynamic problem statistics */
4153 SCIP_MEM* mem, /**< block memory pools */
4154 SCIP_PROB* origprob, /**< original problem */
4155 SCIP_PROB* transprob, /**< transformed problem after presolve */
4156 SCIP_PRIMAL* primal, /**< primal data */
4157 SCIP_TREE* tree, /**< branch and bound tree */
4158 SCIP_REOPT* reopt, /**< reoptimization data structure */
4159 SCIP_LP* lp, /**< LP data */
4160 SCIP_RELAXATION* relaxation, /**< global relaxation data */
4161 SCIP_PRICESTORE* pricestore, /**< pricing storage */
4162 SCIP_SEPASTORE* sepastore, /**< separation storage */
4163 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4164 SCIP_CUTPOOL* cutpool, /**< global cut pool */
4165 SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
4166 SCIP_CONFLICT* conflict, /**< conflict analysis data */
4167 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
4168 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4169 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4170 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4171 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4172 SCIP_Bool* postpone, /**< pointer to store whether the node should be postponed */
4173 SCIP_Bool* unbounded, /**< pointer to store whether the focus node is unbounded */
4174 SCIP_Bool* infeasible, /**< pointer to store whether the focus node's solution is infeasible */
4175 SCIP_Bool* restart, /**< should solving process be started again with presolving? */
4176 SCIP_Bool* afternodeheur, /**< pointer to store whether AFTERNODE heuristics were already called */
4177 SCIP_Bool* stopped /**< pointer to store whether solving was interrupted */
4178 )
4179{
4180 SCIP_NODE* focusnode;
4181 SCIP_Longint lastdomchgcount;
4182 SCIP_Longint afterlpproplps;
4183 SCIP_Real restartfac;
4184 SCIP_Longint lastlpcount;
4185 SCIP_HEURTIMING heurtiming;
4186 int actdepth;
4187 int nlperrors;
4188 int nloops;
4189 SCIP_Bool foundsol;
4190 SCIP_Bool focusnodehaslp;
4191 SCIP_Bool lpsolved;
4192 SCIP_Bool initiallpsolved;
4193 SCIP_Bool fullseparation;
4194 SCIP_Bool solverelaxagain;
4195 SCIP_Bool solvelpagain;
4196 SCIP_Bool propagateagain;
4197 SCIP_Bool fullpropagation;
4198 SCIP_Bool branched;
4199 SCIP_Bool forcedlpsolve;
4200 SCIP_Bool wasforcedlpsolve;
4201 SCIP_Bool pricingaborted;
4202
4203 assert(set != NULL);
4204 assert(stat != NULL);
4205 assert(origprob != NULL);
4206 assert(transprob != NULL);
4207 assert(tree != NULL);
4208 assert(primal != NULL);
4209 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4210 assert(SCIPconflictGetNConflicts(conflict) == 0);
4211 assert(cutoff != NULL);
4212 assert(postpone != NULL);
4213 assert(unbounded != NULL);
4214 assert(infeasible != NULL);
4215 assert(restart != NULL);
4216 assert(afternodeheur != NULL);
4217
4218 *cutoff = FALSE;
4219 *postpone = FALSE;
4220 *unbounded = FALSE;
4221 *infeasible = FALSE;
4222 *restart = FALSE;
4223 *afternodeheur = FALSE;
4224 *stopped = FALSE;
4225 pricingaborted = FALSE;
4226
4227 focusnode = SCIPtreeGetFocusNode(tree);
4228 assert(focusnode != NULL);
4229 assert(SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
4230 actdepth = SCIPnodeGetDepth(focusnode);
4231
4232 /* invalidate relaxation solution */
4234
4235 /* clear the storage of external branching candidates */
4237
4238 SCIPsetDebugMsg(set, "Processing node %" SCIP_LONGINT_FORMAT " in depth %d, %d siblings\n",
4239 stat->nnodes, actdepth, tree->nsiblings);
4240 SCIPsetDebugMsg(set, "current pseudosolution: obj=%g\n", SCIPlpGetPseudoObjval(lp, set, transprob));
4241 /*debug(SCIPprobPrintPseudoSol(transprob, set));*/
4242
4243 /* check, if we want to solve the LP at the selected node:
4244 * - solve the LP, if the lp solve depth and frequency demand solving
4245 * - solve the root LP, if the LP solve frequency is set to 0
4246 * - solve the root LP, if there are continuous variables present
4247 * - don't solve the node if its cut off by the pseudo objective value anyway
4248 */
4249 focusnodehaslp = (set->lp_solvedepth == -1 || actdepth <= set->lp_solvedepth);
4250 focusnodehaslp = focusnodehaslp && (set->lp_solvefreq >= 1 && actdepth % set->lp_solvefreq == 0);
4251 focusnodehaslp = focusnodehaslp || (actdepth == 0 && set->lp_solvefreq == 0);
4252 focusnodehaslp = focusnodehaslp && SCIPsetIsLT(set, SCIPlpGetPseudoObjval(lp, set, transprob), primal->cutoffbound);
4253 focusnodehaslp = set->reopt_enable ? focusnodehaslp && SCIPreoptGetSolveLP(reopt, set, focusnode) : focusnodehaslp;
4254 SCIPtreeSetFocusNodeLP(tree, focusnodehaslp);
4255
4256 /* external node solving loop:
4257 * - propagate domains
4258 * - solve SCIP_LP
4259 * - enforce constraints
4260 * if a constraint handler adds constraints to enforce its own constraints, both, propagation and LP solving
4261 * is applied again (if applicable on current node); however, if the new constraints don't have the enforce flag set,
4262 * it is possible, that the current infeasible solution is not cut off; in this case, we have to declare the solution
4263 * infeasible and perform a branching
4264 */
4265 lastdomchgcount = stat->domchgcount;
4266 lastlpcount = stat->lpcount;
4267 initiallpsolved = FALSE;
4268 fullseparation = TRUE;
4269 heurtiming = SCIP_HEURTIMING_BEFORENODE;
4270 nlperrors = 0;
4271 stat->npricerounds = 0;
4272 stat->nseparounds = 0;
4273 solverelaxagain = TRUE;
4274 solvelpagain = TRUE;
4275 propagateagain = TRUE;
4276 fullpropagation = TRUE;
4277 forcedlpsolve = FALSE;
4278 nloops = 0;
4279
4280 while( !(*cutoff) && !(*postpone) && (solverelaxagain || solvelpagain || propagateagain) && nlperrors < MAXNLPERRORS && !(*restart) )
4281 {
4282 SCIP_Bool lperror;
4283 SCIP_Bool solverelax;
4284 SCIP_Bool solvelp;
4285 SCIP_Bool propagate;
4286 SCIP_Bool forcedenforcement;
4287 SCIP_Bool relaxcalled;
4288
4289 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4290
4291 *unbounded = FALSE;
4292 *infeasible = FALSE;
4293 foundsol = FALSE;
4294
4295 nloops++;
4296 lperror = FALSE;
4297 lpsolved = FALSE;
4298 relaxcalled = FALSE;
4299 forcedenforcement = FALSE;
4300 afterlpproplps = -1L;
4301
4302 while( !lperror && !(*cutoff) && (propagateagain || solvelpagain || solverelaxagain
4303 || (afterlpproplps < stat->nnodelps && lpsolved) || relaxcalled) )
4304 {
4305 solverelax = solverelaxagain;
4306 solverelaxagain = FALSE;
4307 solvelp = solvelpagain;
4308 solvelpagain = FALSE;
4309 propagate = propagateagain;
4310 propagateagain = FALSE;
4311
4312 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4313 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
4314 conflict, cliquetable, cutoff) );
4315
4316 /* propagate domains before lp solving and solve relaxation and lp */
4317 SCIPsetDebugMsg(set, " -> node solving loop: call propagators that are applicable before%s LP is solved\n",
4318 lpsolved ? " and after" : "");
4319 SCIP_CALL( propAndSolve(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp,
4320 relaxation, pricestore, sepastore, branchcand, cutpool, delayedcutpool, conflict, conflictstore, eventfilter,
4321 eventqueue, cliquetable, focusnode, actdepth, propagate, solvelp, solverelax, forcedlpsolve, initiallpsolved,
4322 fullseparation, &afterlpproplps, &heurtiming, &nlperrors, &fullpropagation, &propagateagain, &lpsolved, &relaxcalled,
4323 &solvelpagain, &solverelaxagain, cutoff, postpone, unbounded, stopped, &lperror, &pricingaborted, &forcedenforcement) );
4324 initiallpsolved |= lpsolved;
4325
4326 /* time or solution limit was hit and we already created a dummy child node to terminate fast */
4327 if( *stopped )
4328 {
4329 /* reset LP feastol to normal value, in case someone tightened it during node solving */
4331 return SCIP_OKAY;
4332 }
4333 }
4334 fullseparation = FALSE;
4335
4336 /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4337 updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4338
4339 /* call primal heuristics that should be applied after the LP relaxation of the node was solved;
4340 * if this is the first loop of the root node, call also AFTERNODE heuristics already here, since they might help
4341 * to improve the primal bound, thereby producing additional reduced cost strengthenings and strong branching
4342 * bound fixings which also might lead to a restart
4343 */
4344 if( !(*postpone) && (!(*cutoff) || SCIPtreeGetNNodes(tree) > 0) )
4345 {
4346 if( actdepth == 0 && !(*afternodeheur) )
4347 {
4348 SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL,
4349 SCIP_HEURTIMING_AFTERLPLOOP | SCIP_HEURTIMING_AFTERNODE, *cutoff, &foundsol, unbounded) );
4350 *afternodeheur = TRUE; /* the AFTERNODE heuristics should not be called again after the node */
4351 }
4352 else if( lpsolved || SCIPrelaxationIsSolValid(relaxation) )
4353 {
4354 SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, NULL, SCIP_HEURTIMING_AFTERLPLOOP,
4355 *cutoff, &foundsol, unbounded) );
4356 }
4357 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4358
4359 /* heuristics might have found a solution or set the cutoff bound such that the current node is cut off */
4360 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4361 }
4362
4363 /* check if heuristics leave us with an invalid LP */
4364 if( lp->resolvelperror )
4365 {
4366 if( forcedlpsolve )
4367 {
4368 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
4369 stat->nnodes, stat->nlps);
4370 return SCIP_LPERROR;
4371 }
4373 lp->resolvelperror = FALSE;
4374 nlperrors++;
4375 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4376 "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
4377 stat->nnodes, stat->nlps, nlperrors);
4378 }
4379
4380 if( pricingaborted && !(*cutoff) && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL )
4381 {
4383
4384 /* if we just ran into the time limit this is not really a numerical trouble;
4385 * however, if this is not the case, we print messages about numerical troubles in the current LP
4386 */
4387 if( !SCIPsolveIsStopped(set, stat, FALSE) )
4388 {
4389 if( forcedlpsolve )
4390 {
4391 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " cannot be dealt with\n",
4392 stat->nnodes, stat->nlps);
4393 return SCIP_LPERROR;
4394 }
4395 nlperrors++;
4396 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4397 "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- using pseudo solution instead (loop %d)\n",
4398 stat->nnodes, stat->nlps, nlperrors);
4399 }
4400 }
4401
4402 /* if an improved solution was found, propagate and solve the relaxations again */
4403 if( foundsol && !(*cutoff) )
4404 {
4405 propagateagain = TRUE;
4406 solvelpagain = TRUE;
4407 solverelaxagain = TRUE;
4408 markRelaxsUnsolved(set, relaxation);
4409 }
4410
4411 /* check for immediate restart */
4412 *restart = *restart || (actdepth == 0 && restartAllowed(set, stat) && (stat->userrestart
4413 || (stat->nrootintfixingsrun > set->presol_immrestartfac * (transprob->nvars - transprob->ncontvars)
4414 && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars))) );
4415
4416 /* enforce constraints */
4417 branched = FALSE;
4418 if( !(*postpone) && !(*restart) && !(*cutoff) && !solverelaxagain && !solvelpagain && !propagateagain )
4419 {
4420 /* if the solution changed since the last enforcement, we have to completely reenforce it; otherwise, we
4421 * only have to enforce the additional constraints added in the last enforcement, but keep the infeasible
4422 * flag TRUE in order to not declare the infeasible solution feasible due to disregarding the already
4423 * enforced constraints
4424 */
4425 if( lastdomchgcount != stat->domchgcount || lastlpcount != stat->lpcount )
4426 {
4427 lastdomchgcount = stat->domchgcount;
4428 lastlpcount = stat->lpcount;
4429 *infeasible = FALSE;
4430 }
4431
4432 /* call constraint enforcement */
4433 SCIP_CALL( enforceConstraints(blkmem, set, messagehdlr, stat, transprob, primal, tree, lp, relaxation, sepastore,
4434 branchcand, &branched, cutoff, infeasible, &propagateagain, &solvelpagain, &solverelaxagain,
4435 forcedenforcement) );
4436 assert(branched == (tree->nchildren > 0));
4437 assert(!branched || (!(*cutoff) && *infeasible && !propagateagain && !solvelpagain));
4438 assert(!(*cutoff) || (!branched && *infeasible && !propagateagain && !solvelpagain));
4439 assert(*infeasible || (!branched && !(*cutoff) && !propagateagain && !solvelpagain));
4440 assert(!propagateagain || (!branched && !(*cutoff) && *infeasible));
4441 assert(!solvelpagain || (!branched && !(*cutoff) && *infeasible));
4442
4443 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4444
4445 /* apply found cuts */
4446 SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4447 eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_LP, cutoff, &propagateagain,
4448 &solvelpagain, &solverelaxagain) );
4449
4450 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4451 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4452
4453 /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4454 updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4455 }
4456 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4457
4458 /* The enforcement detected no infeasibility, so, no branching was performed,
4459 * but the pricing was aborted and the current feasible solution does not have to be the
4460 * best solution in the current subtree --> we have to do a pseudo branching,
4461 * so we set infeasible TRUE and add the current solution to the solution pool
4462 */
4463 if( pricingaborted && !(*infeasible) && !(*cutoff) && !(*postpone) && !(*restart) )
4464 {
4465 SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
4466 SCIP_SOL* sol;
4467 SCIP_Bool stored;
4468
4469 /* in case the relaxation was enforced add this solution, otherwise decide between LP and pseudosol */
4471 || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
4472 {
4473 SCIP_SOL* relaxsol;
4474
4475 SCIP_CALL( SCIPsolCreateRelaxSol(&relaxsol, blkmem, set, stat, primal, tree, relaxation, NULL) );
4476
4477 SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4478 eventqueue, eventfilter, relaxsol, FALSE, FALSE, TRUE, TRUE, TRUE,
4479 &stored) );
4480
4481 SCIP_CALL( SCIPsolFree(&relaxsol, blkmem, primal) );
4482
4483 if( stored )
4484 {
4485 stat->nrelaxsolsfound++;
4486
4487 if( primal->nbestsolsfound != oldnbestsolsfound )
4488 {
4489 stat->nrelaxbestsolsfound++;
4491 }
4492 }
4493 }
4494 else
4495 {
4496 SCIP_CALL( SCIPsolCreateCurrentSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4497 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4498 eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
4499
4500 if( stored )
4501 {
4502 stat->nlpsolsfound++;
4503
4504 if( primal->nbestsolsfound != oldnbestsolsfound )
4505 {
4506 stat->nlpbestsolsfound++;
4508 }
4509 }
4510 }
4511
4512 *infeasible = TRUE;
4513 }
4514
4515 /* if the node is infeasible, but no constraint handler could resolve the infeasibility
4516 * -> branch on LP, external candidates, or the pseudo solution
4517 * -> e.g. select non-fixed binary or integer variable x with value x', create three
4518 * sons: x <= x'-1, x = x', and x >= x'+1.
4519 * In the left and right branch, the current solution is cut off. In the middle
4520 * branch, the constraints can hopefully reduce domains of other variables to cut
4521 * off the current solution.
4522 * In LP branching, we cannot allow adding constraints, because this does not necessary change the LP and can
4523 * therefore lead to an infinite loop.
4524 */
4525 wasforcedlpsolve = forcedlpsolve;
4526 forcedlpsolve = FALSE;
4527 if( (*infeasible) && !(*cutoff) && !(*postpone) && !(*restart)
4528 && (!(*unbounded) || SCIPbranchcandGetNExternCands(branchcand) > 0 || SCIPbranchcandGetNPseudoCands(branchcand) > 0)
4529 && !solverelaxagain && !solvelpagain && !propagateagain && !branched )
4530 {
4531 SCIP_RESULT result = SCIP_DIDNOTRUN;
4532 int nlpcands = 0;
4533
4534 if( SCIPtreeHasFocusNodeLP(tree) )
4535 {
4536 SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nlpcands, NULL, NULL) );
4537 }
4538
4539 if ( nlpcands > 0 || SCIPbranchcandGetNExternCands(branchcand) > 0 )
4540 {
4541 /* If there are LP candidates and their maximal priority is at least the maximal priority of the external
4542 * candidates, then branch on the LP candidates. Note that due to implicit integer variables,
4543 * SCIPbranchcandGetLPMaxPrio(branchcand) might be finite and SCIPbranchcandGetNPrioLPCands(branchcand) > 0,
4544 * but nlpcands == 0. */
4545 if ( SCIPbranchcandGetLPMaxPrio(branchcand) >= SCIPbranchcandGetExternMaxPrio(branchcand) && nlpcands > 0 )
4546 {
4547 assert( SCIPbranchcandGetNPrioLPCands(branchcand) > 0 );
4548 assert( nlpcands > 0 );
4549
4550 /* branch on LP solution */
4551 SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on LP solution with %d fractionals\n",
4552 SCIPnodeGetDepth(focusnode), nlpcands);
4553 SCIP_CALL( SCIPbranchExecLP(blkmem, set, stat, transprob, origprob, tree, reopt, lp, sepastore, branchcand,
4554 eventqueue, primal->cutoffbound, FALSE, &result) );
4555 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4556 assert(result != SCIP_DIDNOTRUN && result != SCIP_DIDNOTFIND);
4557 }
4558 else
4559 {
4560 assert( SCIPbranchcandGetNPrioExternCands(branchcand) > 0 );
4561 assert( SCIPbranchcandGetNExternCands(branchcand) > 0 );
4562
4563 /* branch on external candidates */
4564 SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on %d external branching candidates.\n",
4565 SCIPnodeGetDepth(focusnode), SCIPbranchcandGetNExternCands(branchcand));
4566 SCIP_CALL( SCIPbranchExecExtern(blkmem, set, stat, transprob, origprob, tree, reopt, lp, sepastore, branchcand,
4567 eventqueue, primal->cutoffbound, TRUE, &result) );
4568 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4569 }
4570 }
4571
4572 if( result == SCIP_DIDNOTRUN || result == SCIP_DIDNOTFIND )
4573 {
4574 /* branch on pseudo solution */
4575 SCIPsetDebugMsg(set, "infeasibility in depth %d was not resolved: branch on pseudo solution with %d unfixed integers\n",
4576 SCIPnodeGetDepth(focusnode), SCIPbranchcandGetNPseudoCands(branchcand));
4577 SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
4578 primal->cutoffbound, TRUE, &result) );
4579 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
4580 }
4581
4582 /* SCIP cannot guarantee convergence if it is necessary to branch on unbounded variables */
4583 if( result == SCIP_BRANCHED )
4584 {
4585 SCIP_VAR* var = stat->lastbranchvar;
4586
4587 if( var != NULL && !stat->branchedunbdvar && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS
4589 {
4590 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_NORMAL,
4591 "Starting spatial branch-and-bound on unbounded variable <%s> ([%g,%g]) - cannot guarantee finite termination.\n",
4593 stat->branchedunbdvar = TRUE;
4594 }
4595 }
4596
4597 switch( result )
4598 {
4599 case SCIP_CUTOFF:
4600 assert(tree->nchildren == 0);
4601 *cutoff = TRUE;
4602 SCIPsetDebugMsg(set, " -> branching rule detected cutoff\n");
4603 break;
4604 case SCIP_CONSADDED:
4605 assert(tree->nchildren == 0);
4606 if( nlpcands > 0 )
4607 {
4608 SCIPerrorMessage("LP branching rule added constraint, which was not allowed this time\n");
4609 return SCIP_INVALIDRESULT;
4610 }
4611 propagateagain = TRUE;
4612 solvelpagain = TRUE;
4613 solverelaxagain = TRUE;
4614 markRelaxsUnsolved(set, relaxation);
4615 break;
4616 case SCIP_REDUCEDDOM:
4617 assert(tree->nchildren == 0);
4618 propagateagain = TRUE;
4619 solvelpagain = TRUE;
4620 solverelaxagain = TRUE;
4621 markRelaxsUnsolved(set, relaxation);
4622 break;
4623 case SCIP_SEPARATED:
4624 assert(tree->nchildren == 0);
4625 assert(SCIPsepastoreGetNCuts(sepastore) > 0);
4626 solvelpagain = TRUE;
4627 solverelaxagain = TRUE;
4628 markRelaxsUnsolved(set, relaxation);
4629 break;
4630 case SCIP_BRANCHED:
4631 assert(tree->nchildren >= 1);
4632 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4633 branched = TRUE;
4634
4635 /* increase the number of internal nodes */
4636 stat->ninternalnodes++;
4637 stat->ntotalinternalnodes++;
4638 break;
4639 case SCIP_DIDNOTFIND: /*lint -fallthrough*/
4640 case SCIP_DIDNOTRUN:
4641 /* all integer variables in the infeasible solution are fixed,
4642 * - if no continuous variables exist and all variables are known, the infeasible pseudo solution is completely
4643 * fixed, and the node can be cut off
4644 * - if at least one continuous variable exists or we do not know all variables due to external pricers, we
4645 * cannot resolve the infeasibility by branching -> solve LP (and maybe price in additional variables)
4646 */
4647 assert(tree->nchildren == 0);
4648 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4649 assert(SCIPbranchcandGetNPseudoCands(branchcand) == 0);
4650
4651 if( transprob->ncontvars == 0 && set->nactivepricers == 0 )
4652 {
4653 *cutoff = TRUE;
4654 SCIPsetDebugMsg(set, " -> cutoff because all variables are fixed in current node\n");
4655 }
4656 else
4657 {
4658 /* feasible LP solutions with all integers fixed must be feasible
4659 * if also no external branching candidates were available
4660 */
4661 assert(!SCIPtreeHasFocusNodeLP(tree) || pricingaborted);
4662
4664 {
4665 SCIP_NODE* node;
4666
4667 /* as we hit the time or iteration limit or another interrupt (e.g., gap limit), we do not want to solve the LP again.
4668 * in order to terminate correctly, we create a "branching" with only one child node
4669 * that is a copy of the focusnode
4670 */
4671 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, 1.0, focusnode->estimate) );
4672 assert(tree->nchildren >= 1);
4673 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4674 branched = TRUE;
4675 }
4676 else
4677 {
4678 SCIP_VERBLEVEL verblevel;
4679
4680 if( pricingaborted )
4681 {
4682 SCIPerrorMessage("pricing was aborted, but no branching could be created!\n");
4683 return SCIP_INVALIDRESULT;
4684 }
4685
4686 if( wasforcedlpsolve )
4687 {
4688 assert(SCIPtreeHasFocusNodeLP(tree));
4689 SCIPerrorMessage("LP was solved, all integers fixed, some constraint still infeasible, but no branching could be created!\n");
4690 return SCIP_INVALIDRESULT;
4691 }
4692
4693 verblevel = SCIP_VERBLEVEL_FULL;
4694
4695 if( !tree->forcinglpmessage && set->disp_verblevel == SCIP_VERBLEVEL_HIGH )
4696 {
4697 verblevel = SCIP_VERBLEVEL_HIGH;
4698
4699 /* remember that the forcing LP solving message was posted and do only post it again if the
4700 * verblevel is SCIP_VERBLEVEL_FULL
4701 */
4702 tree->forcinglpmessage = TRUE;
4703 }
4704
4705 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, verblevel,
4706 "(node %" SCIP_LONGINT_FORMAT ") forcing the solution of an LP (last LP %" SCIP_LONGINT_FORMAT ")...\n", stat->nnodes, stat->nlps);
4707
4708 /* solve the LP in the next loop */
4710 solvelpagain = TRUE;
4711 forcedlpsolve = TRUE; /* this LP must be solved without error - otherwise we have to abort */
4712 }
4713 }
4714 break;
4715 default:
4716 SCIPerrorMessage("invalid result code <%d> from SCIPbranchLP(), SCIPbranchExt() or SCIPbranchPseudo()\n", result);
4717 return SCIP_INVALIDRESULT;
4718 } /*lint !e788*/
4719 assert(*cutoff || solvelpagain || propagateagain || branched); /* something must have been done */
4720 assert(!(*cutoff) || (!solvelpagain && !propagateagain && !branched));
4721 assert(!solvelpagain || (!(*cutoff) && !branched));
4722 assert(!propagateagain || (!(*cutoff) && !branched));
4723 assert(!branched || (!solvelpagain && !propagateagain));
4724 assert(branched == (tree->nchildren > 0));
4725
4726 /* apply found cuts */
4727 SCIP_CALL( applyCuts(blkmem, set, stat, transprob, origprob, tree, reopt, lp, relaxation, sepastore, branchcand,
4728 eventqueue, eventfilter, cliquetable, (actdepth == 0), SCIP_EFFICIACYCHOICE_LP, cutoff, &propagateagain,
4729 &solvelpagain, &solverelaxagain) );
4730
4731 /* update lower bound with the pseudo objective value, and cut off node by bounding */
4732 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, cutoff) );
4733
4734 /* update the cutoff, propagateagain, and solverelaxagain status of current solving loop */
4735 updateLoopStatus(set, stat, tree, actdepth, cutoff, &propagateagain, &solverelaxagain);
4736 }
4737
4738 /* check for immediate restart */
4739 *restart = *restart || (actdepth == 0 && restartAllowed(set, stat) && (stat->userrestart
4740 || (stat->nrootintfixingsrun > set->presol_immrestartfac * (transprob->nvars - transprob->ncontvars)
4741 && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars))) );
4742
4743 SCIPsetDebugMsg(set, "node solving iteration %d finished: cutoff=%u, postpone=%u, propagateagain=%u, solverelaxagain=%u, solvelpagain=%u, nlperrors=%d, restart=%u\n",
4744 nloops, *cutoff, *postpone, propagateagain, solverelaxagain, solvelpagain, nlperrors, *restart);
4745 }
4746 assert(SCIPsepastoreGetNCuts(sepastore) == 0);
4747 assert(*cutoff || SCIPconflictGetNConflicts(conflict) == 0);
4748
4749 /* flush the conflict set storage */
4750 SCIP_CALL( SCIPconflictFlushConss(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cliquetable) );
4751
4752 /* check for too many LP errors */
4753 if( nlperrors >= MAXNLPERRORS )
4754 {
4755 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- aborting\n", stat->nnodes, stat->nlps);
4756 return SCIP_LPERROR;
4757 }
4758
4759 /* check for final restart */
4760 restartfac = set->presol_subrestartfac;
4761 if( actdepth == 0 )
4762 restartfac = MIN(restartfac, set->presol_restartfac);
4763 *restart = *restart || (restartAllowed(set, stat) && (stat->userrestart
4764 || (stat->nrootintfixingsrun > restartfac * (transprob->nvars - transprob->ncontvars)
4765 && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars))) );
4766
4767 /* remember the last root LP solution */
4768 if( actdepth == 0 && !(*cutoff) && !(*unbounded) && !(*postpone) )
4769 {
4770 /* the root pseudo objective value and pseudo objective value should be equal in the root node */
4771 assert(SCIPsetIsRelEQ(set, SCIPlpGetGlobalPseudoObjval(lp, set, transprob), SCIPlpGetPseudoObjval(lp, set, transprob)));
4772
4773 SCIPprobStoreRootSol(transprob, set, stat, lp, SCIPtreeHasFocusNodeLP(tree));
4774 }
4775
4776 /* check for cutoff */
4777 if( *cutoff )
4778 {
4779 SCIP_CALL( SCIPnodeCutoff(focusnode, set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
4780
4781 /* the LP might have been unbounded but not enforced, because the node is cut off anyway */
4782 *unbounded = FALSE;
4783 *infeasible = TRUE;
4784 }
4785 else if( !(*unbounded) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && lp->looseobjvalinf == 0 )
4786 {
4787 /* update the regression statistic nlpbranchcands and LP objective value */
4788 int nlpbranchcands;
4789 SCIP_Real lpobjval;
4790
4791 /* get number of LP candidate variables */
4792 SCIP_CALL( SCIPbranchcandGetLPCands(branchcand, set, stat, lp, NULL, NULL, NULL, &nlpbranchcands, NULL, NULL) );
4793
4794 /* get LP objective value */
4795 lpobjval = SCIPlpGetObjval(lp, set, transprob);
4796 assert(lpobjval != SCIP_INVALID); /*lint !e777*/
4797
4798 /* add the observation to the regression */
4799 SCIPregressionAddObservation(stat->regressioncandsobjval, (SCIP_Real)nlpbranchcands, lpobjval);
4800 }
4801
4802 /* reset LP feastol to normal value, in case someone tightened it during node solving */
4804
4805 return SCIP_OKAY;
4806}
4807
4808/** if feasible, adds current solution to the solution storage */
4809static
4811 BMS_BLKMEM* blkmem, /**< block memory buffers */
4812 SCIP_SET* set, /**< global SCIP settings */
4813 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4814 SCIP_STAT* stat, /**< dynamic problem statistics */
4815 SCIP_PROB* origprob, /**< original problem */
4816 SCIP_PROB* transprob, /**< transformed problem after presolve */
4817 SCIP_PRIMAL* primal, /**< primal data */
4818 SCIP_RELAXATION* relaxation, /**< global relaxation data */
4819 SCIP_TREE* tree, /**< branch and bound tree */
4820 SCIP_REOPT* reopt, /**< reoptimization data structure */
4821 SCIP_LP* lp, /**< LP data */
4822 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4823 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4824 SCIP_Bool checksol /**< should the solution be checked? */
4825 )
4826{
4827 SCIP_Longint oldnbestsolsfound = primal->nbestsolsfound;
4828 SCIP_SOL* sol;
4829 SCIP_Bool foundsol;
4830
4831 /* found a feasible solution */
4833 || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
4834 {
4835 /* start clock for relaxation solutions */
4837
4838 SCIP_CALL( SCIPsolCreateRelaxSol(&sol, blkmem, set, stat, primal, tree, relaxation, NULL) );
4839
4840 SCIPsetDebugMsg(set, "found relaxation solution with objective %f\n", SCIPsolGetObj(sol, set, transprob, origprob));
4841
4842 if( checksol || set->misc_exactsolve )
4843 {
4844 /* if we want to solve exactly, we have to check the solution exactly again */
4845 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4846 eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &foundsol) );
4847 }
4848 else
4849 {
4850 SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4851 eventqueue, eventfilter, &sol, &foundsol) );
4852 }
4853
4854 if( foundsol )
4855 {
4856 stat->nrelaxsolsfound++;
4857
4858 if( primal->nbestsolsfound != oldnbestsolsfound )
4859 {
4860 stat->nrelaxbestsolsfound++;
4862 }
4863 }
4864
4865 /* stop clock for relaxation solutions */
4867 }
4868 else if( SCIPtreeHasFocusNodeLP(tree) )
4869 {
4870 assert(lp->primalfeasible);
4871
4872 /* start clock for LP solutions */
4874
4875 /* add solution to storage */
4876 SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4877
4878 SCIPsetDebugMsg(set, "found lp solution with objective %f\n", SCIPsolGetObj(sol, set, transprob, origprob));
4879
4880 if( checksol || set->misc_exactsolve )
4881 {
4882 /* if we want to solve exactly, we have to check the solution exactly again */
4883 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4884 eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &foundsol) );
4885 }
4886 else
4887 {
4888 SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4889 eventqueue, eventfilter, &sol, &foundsol) );
4890 }
4891
4892 if( foundsol )
4893 {
4894 stat->nlpsolsfound++;
4895
4896 if( primal->nbestsolsfound != oldnbestsolsfound )
4897 {
4898 stat->nlpbestsolsfound++;
4900 }
4901 }
4902
4903 /* stop clock for LP solutions */
4904 SCIPclockStop(stat->lpsoltime, set);
4905 }
4906 else
4907 {
4908 /* start clock for pseudo solutions */
4910
4911 /* add solution to storage */
4912 SCIP_CALL( SCIPsolCreatePseudoSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
4913
4914 SCIPsetDebugMsg(set, "found pseudo solution with objective %f\n", SCIPsolGetObj(sol, set, transprob, origprob));
4915
4916 if( checksol || set->misc_exactsolve )
4917 {
4918 /* if we want to solve exactly, we have to check the solution exactly again */
4919 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4920 eventqueue, eventfilter, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &foundsol) );
4921 }
4922 else
4923 {
4924 SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt, lp,
4925 eventqueue, eventfilter, &sol, &foundsol) );
4926 }
4927
4928 /* stop clock for pseudo solutions */
4930
4931 if( foundsol )
4932 {
4933 stat->npssolsfound++;
4934
4935 if( primal->nbestsolsfound != oldnbestsolsfound )
4936 {
4937 stat->npsbestsolsfound++;
4939 }
4940 }
4941 }
4942
4943 return SCIP_OKAY;
4944}
4945
4946/** main solving loop */
4948 BMS_BLKMEM* blkmem, /**< block memory buffers */
4949 SCIP_SET* set, /**< global SCIP settings */
4950 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4951 SCIP_STAT* stat, /**< dynamic problem statistics */
4952 SCIP_MEM* mem, /**< block memory pools */
4953 SCIP_PROB* origprob, /**< original problem */
4954 SCIP_PROB* transprob, /**< transformed problem after presolve */
4955 SCIP_PRIMAL* primal, /**< primal data */
4956 SCIP_TREE* tree, /**< branch and bound tree */
4957 SCIP_REOPT* reopt, /**< reoptimization data structure */
4958 SCIP_LP* lp, /**< LP data */
4959 SCIP_RELAXATION* relaxation, /**< global relaxation data */
4960 SCIP_PRICESTORE* pricestore, /**< pricing storage */
4961 SCIP_SEPASTORE* sepastore, /**< separation storage */
4962 SCIP_CUTPOOL* cutpool, /**< global cut pool */
4963 SCIP_CUTPOOL* delayedcutpool, /**< global delayed cut pool */
4964 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4965 SCIP_CONFLICT* conflict, /**< conflict analysis data */
4966 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
4967 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4968 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4969 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4970 SCIP_Bool* restart /**< should solving process be started again with presolving? */
4971 )
4972{
4973 SCIP_NODESEL* nodesel;
4974 SCIP_NODE* focusnode;
4975 SCIP_NODE* nextnode;
4976 SCIP_EVENT event;
4977 SCIP_Real restartfac;
4978 SCIP_Real restartconfnum;
4979 int nnodes;
4980 int depth;
4981 SCIP_Bool cutoff;
4982 SCIP_Bool postpone;
4983 SCIP_Bool unbounded;
4984 SCIP_Bool infeasible;
4985 SCIP_Bool foundsol;
4986
4987 assert(set != NULL);
4988 assert(blkmem != NULL);
4989 assert(stat != NULL);
4990 assert(transprob != NULL);
4991 assert(tree != NULL);
4992 assert(lp != NULL);
4993 assert(pricestore != NULL);
4994 assert(sepastore != NULL);
4995 assert(branchcand != NULL);
4996 assert(cutpool != NULL);
4997 assert(delayedcutpool != NULL);
4998 assert(primal != NULL);
4999 assert(eventfilter != NULL);
5000 assert(eventqueue != NULL);
5001 assert(restart != NULL);
5002
5003 /* check for immediate restart (if problem solving marked to be restarted was aborted) */
5004 restartfac = set->presol_subrestartfac;
5005 if( SCIPtreeGetCurrentDepth(tree) == 0 )
5006 restartfac = MIN(restartfac, set->presol_restartfac);
5007 *restart = restartAllowed(set, stat) && (stat->userrestart
5008 || (stat->nrootintfixingsrun > restartfac * (transprob->nvars - transprob->ncontvars)
5009 && (stat->nruns == 1 || transprob->nvars <= (1.0-set->presol_restartminred) * stat->prevrunnvars)) );
5010
5011 /* calculate the number of successful conflict analysis calls that should trigger a restart */
5012 if( set->conf_restartnum > 0 )
5013 {
5014 int i;
5015
5016 restartconfnum = (SCIP_Real)set->conf_restartnum;
5017 for( i = 0; i < stat->nconfrestarts; ++i )
5018 restartconfnum *= set->conf_restartfac;
5019 }
5020 else
5021 restartconfnum = SCIP_REAL_MAX;
5022 assert(restartconfnum >= 0.0);
5023
5024 /* switch status to UNKNOWN */
5026
5027 focusnode = NULL;
5028 nextnode = NULL;
5029 unbounded = FALSE;
5030 postpone = FALSE;
5031
5032 while( !SCIPsolveIsStopped(set, stat, TRUE) && !(*restart) )
5033 {
5034 SCIP_Longint nsuccessconflicts;
5035 SCIP_Bool afternodeheur;
5036 SCIP_Bool stopped;
5037 SCIP_Bool branched;
5038
5039 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5040
5041 foundsol = FALSE;
5042 infeasible = FALSE;
5043
5044 do
5045 {
5046 /* update the memory saving flag, switch algorithms respectively */
5047 SCIPstatUpdateMemsaveMode(stat, set, messagehdlr, mem);
5048
5049 /* get the current node selector */
5050 nodesel = SCIPsetGetNodesel(set, stat);
5051
5052 /* inform tree about the current node selector */
5053 SCIP_CALL( SCIPtreeSetNodesel(tree, set, messagehdlr, stat, nodesel) );
5054
5055 /* the next node was usually already selected in the previous solving loop before the primal heuristics were
5056 * called, because they need to know, if the next node will be a child/sibling (plunging) or not;
5057 * if the heuristics found a new best solution that cut off some of the nodes, the node selector must be called
5058 * again, because the selected next node may be invalid due to cut off
5059 */
5060 if( nextnode == NULL )
5061 {
5062 /* select next node to process */
5063 SCIP_CALL( SCIPnodeselSelect(nodesel, set, &nextnode) );
5064 }
5065 focusnode = nextnode;
5066 nextnode = NULL;
5067 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5068
5069 /* start node activation timer */
5071
5072 /* focus selected node */
5073 SCIP_CALL( SCIPnodeFocus(&focusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt,
5074 lp, branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, FALSE, FALSE) );
5075 if( cutoff )
5076 stat->ndelayedcutoffs++;
5077
5078 /* stop node activation timer */
5080
5081 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5082 }
5083 while( cutoff ); /* select new node, if the current one was located in a cut off subtree */
5084
5085 assert(SCIPtreeGetCurrentNode(tree) == focusnode);
5086 assert(SCIPtreeGetFocusNode(tree) == focusnode);
5087
5088 /* if no more node was selected, we finished optimization */
5089 if( focusnode == NULL )
5090 {
5091 assert(SCIPtreeGetNNodes(tree) == 0);
5092 break;
5093 }
5094
5095 /* update maxdepth and node count statistics */
5096 depth = SCIPnodeGetDepth(focusnode);
5097 stat->maxdepth = MAX(stat->maxdepth, depth);
5098 stat->maxtotaldepth = MAX(stat->maxtotaldepth, depth);
5099 stat->nnodes++;
5100 stat->ntotalnodes++;
5101
5102 /* update reference bound statistic, if available */
5103 if( SCIPsetIsGE(set, SCIPnodeGetLowerbound(focusnode), stat->referencebound) )
5104 stat->nnodesaboverefbound++;
5105
5106 /* issue NODEFOCUSED event */
5108 SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
5109 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
5110
5111 /* solve focus node */
5112 SCIP_CALL( solveNode(blkmem, set, messagehdlr, stat, mem, origprob, transprob, primal, tree, reopt, lp, relaxation,
5113 pricestore, sepastore, branchcand, cutpool, delayedcutpool, conflict, conflictstore, eventfilter, eventqueue,
5114 cliquetable, &cutoff, &postpone, &unbounded, &infeasible, restart, &afternodeheur, &stopped) );
5115 assert(!cutoff || infeasible);
5116 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5117 assert(SCIPtreeGetCurrentNode(tree) == focusnode);
5118 assert(SCIPtreeGetFocusNode(tree) == focusnode);
5119
5120 branched = (tree->nchildren > 0);
5121
5122 if( stopped )
5123 break;
5124
5125 /* check for restart */
5126 if( !(*restart) && !postpone )
5127 {
5128 /* change color of node in visualization */
5129 SCIPvisualSolvedNode(stat->visual, set, stat, focusnode);
5130
5131 /* check, if the current solution is feasible */
5132 if( !infeasible )
5133 {
5134 SCIP_Bool feasible;
5135
5136 assert(!SCIPtreeHasFocusNodeLP(tree) || (lp->flushed && lp->solved));
5137 assert(!cutoff);
5138
5139 /* in the unbounded case, we check the solution w.r.t. the original problem, because we do not want to rely
5140 * on the LP feasibility and integrality is not checked for unbounded solutions, anyway
5141 */
5142 if( unbounded )
5143 {
5144 SCIP_SOL* sol;
5145
5147 || SCIPsetIsGT(set, SCIPrelaxationGetSolObj(relaxation), SCIPlpGetObjval(lp, set, transprob))) )
5148 {
5149 SCIP_CALL( SCIPsolCreateRelaxSol(&sol, blkmem, set, stat, primal, tree, relaxation, NULL) );
5150 }
5151 else if( SCIPtreeHasFocusNodeLP(tree) )
5152 {
5153 SCIP_CALL( SCIPsolCreateLPSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
5154 }
5155 else
5156 {
5157 SCIP_CALL( SCIPsolCreatePseudoSol(&sol, blkmem, set, stat, transprob, primal, tree, lp, NULL) );
5158 }
5159 SCIP_CALL( SCIPcheckSolOrig(set->scip, sol, &feasible, FALSE, FALSE) );
5160
5161 SCIP_CALL( SCIPsolFree(&sol, blkmem, primal) );
5162 }
5163 else
5164 feasible = TRUE;
5165
5166 /* node solution is feasible: add it to the solution store */
5167 if( feasible )
5168 {
5169 SCIP_CALL( addCurrentSolution(blkmem, set, messagehdlr, stat, origprob, transprob, primal, relaxation, tree, reopt,
5170 lp, eventqueue, eventfilter, FALSE) );
5171
5172 /* issue NODEFEASIBLE event */
5174 SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
5175 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
5176
5177
5178 /* update the cutoff pointer if the new solution made the cutoff bound equal to the lower bound */
5179 SCIP_CALL( applyBounding(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue, conflict, cliquetable, &cutoff) );
5180
5181 /* increment number of feasible leaf nodes */
5182 stat->nfeasleaves++;
5183
5184
5185 if( set->reopt_enable )
5186 {
5187 assert(reopt != NULL);
5188 SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEFEASIBLE, lp,
5189 SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
5190 focusnode->lowerbound, tree->effectiverootdepth) );
5191 }
5192 }
5193 }
5194 else if( !unbounded || branched )
5195 {
5196 /* node solution is not feasible */
5197 if( !branched )
5198 {
5199 assert(tree->nchildren == 0);
5200
5201 /* change color of node in visualization output */
5202 SCIPvisualCutoffNode(stat->visual, set, stat, focusnode, TRUE);
5203
5204 /* issue NODEINFEASIBLE event */
5206
5207 /* we only increase the number of objective leaf nodes if we hit the LP objective limit; we might have also
5208 * hit the objective limit at a node that is actually infeasible, or a dual reduction led to an infeasibility prior
5209 * to LP solving such that the node will be marked as infeasible */
5211 stat->nobjleaves++;
5212 else
5213 stat->ninfeasleaves++;
5214
5215 if( set->reopt_enable )
5216 {
5217 assert(reopt != NULL);
5218 SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEINFEASIBLE, lp,
5219 SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
5220 focusnode->lowerbound, tree->effectiverootdepth) );
5221 }
5222
5223 /* increase the cutoff counter of the branching variable */
5224 if( stat->lastbranchvar != NULL )
5225 {
5226 SCIP_CALL( SCIPvarIncCutoffSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
5227 }
5228 /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
5229 }
5230 else
5231 {
5232 assert(tree->nchildren > 0);
5233
5234 /* issue NODEBRANCHED event */
5236
5237 if( set->reopt_enable )
5238 {
5239 assert(reopt != NULL);
5240 SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEBRANCHED, lp,
5241 SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode,
5242 focusnode->lowerbound, tree->effectiverootdepth) );
5243 }
5244 }
5245 SCIP_CALL( SCIPeventChgNode(&event, focusnode) );
5246 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
5247 }
5248 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5249
5250 /* if no branching was created, the node was not cut off, but its lower bound is still smaller than
5251 * the cutoff bound, we have to branch on a non-fixed variable;
5252 * this can happen, if we want to solve exactly, the current solution was declared feasible by the
5253 * constraint enforcement, but in exact solution checking it was found out to be infeasible;
5254 * in this case, no branching would have been generated by the enforcement of constraints, but we
5255 * have to further investigate the current sub tree;
5256 * note that we must not check tree->nchildren > 0 here to determine whether we branched, we rather
5257 * check it directly after solveNode() and store the result, because an event handler might impose a
5258 * new cutoff bound (as is the case in ParaSCIP)
5259 */
5260 if( !cutoff && !unbounded && !branched && SCIPnodeGetLowerbound(focusnode) < primal->cutoffbound )
5261 {
5262 SCIP_RESULT result;
5263
5264 assert(set->misc_exactsolve);
5265
5266 do
5267 {
5268 result = SCIP_DIDNOTRUN;
5269 if( SCIPbranchcandGetNPseudoCands(branchcand) == 0 )
5270 {
5271 if( transprob->ncontvars > 0 )
5272 {
5273 /**@todo call PerPlex */
5274 SCIPerrorMessage("cannot branch on all-fixed LP -- have to call PerPlex instead\n");
5275 }
5276 }
5277 else
5278 {
5279 SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
5280 eventqueue, primal->cutoffbound, FALSE, &result) );
5281 assert(result != SCIP_DIDNOTRUN && result != SCIP_DIDNOTFIND);
5282 }
5283 }
5284 while( result == SCIP_REDUCEDDOM );
5285 }
5286 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5287
5288 /* select node to process in next solving loop; the primal heuristics need to know whether a child/sibling
5289 * (plunging) will be selected as next node or not
5290 */
5291 SCIP_CALL( SCIPnodeselSelect(nodesel, set, &nextnode) );
5292 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5293
5294 /* call primal heuristics that should be applied after the node was solved */
5295 nnodes = SCIPtreeGetNNodes(tree);
5296 stopped = SCIPsolveIsStopped(set, stat, FALSE);
5297 if( !afternodeheur && (!cutoff || nnodes > 0) && !stopped )
5298 {
5299 SCIP_CALL( SCIPprimalHeuristics(set, stat, transprob, primal, tree, lp, nextnode, SCIP_HEURTIMING_AFTERNODE,
5300 cutoff, &foundsol, &unbounded) );
5301 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5302
5303 stopped = SCIPsolveIsStopped(set, stat, FALSE);
5304 }
5305
5306 /* if the heuristics found a new best solution that cut off some of the nodes, the node selector must be called
5307 * again, because the selected next node may be invalid due to cut off
5308 */
5309 assert(!tree->cutoffdelayed);
5310
5311 if( nnodes != SCIPtreeGetNNodes(tree) || stopped )
5312 nextnode = NULL;
5313 }
5314 else if( !infeasible && !postpone )
5315 {
5316 /* The current solution was not proven to be infeasible, but due to the restart, this does not mean that it is
5317 * feasible, we might just have skipped the check. Thus, we try to add it to the solution store, but check it
5318 * again.
5319 */
5320 SCIP_CALL( addCurrentSolution(blkmem, set, messagehdlr, stat, origprob, transprob, primal, relaxation, tree, reopt, lp,
5321 eventqueue, eventfilter, TRUE) );
5322
5323 if( set->reopt_enable )
5324 {
5325 assert(reopt != NULL);
5326 SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, focusnode, SCIP_EVENTTYPE_NODEFEASIBLE, lp,
5327 SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode, focusnode->lowerbound,
5328 tree->effectiverootdepth) );
5329 }
5330 }
5331 /* we want to put the focusnode back into the leaf queue if it was postponed */
5332 else if( postpone )
5333 {
5334 SCIP_NODE* newfocusnode = NULL;
5335
5336 /* @todo should we re-install the old focus node in order to somehow set the forks more clever? */
5337 SCIP_CALL( SCIPnodeFocus(&newfocusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
5338 branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, TRUE, FALSE) );
5339 }
5340 /* compute number of successfully applied conflicts */
5341 nsuccessconflicts = SCIPconflictGetNPropSuccess(conflict) + SCIPconflictGetNInfeasibleLPSuccess(conflict)
5344
5345 /* trigger restart due to conflicts and the restart parameters allow another restart */
5346 if( nsuccessconflicts >= restartconfnum && restartAllowed(set, stat) )
5347 {
5348 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
5349 "(run %d, node %" SCIP_LONGINT_FORMAT ") restarting after %" SCIP_LONGINT_FORMAT " successful conflict analysis calls\n",
5350 stat->nruns, stat->nnodes, nsuccessconflicts);
5351 *restart = TRUE;
5352
5353 stat->nconfrestarts++;
5354 }
5355
5356 /* restart if the userrestart was set to true, we have still some nodes left and the restart parameters allow
5357 * another restart
5358 */
5359 *restart = *restart || (stat->userrestart && SCIPtreeGetNNodes(tree) > 0 && restartAllowed(set, stat));
5360 if( restartAllowed(set, stat) && set->limit_autorestartnodes == stat->nnodes && stat->ntotalnodes - stat->nruns + 1 == set->limit_autorestartnodes )
5361 {
5362 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
5363 "(run %d, node %" SCIP_LONGINT_FORMAT ") restarting: triggering parameter controlled restart)\n",
5364 stat->nruns, stat->nnodes);
5365 *restart = TRUE;
5366 }
5367 /* if restart limit was exceeded, change the status; if status is different from unknown, ie some other limit was
5368 * hit, leave it unchanged
5369 */
5370 if( *restart && stat->status == SCIP_STATUS_UNKNOWN && set->limit_restarts >= 0 && stat->nruns > set->limit_restarts )
5371 {
5372 *restart = FALSE;
5374 }
5375
5376 /* display node information line */
5377 SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, (SCIPnodeGetDepth(focusnode) == 0) && infeasible && !foundsol, TRUE) );
5378
5379 SCIPsetDebugMsg(set, "Processing of node %" SCIP_LONGINT_FORMAT " in depth %d finished. %d siblings, %d children, %d leaves left\n",
5380 stat->nnodes, SCIPnodeGetDepth(focusnode), tree->nsiblings, tree->nchildren, SCIPtreeGetNLeaves(tree));
5381 SCIPsetDebugMsg(set, "**********************************************************************\n");
5382 }
5383
5384 /* update the primal-dual integral if node or time limits were hit or an interruption signal was called */
5385 if( SCIPsolveIsStopped(set, stat, TRUE) )
5386 {
5388 }
5389
5390 assert(BMSgetNUsedBufferMemory(mem->buffer) == 0);
5391
5392 SCIPsetDebugMsg(set, "Problem solving finished with status %d (restart=%u, userrestart=%u)\n", stat->status, *restart, stat->userrestart);
5393
5394 /* cuts off nodes with lower bound is not better than given cutoff bound, manually; this necessary to ensure that
5395 * SCIP terminates with a proper solve stage
5396 */
5397 SCIP_CALL( SCIPtreeCutoff(tree, reopt, blkmem, set, stat, eventfilter, eventqueue, lp, primal->cutoffbound) );
5398
5399 /* if the current node is the only remaining node, and if its lower bound exceeds the upper bound, we have
5400 * to delete it manually in order to get to the SOLVED stage instead of thinking, that only the gap limit
5401 * was reached (this may happen, if the current node is the one defining the global lower bound and a
5402 * feasible solution with the same value was found at this node)
5403 */
5404 if( tree->focusnode != NULL && SCIPtreeGetNNodes(tree) == 0
5405 && SCIPsetIsGE(set, tree->focusnode->lowerbound, primal->cutoffbound) )
5406 {
5407 if( set->reopt_enable )
5408 {
5409 assert(reopt != NULL);
5411 SCIPlpGetSolstat(lp), tree->root == focusnode, tree->focusnode == focusnode, tree->focusnode->lowerbound,
5412 tree->effectiverootdepth) );
5413 }
5414
5415 focusnode = NULL;
5416 SCIP_CALL( SCIPnodeFocus(&focusnode, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp,
5417 branchcand, conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, FALSE, FALSE) );
5418 }
5419
5420 /* check whether we finished solving */
5421 if( SCIPtreeGetNNodes(tree) == 0 && SCIPtreeGetCurrentNode(tree) == NULL )
5422 {
5423 /* no restart necessary */
5424 *restart = FALSE;
5425
5426 /* set the solution status */
5427 if( unbounded || SCIPsetIsInfinity(set, -SCIPgetUpperbound(set->scip)) )
5428 {
5429 if( primal->nsols > 0 )
5430 {
5431 /* switch status to UNBOUNDED */
5433 }
5434 else
5435 {
5436 /* switch status to INFORUNB */
5438 }
5439 }
5440 else if( primal->nlimsolsfound == 0 )
5441 {
5442 assert(primal->nsols == 0 || SCIPsetIsGT(set, SCIPsolGetObj(primal->sols[0], set, transprob, origprob),
5443 SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(transprob, set))));
5444
5445 /* switch status to INFEASIBLE */
5447 }
5448 else
5449 {
5450 /* switch status to OPTIMAL */
5452 }
5453 }
5454
5455 return SCIP_OKAY;
5456}
SCIP_RETCODE SCIPbranchcandGetLPCands(SCIP_BRANCHCAND *branchcand, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: branch.c:405
int SCIPbranchcandGetNExternCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:507
SCIP_RETCODE SCIPbranchExecPseudo(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:2769
int SCIPbranchcandGetNPrioExternCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:517
void SCIPbranchcandClearExternCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:697
int SCIPbranchcandGetExternMaxPrio(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:497
int SCIPbranchcandGetNPseudoCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:852
int SCIPbranchcandGetNPrioLPCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:487
SCIP_RETCODE SCIPbranchExecExtern(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:2638
SCIP_RETCODE SCIPbranchExecLP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:2536
int SCIPbranchcandGetLPMaxPrio(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:477
internal methods for branching rules and branching candidate storage
SCIP_VAR * h
Definition: circlepacking.c:68
SCIP_Real * r
Definition: circlepacking.c:59
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:360
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:290
SCIP_Real SCIPclockGetLastTime(SCIP_CLOCK *clck)
Definition: clock.c:529
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:438
internal methods for clocks and timing issues
SCIP_Longint SCIPgetConcurrentMemTotal(SCIP *scip)
Definition: concurrent.c:288
int SCIPgetNConcurrentSolvers(SCIP *scip)
Definition: concurrent.c:117
helper functions for concurrent scip solvers
internal methods for conflict analysis
int SCIPconflictGetNConflicts(SCIP_CONFLICT *conflict)
SCIP_Longint SCIPconflictGetNInfeasibleLPSuccess(SCIP_CONFLICT *conflict)
SCIP_Longint SCIPconflictGetNBoundexceedingLPSuccess(SCIP_CONFLICT *conflict)
SCIP_RETCODE SCIPconflictAnalyzePseudo(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *success)
SCIP_RETCODE SCIPconflictAnalyzeLP(SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *success)
SCIP_Longint SCIPconflictGetNPseudoSuccess(SCIP_CONFLICT *conflict)
SCIP_Longint SCIPconflictGetNPropSuccess(SCIP_CONFLICT *conflict)
SCIP_Longint SCIPconflictGetNStrongbranchSuccess(SCIP_CONFLICT *conflict)
SCIP_RETCODE SCIPconflictFlushConss(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable)
SCIP_RETCODE SCIPconshdlrSeparateLP(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, int depth, SCIP_Bool execdelayed, SCIP_RESULT *result)
Definition: cons.c:2877
SCIP_RETCODE SCIPconshdlrEnforceRelaxSol(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_SEPASTORE *sepastore, SCIP_SOL *relaxsol, SCIP_Bool solinfeasible, SCIP_RESULT *result)
Definition: cons.c:3163
SCIP_RETCODE SCIPconshdlrSeparateSol(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, int depth, SCIP_Bool execdelayed, SCIP_RESULT *result)
Definition: cons.c:3034
SCIP_RETCODE SCIPconshdlrEnforceLPSol(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_SEPASTORE *sepastore, SCIP_Bool solinfeasible, SCIP_RESULT *result)
Definition: cons.c:3351
SCIP_RETCODE SCIPconshdlrInitLP(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_Bool initkeptconss, SCIP_Bool *cutoff)
Definition: cons.c:2770
SCIP_RETCODE SCIPconshdlrPropagate(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, int depth, SCIP_Bool fullpropagation, SCIP_Bool execdelayed, SCIP_Bool instrongbranching, SCIP_PROPTIMING proptiming, SCIP_RESULT *result)
Definition: cons.c:3822
SCIP_RETCODE SCIPconshdlrEnforcePseudoSol(SCIP_CONSHDLR *conshdlr, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_BRANCHCAND *branchcand, SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_Bool forced, SCIP_RESULT *result)
Definition: cons.c:3556
internal methods for constraints and constraint handlers
SCIP_RETCODE SCIPcutpoolSeparate(SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, SCIP_Bool cutpoolisdelayed, SCIP_Bool root, SCIP_RESULT *result)
Definition: cutpool.c:835
internal methods for storing cuts in a cut pool
#define 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:17115
SCIP_PROPTIMING SCIPconshdlrGetPropTiming(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5250
SCIP_Bool SCIPconshdlrWasSolSeparationDelayed(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5210
int SCIPconshdlrGetSepaPriority(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5100
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4197
SCIP_Bool SCIPconshdlrWasLPSeparationDelayed(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5200
SCIP_Bool SCIPconshdlrWasPropagationDelayed(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5220
int SCIPheurGetPriority(SCIP_HEUR *heur)
Definition: heur.c:1514
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1453
BMS_BUFMEM * SCIPbuffer(SCIP *scip)
Definition: scip_mem.c:72
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:7500
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7530
SCIP_Bool SCIPnodeIsActive(SCIP_NODE *node)
Definition: tree.c:8297
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7520
SCIP_Bool SCIPnodeIsPropagatedAgain(SCIP_NODE *node)
Definition: tree.c:8307
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:17619
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17788
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17537
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18143
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17583
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17767
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17418
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18451
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18133
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:18477
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:18509
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:18497
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:18489
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:8671
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:13103
void SCIPlpSetIsRelax(SCIP_LP *lp, SCIP_Bool relax)
Definition: lp.c:17784
SCIP_Bool SCIPlpIsRelax(SCIP_LP *lp)
Definition: lp.c:17797
SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13119
SCIP_RETCODE SCIPlpGetProvedLowerbound(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *bound)
Definition: lp.c:16491
SCIP_LPI * SCIPlpGetLPI(SCIP_LP *lp)
Definition: lp.c:17774
SCIP_RETCODE SCIPlpRemoveRedundantRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:15929
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17847
SCIP_Bool SCIPlpIsSolved(SCIP_LP *lp)
Definition: lp.c:17807
SCIP_Real SCIPlpGetGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13270
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:17575
SCIP_RETCODE SCIPlpSolveAndEval(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_Longint itlim, SCIP_Bool limitresolveiters, SCIP_Bool aging, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:12413
void SCIPlpResetFeastol(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:10281
SCIP_RETCODE SCIPlpGetPrimalRay(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *ray)
Definition: lp.c:14991
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:17622
SCIP_Real SCIPlpGetPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13302
internal methods for LP management
interface methods for specific LP solvers
size_t BMSgetNUsedBufferMemory(BMS_BUFMEM *buffer)
Definition: memory.c:3129
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:427
void SCIPmessagePrintVerbInfo(SCIP_MESSAGEHDLR *messagehdlr, SCIP_VERBLEVEL verblevel, SCIP_VERBLEVEL msgverblevel, const char *formatstr,...)
Definition: message.c:678
SCIP_RETCODE SCIPnodeselSelect(SCIP_NODESEL *nodesel, SCIP_SET *set, SCIP_NODE **selnode)
Definition: nodesel.c:1030
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:1575
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:1505
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:1281
internal methods for collecting primal CIP solutions and primal informations
SCIP_Real SCIPprobGetObjlim(SCIP_PROB *prob, SCIP_SET *set)
Definition: prob.c:2362
SCIP_Real SCIPprobExternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:2157
void SCIPprobStoreRootSol(SCIP_PROB *prob, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Bool roothaslp)
Definition: prob.c:1778
SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
Definition: prob.c:2350
void SCIPprobUpdateBestRootSol(SCIP_PROB *prob, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: prob.c:1805
SCIP_Real SCIPprobInternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:2179
internal methods for storing and manipulating the main problem
SCIP_RETCODE SCIPpropExec(SCIP_PROP *prop, SCIP_SET *set, SCIP_STAT *stat, int depth, SCIP_Bool execdelayed, SCIP_Bool instrongbranching, SCIP_PROPTIMING proptiming, SCIP_RESULT *result)
Definition: prop.c:645
internal methods for propagators
public methods for managing constraints
public methods for primal heuristics
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
public data structures and miscellaneous methods
public methods for variable pricers
public methods for propagators
public methods for relaxation handlers
public methods for separators
public methods for branch and bound tree
public methods for problem variables
void SCIPrelaxationSetSolValid(SCIP_RELAXATION *relaxation, SCIP_Bool isvalid, SCIP_Bool includeslp)
Definition: relax.c:795
SCIP_Real SCIPrelaxationGetSolObj(SCIP_RELAXATION *relaxation)
Definition: relax.c:839
SCIP_Bool SCIPrelaxIsSolved(SCIP_RELAX *relax, SCIP_STAT *stat)
Definition: relax.c:708
SCIP_RETCODE SCIPrelaxExec(SCIP_RELAX *relax, SCIP_SET *set, SCIP_TREE *tree, SCIP_STAT *stat, int depth, SCIP_Real *lowerbound, SCIP_RESULT *result)
Definition: relax.c:353
SCIP_Bool SCIPrelaxationIsLpIncludedForSol(SCIP_RELAXATION *relaxation)
Definition: relax.c:818
SCIP_Bool SCIPrelaxationIsSolValid(SCIP_RELAXATION *relaxation)
Definition: relax.c:808
internal methods for relaxators
SCIP_RETCODE SCIPreoptCheckCutoff(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_EVENTTYPE eventtype, SCIP_LP *lp, SCIP_LPSOLSTAT lpsolstat, SCIP_Bool isrootnode, SCIP_Bool isfocusnode, SCIP_Real lowerbound, int effectiverootdepth)
Definition: reopt.c:5989
SCIP_RETCODE SCIPreoptApplyCuts(SCIP_REOPT *reopt, SCIP_NODE *node, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_Bool root)
Definition: reopt.c:7730
SCIP_Bool SCIPreoptGetSolveLP(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node)
Definition: reopt.c:7860
data structures and methods for collecting reoptimization information
public methods for concurrent solving mode
public methods for memory management
public methods for global and local (sub)problems
public methods for solutions
public methods for querying solving statistics
SCIP_RETCODE SCIPsepaExecLP(SCIP_SEPA *sepa, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, int depth, SCIP_Real bounddist, SCIP_Bool allowlocal, SCIP_Bool execdelayed, SCIP_RESULT *result)
Definition: sepa.c:403
SCIP_RETCODE SCIPsepaExecSol(SCIP_SEPA *sepa, SCIP_SET *set, SCIP_STAT *stat, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, int depth, SCIP_Bool allowlocal, SCIP_Bool execdelayed, SCIP_RESULT *result)
Definition: sepa.c:521
internal methods for separators
void SCIPsepastoreEndInitialLP(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:144
SCIP_RETCODE SCIPsepastoreClearCuts(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp)
Definition: sepastore.c:1027
int SCIPsepastoreGetNCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1149
SCIP_RETCODE SCIPsepastoreAddCut(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool root, SCIP_Bool *infeasible)
Definition: sepastore.c:428
void SCIPsepastoreStartForceCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:156
void SCIPsepastoreEndForceCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:167
void SCIPsepastoreStartInitialLP(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:132
SCIP_RETCODE SCIPsepastoreApplyCuts(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool root, SCIP_EFFICIACYCHOICE efficiacychoice, SCIP_Bool *cutoff)
Definition: sepastore.c:921
int SCIPsepastoreGetNCutsApplied(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1200
internal methods for storing separated cuts
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6293
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6397
int SCIPsetGetSepaMaxcuts(SCIP_SET *set, SCIP_Bool root)
Definition: set.c:5917
SCIP_Bool 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:3390
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:2971
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:4947
#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:3737
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:3780
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
static SCIP_RETCODE solveNodeLP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_MEM *mem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_CUTPOOL *delayedcutpool, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool initiallpsolved, SCIP_Bool fullseparation, SCIP_Bool newinitconss, SCIP_Bool *propagateagain, SCIP_Bool *solverelaxagain, SCIP_Bool *cutoff, SCIP_Bool *unbounded, SCIP_Bool *lperror, SCIP_Bool *pricingaborted)
Definition: solve.c:3046
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:3290
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:3681
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:4810
SCIP_Bool SCIPsolveIsStopped(SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool checknodelimits)
Definition: solve.c:102
static SCIP_RETCODE priceAndCutLoop(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_MEM *mem, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_PRICESTORE *pricestore, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, SCIP_CUTPOOL *delayedcutpool, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool fullseparation, SCIP_Bool *propagateagain, SCIP_Bool *cutoff, SCIP_Bool *unbounded, SCIP_Bool *lperror, SCIP_Bool *pricingaborted)
Definition: solve.c:2361
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:4148
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:3028
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:4131
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:2379
SCIP_Bool SCIPtreeIsFocusNodeLPConstructed(SCIP_TREE *tree)
Definition: tree.c:8465
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:8410
SCIP_Bool SCIPtreeProbing(SCIP_TREE *tree)
Definition: tree.c:8384
int SCIPtreeGetFocusDepth(SCIP_TREE *tree)
Definition: tree.c:8427
SCIP_RETCODE SCIPtreeSetNodesel(SCIP_TREE *tree, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_NODESEL *nodesel)
Definition: tree.c:5194
void SCIPnodeSetEstimate(SCIP_NODE *node, SCIP_SET *set, SCIP_Real newestimate)
Definition: tree.c:2484
SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
Definition: tree.c:8485
void SCIPnodeMarkPropagated(SCIP_NODE *node, SCIP_TREE *tree)
Definition: tree.c:1327
int SCIPtreeGetNLeaves(SCIP_TREE *tree)
Definition: tree.c:8347
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:8519
SCIP_Real SCIPtreeGetLowerbound(SCIP_TREE *tree, SCIP_SET *set)
Definition: tree.c:7323
void SCIPtreeSetFocusNodeLP(SCIP_TREE *tree, SCIP_Bool solvelp)
Definition: tree.c:8454
int SCIPtreeGetNNodes(SCIP_TREE *tree)
Definition: tree.c:8357
SCIP_Bool SCIPtreeHasFocusNodeLP(SCIP_TREE *tree)
Definition: tree.c:8444
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:4408
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:8502
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:2424
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:5222
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:3646
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:3518
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:14476
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:14378
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:15614
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)