Scippy

SCIP

Solving Constraint Integer Programs

conflict_graphanalysis.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file conflict_graphanalysis.c
26 * @ingroup OTHER_CFILES
27 * @brief methods and datastructures for conflict analysis
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Stefan Heinz
31 * @author Marc Pfetsch
32 * @author Michael Winkler
33 * @author Jakob Witzig
34 *
35 * This file implements a conflict analysis method like the one used in modern
36 * SAT solvers like zchaff. The algorithm works as follows:
37 *
38 * Given is a set of bound changes that are not allowed being applied simultaneously, because they
39 * render the current node infeasible (e.g. because a single constraint is infeasible in the these
40 * bounds, or because the LP relaxation is infeasible). The goal is to deduce a clause on variables
41 * -- a conflict clause -- representing the "reason" for this conflict, i.e., the branching decisions
42 * or the deductions (applied e.g. in domain propagation) that lead to the conflict. This clause can
43 * then be added to the constraint set to help cutting off similar parts of the branch and bound
44 * tree, that would lead to the same conflict. A conflict clause can also be generated, if the
45 * conflict was detected by a locally valid constraint. In this case, the resulting conflict clause
46 * is also locally valid in the same depth as the conflict detecting constraint. If all involved
47 * variables are binary, a linear (set covering) constraint can be generated, otherwise a bound
48 * disjunction constraint is generated. Details are given in
49 *
50 * Tobias Achterberg, Conflict Analysis in Mixed Integer Programming@n
51 * Discrete Optimization, 4, 4-20 (2007)
52 *
53 * See also @ref CONF. Here is an outline of the algorithm:
54 *
55 * -# Put all the given bound changes to a priority queue, which is ordered,
56 * such that the bound change that was applied last due to branching or deduction
57 * is at the top of the queue. The variables in the queue are always active
58 * problem variables. Because binary variables are preferred over general integer
59 * variables, integer variables are put on the priority queue prior to the binary
60 * variables. Create an empty conflict set.
61 * -# Remove the top bound change b from the priority queue.
62 * -# Perform the following case distinction:
63 * -# If the remaining queue is non-empty, and bound change b' (the one that is now
64 * on the top of the queue) was applied at the same depth level as b, and if
65 * b was a deduction with known inference reason, and if the inference constraint's
66 * valid depth is smaller or equal to the conflict detecting constraint's valid
67 * depth:
68 * - Resolve bound change b by asking the constraint that inferred the
69 * bound change to put all the bound changes on the priority queue, that
70 * lead to the deduction of b.
71 * Note that these bound changes have at most the same inference depth
72 * level as b, and were deduced earlier than b.
73 * -# Otherwise, the bound change b was a branching decision or a deduction with
74 * missing inference reason, or the inference constraint's validity is more local
75 * than the one of the conflict detecting constraint.
76 * - If a the bound changed corresponds to a binary variable, add it or its
77 * negation to the conflict set, depending on which of them is currently fixed to
78 * FALSE (i.e., the conflict set consists of literals that cannot be FALSE
79 * altogether at the same time).
80 * - Otherwise put the bound change into the conflict set.
81 * Note that if the bound change was a branching, all deduced bound changes
82 * remaining in the priority queue have smaller inference depth level than b,
83 * since deductions are always applied after the branching decisions. However,
84 * there is the possibility, that b was a deduction, where the inference
85 * reason was not given or the inference constraint was too local.
86 * With this lack of information, we must treat the deduced bound change like
87 * a branching, and there may exist other deduced bound changes of the same
88 * inference depth level in the priority queue.
89 * -# If priority queue is non-empty, goto step 2.
90 * -# The conflict set represents the conflict clause saying that at least one
91 * of the conflict variables must take a different value. The conflict set is then passed
92 * to the conflict handlers, that may create a corresponding constraint (e.g. a logicor
93 * constraint or bound disjunction constraint) out of these conflict variables and
94 * add it to the problem.
95 *
96 * If all deduced bound changes come with (global) inference information, depending on
97 * the conflict analyzing strategy, the resulting conflict set has the following property:
98 * - 1-FirstUIP: In the depth level where the conflict was found, at most one variable
99 * assigned at that level is member of the conflict set. This conflict variable is the
100 * first unique implication point of its depth level (FUIP).
101 * - All-FirstUIP: For each depth level, at most one variable assigned at that level is
102 * member of the conflict set. This conflict variable is the first unique implication
103 * point of its depth level (FUIP).
104 *
105 * The user has to do the following to get the conflict analysis running in its
106 * current implementation:
107 * - A constraint handler or propagator supporting the conflict analysis must implement
108 * the CONSRESPROP/PROPRESPROP call, that processes a bound change inference b and puts all
109 * the reason bounds leading to the application of b with calls to
110 * SCIPaddConflictBound() on the conflict queue (algorithm step 3.(a)).
111 * - If the current bounds lead to a deduction of a bound change (e.g. in domain
112 * propagation), a constraint handler should call SCIPinferVarLbCons() or
113 * SCIPinferVarUbCons(), thus providing the constraint that inferred the bound change.
114 * A propagator should call SCIPinferVarLbProp() or SCIPinferVarUbProp() instead,
115 * thus providing a pointer to itself.
116 * - If (in the current bounds) an infeasibility is detected, the constraint handler or
117 * propagator should
118 * 1. call SCIPinitConflictAnalysis() to initialize the conflict queue,
119 * 2. call SCIPaddConflictBound() for each bound that lead to the conflict,
120 * 3. call SCIPanalyzeConflictCons() or SCIPanalyzeConflict() to analyze the conflict
121 * and add an appropriate conflict constraint.
122 */
123
124/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
125
126#include "lpi/lpi.h"
129#include "scip/clock.h"
130#include "scip/conflict.h"
131#include "scip/cons.h"
132#include "scip/cons_linear.h"
133#include "scip/cuts.h"
134#include "scip/history.h"
135#include "scip/lp.h"
136#include "scip/presolve.h"
137#include "scip/prob.h"
138#include "scip/prop.h"
139#include "scip/pub_conflict.h"
140#include "scip/pub_cons.h"
141#include "scip/pub_lp.h"
142#include "scip/pub_message.h"
143#include "scip/pub_misc.h"
144#include "scip/pub_misc_sort.h"
145#include "scip/pub_paramset.h"
146#include "scip/pub_prop.h"
147#include "scip/pub_tree.h"
148#include "scip/pub_var.h"
149#include "scip/scip_conflict.h"
150#include "scip/scip_cons.h"
151#include "scip/scip_mem.h"
152#include "scip/scip_sol.h"
153#include "scip/scip_var.h"
154#include "scip/scip_message.h"
155#include "scip/set.h"
156#include "scip/sol.h"
157#include "scip/struct_conflict.h"
158#include "scip/struct_lp.h"
159#include "scip/struct_prob.h"
160#include "scip/struct_set.h"
161#include "scip/struct_stat.h"
162#include "scip/struct_tree.h"
163#include "scip/struct_var.h"
164#include "scip/tree.h"
165#include "scip/var.h"
166#include "scip/visual.h"
167#include <string.h>
168#ifndef _WIN32
169#include <strings.h> /*lint --e{766}*/
170#endif
171
172/* #define SCIP_CONFGRAPH */
173/* #define SCIP_CONFGRAPH_DOT */
174
175
176#if defined(SCIP_CONFGRAPH) || defined(SCIP_CONFGRAPH_DOT)
177/*
178 * Output of Conflict Graph
179 */
180
181#include <stdio.h>
182#include "scip/scip_message.h"
183
184static FILE* confgraphfile = NULL; /**< output file for current conflict graph */
185static SCIP_BDCHGINFO* confgraphcurrentbdchginfo = NULL; /**< currently resolved bound change */
186static int confgraphnconflictsets = 0; /**< number of conflict sets marked in the graph */
187
188/** writes a node section to the conflict graph file */
189static
190void confgraphWriteNode(
191 void* idptr, /**< id of the node */
192 const char* label, /**< label of the node */
193 const char* nodetype, /**< type of the node */
194 const char* fillcolor, /**< color of the node's interior */
195 const char* bordercolor /**< color of the node's border */
196 )
197{
198 assert(confgraphfile != NULL);
199
200#ifdef SCIP_CONFGRAPH_DOT
201 SCIPdotWriteNode(confgraphfile, (int)(size_t) idptr, label, nodetype, fillcolor, bordercolor); /*lint !e571*/
202
203#else
204 SCIPgmlWriteNode(confgraphfile, (unsigned int)(size_t)idptr, label, nodetype, fillcolor, bordercolor); /*lint !e571*/
205
206#endif
207}
208
209/** writes an edge section to the conflict graph file */
210static
211void confgraphWriteEdge(
212 void* source, /**< source node of the edge */
213 void* target, /**< target node of the edge */
214 const char* color /**< color of the edge */
215 )
216{
217 assert(confgraphfile != NULL);
218
219#ifdef SCIP_CONFGRAPH_DOT
220 SCIPdotWriteArc(confgraphfile, (int)(size_t)source, (int)(size_t)target, color); /*lint !e571*/
221
222#else
223#ifndef SCIP_CONFGRAPH_EDGE
224 SCIPgmlWriteArc(confgraphfile, (unsigned int)(size_t)source, (unsigned int)(size_t)target, NULL, color); /*lint !e571*/
225
226#else
227 SCIPgmlWriteEdge(confgraphfile, (unsigned int)(size_t)source, (unsigned int)(size_t)target, NULL, color); /*lint !e571*/
228#endif
229#endif
230}
231
232/** creates a file to output the current conflict graph into; adds the conflict vertex to the graph */
233static
234SCIP_RETCODE confgraphCreate(
235 SCIP_SET* set, /**< global SCIP settings */
236 SCIP_CONFLICT* conflict /**< conflict analysis data */
237 )
238{
239 char fname[SCIP_MAXSTRLEN];
240
241 assert(conflict != NULL);
242 assert(confgraphfile == NULL);
243
244#ifdef SCIP_CONFGRAPH_DOT
245 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "conf%p%d.dot", conflict, conflict->count);
246#else
247 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "conf%p%d.gml", conflict, conflict->count);
248#endif
249 SCIPinfoMessage(set->scip, NULL, "storing conflict graph in file <%s>\n", fname);
250
251 confgraphfile = fopen(fname, "w");
252
253 if( confgraphfile == NULL )
254 {
255 SCIPerrorMessage("cannot open graph file <%s>\n", fname);
256 SCIPABORT(); /*lint !e527*/
257 return SCIP_WRITEERROR;
258 }
259
260#ifdef SCIP_CONFGRAPH_DOT
261 SCIPdotWriteOpening(confgraphfile);
262#else
263 SCIPgmlWriteOpening(confgraphfile, TRUE);
264#endif
265 confgraphWriteNode(NULL, "conflict", "ellipse", "#ff0000", "#000000");
266
267 confgraphcurrentbdchginfo = NULL;
268
269 return SCIP_OKAY;
270}
271
272/** closes conflict graph file */
273static
274void confgraphFree(
275 void
276 )
277{
278 if( confgraphfile != NULL )
279 {
280#ifdef SCIP_CONFGRAPH_DOT
281 SCIPdotWriteClosing(confgraphfile);
282#else
283 SCIPgmlWriteClosing(confgraphfile);
284#endif
285 fclose(confgraphfile);
286
287 confgraphfile = NULL;
288 confgraphnconflictsets = 0;
289 }
290}
291
292/** adds a bound change node to the conflict graph and links it to the currently resolved bound change */
293static
294void confgraphAddBdchg(
295 SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict graph */
296 )
297{
298 const char* colors[] = {
299 "#8888ff", /* blue for constraint resolving */
300 "#ffff00", /* yellow for propagator resolving */
301 "#55ff55" /* green branching decision */
302 };
303 char label[SCIP_MAXSTRLEN];
304 char depth[SCIP_MAXSTRLEN];
305 int col;
306
307 switch( SCIPbdchginfoGetChgtype(bdchginfo) )
308 {
310 col = 2;
311 break;
313 col = 0;
314 break;
316 col = (SCIPbdchginfoGetInferProp(bdchginfo) == NULL ? 1 : 0);
317 break;
318 default:
319 SCIPerrorMessage("invalid bound change type\n");
320 col = 0;
321 SCIPABORT();
322 break;
323 }
324
325 if( SCIPbdchginfoGetDepth(bdchginfo) == INT_MAX )
326 (void) SCIPsnprintf(depth, SCIP_MAXSTRLEN, "dive");
327 else
328 (void) SCIPsnprintf(depth, SCIP_MAXSTRLEN, "%d", SCIPbdchginfoGetDepth(bdchginfo));
329 (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "%s %s %g\n[%s:%d]", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
330 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
331 SCIPbdchginfoGetNewbound(bdchginfo), depth, SCIPbdchginfoGetPos(bdchginfo));
332 confgraphWriteNode(bdchginfo, label, "ellipse", colors[col], "#000000");
333 confgraphWriteEdge(bdchginfo, confgraphcurrentbdchginfo, "#000000");
334}
335
336/** links the already existing bound change node to the currently resolved bound change */
337static
338void confgraphLinkBdchg(
339 SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict graph */
340 )
341{
342 confgraphWriteEdge(bdchginfo, confgraphcurrentbdchginfo, "#000000");
343}
344
345/** marks the given bound change to be the currently resolved bound change */
346static
347void confgraphSetCurrentBdchg(
348 SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict graph */
349 )
350{
351 confgraphcurrentbdchginfo = bdchginfo;
352}
353
354/** marks given conflict set in the conflict graph */
355static
356void confgraphMarkConflictset(
357 SCIP_CONFLICTSET* conflictset /**< conflict set */
358 )
359{
360 char label[SCIP_MAXSTRLEN];
361 int i;
362
363 assert(conflictset != NULL);
364
365 confgraphnconflictsets++;
366 (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "conf %d (%d)", confgraphnconflictsets, conflictset->validdepth);
367 confgraphWriteNode((void*)(size_t)confgraphnconflictsets, label, "rectangle", "#ff00ff", "#000000"); /*lint !e571*/
368 for( i = 0; i < conflictset->nbdchginfos; ++i )
369 confgraphWriteEdge((void*)(size_t)confgraphnconflictsets, conflictset->bdchginfos[i], "#ff00ff"); /*lint !e571*/
370}
371
372#endif
373
374/** Conflict sets */
375
376/** resizes the arrays of the conflict set to be able to store at least num bound change entries */
377static
379 SCIP_CONFLICTSET* conflictset, /**< conflict set */
380 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
381 SCIP_SET* set, /**< global SCIP settings */
382 int num /**< minimal number of slots in arrays */
383 )
384{
385 assert(conflictset != NULL);
386 assert(set != NULL);
387
388 if( num > conflictset->bdchginfossize )
389 {
390 int newsize;
391
392 newsize = SCIPsetCalcMemGrowSize(set, num);
393 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->bdchginfos, conflictset->bdchginfossize, newsize) );
394 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->relaxedbds, conflictset->bdchginfossize, newsize) );
395 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->sortvals, conflictset->bdchginfossize, newsize) );
396 conflictset->bdchginfossize = newsize;
397 }
398 assert(num <= conflictset->bdchginfossize);
399
400 return SCIP_OKAY;
401}
402
403/** adds a bound change to a conflict set */
404static
406 SCIP_CONFLICTSET* conflictset, /**< conflict set */
407 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
408 SCIP_SET* set, /**< global SCIP settings */
409 SCIP_BDCHGINFO* bdchginfo, /**< bound change to add to the conflict set */
410 SCIP_Real relaxedbd /**< relaxed bound */
411 )
412{
413 SCIP_BDCHGINFO** bdchginfos;
414 SCIP_Real* relaxedbds;
415 int* sortvals;
416 SCIP_VAR* var;
417 SCIP_BOUNDTYPE boundtype;
418 int idx;
419 int sortval;
420 int pos;
421
422 assert(conflictset != NULL);
423 assert(bdchginfo != NULL);
424
425 /* allocate memory for additional element */
426 SCIP_CALL( conflictsetEnsureBdchginfosMem(conflictset, blkmem, set, conflictset->nbdchginfos+1) );
427
428 /* insert the new bound change in the arrays sorted by increasing variable index and by bound type */
429 bdchginfos = conflictset->bdchginfos;
430 relaxedbds = conflictset->relaxedbds;
431 sortvals = conflictset->sortvals;
432 var = SCIPbdchginfoGetVar(bdchginfo);
433 boundtype = SCIPbdchginfoGetBoundtype(bdchginfo);
434 idx = SCIPvarGetIndex(var);
435 assert(idx < INT_MAX/2);
436 assert((int)boundtype == 0 || (int)boundtype == 1);
437 sortval = 2*idx + (int)boundtype; /* first sorting criteria: variable index, second criteria: boundtype */
438
439 /* insert new element into the sorted arrays; if an element exits with the same value insert the new element afterwards
440 *
441 * @todo check if it better (faster) to first search for the position O(log n) and compare the sort values and if
442 * they are equal just replace the element and if not run the insert method O(n)
443 */
444
445 SCIPsortedvecInsertIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, sortval, (void*)bdchginfo, relaxedbd, &conflictset->nbdchginfos, &pos);
446 assert(pos == conflictset->nbdchginfos - 1 || sortval < sortvals[pos+1]);
447
448 /* merge multiple bound changes */
449 if( pos > 0 && sortval == sortvals[pos-1] )
450 {
451 /* this is a multiple bound change */
452 if( SCIPbdchginfoIsTighter(bdchginfo, bdchginfos[pos-1]) )
453 {
454 /* remove the "old" bound change since the "new" one in tighter */
455 SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos-1, &conflictset->nbdchginfos);
456 }
457 else if( SCIPbdchginfoIsTighter(bdchginfos[pos-1], bdchginfo) )
458 {
459 /* remove the "new" bound change since the "old" one is tighter */
460 SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos, &conflictset->nbdchginfos);
461 }
462 else
463 {
464 /* both bound change are equivalent; hence, keep the worse relaxed bound and remove one of them */
465 relaxedbds[pos-1] = boundtype == SCIP_BOUNDTYPE_LOWER ? MAX(relaxedbds[pos-1], relaxedbd) : MIN(relaxedbds[pos-1], relaxedbd);
466 SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos, &conflictset->nbdchginfos);
467 }
468 }
469
470 if( SCIPvarIsRelaxationOnly(var) )
471 conflictset->hasrelaxonlyvar = TRUE;
472
473 return SCIP_OKAY;
474}
475
476/** calculates the conflict and the repropagation depths of the conflict set */
477static
479 SCIP_CONFLICTSET* conflictset /**< conflict set */
480 )
481{
482 int maxdepth[2];
483 int i;
484
485 assert(conflictset != NULL);
486 assert(conflictset->validdepth <= conflictset->insertdepth);
487
488 /* get the depth of the last and last but one bound change */
489 maxdepth[0] = conflictset->validdepth;
490 maxdepth[1] = conflictset->validdepth;
491 for( i = 0; i < conflictset->nbdchginfos; ++i )
492 {
493 int depth;
494
495 depth = SCIPbdchginfoGetDepth(conflictset->bdchginfos[i]);
496 assert(depth >= 0);
497 if( depth > maxdepth[0] )
498 {
499 maxdepth[1] = maxdepth[0];
500 maxdepth[0] = depth;
501 }
502 else if( depth > maxdepth[1] )
503 maxdepth[1] = depth;
504 }
505 assert(maxdepth[0] >= maxdepth[1]);
506
507 conflictset->conflictdepth = maxdepth[0];
508 conflictset->repropdepth = maxdepth[1];
509}
510
511/** identifies the depth, at which the conflict set should be added:
512 * - if the branching rule operates on variables only, and if all branching variables up to a certain
513 * depth level are member of the conflict, the conflict constraint can only be violated in the subtree
514 * of the node at that depth, because in all other nodes, at least one of these branching variables
515 * violates its conflicting bound, such that the conflict constraint is feasible
516 * - if there is at least one branching variable in a node, we assume, that this branching was performed
517 * on variables, and that the siblings of this node are disjunct w.r.t. the branching variables' fixings
518 * - we have to add the conflict set at least in the valid depth of the initial conflict set,
519 * so we start searching at the first branching after this depth level, i.e. validdepth+1
520 */
521static
523 SCIP_CONFLICTSET* conflictset, /**< conflict set */
524 SCIP_SET* set, /**< global SCIP settings */
525 SCIP_TREE* tree /**< branch and bound tree */
526 )
527{
528 SCIP_Bool* branchingincluded;
529 int currentdepth;
530 int i;
531
532 assert(conflictset != NULL);
533 assert(set != NULL);
534 assert(tree != NULL);
535
536 /* the conflict set must not be inserted prior to its valid depth */
537 conflictset->insertdepth = conflictset->validdepth;
538 assert(conflictset->insertdepth >= 0);
539
540 currentdepth = SCIPtreeGetCurrentDepth(tree);
541 assert(currentdepth == tree->pathlen-1);
542
543 /* mark the levels for which a branching variable is included in the conflict set */
544 SCIP_CALL( SCIPsetAllocBufferArray(set, &branchingincluded, currentdepth+2) );
545 BMSclearMemoryArray(branchingincluded, currentdepth+2);
546 for( i = 0; i < conflictset->nbdchginfos; ++i )
547 {
548 int depth;
549
550 depth = SCIPbdchginfoGetDepth(conflictset->bdchginfos[i]);
551 depth = MIN(depth, currentdepth+1); /* put diving/probing/strong branching changes in this depth level */
552 branchingincluded[depth] = TRUE;
553 }
554
555 /* skip additional depth levels where branching on the conflict variables was applied */
556 while( conflictset->insertdepth < currentdepth && branchingincluded[conflictset->insertdepth+1] )
557 conflictset->insertdepth++;
558
559 /* free temporary memory */
560 SCIPsetFreeBufferArray(set, &branchingincluded);
561
562 assert(conflictset->validdepth <= conflictset->insertdepth && conflictset->insertdepth <= currentdepth);
563
564 return SCIP_OKAY;
565}
566
567/** checks whether the first conflict set is redundant to the second one */
568static
570 SCIP_CONFLICTSET* conflictset1, /**< first conflict conflict set */
571 SCIP_CONFLICTSET* conflictset2 /**< second conflict conflict set */
572 )
573{
574 int i1;
575 int i2;
576
577 assert(conflictset1 != NULL);
578 assert(conflictset2 != NULL);
579
580 /* if conflictset1 has smaller validdepth, it is definitely not redundant to conflictset2 */
581 if( conflictset1->validdepth < conflictset2->validdepth )
582 return FALSE;
583
584 /* check, if all bound changes in conflictset2 are also present at least as tight in conflictset1;
585 * we can stop immediately, if more bound changes are remaining in conflictset2 than in conflictset1
586 */
587 for( i1 = 0, i2 = 0; i2 < conflictset2->nbdchginfos && conflictset1->nbdchginfos - i1 >= conflictset2->nbdchginfos - i2;
588 ++i1, ++i2 )
589 {
590 int sortval;
591
592 assert(i2 == 0 || conflictset2->sortvals[i2-1] < conflictset2->sortvals[i2]);
593
594 sortval = conflictset2->sortvals[i2];
595 for( ; i1 < conflictset1->nbdchginfos && conflictset1->sortvals[i1] < sortval; ++i1 ) /*lint !e445*/
596 {
597 /* while scanning conflictset1, check consistency */
598 assert(i1 == 0 || conflictset1->sortvals[i1-1] < conflictset1->sortvals[i1]);
599 }
600 if( i1 >= conflictset1->nbdchginfos || conflictset1->sortvals[i1] > sortval
601 || SCIPbdchginfoIsTighter(conflictset2->bdchginfos[i2], conflictset1->bdchginfos[i1]) )
602 return FALSE;
603 }
604
605 return (i2 == conflictset2->nbdchginfos);
606}
607
608#ifdef SCIP_DEBUG
609/** prints a conflict set to the screen */
611 SCIP_CONFLICTSET* conflictset /**< conflict set */
612 )
613{
614 int i;
615
616 assert(conflictset != NULL);
617 for( i = 0; i < conflictset->nbdchginfos; ++i )
618 {
619 SCIPdebugPrintf(" [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(conflictset->bdchginfos[i]),
621 SCIPbdchginfoGetBoundtype(conflictset->bdchginfos[i]) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
622 SCIPbdchginfoGetNewbound(conflictset->bdchginfos[i]), conflictset->relaxedbds[i]);
623 }
624 SCIPdebugPrintf("\n");
625}
626#endif
627
628
629/** check conflict set for redundancy, other conflicts in the same conflict analysis could have led to global reductions
630 * an made this conflict set redundant
631 */
632static
634 SCIP_SET* set, /**< global SCIP settings */
635 SCIP_CONFLICTSET* conflictset /**< conflict set */
636 )
637{
638 SCIP_BDCHGINFO** bdchginfos;
639 SCIP_VAR* var;
640 SCIP_Real* relaxedbds;
642 int v;
643
644 assert(set != NULL);
645 assert(conflictset != NULL);
646
647 bdchginfos = conflictset->bdchginfos;
648 relaxedbds = conflictset->relaxedbds;
649 assert(bdchginfos != NULL);
650 assert(relaxedbds != NULL);
651
652 /* check all boundtypes and bounds for redundancy */
653 for( v = conflictset->nbdchginfos - 1; v >= 0; --v )
654 {
655 var = SCIPbdchginfoGetVar(bdchginfos[v]);
656 assert(var != NULL);
657 assert(SCIPvarGetProbindex(var) >= 0);
658
659 /* check if the relaxed bound is really a relaxed bound */
660 assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
661 assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
662
663 bound = relaxedbds[v];
664
665 if( SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_UPPER )
666 {
667 if( SCIPvarIsIntegral(var) )
668 {
669 assert(SCIPsetIsIntegral(set, bound));
670 bound += 1.0;
671 }
672
673 /* check if the bound is already fulfilled globally */
675 return TRUE;
676 }
677 else
678 {
679 assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_LOWER);
680
681 if( SCIPvarIsIntegral(var) )
682 {
683 assert(SCIPsetIsIntegral(set, bound));
684 bound -= 1.0;
685 }
686
687 /* check if the bound is already fulfilled globally */
689 return TRUE;
690 }
691 }
692
693 return FALSE;
694}
695
696/** find global fixings which can be derived from the new conflict set */
697static
699 SCIP_SET* set, /**< global SCIP settings */
700 SCIP_PROB* prob, /**< transformed problem after presolve */
701 SCIP_STAT* stat, /**< dynamic SCIP statistics */
702 SCIP_TREE* tree, /**< tree data */
703 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
704 BMS_BLKMEM* blkmem, /**< block memory */
705 SCIP_PROB* origprob, /**< original problem */
706 SCIP_REOPT* reopt, /**< reoptimization data */
707 SCIP_LP* lp, /**< LP data */
708 SCIP_CONFLICTSET* conflictset, /**< conflict set to add to the tree */
709 int* nbdchgs, /**< number of global deducted bound changes due to the conflict set */
710 int* nredvars, /**< number of redundant and removed variables from conflict set */
711 SCIP_Bool* redundant /**< did we found a global reduction on a conflict set variable, which makes this conflict redundant */
712 )
713{
714 SCIP_BDCHGINFO** bdchginfos;
715 SCIP_Real* relaxedbds;
716 SCIP_VAR* var;
717 SCIP_Bool* boundtypes;
718 SCIP_Real* bounds;
719 SCIP_Longint* nbinimpls;
720 int* sortvals;
722 SCIP_Bool isupper;
723 int ntrivialredvars;
724 int nbdchginfos;
725 int nzeroimpls;
726 int v;
727
728 assert(set != NULL);
729 assert(prob != NULL);
730 assert(SCIPprobIsTransformed(prob));
731 assert(conflictset != NULL);
732 assert(nbdchgs != NULL);
733 assert(nredvars != NULL);
734 /* only check conflict sets with more than one variable */
735 assert(conflictset->nbdchginfos > 1);
736
737 *nbdchgs = 0;
738 *nredvars = 0;
739
740 /* due to other conflict in the same conflict analysis, this conflict set might have become redundant */
741 *redundant = checkRedundancy(set, conflictset);
742
743 if( *redundant )
744 return SCIP_OKAY;
745
746 bdchginfos = conflictset->bdchginfos;
747 relaxedbds = conflictset->relaxedbds;
748 nbdchginfos = conflictset->nbdchginfos;
749 sortvals = conflictset->sortvals;
750
751 assert(bdchginfos != NULL);
752 assert(relaxedbds != NULL);
753 assert(sortvals != NULL);
754
755 /* check if the boolean representation of boundtypes matches the 'standard' definition */
756 assert(SCIP_BOUNDTYPE_LOWER == FALSE); /*lint !e641 !e506*/
757 assert(SCIP_BOUNDTYPE_UPPER == TRUE); /*lint !e641 !e506*/
758
759 ntrivialredvars = 0;
760
761 /* due to multiple conflict sets for one conflict, it can happen, that we already have redundant information in the
762 * conflict set
763 */
764 for( v = nbdchginfos - 1; v >= 0; --v )
765 {
766 var = SCIPbdchginfoGetVar(bdchginfos[v]);
767 bound = relaxedbds[v];
769
770 /* for integral variable we can increase/decrease the conflicting bound */
771 if( SCIPvarIsIntegral(var) )
772 bound += (isupper ? -1.0 : +1.0);
773
774 /* if conflict variable cannot fulfill the conflict we can remove it */
775 if( (isupper && SCIPsetIsFeasLT(set, bound, SCIPvarGetLbGlobal(var))) ||
776 (!isupper && SCIPsetIsFeasGT(set, bound, SCIPvarGetUbGlobal(var))) )
777 {
778 SCIPsetDebugMsg(set, "remove redundant variable <%s> from conflict set\n", SCIPvarGetName(var));
779
780 bdchginfos[v] = bdchginfos[nbdchginfos - 1];
781 relaxedbds[v] = relaxedbds[nbdchginfos - 1];
782 sortvals[v] = sortvals[nbdchginfos - 1];
783
784 --nbdchginfos;
785 ++ntrivialredvars;
786 }
787 }
788 assert(ntrivialredvars + nbdchginfos == conflictset->nbdchginfos);
789
790 SCIPsetDebugMsg(set, "trivially removed %d redundant of %d variables from conflictset (%p)\n", ntrivialredvars, conflictset->nbdchginfos, (void*)conflictset);
791 conflictset->nbdchginfos = nbdchginfos;
792
793 /* all variables where removed, the conflict cannot be fulfilled, i.e., we have an infeasibility proof */
794 if( conflictset->nbdchginfos == 0 )
795 return SCIP_OKAY;
796
797 /* do not check to big or trivial conflicts */
798 if( conflictset->nbdchginfos > set->conf_maxvarsdetectimpliedbounds || conflictset->nbdchginfos == 1 )
799 {
800 *nredvars = ntrivialredvars;
801 return SCIP_OKAY;
802 }
803
804 /* create array of boundtypes, and bound values in conflict set */
805 SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtypes, nbdchginfos) );
806 SCIP_CALL( SCIPsetAllocBufferArray(set, &bounds, nbdchginfos) );
807 /* memory for the estimates for binary implications used for sorting */
808 SCIP_CALL( SCIPsetAllocBufferArray(set, &nbinimpls, nbdchginfos) );
809
810 nzeroimpls = 0;
811
812 /* collect estimates and initialize variables, boundtypes, and bounds array */
813 for( v = 0; v < nbdchginfos; ++v )
814 {
815 var = SCIPbdchginfoGetVar(bdchginfos[v]);
816 boundtypes[v] = (SCIP_Bool) SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(bdchginfos[v]));
817 bounds[v] = relaxedbds[v];
818
819 assert(SCIPvarGetProbindex(var) >= 0);
820
821 /* check if the relaxed bound is really a relaxed bound */
822 assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
823 assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
824
825 /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
826 if( SCIPvarIsBinary(var) )
827 {
828 if( !boundtypes[v] )
829 {
830 assert(SCIPsetIsZero(set, bounds[v]));
831 bounds[v] = 1.0;
832 nbinimpls[v] = (SCIP_Longint)SCIPvarGetNCliques(var, TRUE) * 2;
833 }
834 else
835 {
836 assert(SCIPsetIsEQ(set, bounds[v], 1.0));
837 bounds[v] = 0.0;
838 nbinimpls[v] = (SCIP_Longint)SCIPvarGetNCliques(var, FALSE) * 2;
839 }
840 }
841 else if( SCIPvarIsIntegral(var) )
842 {
843 assert(SCIPsetIsIntegral(set, bounds[v]));
844
845 bounds[v] += ((!boundtypes[v]) ? +1.0 : -1.0);
846 nbinimpls[v] = (boundtypes[v] ? SCIPvarGetNVlbs(var) : SCIPvarGetNVubs(var));
847 }
848 else if( ((!boundtypes[v]) && SCIPsetIsFeasEQ(set, SCIPvarGetLbGlobal(var), bounds[v]))
849 || ((boundtypes[v]) && SCIPsetIsFeasEQ(set, SCIPvarGetUbGlobal(var), bounds[v])) )
850 {
851 /* the literal is satisfied in global bounds (may happen due to weak "negation" of continuous variables)
852 * -> discard the conflict constraint
853 */
854 break;
855 }
856 else
857 {
858 nbinimpls[v] = (boundtypes[v] ? SCIPvarGetNVlbs(var) : SCIPvarGetNVubs(var));
859 }
860
861 if( nbinimpls[v] == 0 )
862 ++nzeroimpls;
863 }
864
865 /* starting to derive global bound changes */
866 if( v == nbdchginfos && ((!set->conf_fullshortenconflict && nzeroimpls < 2) || (set->conf_fullshortenconflict && nzeroimpls < nbdchginfos)) )
867 {
868 SCIP_VAR** vars;
869 SCIP_Bool* redundants;
870 SCIP_Bool glbinfeas;
871
872 /* sort variables in increasing order of binary implications to gain speed later on */
873 SCIPsortLongPtrRealRealBool(nbinimpls, (void**)bdchginfos, relaxedbds, bounds, boundtypes, v);
874
875 SCIPsetDebugMsg(set, "checking for global reductions and redundant conflict variables(in %s) on conflict:\n", SCIPprobGetName(prob));
876 SCIPsetDebugMsg(set, "[");
877 for( v = 0; v < nbdchginfos; ++v )
878 {
879 SCIPsetDebugMsgPrint(set, "%s %s %g", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfos[v])), (!boundtypes[v]) ? ">=" : "<=", bounds[v]);
880 if( v < nbdchginfos - 1 )
882 }
884
886 SCIP_CALL( SCIPsetAllocCleanBufferArray(set, &redundants, v) );
887
888 /* initialize conflict variable data */
889 for( v = 0; v < nbdchginfos; ++v )
890 vars[v] = SCIPbdchginfoGetVar(bdchginfos[v]);
891
892 SCIP_CALL( SCIPshrinkDisjunctiveVarSet(set->scip, vars, bounds, boundtypes, redundants, nbdchginfos, nredvars, \
893 nbdchgs, redundant, &glbinfeas, set->conf_fullshortenconflict) );
894
895 if( glbinfeas )
896 {
897 SCIPsetDebugMsg(set, "conflict set (%p) led to global infeasibility\n", (void*) conflictset);
898
899 SCIP_CALL( SCIPnodeCutoff(SCIPtreeGetRootNode(tree), set, stat, eventfilter, tree, prob, origprob, reopt, lp, blkmem) );
900
901 /* clear the memory array before freeing it */
902 BMSclearMemoryArray(redundants, nbdchginfos);
903 goto TERMINATE;
904 }
905
906#ifdef SCIP_DEBUG
907 if( *nbdchgs > 0 )
908 {
909 SCIPsetDebugMsg(set, "conflict set (%p) led to %d global bound reductions\n", (void*) conflictset, *nbdchgs);
910 }
911#endif
912
913 /* remove as redundant marked variables */
914 if( *redundant )
915 {
916 SCIPsetDebugMsg(set, "conflict set (%p) is redundant because at least one global reduction, fulfills the conflict constraint\n", (void*)conflictset);
917
918 /* clear the memory array before freeing it */
919 BMSclearMemoryArray(redundants, nbdchginfos);
920 }
921 else if( *nredvars > 0 )
922 {
923 assert(bdchginfos == conflictset->bdchginfos);
924 assert(relaxedbds == conflictset->relaxedbds);
925 assert(sortvals == conflictset->sortvals);
926
927 for( v = nbdchginfos - 1; v >= 0; --v )
928 {
929 /* if conflict variable was marked to be redundant remove it */
930 if( redundants[v] )
931 {
932 SCIPsetDebugMsg(set, "remove redundant variable <%s> from conflict set\n", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfos[v])));
933
934 bdchginfos[v] = bdchginfos[nbdchginfos - 1];
935 relaxedbds[v] = relaxedbds[nbdchginfos - 1];
936 sortvals[v] = sortvals[nbdchginfos - 1];
937
938 /* reset redundants[v] to 0 */
939 redundants[v] = 0;
940
941 --nbdchginfos;
942 }
943 }
944 assert((*nredvars) + nbdchginfos == conflictset->nbdchginfos);
945
946 SCIPsetDebugMsg(set, "removed %d redundant of %d variables from conflictset (%p)\n", (*nredvars), conflictset->nbdchginfos, (void*)conflictset);
947 conflictset->nbdchginfos = nbdchginfos;
948 }
949 else
950 {
951 /* clear the memory array before freeing it */
952 BMSclearMemoryArray(redundants, nbdchginfos);
953 }
954
955 TERMINATE:
956 SCIPsetFreeCleanBufferArray(set, &redundants);
958 }
959
960 /* free temporary memory */
961 SCIPsetFreeBufferArray(set, &nbinimpls);
962 SCIPsetFreeBufferArray(set, &bounds);
963 SCIPsetFreeBufferArray(set, &boundtypes);
964
965 *nredvars += ntrivialredvars;
966
967 return SCIP_OKAY;
968}
969
970/** clears the given conflict set */
971static
973 SCIP_CONFLICTSET* conflictset /**< conflict set */
974 )
975{
976 assert(conflictset != NULL);
977
978 conflictset->nbdchginfos = 0;
979 conflictset->validdepth = 0;
980 conflictset->insertdepth = 0;
981 conflictset->conflictdepth = 0;
982 conflictset->repropdepth = 0;
983 conflictset->repropagate = TRUE;
984 conflictset->usescutoffbound = FALSE;
985 conflictset->hasrelaxonlyvar = FALSE;
986 conflictset->conflicttype = SCIP_CONFTYPE_UNKNOWN;
987}
988
989/** creates an empty conflict set */
991 SCIP_CONFLICTSET** conflictset, /**< pointer to store the conflict set */
992 BMS_BLKMEM* blkmem /**< block memory of transformed problem */
993 )
994{
995 assert(conflictset != NULL);
996
997 SCIP_ALLOC( BMSallocBlockMemory(blkmem, conflictset) );
998 (*conflictset)->bdchginfos = NULL;
999 (*conflictset)->relaxedbds = NULL;
1000 (*conflictset)->sortvals = NULL;
1001 (*conflictset)->bdchginfossize = 0;
1002
1003 conflictsetClear(*conflictset);
1004
1005 return SCIP_OKAY;
1006}
1007
1008/** creates a copy of the given conflict set, allocating an additional amount of memory */
1009static
1011 SCIP_CONFLICTSET** targetconflictset, /**< pointer to store the conflict set */
1012 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
1013 SCIP_CONFLICTSET* sourceconflictset, /**< source conflict set */
1014 int nadditionalelems /**< number of additional elements to allocate memory for */
1015 )
1016{
1017 int targetsize;
1018
1019 assert(targetconflictset != NULL);
1020 assert(sourceconflictset != NULL);
1021
1022 targetsize = sourceconflictset->nbdchginfos + nadditionalelems;
1023 SCIP_ALLOC( BMSallocBlockMemory(blkmem, targetconflictset) );
1024 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetconflictset)->bdchginfos, targetsize) );
1025 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetconflictset)->relaxedbds, targetsize) );
1026 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetconflictset)->sortvals, targetsize) );
1027 (*targetconflictset)->bdchginfossize = targetsize;
1028
1029 BMScopyMemoryArray((*targetconflictset)->bdchginfos, sourceconflictset->bdchginfos, sourceconflictset->nbdchginfos);
1030 BMScopyMemoryArray((*targetconflictset)->relaxedbds, sourceconflictset->relaxedbds, sourceconflictset->nbdchginfos);
1031 BMScopyMemoryArray((*targetconflictset)->sortvals, sourceconflictset->sortvals, sourceconflictset->nbdchginfos);
1032
1033 (*targetconflictset)->nbdchginfos = sourceconflictset->nbdchginfos;
1034 (*targetconflictset)->validdepth = sourceconflictset->validdepth;
1035 (*targetconflictset)->insertdepth = sourceconflictset->insertdepth;
1036 (*targetconflictset)->conflictdepth = sourceconflictset->conflictdepth;
1037 (*targetconflictset)->repropdepth = sourceconflictset->repropdepth;
1038 (*targetconflictset)->usescutoffbound = sourceconflictset->usescutoffbound;
1039 (*targetconflictset)->hasrelaxonlyvar = sourceconflictset->hasrelaxonlyvar;
1040 (*targetconflictset)->conflicttype = sourceconflictset->conflicttype;
1041
1042 return SCIP_OKAY;
1043}
1044
1045/** frees a conflict set */
1047 SCIP_CONFLICTSET** conflictset, /**< pointer to the conflict set */
1048 BMS_BLKMEM* blkmem /**< block memory of transformed problem */
1049 )
1050{
1051 assert(conflictset != NULL);
1052 assert(*conflictset != NULL);
1053
1054 BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->bdchginfos, (*conflictset)->bdchginfossize);
1055 BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->relaxedbds, (*conflictset)->bdchginfossize);
1056 BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->sortvals, (*conflictset)->bdchginfossize);
1057 BMSfreeBlockMemory(blkmem, conflictset);
1058}
1059
1060/** calculates the score of the conflict set
1061 *
1062 * the score is weighted sum of number of bound changes, repropagation depth, and valid depth
1063 */
1064static
1066 SCIP_CONFLICTSET* conflictset, /**< conflict set */
1067 SCIP_SET* set /**< global SCIP settings */
1068 )
1069{
1070 assert(conflictset != NULL);
1071
1072 return -(set->conf_weightsize * conflictset->nbdchginfos
1073 + set->conf_weightrepropdepth * conflictset->repropdepth
1074 + set->conf_weightvaliddepth * conflictset->validdepth);
1075}
1076
1077
1078/*
1079 * Conflict Handler
1080 */
1081
1082/** compares two conflict handlers w. r. to their priority */
1083SCIP_DECL_SORTPTRCOMP(SCIPconflicthdlrComp)
1084{ /*lint --e{715}*/
1085 return ((SCIP_CONFLICTHDLR*)elem2)->priority - ((SCIP_CONFLICTHDLR*)elem1)->priority;
1086}
1087
1088/** comparison method for sorting conflict handler w.r.t. to their name */
1089SCIP_DECL_SORTPTRCOMP(SCIPconflicthdlrCompName)
1090{
1092}
1093
1094/** method to call, when the priority of a conflict handler was changed */
1095static
1096SCIP_DECL_PARAMCHGD(paramChgdConflicthdlrPriority)
1097{ /*lint --e{715}*/
1098 SCIP_PARAMDATA* paramdata;
1099
1100 paramdata = SCIPparamGetData(param);
1101 assert(paramdata != NULL);
1102
1103 /* use SCIPsetConflicthdlrPriority() to mark the conflicthdlrs unsorted */
1104 SCIP_CALL( SCIPsetConflicthdlrPriority(scip, (SCIP_CONFLICTHDLR*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
1105
1106 return SCIP_OKAY;
1107}
1108
1109/** copies the given conflict handler to a new scip */
1111 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1112 SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
1113 )
1114{
1115 assert(conflicthdlr != NULL);
1116 assert(set != NULL);
1117 assert(set->scip != NULL);
1118
1119 if( conflicthdlr->conflictcopy != NULL )
1120 {
1121 SCIPsetDebugMsg(set, "including conflict handler %s in subscip %p\n", SCIPconflicthdlrGetName(conflicthdlr), (void*)set->scip);
1122 SCIP_CALL( conflicthdlr->conflictcopy(set->scip, conflicthdlr) );
1123 }
1124
1125 return SCIP_OKAY;
1126}
1127
1128/** internal method for creating a conflict handler */
1129static
1131 SCIP_CONFLICTHDLR** conflicthdlr, /**< pointer to conflict handler data structure */
1132 SCIP_SET* set, /**< global SCIP settings */
1133 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1134 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
1135 const char* name, /**< name of conflict handler */
1136 const char* desc, /**< description of conflict handler */
1137 int priority, /**< priority of the conflict handler */
1138 SCIP_DECL_CONFLICTCOPY((*conflictcopy)), /**< copy method of conflict handler or NULL if you don't want to copy your plugin into sub-SCIPs */
1139 SCIP_DECL_CONFLICTFREE((*conflictfree)), /**< destructor of conflict handler */
1140 SCIP_DECL_CONFLICTINIT((*conflictinit)), /**< initialize conflict handler */
1141 SCIP_DECL_CONFLICTEXIT((*conflictexit)), /**< deinitialize conflict handler */
1142 SCIP_DECL_CONFLICTINITSOL((*conflictinitsol)),/**< solving process initialization method of conflict handler */
1143 SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol)),/**< solving process deinitialization method of conflict handler */
1144 SCIP_DECL_CONFLICTEXEC((*conflictexec)), /**< conflict processing method of conflict handler */
1145 SCIP_CONFLICTHDLRDATA* conflicthdlrdata /**< conflict handler data */
1146 )
1147{
1149 char paramdesc[SCIP_MAXSTRLEN];
1150
1151 assert(conflicthdlr != NULL);
1152 assert(name != NULL);
1153 assert(desc != NULL);
1154
1155 SCIP_ALLOC( BMSallocMemory(conflicthdlr) );
1156 BMSclearMemory(*conflicthdlr);
1157
1158 SCIP_ALLOC( BMSduplicateMemoryArray(&(*conflicthdlr)->name, name, strlen(name)+1) );
1159 SCIP_ALLOC( BMSduplicateMemoryArray(&(*conflicthdlr)->desc, desc, strlen(desc)+1) );
1160 (*conflicthdlr)->priority = priority;
1161 (*conflicthdlr)->conflictcopy = conflictcopy;
1162 (*conflicthdlr)->conflictfree = conflictfree;
1163 (*conflicthdlr)->conflictinit = conflictinit;
1164 (*conflicthdlr)->conflictexit = conflictexit;
1165 (*conflicthdlr)->conflictinitsol = conflictinitsol;
1166 (*conflicthdlr)->conflictexitsol = conflictexitsol;
1167 (*conflicthdlr)->conflictexec = conflictexec;
1168 (*conflicthdlr)->conflicthdlrdata = conflicthdlrdata;
1169 (*conflicthdlr)->initialized = FALSE;
1170
1171 SCIP_CALL( SCIPclockCreate(&(*conflicthdlr)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
1172 SCIP_CALL( SCIPclockCreate(&(*conflicthdlr)->conflicttime, SCIP_CLOCKTYPE_DEFAULT) );
1173
1174 /* add parameters */
1175 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "conflict/%s/priority", name);
1176 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of conflict handler <%s>", name);
1177 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc, &(*conflicthdlr)->priority, TRUE, \
1178 priority, INT_MIN, INT_MAX, paramChgdConflicthdlrPriority, (SCIP_PARAMDATA*)(*conflicthdlr)) ); /*lint !e740*/
1179
1180 return SCIP_OKAY;
1181}
1182
1183/** creates a conflict handler */
1185 SCIP_CONFLICTHDLR** conflicthdlr, /**< pointer to conflict handler data structure */
1186 SCIP_SET* set, /**< global SCIP settings */
1187 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1188 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
1189 const char* name, /**< name of conflict handler */
1190 const char* desc, /**< description of conflict handler */
1191 int priority, /**< priority of the conflict handler */
1192 SCIP_DECL_CONFLICTCOPY((*conflictcopy)), /**< copy method of conflict handler or NULL if you don't want to
1193 * copy your plugin into sub-SCIPs */
1194 SCIP_DECL_CONFLICTFREE((*conflictfree)), /**< destructor of conflict handler */
1195 SCIP_DECL_CONFLICTINIT((*conflictinit)), /**< initialize conflict handler */
1196 SCIP_DECL_CONFLICTEXIT((*conflictexit)), /**< deinitialize conflict handler */
1197 SCIP_DECL_CONFLICTINITSOL((*conflictinitsol)),/**< solving process initialization method of conflict handler */
1198 SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol)),/**< solving process deinitialization method of conflict handler */
1199 SCIP_DECL_CONFLICTEXEC((*conflictexec)), /**< conflict processing method of conflict handler */
1200 SCIP_CONFLICTHDLRDATA* conflicthdlrdata /**< conflict handler data */
1201 )
1202{
1203 assert(conflicthdlr != NULL);
1204 assert(name != NULL);
1205 assert(desc != NULL);
1206
1207 SCIP_CALL_FINALLY( doConflicthdlrCreate(conflicthdlr, set, messagehdlr, blkmem, name, desc, priority,
1208 conflictcopy, conflictfree, conflictinit, conflictexit, conflictinitsol, conflictexitsol, conflictexec,
1209 conflicthdlrdata), (void) SCIPconflicthdlrFree(conflicthdlr, set) );
1210
1211 return SCIP_OKAY;
1212}
1213
1214/** calls destructor and frees memory of conflict handler */
1216 SCIP_CONFLICTHDLR** conflicthdlr, /**< pointer to conflict handler data structure */
1217 SCIP_SET* set /**< global SCIP settings */
1218 )
1219{
1220 assert(conflicthdlr != NULL);
1221 if( *conflicthdlr == NULL )
1222 return SCIP_OKAY;
1223 assert(!(*conflicthdlr)->initialized);
1224 assert(set != NULL);
1225
1226 /* call destructor of conflict handler */
1227 if( (*conflicthdlr)->conflictfree != NULL )
1228 {
1229 SCIP_CALL( (*conflicthdlr)->conflictfree(set->scip, *conflicthdlr) );
1230 }
1231
1232 SCIPclockFree(&(*conflicthdlr)->conflicttime);
1233 SCIPclockFree(&(*conflicthdlr)->setuptime);
1234
1235 BMSfreeMemoryArrayNull(&(*conflicthdlr)->name);
1236 BMSfreeMemoryArrayNull(&(*conflicthdlr)->desc);
1237 BMSfreeMemory(conflicthdlr);
1238
1239 return SCIP_OKAY;
1240}
1241
1242/** calls initialization method of conflict handler */
1244 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1245 SCIP_SET* set /**< global SCIP settings */
1246 )
1247{
1248 assert(conflicthdlr != NULL);
1249 assert(set != NULL);
1250
1251 if( conflicthdlr->initialized )
1252 {
1253 SCIPerrorMessage("conflict handler <%s> already initialized\n", conflicthdlr->name);
1254 return SCIP_INVALIDCALL;
1255 }
1256
1257 if( set->misc_resetstat )
1258 {
1259 SCIPclockReset(conflicthdlr->setuptime);
1260 SCIPclockReset(conflicthdlr->conflicttime);
1261 }
1262
1263 /* call initialization method of conflict handler */
1264 if( conflicthdlr->conflictinit != NULL )
1265 {
1266 /* start timing */
1267 SCIPclockStart(conflicthdlr->setuptime, set);
1268
1269 SCIP_CALL( conflicthdlr->conflictinit(set->scip, conflicthdlr) );
1270
1271 /* stop timing */
1272 SCIPclockStop(conflicthdlr->setuptime, set);
1273 }
1274 conflicthdlr->initialized = TRUE;
1275
1276 return SCIP_OKAY;
1277}
1278
1279/** calls exit method of conflict handler */
1281 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1282 SCIP_SET* set /**< global SCIP settings */
1283 )
1284{
1285 assert(conflicthdlr != NULL);
1286 assert(set != NULL);
1287
1288 if( !conflicthdlr->initialized )
1289 {
1290 SCIPerrorMessage("conflict handler <%s> not initialized\n", conflicthdlr->name);
1291 return SCIP_INVALIDCALL;
1292 }
1293
1294 /* call deinitialization method of conflict handler */
1295 if( conflicthdlr->conflictexit != NULL )
1296 {
1297 /* start timing */
1298 SCIPclockStart(conflicthdlr->setuptime, set);
1299
1300 SCIP_CALL( conflicthdlr->conflictexit(set->scip, conflicthdlr) );
1301
1302 /* stop timing */
1303 SCIPclockStop(conflicthdlr->setuptime, set);
1304 }
1305 conflicthdlr->initialized = FALSE;
1306
1307 return SCIP_OKAY;
1308}
1309
1310/** informs conflict handler that the branch and bound process is being started */
1312 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1313 SCIP_SET* set /**< global SCIP settings */
1314 )
1315{
1316 assert(conflicthdlr != NULL);
1317 assert(set != NULL);
1318
1319 /* call solving process initialization method of conflict handler */
1320 if( conflicthdlr->conflictinitsol != NULL )
1321 {
1322 /* start timing */
1323 SCIPclockStart(conflicthdlr->setuptime, set);
1324
1325 SCIP_CALL( conflicthdlr->conflictinitsol(set->scip, conflicthdlr) );
1326
1327 /* stop timing */
1328 SCIPclockStop(conflicthdlr->setuptime, set);
1329 }
1330
1331 return SCIP_OKAY;
1332}
1333
1334/** informs conflict handler that the branch and bound process data is being freed */
1336 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1337 SCIP_SET* set /**< global SCIP settings */
1338 )
1339{
1340 assert(conflicthdlr != NULL);
1341 assert(set != NULL);
1342
1343 /* call solving process deinitialization method of conflict handler */
1344 if( conflicthdlr->conflictexitsol != NULL )
1345 {
1346 /* start timing */
1347 SCIPclockStart(conflicthdlr->setuptime, set);
1348
1349 SCIP_CALL( conflicthdlr->conflictexitsol(set->scip, conflicthdlr) );
1350
1351 /* stop timing */
1352 SCIPclockStop(conflicthdlr->setuptime, set);
1353 }
1354
1355 return SCIP_OKAY;
1356}
1357
1358/** calls execution method of conflict handler */
1360 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1361 SCIP_SET* set, /**< global SCIP settings */
1362 SCIP_NODE* node, /**< node to add conflict constraint to */
1363 SCIP_NODE* validnode, /**< node at which the constraint is valid */
1364 SCIP_BDCHGINFO** bdchginfos, /**< bound change resembling the conflict set */
1365 SCIP_Real* relaxedbds, /**< array with relaxed bounds which are efficient to create a valid conflict */
1366 int nbdchginfos, /**< number of bound changes in the conflict set */
1367 SCIP_CONFTYPE conftype, /**< type of the conflict */
1368 SCIP_Bool usescutoffbound, /**< depends the conflict on the cutoff bound? */
1369 SCIP_Bool resolved, /**< was the conflict set already used to create a constraint? */
1370 SCIP_RESULT* result /**< pointer to store the result of the callback method */
1371 )
1372{
1373 assert(conflicthdlr != NULL);
1374 assert(set != NULL);
1375 assert(bdchginfos != NULL || nbdchginfos == 0);
1376 assert(result != NULL);
1377
1378 /* call solution start method of conflict handler */
1379 *result = SCIP_DIDNOTRUN;
1380 if( conflicthdlr->conflictexec != NULL )
1381 {
1382 /* start timing */
1383 SCIPclockStart(conflicthdlr->conflicttime, set);
1384
1385 SCIP_CALL( conflicthdlr->conflictexec(set->scip, conflicthdlr, node, validnode, bdchginfos, relaxedbds, nbdchginfos,
1386 conftype, usescutoffbound, set->conf_separate, (SCIPnodeGetDepth(validnode) > 0), set->conf_dynamic,
1387 set->conf_removable, resolved, result) );
1388
1389 /* stop timing */
1390 SCIPclockStop(conflicthdlr->conflicttime, set);
1391
1392 if( *result != SCIP_CONSADDED
1393 && *result != SCIP_DIDNOTFIND
1394 && *result != SCIP_DIDNOTRUN )
1395 {
1396 SCIPerrorMessage("execution method of conflict handler <%s> returned invalid result <%d>\n",
1397 conflicthdlr->name, *result);
1398 return SCIP_INVALIDRESULT;
1399 }
1400 }
1401
1402 return SCIP_OKAY;
1403}
1404
1405/** gets user data of conflict handler */
1407 SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
1408 )
1409{
1410 assert(conflicthdlr != NULL);
1411
1412 return conflicthdlr->conflicthdlrdata;
1413}
1414
1415/** sets user data of conflict handler; user has to free old data in advance! */
1417 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1418 SCIP_CONFLICTHDLRDATA* conflicthdlrdata /**< new conflict handler user data */
1419 )
1420{
1421 assert(conflicthdlr != NULL);
1422
1423 conflicthdlr->conflicthdlrdata = conflicthdlrdata;
1424}
1425
1426/** set copy method of conflict handler */
1428 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1429 SCIP_DECL_CONFLICTCOPY((*conflictcopy)) /**< copy method of the conflict handler */
1430 )
1431{
1432 assert(conflicthdlr != NULL);
1433
1434 conflicthdlr->conflictcopy = conflictcopy;
1435}
1436
1437/** set destructor of conflict handler */
1439 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1440 SCIP_DECL_CONFLICTFREE((*conflictfree)) /**< destructor of conflict handler */
1441 )
1442{
1443 assert(conflicthdlr != NULL);
1444
1445 conflicthdlr->conflictfree = conflictfree;
1446}
1447
1448/** set initialization method of conflict handler */
1449
1451 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1452 SCIP_DECL_CONFLICTINIT((*conflictinit)) /**< initialization method conflict handler */
1453 )
1454{
1455 assert(conflicthdlr != NULL);
1456
1457 conflicthdlr->conflictinit = conflictinit;
1458}
1459
1460/** set deinitialization method of conflict handler */
1462 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1463 SCIP_DECL_CONFLICTEXIT((*conflictexit)) /**< deinitialization method conflict handler */
1464 )
1465{
1466 assert(conflicthdlr != NULL);
1467
1468 conflicthdlr->conflictexit = conflictexit;
1469}
1470
1471/** set solving process initialization method of conflict handler */
1473 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1474 SCIP_DECL_CONFLICTINITSOL((*conflictinitsol))/**< solving process initialization method of conflict handler */
1475 )
1476{
1477 assert(conflicthdlr != NULL);
1478
1479 conflicthdlr->conflictinitsol = conflictinitsol;
1480}
1481
1482/** set solving process deinitialization method of conflict handler */
1484 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1485 SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol))/**< solving process deinitialization method of conflict handler */
1486 )
1487{
1488 assert(conflicthdlr != NULL);
1489
1490 conflicthdlr->conflictexitsol = conflictexitsol;
1491}
1492
1493/** gets name of conflict handler */
1495 SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
1496 )
1497{
1498 assert(conflicthdlr != NULL);
1499
1500 return conflicthdlr->name;
1501}
1502
1503/** gets description of conflict handler */
1505 SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
1506 )
1507{
1508 assert(conflicthdlr != NULL);
1509
1510 return conflicthdlr->desc;
1511}
1512
1513/** gets priority of conflict handler */
1515 SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
1516 )
1517{
1518 assert(conflicthdlr != NULL);
1519
1520 return conflicthdlr->priority;
1521}
1522
1523/** sets priority of conflict handler */
1525 SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
1526 SCIP_SET* set, /**< global SCIP settings */
1527 int priority /**< new priority of the conflict handler */
1528 )
1529{
1530 assert(conflicthdlr != NULL);
1531 assert(set != NULL);
1532
1533 conflicthdlr->priority = priority;
1534 set->conflicthdlrssorted = FALSE;
1535}
1536
1537/** is conflict handler initialized? */
1539 SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
1540 )
1541{
1542 assert(conflicthdlr != NULL);
1543
1544 return conflicthdlr->initialized;
1545}
1546
1547/** enables or disables all clocks of \p conflicthdlr, depending on the value of the flag */
1549 SCIP_CONFLICTHDLR* conflicthdlr, /**< the conflict handler for which all clocks should be enabled or disabled */
1550 SCIP_Bool enable /**< should the clocks of the conflict handler be enabled? */
1551 )
1552{
1553 assert(conflicthdlr != NULL);
1554
1555 SCIPclockEnableOrDisable(conflicthdlr->setuptime, enable);
1556 SCIPclockEnableOrDisable(conflicthdlr->conflicttime, enable);
1557}
1558
1559/** gets time in seconds used in this conflict handler for setting up for next stages */
1561 SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
1562 )
1563{
1564 assert(conflicthdlr != NULL);
1565
1566 return SCIPclockGetTime(conflicthdlr->setuptime);
1567}
1568
1569/** gets time in seconds used in this conflict handler */
1571 SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
1572 )
1573{
1574 assert(conflicthdlr != NULL);
1575
1576 return SCIPclockGetTime(conflicthdlr->conflicttime);
1577}
1578
1579/** return TRUE if conflict graph analysis is applicable */
1581 SCIP_SET* set /**< global SCIP settings */
1582 )
1583{
1584 /* check, if propagation conflict analysis is enabled */
1585 if( !set->conf_enable || !set->conf_useprop )
1586 return FALSE;
1587
1588 /* check, if there are any conflict handlers to use a conflict set */
1589 if( set->nconflicthdlrs == 0 )
1590 return FALSE;
1591
1592 return TRUE;
1593}
1594
1595/** resizes the array of the temporary bound change informations to be able to store at least num bound change entries */
1596static
1598 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1599 SCIP_SET* set, /**< global SCIP settings */
1600 int num /**< minimal number of slots in arrays */
1601 )
1602{
1603 assert(conflict != NULL);
1604 assert(set != NULL);
1605
1606 if( num > conflict->tmpbdchginfossize )
1607 {
1608 int newsize;
1609
1610 newsize = SCIPsetCalcMemGrowSize(set, num);
1611 SCIP_ALLOC( BMSreallocMemoryArray(&conflict->tmpbdchginfos, newsize) );
1612 conflict->tmpbdchginfossize = newsize;
1613 }
1614 assert(num <= conflict->tmpbdchginfossize);
1615
1616 return SCIP_OKAY;
1617}
1618
1619/** creates a temporary bound change information object that is destroyed after the conflict sets are flushed */
1621 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1622 BMS_BLKMEM* blkmem, /**< block memory */
1623 SCIP_SET* set, /**< global SCIP settings */
1624 SCIP_VAR* var, /**< active variable that changed the bounds */
1625 SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1626 SCIP_Real oldbound, /**< old value for bound */
1627 SCIP_Real newbound, /**< new value for bound */
1628 SCIP_BDCHGINFO** bdchginfo /**< pointer to store bound change information */
1629 )
1630{
1631 assert(conflict != NULL);
1632
1634 SCIP_CALL( SCIPbdchginfoCreate(&conflict->tmpbdchginfos[conflict->ntmpbdchginfos], blkmem,
1635 var, boundtype, oldbound, newbound) );
1636 *bdchginfo = conflict->tmpbdchginfos[conflict->ntmpbdchginfos];
1637 conflict->ntmpbdchginfos++;
1638
1639 return SCIP_OKAY;
1640}
1641
1642/** frees all temporarily created bound change information data */
1643static
1645 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1646 BMS_BLKMEM* blkmem /**< block memory */
1647 )
1648{
1649 int i;
1650
1651 assert(conflict != NULL);
1652
1653 for( i = 0; i < conflict->ntmpbdchginfos; ++i )
1654 SCIPbdchginfoFree(&conflict->tmpbdchginfos[i], blkmem);
1655 conflict->ntmpbdchginfos = 0;
1656}
1657
1658/** increases the conflict score of the variable in the given direction */
1659static
1661 SCIP_VAR* var, /**< problem variable */
1662 BMS_BLKMEM* blkmem, /**< block memory */
1663 SCIP_SET* set, /**< global SCIP settings */
1664 SCIP_STAT* stat, /**< dynamic problem statistics */
1665 SCIP_BOUNDTYPE boundtype, /**< type of bound for which the score should be increased */
1666 SCIP_Real value, /**< value of the bound */
1667 SCIP_Real weight /**< weight of this VSIDS updates */
1668 )
1669{
1670 SCIP_BRANCHDIR branchdir;
1671
1672 assert(var != NULL);
1673 assert(stat != NULL);
1674
1675 /* weight the VSIDS by the given weight */
1676 weight *= stat->vsidsweight;
1677
1678 if( SCIPsetIsZero(set, weight) )
1679 return SCIP_OKAY;
1680
1681 branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
1682 SCIP_CALL( SCIPvarIncVSIDS(var, blkmem, set, stat, branchdir, value, weight) );
1683 SCIPhistoryIncVSIDS(stat->glbhistory, branchdir, weight);
1684 SCIPhistoryIncVSIDS(stat->glbhistorycrun, branchdir, weight);
1685
1686 return SCIP_OKAY;
1687}
1688
1689/** update conflict statistics */
1690static
1692 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1693 BMS_BLKMEM* blkmem, /**< block memory */
1694 SCIP_SET* set, /**< global SCIP settings */
1695 SCIP_STAT* stat, /**< dynamic problem statistics */
1696 SCIP_CONFLICTSET* conflictset, /**< conflict set to add to the tree */
1697 int insertdepth /**< depth level at which the conflict set should be added */
1698 )
1699{
1700 if( insertdepth > 0 )
1701 {
1702 conflict->nappliedlocconss++;
1703 conflict->nappliedlocliterals += conflictset->nbdchginfos;
1704 }
1705 else
1706 {
1707 int i;
1708 int conflictlength;
1709 conflictlength = conflictset->nbdchginfos;
1710
1711 for( i = 0; i < conflictlength; i++ )
1712 {
1713 SCIP_VAR* var;
1714 SCIP_BRANCHDIR branchdir;
1715 SCIP_BOUNDTYPE boundtype;
1717
1718 assert(stat != NULL);
1719
1720 var = conflictset->bdchginfos[i]->var;
1721 boundtype = SCIPbdchginfoGetBoundtype(conflictset->bdchginfos[i]);
1722 bound = conflictset->relaxedbds[i];
1723
1724 branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
1725
1726 SCIP_CALL( SCIPvarIncNActiveConflicts(var, blkmem, set, stat, branchdir, bound, (SCIP_Real)conflictlength) );
1727 SCIPhistoryIncNActiveConflicts(stat->glbhistory, branchdir, (SCIP_Real)conflictlength);
1728 SCIPhistoryIncNActiveConflicts(stat->glbhistorycrun, branchdir, (SCIP_Real)conflictlength);
1729
1730 /* each variable which is part of the conflict gets an increase in the VSIDS */
1731 SCIP_CALL( incVSIDS(var, blkmem, set, stat, boundtype, bound, set->conf_conflictweight) );
1732 }
1733 conflict->nappliedglbconss++;
1734 conflict->nappliedglbliterals += conflictset->nbdchginfos;
1735 }
1736
1737 return SCIP_OKAY;
1738}
1739
1740/** adds the given conflict set as conflict constraint to the problem */
1741static
1743 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1744 BMS_BLKMEM* blkmem, /**< block memory */
1745 SCIP_SET* set, /**< global SCIP settings */
1746 SCIP_STAT* stat, /**< dynamic problem statistics */
1747 SCIP_PROB* transprob, /**< transformed problem after presolve */
1748 SCIP_PROB* origprob, /**< original problem */
1749 SCIP_TREE* tree, /**< branch and bound tree */
1750 SCIP_REOPT* reopt, /**< reoptimization data structure */
1751 SCIP_LP* lp, /**< current LP data */
1752 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1753 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1754 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1755 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1756 SCIP_CONFLICTSET* conflictset, /**< conflict set to add to the tree */
1757 int insertdepth, /**< depth level at which the conflict set should be added */
1758 SCIP_Bool* success /**< pointer to store whether the addition was successful */
1759 )
1760{
1761 SCIP_Bool redundant;
1762 int h;
1763
1764 assert(conflict != NULL);
1765 assert(tree != NULL);
1766 assert(tree->path != NULL);
1767 assert(conflictset != NULL);
1768 assert(conflictset->validdepth <= insertdepth);
1769 assert(success != NULL);
1770
1771 *success = FALSE;
1772 redundant = FALSE;
1773
1774 /* try to derive global bound changes and shorten the conflictset by using implication and clique and variable bound
1775 * information
1776 */
1777 if( conflictset->nbdchginfos > 1 && insertdepth == 0 && !lp->strongbranching )
1778 {
1779 int nbdchgs;
1780 int nredvars;
1781#ifdef SCIP_DEBUG
1782 int oldnbdchginfos = conflictset->nbdchginfos;
1783#endif
1784 assert(conflictset->validdepth == 0);
1785
1786 /* check conflict set on debugging solution */
1787 SCIP_CALL( SCIPdebugCheckConflict(blkmem, set, tree->root, conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos) );
1788
1789 SCIPclockStart(conflict->dIBclock, set);
1790
1791 /* find global bound changes which can be derived from the new conflict set */
1792 SCIP_CALL( detectImpliedBounds(set, transprob, stat, tree, eventfilter, blkmem, origprob, reopt, lp, conflictset, &nbdchgs, &nredvars, &redundant) );
1793
1794 /* all variables where removed, we have an infeasibility proof */
1795 if( conflictset->nbdchginfos == 0 )
1796 return SCIP_OKAY;
1797
1798 /* debug check for reduced conflict set */
1799 if( nredvars > 0 )
1800 {
1801 /* check conflict set on debugging solution */
1802 SCIP_CALL( SCIPdebugCheckConflict(blkmem, set, tree->root, conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos) ); /*lint !e506 !e774*/
1803 }
1804
1805#ifdef SCIP_DEBUG
1806 SCIPsetDebugMsg(set, " -> conflict set removed %d redundant variables (old nvars %d, new nvars = %d)\n", nredvars, oldnbdchginfos, conflictset->nbdchginfos);
1807 SCIPsetDebugMsg(set, " -> conflict set led to %d global bound changes %s(cdpt:%d, fdpt:%d, confdpt:%d, len:%d):\n",
1808 nbdchgs, redundant ? "(conflict became redundant) " : "", SCIPtreeGetCurrentDepth(tree), SCIPtreeGetFocusDepth(tree),
1809 conflictset->conflictdepth, conflictset->nbdchginfos);
1810 conflictsetPrint(conflictset);
1811#endif
1812
1813 SCIPclockStop(conflict->dIBclock, set);
1814
1815 if( redundant )
1816 {
1817 if( nbdchgs > 0 )
1818 *success = TRUE;
1819
1820 return SCIP_OKAY;
1821 }
1822 }
1823
1824 /* in case the conflict set contains only one bound change which is globally valid we apply that bound change
1825 * directly (except if we are in strong branching or diving - in this case a bound change would yield an unflushed LP
1826 * and is not handled when restoring the information)
1827 *
1828 * @note A bound change can only be applied if it is are related to the active node or if is a global bound
1829 * change. Bound changes which are related to any other node cannot be handled at point due to the internal
1830 * data structure
1831 */
1832 if( conflictset->nbdchginfos == 1 && insertdepth == 0 && !lp->strongbranching && !lp->diving )
1833 {
1834 SCIP_VAR* var;
1836 SCIP_BOUNDTYPE boundtype;
1837
1838 var = conflictset->bdchginfos[0]->var;
1839 assert(var != NULL);
1840
1841 boundtype = SCIPboundtypeOpposite((SCIP_BOUNDTYPE) conflictset->bdchginfos[0]->boundtype);
1842 bound = conflictset->relaxedbds[0];
1843
1844 /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
1845 if( SCIPvarIsIntegral(var) )
1846 {
1847 assert(SCIPsetIsIntegral(set, bound));
1848 bound += (boundtype == SCIP_BOUNDTYPE_LOWER ? +1.0 : -1.0);
1849 }
1850
1851 SCIPsetDebugMsg(set, " -> apply global bound change: <%s> %s %g\n",
1852 SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", bound);
1853
1854 SCIP_CALL( SCIPnodeAddBoundchg(tree->path[conflictset->validdepth], blkmem, set, stat, transprob, origprob, tree,
1855 reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, bound, boundtype, FALSE) );
1856
1857 *success = TRUE;
1858 SCIP_CALL( updateStatistics(conflict, blkmem, set, stat, conflictset, insertdepth) );
1859 }
1860 else if( !conflictset->hasrelaxonlyvar )
1861 {
1862 /* sort conflict handlers by priority */
1864
1865 /* call conflict handlers to create a conflict constraint */
1866 for( h = 0; h < set->nconflicthdlrs; ++h )
1867 {
1868 SCIP_RESULT result;
1869
1870 assert(conflictset->conflicttype != SCIP_CONFTYPE_UNKNOWN);
1871
1872 SCIP_CALL( SCIPconflicthdlrExec(set->conflicthdlrs[h], set, tree->path[insertdepth],
1873 tree->path[conflictset->validdepth], conflictset->bdchginfos, conflictset->relaxedbds,
1874 conflictset->nbdchginfos, conflictset->conflicttype, conflictset->usescutoffbound, *success, &result) );
1875 if( result == SCIP_CONSADDED )
1876 {
1877 *success = TRUE;
1878 SCIP_CALL( updateStatistics(conflict, blkmem, set, stat, conflictset, insertdepth) );
1879 }
1880
1881 SCIPsetDebugMsg(set, " -> call conflict handler <%s> (prio=%d) to create conflict set with %d bounds returned result %d\n",
1882 SCIPconflicthdlrGetName(set->conflicthdlrs[h]), SCIPconflicthdlrGetPriority(set->conflicthdlrs[h]),
1883 conflictset->nbdchginfos, result);
1884 }
1885 }
1886 else
1887 {
1888 SCIPsetDebugMsg(set, " -> skip conflict set with relaxation-only variable\n");
1889 /* TODO would be nice to still create a constraint?, if we can make sure that we the constraint does not survive a restart */
1890 }
1891
1892 return SCIP_OKAY;
1893}
1894
1895/** calculates the maximal size of conflict sets to be used */
1897 SCIP_SET* set, /**< global SCIP settings */
1898 SCIP_PROB* prob /**< problem data */
1899 )
1900{
1901 int maxsize;
1902
1903 assert(set != NULL);
1904 assert(prob != NULL);
1905
1906 maxsize = (int)(set->conf_maxvarsfac * (prob->nvars - prob->ncontvars));
1907 maxsize = MAX(maxsize, set->conf_minmaxvars);
1908
1909 return maxsize;
1910}
1911
1912/** adds the collected conflict constraints to the corresponding nodes; the best set->conf_maxconss conflict constraints
1913 * are added to the node of their validdepth; additionally (if not yet added, and if repropagation is activated), the
1914 * conflict constraint that triggers the earliest repropagation is added to the node of its validdepth
1915 */
1917 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1918 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
1919 SCIP_SET* set, /**< global SCIP settings */
1920 SCIP_STAT* stat, /**< dynamic problem statistics */
1921 SCIP_PROB* transprob, /**< transformed problem */
1922 SCIP_PROB* origprob, /**< original problem */
1923 SCIP_TREE* tree, /**< branch and bound tree */
1924 SCIP_REOPT* reopt, /**< reoptimization data structure */
1925 SCIP_LP* lp, /**< current LP data */
1926 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1927 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1928 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1929 SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
1930 )
1931{
1932 assert(conflict != NULL);
1933 assert(set != NULL);
1934 assert(stat != NULL);
1935 assert(transprob != NULL);
1936 assert(tree != NULL);
1937
1938 /* is there anything to do? */
1939 if( conflict->nconflictsets > 0 )
1940 {
1941 SCIP_CONFLICTSET* repropconflictset;
1942 int nconflictsetsused;
1943 int focusdepth;
1944#ifndef NDEBUG
1945 int currentdepth;
1946#endif
1947 int cutoffdepth;
1948 int repropdepth;
1949 int maxconflictsets;
1950 int maxsize;
1951 int i;
1952
1953 /* calculate the maximal number of conflict sets to accept, and the maximal size of each accepted conflict set */
1954 maxconflictsets = (set->conf_maxconss == -1 ? INT_MAX : set->conf_maxconss);
1955 maxsize = conflictCalcMaxsize(set, transprob);
1956
1957 focusdepth = SCIPtreeGetFocusDepth(tree);
1958#ifndef NDEBUG
1959 currentdepth = SCIPtreeGetCurrentDepth(tree);
1960 assert(focusdepth <= currentdepth);
1961 assert(currentdepth == tree->pathlen-1);
1962#endif
1963
1964 SCIPsetDebugMsg(set, "flushing %d conflict sets at focus depth %d (maxconflictsets: %d, maxsize: %d)\n",
1965 conflict->nconflictsets, focusdepth, maxconflictsets, maxsize);
1966
1967 /* mark the focus node to have produced conflict sets in the visualization output */
1968 SCIPvisualFoundConflict(stat->visual, stat, tree->path[focusdepth]);
1969
1970 /* insert the conflict sets at the corresponding nodes */
1971 nconflictsetsused = 0;
1972 cutoffdepth = INT_MAX;
1973 repropdepth = INT_MAX;
1974 repropconflictset = NULL;
1975 for( i = 0; i < conflict->nconflictsets && nconflictsetsused < maxconflictsets; ++i )
1976 {
1977 SCIP_CONFLICTSET* conflictset;
1978
1979 conflictset = conflict->conflictsets[i];
1980 assert(conflictset != NULL);
1981 assert(0 <= conflictset->validdepth);
1982 assert(conflictset->validdepth <= conflictset->insertdepth);
1983 assert(conflictset->insertdepth <= focusdepth);
1984 assert(conflictset->insertdepth <= conflictset->repropdepth);
1985 assert(conflictset->repropdepth <= currentdepth || conflictset->repropdepth == INT_MAX); /* INT_MAX for dive/probing/strong */
1986 assert(conflictset->conflictdepth <= currentdepth || conflictset->conflictdepth == INT_MAX); /* INT_MAX for dive/probing/strong */
1987
1988 /* ignore conflict sets that are only valid at a node that was already cut off */
1989 if( conflictset->insertdepth >= cutoffdepth )
1990 {
1991 SCIPsetDebugMsg(set, " -> ignoring conflict set with insertdepth %d >= cutoffdepth %d\n",
1992 conflictset->validdepth, cutoffdepth);
1993 continue;
1994 }
1995
1996 /* if no conflict bounds exist, the node and its sub tree in the conflict set's valid depth can be
1997 * cut off completely
1998 */
1999 if( conflictset->nbdchginfos == 0 )
2000 {
2001 SCIPsetDebugMsg(set, " -> empty conflict set in depth %d cuts off sub tree at depth %d\n",
2002 focusdepth, conflictset->validdepth);
2003
2004 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictset->validdepth], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
2005 cutoffdepth = conflictset->validdepth;
2006 continue;
2007 }
2008
2009 /* if the conflict set is too long, use the conflict set only if it decreases the repropagation depth */
2010 if( conflictset->nbdchginfos > maxsize )
2011 {
2012 SCIPsetDebugMsg(set, " -> conflict set is too long: %d > %d literals\n", conflictset->nbdchginfos, maxsize);
2013 if( set->conf_keepreprop && conflictset->repropagate && conflictset->repropdepth < repropdepth )
2014 {
2015 repropdepth = conflictset->repropdepth;
2016 repropconflictset = conflictset;
2017 }
2018 }
2019 else
2020 {
2021 SCIP_Bool success;
2022
2023 /* call conflict handlers to create a conflict constraint */
2024 SCIP_CALL( conflictAddConflictCons(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
2025 branchcand, eventqueue, eventfilter, cliquetable, conflictset, conflictset->insertdepth, &success) );
2026
2027 /* if no conflict bounds exist, the node and its sub tree in the conflict set's valid depth can be
2028 * cut off completely
2029 */
2030 if( conflictset->nbdchginfos == 0 )
2031 {
2032 assert(!success);
2033
2034 SCIPsetDebugMsg(set, " -> empty conflict set in depth %d cuts off sub tree at depth %d\n",
2035 focusdepth, conflictset->validdepth);
2036
2037 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictset->validdepth], set, stat, eventfilter, tree, transprob,
2038 origprob, reopt, lp, blkmem) );
2039 cutoffdepth = conflictset->validdepth;
2040 continue;
2041 }
2042
2043 if( success )
2044 {
2045 SCIPsetDebugMsg(set, " -> conflict set %d/%d added (cdpt:%d, fdpt:%d, insert:%d, valid:%d, conf:%d, reprop:%d, len:%d):\n",
2046 nconflictsetsused+1, maxconflictsets, SCIPtreeGetCurrentDepth(tree), SCIPtreeGetFocusDepth(tree),
2047 conflictset->insertdepth, conflictset->validdepth, conflictset->conflictdepth, conflictset->repropdepth,
2048 conflictset->nbdchginfos);
2049 SCIPdebug(conflictsetPrint(conflictset));
2050 SCIPdebugPrintf("\n");
2051 if( conflictset->repropagate && conflictset->repropdepth <= repropdepth )
2052 {
2053 repropdepth = conflictset->repropdepth;
2054 repropconflictset = NULL;
2055 }
2056 nconflictsetsused++;
2057 }
2058 }
2059 }
2060
2061 /* reactivate propagation on the first node where one of the new conflict sets trigger a deduction */
2062 if( set->conf_repropagate && repropdepth < cutoffdepth && repropdepth < tree->pathlen )
2063 {
2064 assert(0 <= repropdepth && repropdepth < tree->pathlen);
2065 assert((int) tree->path[repropdepth]->depth == repropdepth);
2066
2067 /* if the conflict constraint of smallest repropagation depth was not yet added, insert it now */
2068 if( repropconflictset != NULL )
2069 {
2070 SCIP_Bool success;
2071
2072 assert(repropconflictset->repropagate);
2073 assert(repropconflictset->repropdepth == repropdepth);
2074
2075 SCIP_CALL( conflictAddConflictCons(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
2076 branchcand, eventqueue, eventfilter, cliquetable, repropconflictset, repropdepth, &success) );
2077
2078 /* if no conflict bounds exist, the node and its sub tree in the conflict set's valid depth can be
2079 * cut off completely
2080 */
2081 if( repropconflictset->nbdchginfos == 0 )
2082 {
2083 assert(!success);
2084
2085 SCIPsetDebugMsg(set, " -> empty reprop conflict set in depth %d cuts off sub tree at depth %d\n",
2086 focusdepth, repropconflictset->validdepth);
2087
2088 SCIP_CALL( SCIPnodeCutoff(tree->path[repropconflictset->validdepth], set, stat, eventfilter, tree,
2089 transprob, origprob, reopt, lp, blkmem) );
2090 }
2091
2092#ifdef SCIP_DEBUG
2093 if( success )
2094 {
2095 SCIPsetDebugMsg(set, " -> additional reprop conflict set added (cdpt:%d, fdpt:%d, insert:%d, valid:%d, conf:%d, reprop:%d, len:%d):\n",
2097 repropconflictset->insertdepth, repropconflictset->validdepth, repropconflictset->conflictdepth,
2098 repropconflictset->repropdepth, repropconflictset->nbdchginfos);
2099 SCIPdebug(conflictsetPrint(repropconflictset));
2100 }
2101#endif
2102 }
2103
2104 /* mark the node in the repropdepth to be propagated again */
2105 SCIPnodePropagateAgain(tree->path[repropdepth], set, stat, tree);
2106
2107 SCIPsetDebugMsg(set, "marked node %p in depth %d to be repropagated due to conflicts found in depth %d\n",
2108 (void*)tree->path[repropdepth], repropdepth, focusdepth);
2109 }
2110
2111 /* free the conflict store */
2112 for( i = 0; i < conflict->nconflictsets; ++i )
2113 {
2114 SCIPconflictsetFree(&conflict->conflictsets[i], blkmem);
2115 }
2116 conflict->nconflictsets = 0;
2117 }
2118
2119 /* free all temporarily created bound change information data */
2120 conflictFreeTmpBdchginfos(conflict, blkmem);
2121
2122 return SCIP_OKAY;
2123}
2124
2125/** resizes conflictsets array to be able to store at least num entries */
2126static
2128 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2129 SCIP_SET* set, /**< global SCIP settings */
2130 int num /**< minimal number of slots in array */
2131 )
2132{
2133 assert(conflict != NULL);
2134 assert(set != NULL);
2135
2136 if( num > conflict->conflictsetssize )
2137 {
2138 int newsize;
2139
2140 newsize = SCIPsetCalcMemGrowSize(set, num);
2141 SCIP_ALLOC( BMSreallocMemoryArray(&conflict->conflictsets, newsize) );
2142 SCIP_ALLOC( BMSreallocMemoryArray(&conflict->conflictsetscores, newsize) );
2143 conflict->conflictsetssize = newsize;
2144 }
2145 assert(num <= conflict->conflictsetssize);
2146
2147 return SCIP_OKAY;
2148}
2149
2150/** inserts conflict set into sorted conflictsets array and deletes the conflict set pointer */
2151static
2153 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2154 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2155 SCIP_SET* set, /**< global SCIP settings */
2156 SCIP_CONFLICTSET** conflictset /**< pointer to conflict set to insert */
2157 )
2158{
2159 SCIP_Real score;
2160 int pos;
2161 int i;
2162 int j;
2163
2164 assert(conflict != NULL);
2165 assert(set != NULL);
2166 assert(conflictset != NULL);
2167 assert(*conflictset != NULL);
2168 assert((*conflictset)->validdepth <= (*conflictset)->insertdepth);
2169 assert(set->conf_allowlocal || (*conflictset)->validdepth == 0);
2170
2171 /* calculate conflict and repropagation depth */
2172 conflictsetCalcConflictDepth(*conflictset);
2173
2174 /* if we apply repropagations, the conflict set should be inserted at most at its repropdepth */
2175 if( set->conf_repropagate )
2176 (*conflictset)->insertdepth = MIN((*conflictset)->insertdepth, (*conflictset)->repropdepth);
2177 else
2178 (*conflictset)->repropdepth = INT_MAX;
2179 assert((*conflictset)->insertdepth <= (*conflictset)->repropdepth);
2180
2181 SCIPsetDebugMsg(set, "inserting conflict set (valid: %d, insert: %d, conf: %d, reprop: %d):\n",
2182 (*conflictset)->validdepth, (*conflictset)->insertdepth, (*conflictset)->conflictdepth, (*conflictset)->repropdepth);
2183 SCIPdebug(conflictsetPrint(*conflictset));
2184
2185 /* get the score of the conflict set */
2186 score = conflictsetCalcScore(*conflictset, set);
2187
2188 /* check, if conflict set is redundant to a better conflict set */
2189 for( pos = 0; pos < conflict->nconflictsets && score < conflict->conflictsetscores[pos]; ++pos )
2190 {
2191 /* check if conflict set is redundant with respect to conflictsets[pos] */
2192 if( conflictsetIsRedundant(*conflictset, conflict->conflictsets[pos]) )
2193 {
2194 SCIPsetDebugMsg(set, " -> conflict set is redundant to: ");
2195 SCIPdebug(conflictsetPrint(conflict->conflictsets[pos]));
2196 SCIPconflictsetFree(conflictset, blkmem);
2197 return SCIP_OKAY;
2198 }
2199
2200 /**@todo like in sepastore.c: calculate overlap between conflictsets -> large overlap reduces score */
2201 }
2202
2203 /* insert conflictset into the sorted conflictsets array */
2204 SCIP_CALL( conflictEnsureConflictsetsMem(conflict, set, conflict->nconflictsets + 1) );
2205 for( i = conflict->nconflictsets; i > pos; --i )
2206 {
2207 assert(score >= conflict->conflictsetscores[i-1]);
2208 conflict->conflictsets[i] = conflict->conflictsets[i-1];
2209 conflict->conflictsetscores[i] = conflict->conflictsetscores[i-1];
2210 }
2211 conflict->conflictsets[pos] = *conflictset;
2212 conflict->conflictsetscores[pos] = score;
2213 conflict->nconflictsets++;
2214
2215 /* remove worse conflictsets that are redundant to the new conflictset */
2216 for( i = pos+1, j = pos+1; i < conflict->nconflictsets; ++i )
2217 {
2218 if( conflictsetIsRedundant(conflict->conflictsets[i], *conflictset) )
2219 {
2220 SCIPsetDebugMsg(set, " -> conflict set dominates: ");
2222 SCIPconflictsetFree(&conflict->conflictsets[i], blkmem);
2223 }
2224 else
2225 {
2226 assert(j <= i);
2227 conflict->conflictsets[j] = conflict->conflictsets[i];
2228 conflict->conflictsetscores[j] = conflict->conflictsetscores[i];
2229 j++;
2230 }
2231 }
2232 assert(j <= conflict->nconflictsets);
2233 conflict->nconflictsets = j;
2234
2235#if defined(SCIP_CONFGRAPH) || defined(SCIP_CONFGRAPH_DOT)
2236 confgraphMarkConflictset(*conflictset);
2237#endif
2238
2239 *conflictset = NULL; /* ownership of pointer is now in the conflictsets array */
2240
2241 return SCIP_OKAY;
2242}
2243
2244/** marks bound to be present in the current conflict and returns whether a bound which is at least as tight was already
2245 * member of the current conflict (i.e., the given bound change does not need to be added)
2246 */
2247static
2249 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2250 SCIP_SET* set, /**< global SCIP settings */
2251 SCIP_BDCHGINFO* bdchginfo, /**< bound change to add to the conflict set */
2252 SCIP_Real relaxedbd /**< relaxed bound */
2253 )
2254{
2255 SCIP_VAR* var;
2256 SCIP_Real newbound;
2257
2258 assert(conflict != NULL);
2259
2260 var = SCIPbdchginfoGetVar(bdchginfo);
2261 newbound = SCIPbdchginfoGetNewbound(bdchginfo);
2262 assert(var != NULL);
2263
2264 switch( SCIPbdchginfoGetBoundtype(bdchginfo) )
2265 {
2267 /* check if the variables lower bound is already member of the conflict */
2268 if( var->conflictlbcount == conflict->count )
2269 {
2270 /* the variable is already member of the conflict; hence check if the new bound is redundant */
2271 if( var->conflictlb > newbound )
2272 {
2273 SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> >= %g since a stronger lower bound exist <%s> >= %g\n",
2274 SCIPvarGetName(var), newbound, SCIPvarGetName(var), var->conflictlb);
2275 return TRUE;
2276 }
2277 else if( var->conflictlb == newbound ) /*lint !e777*/
2278 {
2279 SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> >= %g since this lower bound is already present\n", SCIPvarGetName(var), newbound);
2280 SCIPsetDebugMsg(set, "adjust relaxed lower bound <%g> -> <%g>\n", var->conflictlb, relaxedbd);
2281 var->conflictrelaxedlb = MAX(var->conflictrelaxedlb, relaxedbd);
2282 return TRUE;
2283 }
2284 }
2285
2286 /* add the variable lower bound to the current conflict */
2287 var->conflictlbcount = conflict->count;
2288
2289 /* remember the lower bound and relaxed bound to allow only better/tighter lower bounds for that variables
2290 * w.r.t. this conflict
2291 */
2292 var->conflictlb = newbound;
2293 var->conflictrelaxedlb = relaxedbd;
2294
2295 return FALSE;
2296
2298 /* check if the variables upper bound is already member of the conflict */
2299 if( var->conflictubcount == conflict->count )
2300 {
2301 /* the variable is already member of the conflict; hence check if the new bound is redundant */
2302 if( var->conflictub < newbound )
2303 {
2304 SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> <= %g since a stronger upper bound exist <%s> <= %g\n",
2305 SCIPvarGetName(var), newbound, SCIPvarGetName(var), var->conflictub);
2306 return TRUE;
2307 }
2308 else if( var->conflictub == newbound ) /*lint !e777*/
2309 {
2310 SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> <= %g since this upper bound is already present\n", SCIPvarGetName(var), newbound);
2311 SCIPsetDebugMsg(set, "adjust relaxed upper bound <%g> -> <%g>\n", var->conflictub, relaxedbd);
2312 var->conflictrelaxedub = MIN(var->conflictrelaxedub, relaxedbd);
2313 return TRUE;
2314 }
2315 }
2316
2317 /* add the variable upper bound to the current conflict */
2318 var->conflictubcount = conflict->count;
2319
2320 /* remember the upper bound and relaxed bound to allow only better/tighter upper bounds for that variables
2321 * w.r.t. this conflict
2322 */
2323 var->conflictub = newbound;
2324 var->conflictrelaxedub = relaxedbd;
2325
2326 return FALSE;
2327
2328 default:
2329 SCIPerrorMessage("invalid bound type %d\n", SCIPbdchginfoGetBoundtype(bdchginfo));
2330 SCIPABORT();
2331 return FALSE; /*lint !e527*/
2332 }
2333}
2334/** marks bound to be present in the current conflict and returns whether a bound which is at least as tight was already
2335 * member of the current conflict (i.e., the given bound change does not need to be added)
2336 */
2337static
2339 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2340 SCIP_SET* set, /**< global SCIP settings */
2341 SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
2342 )
2343{
2344 SCIP_VAR* var;
2345 SCIP_Real newbound;
2346
2347 assert(conflict != NULL);
2348
2349 var = SCIPbdchginfoGetVar(bdchginfo);
2350 newbound = SCIPbdchginfoGetNewbound(bdchginfo);
2351 assert(var != NULL);
2352
2353 switch( SCIPbdchginfoGetBoundtype(bdchginfo) )
2354 {
2356 /* the variable is already member of the conflict; hence check if the new bound is redundant */
2357 if( conflict->conflictvarslbs[SCIPvarGetProbindex(var)] < newbound )
2358 {
2359 conflict->conflictvarslbs[SCIPvarGetProbindex(var)] = newbound;
2360 return FALSE;
2361 }
2362 SCIPsetDebugMsg(set, "ResQueue: ignoring redundant bound change <%s> >= %g since a stronger lower bound exist <%s> >= %g\n",
2363 SCIPvarGetName(var), newbound, SCIPvarGetName(var), conflict->conflictvarslbs[SCIPvarGetProbindex(var)]);
2364 return TRUE;
2365
2367 /* the variable is already member of the conflict; hence check if the new bound is redundant */
2368 if( conflict->conflictvarsubs[SCIPvarGetProbindex(var)] > newbound )
2369 {
2370 conflict->conflictvarsubs[SCIPvarGetProbindex(var)] = newbound;
2371 return FALSE;
2372 }
2373 SCIPsetDebugMsg(set, "ResQueue: ignoring redundant bound change <%s> <= %g since a stronger upper bound exist <%s> <= %g\n",
2374 SCIPvarGetName(var), newbound, SCIPvarGetName(var), conflict->conflictvarsubs[SCIPvarGetProbindex(var)]);
2375
2376 return TRUE;
2377
2378 default:
2379 SCIPerrorMessage("invalid bound type %d\n", SCIPbdchginfoGetBoundtype(bdchginfo));
2380 SCIPABORT();
2381 return FALSE; /*lint !e527*/
2382 }
2383}
2384
2385/** puts bound change into the current conflict set */
2386static
2388 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2389 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2390 SCIP_SET* set, /**< global SCIP settings */
2391 SCIP_BDCHGINFO* bdchginfo, /**< bound change to add to the conflict set */
2392 SCIP_Real relaxedbd /**< relaxed bound */
2393 )
2394{
2395 assert(conflict != NULL);
2396 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
2397
2398 /* check if the relaxed bound is really a relaxed bound */
2399 assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
2400 assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
2401
2402 SCIPsetDebugMsg(set, "putting bound change <%s> %s %g(%g) at depth %d to current conflict set\n",
2404 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", SCIPbdchginfoGetNewbound(bdchginfo),
2405 relaxedbd, SCIPbdchginfoGetDepth(bdchginfo));
2406
2407 /* mark the bound to be member of the conflict and check if a bound which is at least as tight is already member of
2408 * the conflict
2409 */
2410 if( !conflictMarkBoundCheckPresence(conflict, set, bdchginfo, relaxedbd) )
2411 {
2412 /* add the bound change to the current conflict set */
2413 SCIP_CALL( conflictsetAddBound(conflict->conflictset, blkmem, set, bdchginfo, relaxedbd) );
2414
2415#if defined(SCIP_CONFGRAPH) || defined(SCIP_CONFGRAPH_DOT)
2416 if( bdchginfo != confgraphcurrentbdchginfo )
2417 confgraphAddBdchg(bdchginfo);
2418#endif
2419 }
2420#if defined(SCIP_CONFGRAPH) || defined(SCIP_CONFGRAPH_DOT)
2421 else
2422 confgraphLinkBdchg(bdchginfo);
2423#endif
2424
2425 return SCIP_OKAY;
2426}
2427
2428/** returns whether the negation of the given bound change would lead to a globally valid literal */
2429static
2431 SCIP_SET* set, /**< global SCIP settings */
2432 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
2433 )
2434{
2435 SCIP_VAR* var;
2436 SCIP_BOUNDTYPE boundtype;
2438
2439 var = SCIPbdchginfoGetVar(bdchginfo);
2440 boundtype = SCIPbdchginfoGetBoundtype(bdchginfo);
2441 bound = SCIPbdchginfoGetNewbound(bdchginfo);
2442
2443 return ( !SCIPvarIsIntegral(var)
2445 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLE(set, bound, SCIPvarGetLbGlobal(var)))));
2446}
2447
2448/** adds given bound change information to the conflict candidate queue */
2449static
2451 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2452 SCIP_SET* set, /**< global SCIP settings */
2453 SCIP_BDCHGINFO* bdchginfo, /**< bound change information */
2454 SCIP_Real relaxedbd, /**< relaxed bound */
2455 SCIP_Bool* success /**< was the bound change successfully added to the queue? */
2456 )
2457{
2458 assert(conflict != NULL);
2459 assert(set != NULL);
2460 assert(bdchginfo != NULL);
2461
2462 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
2463
2464 /* check if the relaxed bound is really a relaxed bound */
2465 assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
2466 assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
2467
2468 if( success != NULL )
2469 *success = FALSE;
2470
2471 if( set->conf_usegenres && !conflict->bdchgonlyconfqueue )
2472 {
2473 if( !betterBoundInResolutionQueue(conflict, set, bdchginfo) )
2474 {
2475 SCIP_CALL( SCIPpqueueInsert(conflict->resbdchgqueue, (void*)bdchginfo) );
2476 if( success != NULL )
2477 *success = TRUE;
2478 }
2479 }
2480 /* mark the bound to be member of the conflict and check if a bound which is at least as tight is already member of
2481 * the conflict
2482 */
2483 if( !conflict->bdchgonlyresqueue && set->conf_useprop && !conflictMarkBoundCheckPresence(conflict, set, bdchginfo, relaxedbd) )
2484 {
2485 /* insert the bound change into the conflict queue */
2486 if( (!set->conf_preferbinary || SCIPvarIsBinary(SCIPbdchginfoGetVar(bdchginfo)))
2487 && !isBoundchgUseless(set, bdchginfo) )
2488 {
2489 SCIP_CALL( SCIPpqueueInsert(conflict->bdchgqueue, (void*)bdchginfo) );
2490 if( success != NULL )
2491 *success = TRUE;
2492 }
2493 else
2494 {
2495 SCIP_CALL( SCIPpqueueInsert(conflict->forcedbdchgqueue, (void*)bdchginfo) );
2496 if( success != NULL )
2497 *success = TRUE;
2498 }
2499
2500#if defined(SCIP_CONFGRAPH) || defined(SCIP_CONFGRAPH_DOT)
2501 confgraphAddBdchg(bdchginfo);
2502#endif
2503 }
2504#if defined(SCIP_CONFGRAPH) || defined(SCIP_CONFGRAPH_DOT)
2505 else
2506 confgraphLinkBdchg(bdchginfo);
2507#endif
2508
2509 return SCIP_OKAY;
2510}
2511
2512/** adds variable's bound to conflict candidate queue */
2513static
2515 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2516 BMS_BLKMEM* blkmem, /**< block memory */
2517 SCIP_SET* set, /**< global SCIP settings */
2518 SCIP_STAT* stat, /**< dynamic problem statistics */
2519 SCIP_VAR* var, /**< problem variable */
2520 SCIP_BOUNDTYPE boundtype, /**< type of bound that was changed: lower or upper bound */
2521 SCIP_BDCHGINFO* bdchginfo, /**< bound change info, or NULL */
2522 SCIP_Real relaxedbd /**< relaxed bound */
2523 )
2524{
2525 SCIP_Bool success;
2526
2527 assert(SCIPvarIsActive(var));
2528 assert(bdchginfo != NULL);
2529 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
2530
2531 SCIPsetDebugMsg(set, " -> adding bound <%s> %s %.15g(%.15g) [status:%d, type:%d, depth:%d, pos:%d, reason:<%s>, info:%d] to candidates\n",
2532 SCIPvarGetName(var),
2533 boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
2534 SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd,
2536 SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
2541 : "none")),
2543
2544 /* the local bound change may be resolved and has to be put on the candidate queue;
2545 * we even put bound changes without inference information on the queue in order to automatically
2546 * eliminate multiple insertions of the same bound change
2547 */
2548 assert(SCIPbdchginfoGetVar(bdchginfo) == var);
2549 assert(SCIPbdchginfoGetBoundtype(bdchginfo) == boundtype);
2550 assert(SCIPbdchginfoGetDepth(bdchginfo) >= 0);
2551 assert(SCIPbdchginfoGetPos(bdchginfo) >= 0);
2552
2553 /* the relaxed bound should be a relaxation */
2554 assert(boundtype == SCIP_BOUNDTYPE_LOWER ? SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)) : SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
2555
2556 /* the relaxed bound should be worse then the old bound of the bound change info */
2557 assert(boundtype == SCIP_BOUNDTYPE_LOWER ? SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) : SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
2558
2559 /* put bound change information into priority queue */
2560 SCIP_CALL( conflictQueueBound(conflict, set, bdchginfo, relaxedbd, &success) );
2561
2562 /* each variable which is add to the conflict graph gets an increase in the VSIDS
2563 *
2564 * @note That is different to the VSIDS presented in the literature
2565 */
2566 /* refactortodo update VSIDS score only in case of successfully adding the bound change to the queue? */
2567 SCIP_CALL( incVSIDS(var, blkmem, set, stat, boundtype, relaxedbd, set->conf_conflictgraphweight) );
2568
2569 return SCIP_OKAY;
2570}
2571
2572/** applies conflict analysis starting with given bound changes, that could not be undone during previous
2573 * infeasibility analysis
2574 */
2576 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2577 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2578 SCIP_SET* set, /**< global SCIP settings */
2579 SCIP_STAT* stat, /**< problem statistics */
2580 SCIP_PROB* prob, /**< problem data */
2581 SCIP_TREE* tree, /**< branch and bound tree */
2582 SCIP_Bool diving, /**< are we in strong branching or diving mode? */
2583 int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
2584 int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
2585 int* nconss, /**< pointer to store the number of generated conflict constraints */
2586 int* nliterals, /**< pointer to store the number of literals in generated conflict constraints */
2587 int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
2588 int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
2589 )
2590{
2591 SCIP_VAR** vars;
2592 SCIP_VAR* var;
2593 SCIP_CONFTYPE conftype;
2594 SCIP_Bool usescutoffbound;
2595 int nvars;
2596 int v;
2597 int nbdchgs;
2598 int maxsize;
2599
2600 assert(prob != NULL);
2601 assert(lbchginfoposs != NULL);
2602 assert(ubchginfoposs != NULL);
2603 assert(nconss != NULL);
2604 assert(nliterals != NULL);
2605 assert(nreconvconss != NULL);
2606 assert(nreconvliterals != NULL);
2607
2608 *nconss = 0;
2609 *nliterals = 0;
2610 *nreconvconss = 0;
2611 *nreconvliterals = 0;
2612
2613 vars = prob->vars;
2614 nvars = prob->nvars;
2615 assert(nvars == 0 || vars != NULL);
2616
2617 maxsize = 2*conflictCalcMaxsize(set, prob);
2618
2619 /* initialize conflict data */
2620 conftype = conflict->conflictset->conflicttype;
2621 usescutoffbound = conflict->conflictset->usescutoffbound;
2622
2623 SCIP_CALL( SCIPconflictInit(conflict, set, stat, prob, conftype, usescutoffbound) );
2624
2625 conflict->conflictset->conflicttype = conftype;
2626 conflict->conflictset->usescutoffbound = usescutoffbound;
2627
2628 /* add remaining bound changes to conflict queue */
2629 SCIPsetDebugMsg(set, "initial conflict set after undoing bound changes:\n");
2630
2631 nbdchgs = 0;
2632 for( v = 0; v < nvars && nbdchgs < maxsize; ++v )
2633 {
2634 var = vars[v];
2635 assert(var != NULL);
2636 assert(var->nlbchginfos >= 0);
2637 assert(var->nubchginfos >= 0);
2638 assert(-1 <= lbchginfoposs[v] && lbchginfoposs[v] <= var->nlbchginfos);
2639 assert(-1 <= ubchginfoposs[v] && ubchginfoposs[v] <= var->nubchginfos);
2640
2641 if( lbchginfoposs[v] == var->nlbchginfos || ubchginfoposs[v] == var->nubchginfos )
2642 {
2643 SCIP_BDCHGINFO* bdchginfo;
2644 SCIP_Real relaxedbd;
2645
2646 /* the strong branching or diving bound stored in the column is responsible for the conflict:
2647 * it cannot be resolved and therefore has to be directly put into the conflict set
2648 */
2649 assert((lbchginfoposs[v] == var->nlbchginfos) != (ubchginfoposs[v] == var->nubchginfos)); /* only one can be tight in the dual! */
2650 assert(lbchginfoposs[v] < var->nlbchginfos || SCIPvarGetLbLP(var, set) > SCIPvarGetLbLocal(var));
2651 assert(ubchginfoposs[v] < var->nubchginfos || SCIPvarGetUbLP(var, set) < SCIPvarGetUbLocal(var));
2652
2653 /* create an artificial bound change information for the diving/strong branching bound change;
2654 * they are freed in the SCIPconflictFlushConss() call
2655 */
2656 if( lbchginfoposs[v] == var->nlbchginfos )
2657 {
2659 SCIPvarGetLbLocal(var), SCIPvarGetLbLP(var, set), &bdchginfo) );
2660 relaxedbd = SCIPvarGetLbLP(var, set);
2661 }
2662 else
2663 {
2665 SCIPvarGetUbLocal(var), SCIPvarGetUbLP(var, set), &bdchginfo) );
2666 relaxedbd = SCIPvarGetUbLP(var, set);
2667 }
2668
2669 /* put variable into the conflict set */
2670 SCIPsetDebugMsg(set, " force: <%s> %s %g [status: %d, type: %d, dive/strong]\n",
2671 SCIPvarGetName(var), lbchginfoposs[v] == var->nlbchginfos ? ">=" : "<=",
2672 lbchginfoposs[v] == var->nlbchginfos ? SCIPvarGetLbLP(var, set) : SCIPvarGetUbLP(var, set),
2673 SCIPvarGetStatus(var), SCIPvarGetType(var));
2674 SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, bdchginfo, relaxedbd) );
2675
2676 /* each variable which is add to the conflict graph gets an increase in the VSIDS
2677 *
2678 * @note That is different to the VSIDS preseted in the literature
2679 */
2680 SCIP_CALL( incVSIDS(var, blkmem, set, stat, SCIPbdchginfoGetBoundtype(bdchginfo), relaxedbd, set->conf_conflictgraphweight) );
2681 nbdchgs++;
2682 }
2683 else
2684 {
2685 /* put remaining bound changes into conflict candidate queue */
2686 if( lbchginfoposs[v] >= 0 )
2687 {
2688 SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, SCIP_BOUNDTYPE_LOWER, \
2689 &var->lbchginfos[lbchginfoposs[v]], SCIPbdchginfoGetNewbound(&var->lbchginfos[lbchginfoposs[v]])) );
2690 nbdchgs++;
2691 }
2692 if( ubchginfoposs[v] >= 0 )
2693 {
2694 assert(!SCIPbdchginfoIsRedundant(&var->ubchginfos[ubchginfoposs[v]]));
2695 SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, SCIP_BOUNDTYPE_UPPER, \
2696 &var->ubchginfos[ubchginfoposs[v]], SCIPbdchginfoGetNewbound(&var->ubchginfos[ubchginfoposs[v]])) );
2697 nbdchgs++;
2698 }
2699 }
2700 }
2701
2702 if( v == nvars )
2703 {
2704 /* check if the conflict analysis is applicable */
2706 {
2707 /* analyze the conflict set, and create conflict constraints on success */
2708 SCIP_CALL( conflictAnalyze(conflict, blkmem, set, stat, prob, tree, diving, 0, FALSE, nconss, nliterals, \
2709 nreconvconss, nreconvliterals) );
2710 }
2711 }
2712
2713 return SCIP_OKAY;
2714}
2715
2716/** check if the bound change info (which is the potential next candidate which is queued) is valid for the current
2717 * conflict analysis; a bound change info can get invalid if after this one was added to the queue, a weaker bound
2718 * change was added to the queue (due the bound widening idea) which immediately makes this bound change redundant; due
2719 * to the priority we did not removed that bound change info since that cost O(log(n)); hence we have to skip/ignore it
2720 * now
2721 *
2722 * The following situations can occur before for example the bound change info (x >= 3) is potentially popped from the
2723 * queue.
2724 *
2725 * Postcondition: the reason why (x >= 3) was queued is that at this time point no lower bound of x was involved yet in
2726 * the current conflict or the lower bound which was involved until then was stronger, e.g., (x >= 2).
2727 *
2728 * 1) during the time until (x >= 3) gets potentially popped no weaker lower bound was added to the queue, in that case
2729 * the conflictlbcount is valid and conflictlb is 3; that is (var->conflictlbcount == conflict->count &&
2730 * var->conflictlb == 3)
2731 *
2732 * 2) a weaker bound change info gets queued (e.g., x >= 4); this bound change is popped before (x >= 3) since it has
2733 * higher priority (which is the time stamp of the bound change info and (x >= 4) has to be done after (x >= 3)
2734 * during propagation or branching)
2735 *
2736 * a) if (x >= 4) is popped and added to the conflict set the conflictlbcount is still valid and conflictlb is at
2737 * most 4; that is (var->conflictlbcount == conflict->count && var->conflictlb >= 4); it follows that any bound
2738 * change info which is stronger than (x >= 4) gets ignored (for example x >= 2)
2739 *
2740 * b) if (x >= 4) is popped and resolved without introducing a new lower bound on x until (x >= 3) is a potentially
2741 * candidate the conflictlbcount indicates that bound change is currently not present; that is
2742 * (var->conflictlbcount != conflict->count)
2743 *
2744 * c) if (x >= 4) is popped and resolved and a new lower bound on x (e.g., x >= 2) is introduced until (x >= 3) is
2745 * pooped, the conflictlbcount indicates that bound change is currently present; that is (var->conflictlbcount ==
2746 * conflict->count); however the (x >= 3) only has be explained if conflictlb matches that one; that is
2747 * (var->conflictlb == bdchginfo->newbound); otherwise it redundant/invalid.
2748 */
2750 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2751 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
2752 )
2753{
2754 SCIP_VAR* var;
2755
2756 assert(bdchginfo != NULL);
2757
2758 var = SCIPbdchginfoGetVar(bdchginfo);
2759 assert(var != NULL);
2760
2761 /* the bound change info of a binary (domained) variable can never be invalid since the concepts of relaxed bounds
2762 * and bound widening do not make sense for these type of variables
2763 */
2764 if( SCIPvarIsBinary(var) )
2765 return FALSE;
2766
2767 /* check if the bdchginfo is invalid since a tight/weaker bound change was already explained */
2769 {
2770 if( var->conflictlbcount != conflict->count || var->conflictlb != SCIPbdchginfoGetNewbound(bdchginfo) ) /*lint !e777*/
2771 {
2772 assert(!SCIPvarIsBinary(var));
2773 return TRUE;
2774 }
2775 }
2776 else
2777 {
2778 assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER);
2779
2780 if( var->conflictubcount != conflict->count || var->conflictub != SCIPbdchginfoGetNewbound(bdchginfo) ) /*lint !e777*/
2781 {
2782 assert(!SCIPvarIsBinary(var));
2783 return TRUE;
2784 }
2785 }
2786
2787 return FALSE;
2788}
2789
2790/** adds given bound changes to a conflict set */
2791static
2793 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2794 SCIP_CONFLICTSET* conflictset, /**< conflict set */
2795 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2796 SCIP_SET* set, /**< global SCIP settings */
2797 SCIP_BDCHGINFO** bdchginfos, /**< bound changes to add to the conflict set */
2798 int nbdchginfos /**< number of bound changes to add */
2799 )
2800{
2801 SCIP_BDCHGINFO** confbdchginfos;
2802 SCIP_BDCHGINFO* bdchginfo;
2803 SCIP_Real* confrelaxedbds;
2804 int* confsortvals;
2805 int confnbdchginfos;
2806 int idx;
2807 int sortval;
2808 int i;
2809 SCIP_BOUNDTYPE boundtype;
2810
2811 assert(conflict != NULL);
2812 assert(conflictset != NULL);
2813 assert(blkmem != NULL);
2814 assert(set != NULL);
2815 assert(bdchginfos != NULL || nbdchginfos == 0);
2816
2817 /* nothing to add */
2818 if( nbdchginfos == 0 )
2819 return SCIP_OKAY;
2820
2821 assert(bdchginfos != NULL);
2822
2823 /* only one element to add, use the single insertion method */
2824 if( nbdchginfos == 1 )
2825 {
2826 bdchginfo = bdchginfos[0];
2827 assert(bdchginfo != NULL);
2828
2829 if( !bdchginfoIsInvalid(conflict, bdchginfo) )
2830 {
2831 SCIP_CALL( conflictsetAddBound(conflictset, blkmem, set, bdchginfo, SCIPbdchginfoGetRelaxedBound(bdchginfo)) );
2832 }
2833 else
2834 {
2835 SCIPsetDebugMsg(set, "-> bound change info [%d:<%s> %s %g] is invalid -> ignore it\n", SCIPbdchginfoGetDepth(bdchginfo),
2837 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
2838 SCIPbdchginfoGetNewbound(bdchginfo));
2839 }
2840
2841 return SCIP_OKAY;
2842 }
2843
2844 confnbdchginfos = conflictset->nbdchginfos;
2845
2846 /* allocate memory for additional element */
2847 SCIP_CALL( conflictsetEnsureBdchginfosMem(conflictset, blkmem, set, confnbdchginfos + nbdchginfos) );
2848
2849 confbdchginfos = conflictset->bdchginfos;
2850 confrelaxedbds = conflictset->relaxedbds;
2851 confsortvals = conflictset->sortvals;
2852
2853 assert(SCIP_BOUNDTYPE_LOWER == FALSE); /*lint !e641 !e506*/
2854 assert(SCIP_BOUNDTYPE_UPPER == TRUE); /*lint !e641 !e506*/
2855
2856 for( i = 0; i < nbdchginfos; ++i )
2857 {
2858 bdchginfo = bdchginfos[i];
2859 assert(bdchginfo != NULL);
2860
2861 /* add only valid bound change infos */
2862 if( !bdchginfoIsInvalid(conflict, bdchginfo) )
2863 {
2864 /* calculate sorting value */
2865 boundtype = SCIPbdchginfoGetBoundtype(bdchginfo);
2866 assert(SCIPbdchginfoGetVar(bdchginfo) != NULL);
2867
2868 idx = SCIPvarGetIndex(SCIPbdchginfoGetVar(bdchginfo));
2869 assert(idx < INT_MAX/2);
2870
2871 assert((int)boundtype == 0 || (int)boundtype == 1);
2872 sortval = 2*idx + (int)boundtype; /* first sorting criteria: variable index, second criteria: boundtype */
2873
2874 /* add new element */
2875 confbdchginfos[confnbdchginfos] = bdchginfo;
2876 confrelaxedbds[confnbdchginfos] = SCIPbdchginfoGetRelaxedBound(bdchginfo);
2877 confsortvals[confnbdchginfos] = sortval;
2878 ++confnbdchginfos;
2879
2881 conflictset->hasrelaxonlyvar = TRUE;
2882 }
2883 else
2884 {
2885 SCIPsetDebugMsg(set, "-> bound change info [%d:<%s> %s %g] is invalid -> ignore it\n", SCIPbdchginfoGetDepth(bdchginfo),
2887 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
2888 SCIPbdchginfoGetNewbound(bdchginfo));
2889 }
2890 }
2891 assert(confnbdchginfos <= conflictset->nbdchginfos + nbdchginfos);
2892
2893 /* sort and merge the new conflict set */
2894 if( confnbdchginfos > conflictset->nbdchginfos )
2895 {
2896 int k = 0;
2897
2898 /* sort array */
2899 SCIPsortIntPtrReal(confsortvals, (void**)confbdchginfos, confrelaxedbds, confnbdchginfos);
2900
2901 i = 1;
2902 /* merge multiple bound changes */
2903 while( i < confnbdchginfos )
2904 {
2905 assert(i > k);
2906
2907 /* is this a multiple bound change */
2908 if( confsortvals[k] == confsortvals[i] )
2909 {
2910 if( SCIPbdchginfoIsTighter(confbdchginfos[k], confbdchginfos[i]) )
2911 ++i;
2912 else if( SCIPbdchginfoIsTighter(confbdchginfos[i], confbdchginfos[k]) )
2913 {
2914 /* replace worse bound change info by tighter bound change info */
2915 confbdchginfos[k] = confbdchginfos[i];
2916 confrelaxedbds[k] = confrelaxedbds[i];
2917 confsortvals[k] = confsortvals[i];
2918 ++i;
2919 }
2920 else
2921 {
2922 assert(confsortvals[k] == confsortvals[i]);
2923
2924 /* both bound change are equivalent; hence, keep the worse relaxed bound and remove one of them */
2925 confrelaxedbds[k] = (confsortvals[k] % 2 == 0) ? MAX(confrelaxedbds[k], confrelaxedbds[i]) : MIN(confrelaxedbds[k], confrelaxedbds[i]);
2926 ++i;
2927 }
2928 }
2929 else
2930 {
2931 /* all bound change infos must be valid */
2932 assert(!bdchginfoIsInvalid(conflict, confbdchginfos[k]));
2933
2934 ++k;
2935 /* move next comparison element to the correct position */
2936 if( k != i )
2937 {
2938 confbdchginfos[k] = confbdchginfos[i];
2939 confrelaxedbds[k] = confrelaxedbds[i];
2940 confsortvals[k] = confsortvals[i];
2941 }
2942 ++i;
2943 }
2944 }
2945 /* last bound change infos must also be valid */
2946 assert(!bdchginfoIsInvalid(conflict, confbdchginfos[k]));
2947 /* the number of bound change infos cannot be decreased, it would mean that the conflict set was not merged
2948 * before
2949 */
2950 assert(conflictset->nbdchginfos <= k + 1 );
2951 assert(k + 1 <= confnbdchginfos);
2952
2953 conflictset->nbdchginfos = k + 1;
2954 }
2955
2956 return SCIP_OKAY;
2957}
2958
2959/** removes and returns next conflict analysis candidate from the candidate queue */
2960static
2962 SCIP_CONFLICT* conflict /**< conflict analysis data */
2963 )
2964{
2965 SCIP_BDCHGINFO* bdchginfo;
2966 SCIP_VAR* var;
2967
2968 assert(conflict != NULL);
2969
2970 if( SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0 )
2971 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->forcedbdchgqueue));
2972 else
2973 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->bdchgqueue));
2974
2975 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
2976
2977 /* if we have a candidate this one should be valid for the current conflict analysis */
2978 assert(!bdchginfoIsInvalid(conflict, bdchginfo));
2979
2980 /* mark the bound change to be no longer in the conflict (it will be either added again to the conflict set or
2981 * replaced by resolving, which might add a weaker change on the same bound to the queue)
2982 */
2983 var = SCIPbdchginfoGetVar(bdchginfo);
2985 {
2986 var->conflictlbcount = 0;
2988 }
2989 else
2990 {
2991 assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER);
2992 var->conflictubcount = 0;
2994 }
2995
2996#if defined(SCIP_CONFGRAPH) || defined(SCIP_CONFGRAPH_DOT)
2997 confgraphSetCurrentBdchg(bdchginfo);
2998#endif
2999
3000 return bdchginfo;
3001}
3002
3003/** returns next conflict analysis candidate from the candidate queue without removing it */
3004static
3006 SCIP_CONFLICT* conflict /**< conflict analysis data */
3007 )
3008{
3009 SCIP_BDCHGINFO* bdchginfo;
3010
3011 assert(conflict != NULL);
3012
3013 if( SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0 )
3014 {
3015 /* get next potential candidate */
3016 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueFirst(conflict->forcedbdchgqueue));
3017
3018 /* check if this candidate is valid */
3019 if( bdchginfoIsInvalid(conflict, bdchginfo) )
3020 {
3021 SCIPdebugMessage("bound change info [%d:<%s> %s %g] is invalid -> pop it from the force queue\n", SCIPbdchginfoGetDepth(bdchginfo),
3023 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3024 SCIPbdchginfoGetNewbound(bdchginfo));
3025
3026 /* pop the invalid bound change info from the queue */
3027 (void)(SCIPpqueueRemove(conflict->forcedbdchgqueue));
3028
3029 /* call method recursively to get next conflict analysis candidate */
3030 bdchginfo = conflictFirstCand(conflict);
3031 }
3032 }
3033 else
3034 {
3035 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueFirst(conflict->bdchgqueue));
3036
3037 /* check if this candidate is valid */
3038 if( bdchginfo != NULL && bdchginfoIsInvalid(conflict, bdchginfo) )
3039 {
3040 SCIPdebugMessage("bound change info [%d:<%s> %s %g] is invalid -> pop it from the queue\n", SCIPbdchginfoGetDepth(bdchginfo),
3042 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3043 SCIPbdchginfoGetNewbound(bdchginfo));
3044
3045 /* pop the invalid bound change info from the queue */
3046 (void)(SCIPpqueueRemove(conflict->bdchgqueue));
3047
3048 /* call method recursively to get next conflict analysis candidate */
3049 bdchginfo = conflictFirstCand(conflict);
3050 }
3051 }
3052 assert(bdchginfo == NULL || !SCIPbdchginfoIsRedundant(bdchginfo));
3053
3054 return bdchginfo;
3055}
3056
3057/** adds the current conflict set (extended by all remaining bound changes in the queue) to the pool of conflict sets */
3058static
3060 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3061 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3062 SCIP_SET* set, /**< global SCIP settings */
3063 SCIP_STAT* stat, /**< dynamic problem statistics */
3064 SCIP_TREE* tree, /**< branch and bound tree */
3065 int validdepth, /**< minimal depth level at which the conflict set is valid */
3066 SCIP_Bool diving, /**< are we in strong branching or diving mode? */
3067 SCIP_Bool repropagate, /**< should the constraint trigger a repropagation? */
3068 SCIP_Bool* success, /**< pointer to store whether the conflict set is valid */
3069 int* nliterals /**< pointer to store the number of literals in the generated conflictset */
3070 )
3071{
3072 SCIP_CONFLICTSET* conflictset;
3073 SCIP_BDCHGINFO** bdchginfos;
3074 int nbdchginfos;
3075 int currentdepth;
3076 int focusdepth;
3077
3078 assert(conflict != NULL);
3079 assert(conflict->conflictset != NULL);
3080 assert(set != NULL);
3081 assert(stat != NULL);
3082 assert(tree != NULL);
3083 assert(success != NULL);
3084 assert(nliterals != NULL);
3085 assert(SCIPpqueueNElems(conflict->forcedbdchgqueue) == 0);
3086
3087 *success = FALSE;
3088 *nliterals = 0;
3089
3090 /* check, whether local conflicts are allowed */
3091 validdepth = MAX(validdepth, conflict->conflictset->validdepth);
3092 if( !set->conf_allowlocal && validdepth > 0 )
3093 return SCIP_OKAY;
3094
3095 focusdepth = SCIPtreeGetFocusDepth(tree);
3096 currentdepth = SCIPtreeGetCurrentDepth(tree);
3097 assert(currentdepth == tree->pathlen-1);
3098 assert(focusdepth <= currentdepth);
3099 assert(0 <= conflict->conflictset->validdepth && conflict->conflictset->validdepth <= currentdepth);
3100 assert(0 <= validdepth && validdepth <= currentdepth);
3101
3102 /* get the elements of the bound change queue */
3103 bdchginfos = (SCIP_BDCHGINFO**)SCIPpqueueElems(conflict->bdchgqueue);
3104 nbdchginfos = SCIPpqueueNElems(conflict->bdchgqueue);
3105
3106 /* create a copy of the current conflict set, allocating memory for the additional elements of the queue */
3107 SCIP_CALL( conflictsetCopy(&conflictset, blkmem, conflict->conflictset, nbdchginfos) );
3108 conflictset->validdepth = validdepth;
3109 conflictset->repropagate = repropagate;
3110
3111 /* add the valid queue elements to the conflict set */
3112 SCIPsetDebugMsg(set, "adding %d variables from the queue as temporary conflict variables\n", nbdchginfos);
3113 SCIP_CALL( conflictsetAddBounds(conflict, conflictset, blkmem, set, bdchginfos, nbdchginfos) );
3114
3115 /* calculate the depth, at which the conflictset should be inserted */
3116 SCIP_CALL( conflictsetCalcInsertDepth(conflictset, set, tree) );
3117 assert(conflictset->validdepth <= conflictset->insertdepth && conflictset->insertdepth <= currentdepth);
3118 SCIPsetDebugMsg(set, " -> conflict with %d literals found at depth %d is active in depth %d and valid in depth %d\n",
3119 conflictset->nbdchginfos, currentdepth, conflictset->insertdepth, conflictset->validdepth);
3120
3121 /* if all branching variables are in the conflict set, the conflict set is of no use;
3122 * don't use conflict sets that are only valid in the probing path but not in the problem tree
3123 */
3124 if( (diving || conflictset->insertdepth < currentdepth) && conflictset->insertdepth <= focusdepth )
3125 {
3126 /* if the conflict should not be located only in the subtree where it is useful, put it to its valid depth level */
3127 if( !set->conf_settlelocal )
3128 conflictset->insertdepth = conflictset->validdepth;
3129
3130 *nliterals = conflictset->nbdchginfos;
3131 SCIPsetDebugMsg(set, " -> final conflict set has %d literals\n", *nliterals);
3132
3133 /* check conflict set on debugging solution */
3134 SCIP_CALL( SCIPdebugCheckConflict(blkmem, set, tree->path[validdepth], \
3135 conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos) ); /*lint !e506 !e774*/
3136
3137 /* move conflictset to the conflictset storage */
3138 SCIP_CALL( conflictInsertConflictset(conflict, blkmem, set, &conflictset) );
3139 *success = TRUE;
3140 }
3141 else
3142 {
3143 /* free the temporary conflict set */
3144 SCIPconflictsetFree(&conflictset, blkmem);
3145 }
3146
3147 return SCIP_OKAY;
3148}
3149
3150/** tries to resolve given bound change
3151 * - resolutions on local constraints are only applied, if the constraint is valid at the
3152 * current minimal valid depth level, because this depth level is the topmost level to add the conflict
3153 * constraint to anyways
3154 *
3155 * @note it is sufficient to explain the relaxed bound change
3156 */
3157static
3159 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3160 SCIP_SET* set, /**< global SCIP settings */
3161 SCIP_BDCHGINFO* bdchginfo, /**< bound change to resolve */
3162 SCIP_Real relaxedbd, /**< the relaxed bound */
3163 int validdepth, /**< minimal depth level at which the conflict is valid */
3164 SCIP_Bool* resolved /**< pointer to store whether the bound change was resolved */
3165 )
3166{
3167 SCIP_VAR* actvar;
3168 SCIP_CONS* infercons;
3169 SCIP_PROP* inferprop;
3170 SCIP_RESULT result;
3171
3172#ifndef NDEBUG
3173 int nforcedbdchgqueue;
3174 int nbdchgqueue;
3175
3176 /* store the current size of the conflict queues */
3177 assert(conflict != NULL);
3178 nforcedbdchgqueue = SCIPpqueueNElems(conflict->forcedbdchgqueue);
3179 nbdchgqueue = SCIPpqueueNElems(conflict->bdchgqueue);
3180#else
3181 assert(conflict != NULL);
3182#endif
3183
3184 assert(resolved != NULL);
3185 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3186
3187 *resolved = FALSE;
3188
3189 actvar = SCIPbdchginfoGetVar(bdchginfo);
3190 assert(actvar != NULL);
3191 assert(SCIPvarIsActive(actvar));
3192
3193#ifdef SCIP_DEBUG
3194 {
3195 int i;
3196 SCIPsetDebugMsg(set, "processing next conflicting bound (depth: %d, valid depth: %d, bdchgtype: %s [%s], vartype: %d): [<%s> %s %g(%g)]\n",
3197 SCIPbdchginfoGetDepth(bdchginfo), validdepth,
3199 : SCIPbdchginfoGetChgtype(bdchginfo) == SCIP_BOUNDCHGTYPE_CONSINFER ? "cons" : "prop",
3203 : SCIPbdchginfoGetInferProp(bdchginfo) == NULL ? "-"
3205 SCIPvarGetType(actvar), SCIPvarGetName(actvar),
3206 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3207 SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd);
3208 SCIPsetDebugMsg(set, " - conflict set :");
3209
3210 for( i = 0; i < conflict->conflictset->nbdchginfos; ++i )
3211 {
3212 SCIPsetDebugMsgPrint(set, " [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(conflict->conflictset->bdchginfos[i]),
3216 }
3218 SCIPsetDebugMsg(set, " - forced candidates :");
3219
3220 for( i = 0; i < SCIPpqueueNElems(conflict->forcedbdchgqueue); ++i )
3221 {
3224 bdchginfoIsInvalid(conflict, info) ? "<!>" : SCIPbdchginfoGetBoundtype(info) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3226 }
3228 SCIPsetDebugMsg(set, " - optional candidates:");
3229
3230 for( i = 0; i < SCIPpqueueNElems(conflict->bdchgqueue); ++i )
3231 {
3232 SCIP_BDCHGINFO* info = (SCIP_BDCHGINFO*)(SCIPpqueueElems(conflict->bdchgqueue)[i]);
3234 bdchginfoIsInvalid(conflict, info) ? "<!>" : SCIPbdchginfoGetBoundtype(info) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3236 }
3238 }
3239#endif
3240
3241 /* check, if the bound change can and should be resolved:
3242 * - resolutions on local constraints should only be applied, if the constraint is valid at the
3243 * current minimal valid depth level (which is initialized with the valid depth level of the initial
3244 * conflict set), because this depth level is the topmost level to add the conflict constraint to anyways
3245 */
3246 switch( SCIPbdchginfoGetChgtype(bdchginfo) )
3247 {
3249 infercons = SCIPbdchginfoGetInferCons(bdchginfo);
3250 assert(infercons != NULL);
3251
3252 if( SCIPconsIsGlobal(infercons) || SCIPconsGetValidDepth(infercons) <= validdepth )
3253 {
3254 SCIP_VAR* infervar;
3255 int inferinfo;
3256 SCIP_BOUNDTYPE inferboundtype;
3257 SCIP_BDCHGIDX* bdchgidx;
3258
3259 /* resolve bound change by asking the constraint that inferred the bound to put all bounds that were
3260 * the reasons for the conflicting bound change on the priority queue
3261 */
3262 infervar = SCIPbdchginfoGetInferVar(bdchginfo);
3263 inferinfo = SCIPbdchginfoGetInferInfo(bdchginfo);
3264 inferboundtype = SCIPbdchginfoGetInferBoundtype(bdchginfo);
3265 bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
3266 assert(infervar != NULL);
3267
3268 SCIPsetDebugMsg(set, "resolving bound <%s> %s %g(%g) [status:%d, type:%d, depth:%d, pos:%d]: <%s> %s %g [cons:<%s>(%s), info:%d]\n",
3269 SCIPvarGetName(actvar),
3270 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3271 SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd,
3272 SCIPvarGetStatus(actvar), SCIPvarGetType(actvar),
3273 SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
3274 SCIPvarGetName(infervar),
3275 inferboundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3276 SCIPgetVarBdAtIndex(set->scip, infervar, inferboundtype, bdchgidx, TRUE),
3277 SCIPconsGetName(infercons),
3278 SCIPconsIsGlobal(infercons) ? "global" : "local",
3279 inferinfo);
3280
3281 /* in case the inference variables is not an active variables, we need to transform the relaxed bound */
3282 if( actvar != infervar )
3283 {
3284 SCIP_VAR* var;
3285 SCIP_Real scalar;
3286 SCIP_Real constant;
3287
3290 || (SCIPvarGetStatus(infervar) == SCIP_VARSTATUS_MULTAGGR && SCIPvarGetMultaggrNVars(infervar) == 1));
3291
3292 scalar = 1.0;
3293 constant = 0.0;
3294
3295 var = infervar;
3296
3297 /* transform given variable to active variable */
3298 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
3299 assert(var == actvar);
3300
3301 relaxedbd *= scalar;
3302 relaxedbd += constant;
3303 }
3304
3305 SCIP_CALL( SCIPconsResolvePropagation(infercons, set, infervar, inferinfo, inferboundtype, bdchgidx, relaxedbd, &result) );
3306 *resolved = (result == SCIP_SUCCESS);
3307 }
3308 break;
3309
3311 inferprop = SCIPbdchginfoGetInferProp(bdchginfo);
3312 if( inferprop != NULL )
3313 {
3314 SCIP_VAR* infervar;
3315 int inferinfo;
3316 SCIP_BOUNDTYPE inferboundtype;
3317 SCIP_BDCHGIDX* bdchgidx;
3318
3319 /* resolve bound change by asking the propagator that inferred the bound to put all bounds that were
3320 * the reasons for the conflicting bound change on the priority queue
3321 */
3322 infervar = SCIPbdchginfoGetInferVar(bdchginfo);
3323 inferinfo = SCIPbdchginfoGetInferInfo(bdchginfo);
3324 inferboundtype = SCIPbdchginfoGetInferBoundtype(bdchginfo);
3325 bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
3326 assert(infervar != NULL);
3327
3328 SCIPsetDebugMsg(set, "resolving bound <%s> %s %g(%g) [status:%d, depth:%d, pos:%d]: <%s> %s %g [prop:<%s>, info:%d]\n",
3329 SCIPvarGetName(actvar),
3330 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3331 SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd,
3332 SCIPvarGetStatus(actvar), SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
3333 SCIPvarGetName(infervar),
3334 inferboundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3335 SCIPgetVarBdAtIndex(set->scip, infervar, inferboundtype, bdchgidx, TRUE),
3336 SCIPpropGetName(inferprop), inferinfo);
3337
3338 SCIP_CALL( SCIPpropResolvePropagation(inferprop, set, infervar, inferinfo, inferboundtype, bdchgidx, relaxedbd, &result) );
3339 *resolved = (result == SCIP_SUCCESS);
3340 }
3341 break;
3342
3344 assert(!(*resolved));
3345 break;
3346
3347 default:
3348 SCIPerrorMessage("invalid bound change type <%d>\n", SCIPbdchginfoGetChgtype(bdchginfo));
3349 return SCIP_INVALIDDATA;
3350 }
3351
3352 SCIPsetDebugMsg(set, "resolving status: %u\n", *resolved);
3353
3354#ifndef NDEBUG
3355 /* subtract the size of the conflicq queues */
3356 nforcedbdchgqueue -= SCIPpqueueNElems(conflict->forcedbdchgqueue);
3357 nbdchgqueue -= SCIPpqueueNElems(conflict->bdchgqueue);
3358
3359 /* in case the bound change was not resolved, the conflict queues should have the same size (contents) */
3360 assert((*resolved) || (nforcedbdchgqueue == 0 && nbdchgqueue == 0));
3361#endif
3362
3363 return SCIP_OKAY;
3364}
3365
3366/** clears the conflict queue and the current conflict set */
3367static
3369 SCIP_CONFLICT* conflict /**< conflict analysis data */
3370 )
3371{
3372 assert(conflict != NULL);
3373
3374 SCIPpqueueClear(conflict->bdchgqueue);
3376 conflictsetClear(conflict->conflictset);
3377}
3378
3379
3380/** clears the resolution conflict analysis queues and the bounds leading to conflict */
3381static
3383 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3384 SCIP_SET* set, /**< global SCIP settings */
3385 SCIP_PROB* prob /**< problem data */
3386 )
3387{
3388 int nvars;
3389 int i;
3390
3391 assert(conflict != NULL);
3392 assert(set != NULL);
3393 assert(prob != NULL);
3394
3395 if( !set->conf_usegenres )
3396 return;
3397
3398 /* clear the resolution conflict analysis queues */
3399 SCIPpqueueClear(conflict->resbdchgqueue);
3400
3401 /* reset the current lower and upper bounds leading to conflict */
3402 nvars = SCIPprobGetNVars(prob);
3403
3404 /* allocate memory for the lower and upper bounds of variables used in the resolution conflict analysis */
3405 if(conflict->conflictprobnvars < nvars)
3406 {
3407 conflict->conflictprobnvars = nvars;
3408 BMSreallocMemoryArray(&conflict->conflictvarslbs, nvars);
3409 BMSreallocMemoryArray(&conflict->conflictvarsubs, nvars);
3410 }
3411
3412 for( i = 0; i < nvars; ++i )
3413 {
3414 conflict->conflictvarslbs[i] = SCIP_REAL_MIN;
3415 conflict->conflictvarsubs[i] = SCIP_REAL_MAX;
3416 }
3417}
3418
3419/** initializes propagation and resolution conflict analysis by clearing the conflict candidate queues */
3421 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3422 SCIP_SET* set, /**< global SCIP settings */
3423 SCIP_STAT* stat, /**< problem statistics */
3424 SCIP_PROB* prob, /**< problem data */
3425 SCIP_CONFTYPE conftype, /**< type of the conflict */
3426 SCIP_Bool usescutoffbound /**< depends the conflict on a cutoff bound? */
3427 )
3428{
3429 assert(conflict != NULL);
3430 assert(set != NULL);
3431 assert(stat != NULL);
3432 assert(prob != NULL);
3433
3434 SCIPsetDebugMsg(set, "initializing conflict analysis\n");
3435
3436 /* clear the conflict candidate queue and the conflict set */
3437 conflictClear(conflict);
3438
3439 /* clear the resolution conflict analysis queues and the bounds leading to conflict */
3440 conflictClearResolution(conflict, set, prob);
3441
3442 /* set conflict type */
3443 assert(conftype == SCIP_CONFTYPE_BNDEXCEEDING || conftype == SCIP_CONFTYPE_INFEASLP
3444 || conftype == SCIP_CONFTYPE_PROPAGATION);
3445 conflict->conflictset->conflicttype = conftype;
3446 conflict->conflictrow->conflicttype = conftype;
3447
3448 /* set whether a cutoff bound is involved */
3449 conflict->conflictset->usescutoffbound = usescutoffbound;
3450
3451 /* increase the conflict counter, such that binary variables of new conflict set and new conflict queue are labeled
3452 * with this new counter
3453 */
3454 conflict->count++;
3455 if( conflict->count == 0 ) /* make sure, 0 is not a valid conflict counter (may happen due to integer overflow) */
3456 conflict->count = 1;
3457
3458 /* increase the conflict score weight for history updates of future conflict reasons */
3459 if( stat->nnodes > stat->lastconflictnode )
3460 {
3461 assert(0.0 < set->conf_scorefac && set->conf_scorefac <= 1.0);
3462 stat->vsidsweight /= set->conf_scorefac;
3463 assert(stat->vsidsweight > 0.0);
3464
3465 /* if the conflict score for the next conflict exceeds 1000.0, rescale all history conflict scores */
3466 if( stat->vsidsweight >= 1000.0 )
3467 {
3468 int v;
3469
3470 for( v = 0; v < prob->nvars; ++v )
3471 {
3472 SCIP_CALL( SCIPvarScaleVSIDS(prob->vars[v], 1.0/stat->vsidsweight) );
3473 }
3476 stat->vsidsweight = 1.0;
3477 }
3478 stat->lastconflictnode = stat->nnodes;
3479 }
3480
3481#if defined(SCIP_CONFGRAPH) || defined(SCIP_CONFGRAPH_DOT)
3482 confgraphFree();
3483 SCIP_CALL( confgraphCreate(set, conflict) );
3484#endif
3485
3486 return SCIP_OKAY;
3487}
3488
3489/** convert variable and bound change to active variable */
3490static
3492 SCIP_VAR** var, /**< pointer to variable */
3493 SCIP_SET* set, /**< global SCIP settings */
3494 SCIP_BOUNDTYPE* boundtype, /**< pointer to type of bound that was changed: lower or upper bound */
3495 SCIP_Real* bound /**< pointer to bound to convert, or NULL */
3496 )
3497{
3498 SCIP_Real scalar;
3499 SCIP_Real constant;
3500
3501 scalar = 1.0;
3502 constant = 0.0;
3503
3504 /* transform given variable to active variable */
3505 SCIP_CALL( SCIPvarGetProbvarSum(var, set, &scalar, &constant) );
3506 assert(SCIPvarGetStatus(*var) == SCIP_VARSTATUS_FIXED || scalar != 0.0); /*lint !e777*/
3507
3509 return SCIP_OKAY;
3510
3511 /* if the scalar of the aggregation is negative, we have to switch the bound type */
3512 if( scalar < 0.0 )
3513 (*boundtype) = SCIPboundtypeOpposite(*boundtype);
3514
3515 if( bound != NULL )
3516 {
3517 (*bound) -= constant;
3518 (*bound) /= scalar;
3519 }
3520
3521 return SCIP_OKAY;
3522}
3523
3524/** returns whether bound change has a valid reason that can be resolved in conflict analysis */
3525static
3527 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
3528 )
3529{
3530 assert(bdchginfo != NULL);
3531 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3532
3535 && SCIPbdchginfoGetInferProp(bdchginfo) != NULL));
3536}
3537
3538
3539/** if only one conflicting bound change of the last depth level was used, and if this can be resolved,
3540 * creates GRASP-like reconvergence conflict constraints in the conflict graph up to the branching variable of this
3541 * depth level
3542 */
3543static
3545 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3546 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3547 SCIP_SET* set, /**< global SCIP settings */
3548 SCIP_STAT* stat, /**< problem statistics */
3549 SCIP_PROB* prob, /**< problem data */
3550 SCIP_TREE* tree, /**< branch and bound tree */
3551 SCIP_Bool diving, /**< are we in strong branching or diving mode? */
3552 int validdepth, /**< minimal depth level at which the initial conflict set is valid */
3553 SCIP_BDCHGINFO* firstuip, /**< first UIP of conflict graph */
3554 int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
3555 int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
3556 )
3557{
3558 SCIP_BDCHGINFO* uip;
3559 SCIP_CONFTYPE conftype;
3560 SCIP_Bool usescutoffbound;
3561 int firstuipdepth;
3562 int focusdepth;
3563 int currentdepth;
3564 int maxvaliddepth;
3565
3566 assert(conflict != NULL);
3567 assert(firstuip != NULL);
3568 assert(nreconvconss != NULL);
3569 assert(nreconvliterals != NULL);
3570 assert(!SCIPbdchginfoIsRedundant(firstuip));
3571
3572 focusdepth = SCIPtreeGetFocusDepth(tree);
3573 currentdepth = SCIPtreeGetCurrentDepth(tree);
3574 assert(currentdepth == tree->pathlen-1);
3575 assert(focusdepth <= currentdepth);
3576
3577 /* check, whether local constraints are allowed; however, don't generate reconvergence constraints that are only valid
3578 * in the probing path and not in the problem tree (i.e. that exceed the focusdepth)
3579 */
3580 maxvaliddepth = (set->conf_allowlocal ? MIN(currentdepth-1, focusdepth) : 0);
3581 if( validdepth > maxvaliddepth )
3582 return SCIP_OKAY;
3583
3584 firstuipdepth = SCIPbdchginfoGetDepth(firstuip);
3585
3586 conftype = conflict->conflictset->conflicttype;
3587 usescutoffbound = conflict->conflictset->usescutoffbound;
3588
3589 /* for each succeeding UIP pair of the last depth level, create one reconvergence constraint */
3590 uip = firstuip;
3591 while( uip != NULL && SCIPbdchginfoGetDepth(uip) == SCIPbdchginfoGetDepth(firstuip) && bdchginfoIsResolvable(uip) )
3592 {
3593 SCIP_BDCHGINFO* oppositeuip;
3594 SCIP_BDCHGINFO* bdchginfo;
3595 SCIP_BDCHGINFO* nextuip;
3596 SCIP_VAR* uipvar;
3597 SCIP_Real oppositeuipbound;
3598 SCIP_BOUNDTYPE oppositeuipboundtype;
3599 int nresolutions;
3600
3601 assert(!SCIPbdchginfoIsRedundant(uip));
3602
3603 SCIPsetDebugMsg(set, "creating reconvergence constraint for UIP <%s> %s %g in depth %d pos %d\n",
3606
3607 /* initialize conflict data */
3608 SCIP_CALL( SCIPconflictInit(conflict, set, stat, prob, conftype, usescutoffbound) );
3609
3610 conflict->conflictset->conflicttype = conftype;
3611 conflict->conflictset->usescutoffbound = usescutoffbound;
3612
3613 /* create a temporary bound change information for the negation of the UIP's bound change;
3614 * this bound change information is freed in the SCIPconflictFlushConss() call;
3615 * for reconvergence constraints for continuous variables we can only use the "negation" !(x <= u) == (x >= u);
3616 * during conflict analysis, we treat a continuous bound "x >= u" in the conflict set as "x > u", and in the
3617 * generated constraint this is negated again to "x <= u" which is correct.
3618 */
3619 uipvar = SCIPbdchginfoGetVar(uip);
3620 oppositeuipboundtype = SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(uip));
3621 oppositeuipbound = SCIPbdchginfoGetNewbound(uip);
3622 if( SCIPvarIsIntegral(uipvar) )
3623 {
3624 assert(SCIPsetIsIntegral(set, oppositeuipbound));
3625 oppositeuipbound += (oppositeuipboundtype == SCIP_BOUNDTYPE_LOWER ? +1.0 : -1.0);
3626 }
3627 SCIP_CALL( conflictCreateTmpBdchginfo(conflict, blkmem, set, uipvar, oppositeuipboundtype, \
3628 oppositeuipboundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_REAL_MIN : SCIP_REAL_MAX, oppositeuipbound, &oppositeuip) );
3629
3630 /* put the negated UIP into the conflict set */
3631 SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, oppositeuip, oppositeuipbound) );
3632
3633 /* put positive UIP into priority queue */
3635
3636 /* resolve the queue until the next UIP is reached */
3637 bdchginfo = conflictFirstCand(conflict);
3638 nextuip = NULL;
3639 nresolutions = 0;
3640 while( bdchginfo != NULL && validdepth <= maxvaliddepth )
3641 {
3642 SCIP_BDCHGINFO* nextbdchginfo;
3643 SCIP_Real relaxedbd;
3644 SCIP_Bool forceresolve;
3645 int bdchgdepth;
3646
3647 /* check if the next bound change must be resolved in every case */
3648 forceresolve = (SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0);
3649
3650 /* remove currently processed candidate and get next conflicting bound from the conflict candidate queue before
3651 * we remove the candidate we have to collect the relaxed bound since removing the candidate from the queue
3652 * invalidates the relaxed bound
3653 */
3654 assert(bdchginfo == conflictFirstCand(conflict));
3655 relaxedbd = SCIPbdchginfoGetRelaxedBound(bdchginfo);
3656 bdchginfo = conflictRemoveCand(conflict);
3657 nextbdchginfo = conflictFirstCand(conflict);
3658 bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
3659 assert(bdchginfo != NULL);
3660 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3661 assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(bdchginfo) >= SCIPbdchginfoGetDepth(nextbdchginfo)
3662 || forceresolve);
3663 assert(bdchgdepth <= firstuipdepth);
3664
3665 /* bound changes that are higher in the tree than the valid depth of the conflict can be ignored;
3666 * multiple insertions of the same bound change can be ignored
3667 */
3668 if( bdchgdepth > validdepth && bdchginfo != nextbdchginfo )
3669 {
3670 SCIP_VAR* actvar;
3671 SCIP_Bool resolved;
3672
3673 actvar = SCIPbdchginfoGetVar(bdchginfo);
3674 assert(actvar != NULL);
3675 assert(SCIPvarIsActive(actvar));
3676
3677 /* check if we have to resolve the bound change in this depth level
3678 * - the starting uip has to be resolved
3679 * - a bound change should be resolved, if it is in the fuip's depth level and not the
3680 * next uip (i.e., if it is not the last bound change in the fuip's depth level)
3681 * - a forced bound change must be resolved in any case
3682 */
3683 resolved = FALSE;
3684 if( bdchginfo == uip
3685 || (bdchgdepth == firstuipdepth
3686 && nextbdchginfo != NULL
3687 && SCIPbdchginfoGetDepth(nextbdchginfo) == bdchgdepth)
3688 || forceresolve )
3689 {
3690 SCIP_CALL( conflictResolveBound(conflict, set, bdchginfo, relaxedbd, validdepth, &resolved) );
3691 }
3692
3693 if( resolved )
3694 nresolutions++;
3695 else if( forceresolve )
3696 {
3697 /* variable cannot enter the conflict clause: we have to make the conflict clause local, s.t.
3698 * the unresolved bound change is active in the whole sub tree of the conflict clause
3699 */
3700 assert(bdchgdepth >= validdepth);
3701 validdepth = bdchgdepth;
3702
3703 SCIPsetDebugMsg(set, "couldn't resolve forced bound change on <%s> -> new valid depth: %d\n",
3704 SCIPvarGetName(actvar), validdepth);
3705 }
3706 else if( bdchginfo != uip )
3707 {
3708 assert(conflict->conflictset != NULL);
3709 assert(conflict->conflictset->nbdchginfos >= 1); /* starting UIP is already member of the conflict set */
3710
3711 /* if this is the first variable of the conflict set besides the current starting UIP, it is the next
3712 * UIP (or the first unresolvable bound change)
3713 */
3714 if( bdchgdepth == firstuipdepth && conflict->conflictset->nbdchginfos == 1 )
3715 {
3716 assert(nextuip == NULL);
3717 nextuip = bdchginfo;
3718 }
3719
3720 /* put bound change into the conflict set */
3721 SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, bdchginfo, relaxedbd) );
3722 assert(conflict->conflictset->nbdchginfos >= 2);
3723 }
3724 else
3725 assert(conflictFirstCand(conflict) == NULL); /* the starting UIP was not resolved */
3726 }
3727
3728 /* get next conflicting bound from the conflict candidate queue (this does not need to be nextbdchginfo, because
3729 * due to resolving the bound changes, a variable could be added to the queue which must be
3730 * resolved before nextbdchginfo)
3731 */
3732 bdchginfo = conflictFirstCand(conflict);
3733 }
3734 assert(nextuip != uip);
3735
3736 /* if only one propagation was resolved, the reconvergence constraint is already member of the constraint set
3737 * (it is exactly the constraint that produced the propagation)
3738 */
3739 if( nextuip != NULL && nresolutions >= 2 && bdchginfo == NULL && validdepth <= maxvaliddepth )
3740 {
3741 int nlits;
3742 SCIP_Bool success;
3743
3744 assert(SCIPbdchginfoGetDepth(nextuip) == SCIPbdchginfoGetDepth(uip));
3745
3746 /* check conflict graph frontier on debugging solution */
3747 SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth], \
3748 bdchginfo, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, \
3749 conflict->conflictset->nbdchginfos, conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
3750
3751 SCIPsetDebugMsg(set, "creating reconvergence constraint from UIP <%s> to UIP <%s> in depth %d with %d literals after %d resolutions\n",
3753 SCIPbdchginfoGetDepth(uip), conflict->conflictset->nbdchginfos, nresolutions);
3754
3755 /* call the conflict handlers to create a conflict set */
3756 SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, FALSE, &success, &nlits) );
3757 if( success )
3758 {
3759 (*nreconvconss)++;
3760 (*nreconvliterals) += nlits;
3761 }
3762 }
3763
3764 /* clear the conflict candidate queue and the conflict set (to make sure, oppositeuip is not referenced anymore) */
3765 conflictClear(conflict);
3766
3767 uip = nextuip;
3768 }
3769
3770 conflict->conflictset->conflicttype = conftype;
3771 conflict->conflictset->usescutoffbound = usescutoffbound;
3772
3773 return SCIP_OKAY;
3774}
3775
3776/** analyzes conflicting bound changes that were added with calls to SCIPconflictAddBound() and
3777 * SCIPconflictAddRelaxedBound(), and on success, calls the conflict handlers to create a conflict constraint out of
3778 * the resulting conflict set; afterwards the conflict queue and the conflict set is cleared
3779 */
3781 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3782 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3783 SCIP_SET* set, /**< global SCIP settings */
3784 SCIP_STAT* stat, /**< problem statistics */
3785 SCIP_PROB* prob, /**< problem data */
3786 SCIP_TREE* tree, /**< branch and bound tree */
3787 SCIP_Bool diving, /**< are we in strong branching or diving mode? */
3788 int validdepth, /**< minimal depth level at which the initial conflict set is valid */
3789 SCIP_Bool mustresolve, /**< should the conflict set only be used, if a resolution was applied? */
3790 int* nconss, /**< pointer to store the number of generated conflict constraints */
3791 int* nliterals, /**< pointer to store the number of literals in generated conflict constraints */
3792 int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
3793 int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
3794 )
3795{
3796 SCIP_BDCHGINFO* bdchginfo;
3797 SCIP_BDCHGINFO** firstuips;
3798 SCIP_CONFTYPE conftype;
3799 int nfirstuips;
3800 int focusdepth;
3801 int currentdepth;
3802 int maxvaliddepth;
3803 int resolvedepth;
3804 int nresolutions;
3805 int lastconsnresolutions;
3806 int lastconsresoldepth;
3807
3808 assert(conflict != NULL);
3809 assert(conflict->conflictset != NULL);
3810 assert(conflict->conflictset->nbdchginfos >= 0);
3811 assert(set != NULL);
3812 assert(stat != NULL);
3813 assert(0 <= validdepth && validdepth <= SCIPtreeGetCurrentDepth(tree));
3814 assert(nconss != NULL);
3815 assert(nliterals != NULL);
3816 assert(nreconvconss != NULL);
3817 assert(nreconvliterals != NULL);
3818
3819 focusdepth = SCIPtreeGetFocusDepth(tree);
3820 currentdepth = SCIPtreeGetCurrentDepth(tree);
3821 assert(currentdepth == tree->pathlen-1);
3822 assert(focusdepth <= currentdepth);
3823
3824 resolvedepth = ((set->conf_fuiplevels >= 0 && set->conf_fuiplevels <= currentdepth)
3825 ? currentdepth - set->conf_fuiplevels + 1 : 0);
3826 assert(0 <= resolvedepth && resolvedepth <= currentdepth + 1);
3827
3828 /* if we must resolve at least one bound change, find the first UIP at least in the last depth level */
3829 if( mustresolve )
3830 resolvedepth = MIN(resolvedepth, currentdepth);
3831
3832 SCIPsetDebugMsg(set, "analyzing conflict with %d+%d conflict candidates and starting conflict set of size %d in depth %d (resolvedepth=%d)\n",
3834 conflict->conflictset->nbdchginfos, currentdepth, resolvedepth);
3835
3836 *nconss = 0;
3837 *nliterals = 0;
3838 *nreconvconss = 0;
3839 *nreconvliterals = 0;
3840
3841 /* check, whether local conflicts are allowed; however, don't generate conflict constraints that are only valid in the
3842 * probing path and not in the problem tree (i.e. that exceed the focusdepth)
3843 */
3844 maxvaliddepth = (set->conf_allowlocal ? MIN(currentdepth-1, focusdepth) : 0);
3845 if( validdepth > maxvaliddepth )
3846 return SCIP_OKAY;
3847
3848 /* allocate temporary memory for storing first UIPs (in each depth level, at most two bound changes can be flagged
3849 * as UIP, namely a binary and a non-binary bound change)
3850 */
3851 SCIP_CALL( SCIPsetAllocBufferArray(set, &firstuips, 2*(currentdepth+1)) ); /*lint !e647*/
3852
3853 /* process all bound changes in the conflict candidate queue */
3854 nresolutions = 0;
3855 lastconsnresolutions = (mustresolve ? 0 : -1);
3856 lastconsresoldepth = (mustresolve ? currentdepth : INT_MAX);
3857 bdchginfo = conflictFirstCand(conflict);
3858 nfirstuips = 0;
3859
3860 /* check if the initial reason on debugging solution */
3861 SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth], \
3862 NULL, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, conflict->conflictset->nbdchginfos, \
3863 conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
3864
3865 while( bdchginfo != NULL && validdepth <= maxvaliddepth )
3866 {
3867 SCIP_BDCHGINFO* nextbdchginfo;
3868 SCIP_Real relaxedbd;
3869 SCIP_Bool forceresolve;
3870 int bdchgdepth;
3871
3872 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3873
3874 /* check if the next bound change must be resolved in every case */
3875 forceresolve = (SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0);
3876
3877 /* resolve next bound change in queue */
3878 bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
3879 assert(0 <= bdchgdepth && bdchgdepth <= currentdepth);
3880 assert(SCIPvarIsActive(SCIPbdchginfoGetVar(bdchginfo)));
3881 assert(bdchgdepth < tree->pathlen);
3882 assert(tree->path[bdchgdepth] != NULL);
3883 assert(tree->path[bdchgdepth]->domchg != NULL);
3884 assert(SCIPbdchginfoGetPos(bdchginfo) < (int)tree->path[bdchgdepth]->domchg->domchgbound.nboundchgs);
3885 assert(tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].var
3886 == SCIPbdchginfoGetVar(bdchginfo));
3887 assert(tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].newbound
3888 == SCIPbdchginfoGetNewbound(bdchginfo)
3891 == SCIPbdchginfoGetNewbound(bdchginfo)); /*lint !e777*/
3892 assert((SCIP_BOUNDTYPE)tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].boundtype
3893 == SCIPbdchginfoGetBoundtype(bdchginfo));
3894
3895 /* create intermediate conflict constraint */
3896 assert(nresolutions >= lastconsnresolutions);
3897 if( !forceresolve )
3898 {
3899 if( nresolutions == lastconsnresolutions )
3900 lastconsresoldepth = bdchgdepth; /* all intermediate depth levels consisted of only unresolved bound changes */
3901 else if( bdchgdepth < lastconsresoldepth && (set->conf_interconss == -1 || *nconss < set->conf_interconss) )
3902 {
3903 int nlits;
3904 SCIP_Bool success;
3905
3906 /* call the conflict handlers to create a conflict set */
3907 SCIPsetDebugMsg(set, "creating intermediate conflictset after %d resolutions up to depth %d (valid at depth %d): %d conflict bounds, %d bounds in queue\n",
3908 nresolutions, bdchgdepth, validdepth, conflict->conflictset->nbdchginfos,
3909 SCIPpqueueNElems(conflict->bdchgqueue));
3910
3911 SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, TRUE, &success, &nlits) );
3912 lastconsnresolutions = nresolutions;
3913 lastconsresoldepth = bdchgdepth;
3914 if( success )
3915 {
3916 (*nconss)++;
3917 (*nliterals) += nlits;
3918 }
3919 }
3920 }
3921
3922 /* remove currently processed candidate and get next conflicting bound from the conflict candidate queue before
3923 * we remove the candidate we have to collect the relaxed bound since removing the candidate from the queue
3924 * invalidates the relaxed bound
3925 */
3926 assert(bdchginfo == conflictFirstCand(conflict));
3927 relaxedbd = SCIPbdchginfoGetRelaxedBound(bdchginfo);
3928 bdchginfo = conflictRemoveCand(conflict);
3929 nextbdchginfo = conflictFirstCand(conflict);
3930 assert(bdchginfo != NULL);
3931 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3932 assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(bdchginfo) >= SCIPbdchginfoGetDepth(nextbdchginfo)
3933 || forceresolve);
3934
3935 /* we don't need to resolve bound changes that are already active in the valid depth of the current conflict set,
3936 * because the conflict set can only be added locally at the valid depth, and all bound changes applied in this
3937 * depth or earlier can be removed from the conflict constraint, since they are already applied in the constraint's
3938 * subtree;
3939 * if the next bound change on the remaining queue is equal to the current bound change,
3940 * this is a multiple insertion in the conflict candidate queue and we can ignore the current
3941 * bound change
3942 */
3943 if( bdchgdepth > validdepth && bdchginfo != nextbdchginfo )
3944 {
3945 SCIP_VAR* actvar;
3946 SCIP_Bool resolved;
3947
3948 actvar = SCIPbdchginfoGetVar(bdchginfo);
3949 assert(actvar != NULL);
3950 assert(SCIPvarIsActive(actvar));
3951
3952 /* check if we want to resolve the bound change in this depth level
3953 * - bound changes should be resolved, if
3954 * (i) we must apply at least one resolution and didn't resolve a bound change yet, or
3955 * (ii) their depth level is at least equal to the minimal resolving depth, and
3956 * they are not the last remaining conflicting bound change in their depth level
3957 * (iii) the bound change resolving is forced (i.e., the forced queue was non-empty)
3958 */
3959 resolved = FALSE;
3960 if( (mustresolve && nresolutions == 0)
3961 || (bdchgdepth >= resolvedepth
3962 && nextbdchginfo != NULL
3963 && SCIPbdchginfoGetDepth(nextbdchginfo) == bdchgdepth)
3964 || forceresolve )
3965 {
3966 SCIP_CALL( conflictResolveBound(conflict, set, bdchginfo, relaxedbd, validdepth, &resolved) );
3967 }
3968
3969 if( resolved )
3970 nresolutions++;
3971 else if( forceresolve )
3972 {
3973 /* variable cannot enter the conflict clause: we have to make the conflict clause local, s.t.
3974 * the unresolved bound change is active in the whole sub tree of the conflict clause
3975 */
3976 assert(bdchgdepth >= validdepth);
3977 validdepth = bdchgdepth;
3978
3979 SCIPsetDebugMsg(set, "couldn't resolve forced bound change on <%s> -> new valid depth: %d\n",
3980 SCIPvarGetName(actvar), validdepth);
3981 }
3982 else
3983 {
3984 /* if this is a UIP (the last bound change in its depth level), it can be used to generate a
3985 * UIP reconvergence constraint
3986 */
3987 if( nextbdchginfo == NULL || SCIPbdchginfoGetDepth(nextbdchginfo) != bdchgdepth )
3988 {
3989 assert(nfirstuips < 2*(currentdepth+1));
3990 firstuips[nfirstuips] = bdchginfo;
3991 nfirstuips++;
3992 }
3993
3994 /* put variable into the conflict set, using the literal that is currently fixed to FALSE */
3995 SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, bdchginfo, relaxedbd) );
3996 }
3997 }
3998
3999 /* check conflict graph frontier on debugging solution */
4000 SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth], \
4001 bdchginfo, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, conflict->conflictset->nbdchginfos, \
4002 conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
4003
4004 /* get next conflicting bound from the conflict candidate queue (this needs not to be nextbdchginfo, because
4005 * due to resolving the bound changes, a bound change could be added to the queue which must be
4006 * resolved before nextbdchginfo)
4007 */
4008 bdchginfo = conflictFirstCand(conflict);
4009 }
4010
4011 /* check, if a valid conflict set was found */
4012 if( bdchginfo == NULL
4013 && nresolutions > lastconsnresolutions
4014 && validdepth <= maxvaliddepth
4015 && (!mustresolve || nresolutions > 0 || conflict->conflictset->nbdchginfos == 0)
4016 && SCIPpqueueNElems(conflict->forcedbdchgqueue) == 0 )
4017 {
4018 int nlits;
4019 SCIP_Bool success;
4020
4021 /* call the conflict handlers to create a conflict set */
4022 SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, TRUE, &success, &nlits) );
4023 if( success )
4024 {
4025 (*nconss)++;
4026 (*nliterals) += nlits;
4027 }
4028 }
4029
4030 /* produce reconvergence constraints defined by succeeding UIP's of the last depth level */
4031 if( set->conf_reconvlevels != 0 && validdepth <= maxvaliddepth )
4032 {
4033 int reconvlevels;
4034 int i;
4035
4036 reconvlevels = (set->conf_reconvlevels == -1 ? INT_MAX : set->conf_reconvlevels);
4037 for( i = 0; i < nfirstuips; ++i )
4038 {
4039 if( SCIPbdchginfoHasInferenceReason(firstuips[i])
4040 && currentdepth - SCIPbdchginfoGetDepth(firstuips[i]) < reconvlevels )
4041 {
4042 SCIP_CALL( conflictCreateReconvergenceConss(conflict, blkmem, set, stat, prob, tree, diving, \
4043 validdepth, firstuips[i], nreconvconss, nreconvliterals) );
4044 }
4045 }
4046 }
4047
4048 /* free the temporary memory */
4049 SCIPsetFreeBufferArray(set, &firstuips);
4050
4051 /* store last conflict type */
4052 conftype = conflict->conflictset->conflicttype;
4053
4054 /* clear the conflict candidate queue and the conflict set */
4055 conflictClear(conflict);
4056
4057 /* restore last conflict type */
4058 conflict->conflictset->conflicttype = conftype;
4059
4060 return SCIP_OKAY;
4061}
4062
4063/** calculates the score of a bound change within a conflict */
4064static
4066 SCIP_Real prooflhs, /**< lhs of proof constraint */
4067 SCIP_Real proofact, /**< activity of the proof constraint */
4068 SCIP_Real proofactdelta, /**< activity change */
4069 SCIP_Real proofcoef, /**< coefficient in proof constraint */
4070 int depth, /**< bound change depth */
4071 int currentdepth, /**< current depth */
4072 SCIP_VAR* var, /**< variable corresponding to bound change */
4073 SCIP_SET* set /**< global SCIP settings */
4074 )
4075{
4076 SCIP_COL* col;
4077 SCIP_Real score;
4078
4079 score = set->conf_proofscorefac * (1.0 - proofactdelta/(prooflhs - proofact));
4080 score = MAX(score, 0.0);
4081 score += set->conf_depthscorefac * (SCIP_Real)(depth+1)/(SCIP_Real)(currentdepth+1);
4082
4084 col = SCIPvarGetCol(var);
4085 else
4086 col = NULL;
4087
4088 if( proofcoef > 0.0 )
4089 {
4090 if( col != NULL && SCIPcolGetNNonz(col) > 0 )
4091 score += set->conf_uplockscorefac
4093 else
4094 score += set->conf_uplockscorefac * SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
4095 }
4096 else
4097 {
4098 if( col != NULL && SCIPcolGetNNonz(col) > 0 )
4099 score += set->conf_downlockscorefac
4101 else
4102 score += set->conf_downlockscorefac * SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL);
4103 }
4104
4105 return score;
4106}
4107
4108/** ensures, that candidate array can store at least num entries */
4109static
4111 SCIP_SET* set, /**< global SCIP settings */
4112 SCIP_VAR*** cands, /**< pointer to candidate array */
4113 SCIP_Real** candscores, /**< pointer to candidate score array */
4114 SCIP_Real** newbounds, /**< pointer to candidate new bounds array */
4115 SCIP_Real** proofactdeltas, /**< pointer to candidate proof delta array */
4116 int* candssize, /**< pointer to size of array */
4117 int num /**< minimal number of candidates to store in array */
4118 )
4119{
4120 assert(cands != NULL);
4121 assert(candssize != NULL);
4122
4123 if( num > *candssize )
4124 {
4125 int newsize;
4126
4127 newsize = SCIPsetCalcMemGrowSize(set, num);
4128 SCIP_CALL( SCIPsetReallocBufferArray(set, cands, newsize) );
4129 SCIP_CALL( SCIPsetReallocBufferArray(set, candscores, newsize) );
4130 SCIP_CALL( SCIPsetReallocBufferArray(set, newbounds, newsize) );
4131 SCIP_CALL( SCIPsetReallocBufferArray(set, proofactdeltas, newsize) );
4132 *candssize = newsize;
4133 }
4134 assert(num <= *candssize);
4135
4136 return SCIP_OKAY;
4137}
4138
4139/** after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
4140 * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
4141 * global bound and we can ignore it by installing a -1 as the corresponding bound change info position
4142 */
4143static
4145 SCIP_VAR* var, /**< problem variable */
4146 int* lbchginfopos, /**< pointer to lower bound change information position */
4147 int* ubchginfopos /**< pointer to upper bound change information position */
4148 )
4149{
4150 assert(var != NULL);
4151 assert(lbchginfopos != NULL);
4152 assert(ubchginfopos != NULL);
4153 assert(-1 <= *lbchginfopos && *lbchginfopos <= var->nlbchginfos);
4154 assert(-1 <= *ubchginfopos && *ubchginfopos <= var->nubchginfos);
4155 assert(*lbchginfopos == -1 || *lbchginfopos == var->nlbchginfos
4156 || var->lbchginfos[*lbchginfopos].redundant
4157 == (var->lbchginfos[*lbchginfopos].oldbound == var->lbchginfos[*lbchginfopos].newbound)); /*lint !e777*/
4158 assert(*ubchginfopos == -1 || *ubchginfopos == var->nubchginfos
4159 || var->ubchginfos[*ubchginfopos].redundant
4160 == (var->ubchginfos[*ubchginfopos].oldbound == var->ubchginfos[*ubchginfopos].newbound)); /*lint !e777*/
4161
4162 if( *lbchginfopos >= 0 && *lbchginfopos < var->nlbchginfos && var->lbchginfos[*lbchginfopos].redundant )
4163 {
4164 assert(SCIPvarGetLbGlobal(var) == var->lbchginfos[*lbchginfopos].oldbound); /*lint !e777*/
4165 *lbchginfopos = -1;
4166 }
4167 if( *ubchginfopos >= 0 && *ubchginfopos < var->nubchginfos && var->ubchginfos[*ubchginfopos].redundant )
4168 {
4169 assert(SCIPvarGetUbGlobal(var) == var->ubchginfos[*ubchginfopos].oldbound); /*lint !e777*/
4170 *ubchginfopos = -1;
4171 }
4172}
4173
4174/** adds variable's bound to conflict candidate queue */
4176 SCIP_CONFLICT* conflict, /**< conflict analysis data */
4177 BMS_BLKMEM* blkmem, /**< block memory */
4178 SCIP_SET* set, /**< global SCIP settings */
4179 SCIP_STAT* stat, /**< dynamic problem statistics */
4180 SCIP_VAR* var, /**< problem variable */
4181 SCIP_BOUNDTYPE boundtype, /**< type of bound that was changed: lower or upper bound */
4182 SCIP_BDCHGIDX* bdchgidx /**< bound change index (time stamp of bound change), or NULL for current time */
4183 )
4184{
4185 SCIP_BDCHGINFO* bdchginfo;
4186
4187 assert(conflict != NULL);
4188 assert(stat != NULL);
4189 assert(var != NULL);
4190
4191 /* convert bound to active problem variable */
4192 SCIP_CALL( convertToActiveVar(&var, set, &boundtype, NULL) );
4193
4194 /* we can ignore fixed variables */
4196 return SCIP_OKAY;
4197
4198 /* if the variable is multi-aggregated, add the bounds of all aggregation variables */
4200 {
4201 SCIP_VAR** vars;
4203 int nvars;
4204 int i;
4205
4206 vars = SCIPvarGetMultaggrVars(var);
4208 nvars = SCIPvarGetMultaggrNVars(var);
4209 for( i = 0; i < nvars; ++i )
4210 {
4211 SCIP_CALL( SCIPconflictAddBound(conflict, blkmem, set, stat, vars[i],
4212 (scalars[i] < 0.0 ? SCIPboundtypeOpposite(boundtype) : boundtype), bdchgidx) );
4213 }
4214
4215 return SCIP_OKAY;
4216 }
4217 assert(SCIPvarIsActive(var));
4218
4219 /* get bound change information */
4220 bdchginfo = SCIPvarGetBdchgInfo(var, boundtype, bdchgidx, FALSE);
4221
4222 /* if bound of variable was not changed (this means it is still the global bound), we can ignore the conflicting
4223 * bound
4224 */
4225 if( bdchginfo == NULL )
4226 return SCIP_OKAY;
4227
4228 assert(SCIPbdchgidxIsEarlier(SCIPbdchginfoGetIdx(bdchginfo), bdchgidx));
4229
4230 SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchginfo, SCIPbdchginfoGetNewbound(bdchginfo)) );
4231
4232 return SCIP_OKAY;
4233}
4234
4235/** adds variable's bound to conflict candidate queue */
4237 SCIP_CONFLICT* conflict, /**< conflict analysis data */
4238 BMS_BLKMEM* blkmem, /**< block memory */
4239 SCIP_SET* set, /**< global SCIP settings */
4240 SCIP_STAT* stat, /**< dynamic problem statistics */
4241 SCIP_VAR* var, /**< problem variable */
4242 SCIP_BOUNDTYPE boundtype, /**< type of bound that was changed: lower or upper bound */
4243 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4244 SCIP_Real relaxedbd /**< the relaxed bound */
4245 )
4246{
4247 SCIP_BDCHGINFO* bdchginfo;
4248 int nbdchgs;
4249
4250 assert(conflict != NULL);
4251 assert(stat != NULL);
4252 assert(var != NULL);
4253
4254 if( !SCIPvarIsActive(var) )
4255 {
4256 /* convert bound to active problem variable */
4257 SCIP_CALL( convertToActiveVar(&var, set, &boundtype, &relaxedbd) );
4258
4259 /* we can ignore fixed variables */
4261 return SCIP_OKAY;
4262
4263 /* if the variable is multi-aggregated, add the bounds of all aggregation variables */
4265 {
4266 SCIPsetDebugMsg(set, "ignoring relaxed bound information since variable <%s> is multi-aggregated active\n", SCIPvarGetName(var));
4267
4268 SCIP_CALL( SCIPconflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchgidx) );
4269
4270 return SCIP_OKAY;
4271 }
4272 }
4273 assert(SCIPvarIsActive(var));
4274
4275 /* get bound change information */
4276 bdchginfo = SCIPvarGetBdchgInfo(var, boundtype, bdchgidx, FALSE);
4277
4278 /* if bound of variable was not changed (this means it is still the global bound), we can ignore the conflicting
4279 * bound
4280 */
4281 if( bdchginfo == NULL )
4282 return SCIP_OKAY;
4283
4284 /* check that the bound change info is not a temporary one */
4285 assert(SCIPbdchgidxGetPos(&bdchginfo->bdchgidx) >= 0);
4286
4287 /* get the position of the bound change information within the bound change array of the variable */
4288 nbdchgs = (int) bdchginfo->pos;
4289 assert(nbdchgs >= 0);
4290
4291 /* if the relaxed bound should be ignored, set the relaxed bound to the bound given by the bdchgidx; that ensures
4292 * that the loop(s) below will be skipped
4293 */
4294 if( set->conf_ignorerelaxedbd )
4295 relaxedbd = SCIPbdchginfoGetNewbound(bdchginfo);
4296
4297 /* search for the bound change information which includes the relaxed bound */
4298 if( boundtype == SCIP_BOUNDTYPE_LOWER )
4299 {
4300 SCIP_Real newbound;
4301
4302 /* adjust relaxed lower bound w.r.t. variable type */
4303 SCIPvarAdjustLb(var, set, &relaxedbd);
4304
4305 /* due to numericis we compare the relaxed lower bound to the one present at the particular time point and take
4306 * the better one
4307 */
4308 newbound = SCIPbdchginfoGetNewbound(bdchginfo);
4309 relaxedbd = MIN(relaxedbd, newbound);
4310
4311 /* check if relaxed lower bound is smaller or equal to global lower bound; if so we can ignore the conflicting
4312 * bound
4313 */
4314 if( SCIPsetIsLE(set, relaxedbd, SCIPvarGetLbGlobal(var)) )
4315 return SCIP_OKAY;
4316
4317 while( nbdchgs > 0 )
4318 {
4319 assert(SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4320
4321 /* check if the old lower bound is greater than or equal to relaxed lower bound; if not we found the bound
4322 * change info which we need to report
4323 */
4324 if( SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) )
4325 break;
4326
4327 bdchginfo = SCIPvarGetBdchgInfoLb(var, nbdchgs-1);
4328
4329 SCIPsetDebugMsg(set, "lower bound change %d oldbd=%.15g, newbd=%.15g, depth=%d, pos=%d, redundant=%u\n",
4330 nbdchgs, SCIPbdchginfoGetOldbound(bdchginfo), SCIPbdchginfoGetNewbound(bdchginfo),
4331 SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
4332 SCIPbdchginfoIsRedundant(bdchginfo));
4333
4334 /* if bound change is redundant (this means it now a global bound), we can ignore the conflicting bound */
4335 if( SCIPbdchginfoIsRedundant(bdchginfo) )
4336 return SCIP_OKAY;
4337
4338 nbdchgs--;
4339 }
4340 assert(SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
4341 }
4342 else
4343 {
4344 SCIP_Real newbound;
4345
4346 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
4347
4348 /* adjust relaxed upper bound w.r.t. variable type */
4349 SCIPvarAdjustUb(var, set, &relaxedbd);
4350
4351 /* due to numericis we compare the relaxed upper bound to the one present at the particular time point and take
4352 * the better one
4353 */
4354 newbound = SCIPbdchginfoGetNewbound(bdchginfo);
4355 relaxedbd = MAX(relaxedbd, newbound);
4356
4357 /* check if relaxed upper bound is greater or equal to global upper bound; if so we can ignore the conflicting
4358 * bound
4359 */
4360 if( SCIPsetIsGE(set, relaxedbd, SCIPvarGetUbGlobal(var)) )
4361 return SCIP_OKAY;
4362
4363 while( nbdchgs > 0 )
4364 {
4365 assert(SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4366
4367 /* check if the old upper bound is smaller than or equal to the relaxed upper bound; if not we found the
4368 * bound change info which we need to report
4369 */
4370 if( SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) )
4371 break;
4372
4373 bdchginfo = SCIPvarGetBdchgInfoUb(var, nbdchgs-1);
4374
4375 SCIPsetDebugMsg(set, "upper bound change %d oldbd=%.15g, newbd=%.15g, depth=%d, pos=%d, redundant=%u\n",
4376 nbdchgs, SCIPbdchginfoGetOldbound(bdchginfo), SCIPbdchginfoGetNewbound(bdchginfo),
4377 SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
4378 SCIPbdchginfoIsRedundant(bdchginfo));
4379
4380 /* if bound change is redundant (this means it now a global bound), we can ignore the conflicting bound */
4381 if( SCIPbdchginfoIsRedundant(bdchginfo) )
4382 return SCIP_OKAY;
4383
4384 nbdchgs--;
4385 }
4386 assert(SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
4387 }
4388
4389 assert(SCIPbdchgidxIsEarlier(SCIPbdchginfoGetIdx(bdchginfo), bdchgidx));
4390
4391 /* put bound change information into priority queue */
4392 SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchginfo, relaxedbd) );
4393
4394 return SCIP_OKAY;
4395}
4396
4397/** checks if the given variable is already part of the current conflict set or queued for resolving with the same or
4398 * even stronger bound
4399 */
4401 SCIP_CONFLICT* conflict, /**< conflict analysis data */
4402 SCIP_VAR* var, /**< problem variable */
4403 SCIP_SET* set, /**< global SCIP settings */
4404 SCIP_BOUNDTYPE boundtype, /**< type of bound for which the score should be increased */
4405 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4406 SCIP_Bool* used /**< pointer to store if the variable is already used */
4407 )
4408{
4409 SCIP_Real newbound;
4410
4411 /* convert bound to active problem variable */
4412 SCIP_CALL( convertToActiveVar(&var, set, &boundtype, NULL) );
4413
4415 *used = FALSE;
4416 else
4417 {
4418 assert(SCIPvarIsActive(var));
4419 assert(var != NULL);
4420
4421 switch( boundtype )
4422 {
4424
4425 newbound = SCIPgetVarLbAtIndex(set->scip, var, bdchgidx, FALSE);
4426
4427 if( var->conflictlbcount == conflict->count && var->conflictlb >= newbound )
4428 {
4429 SCIPsetDebugMsg(set, "already queued bound change <%s> >= %g\n", SCIPvarGetName(var), newbound);
4430 *used = TRUE;
4431 }
4432 else
4433 *used = FALSE;
4434 break;
4436
4437 newbound = SCIPgetVarUbAtIndex(set->scip, var, bdchgidx, FALSE);
4438
4439 if( var->conflictubcount == conflict->count && var->conflictub <= newbound )
4440 {
4441 SCIPsetDebugMsg(set, "already queued bound change <%s> <= %g\n", SCIPvarGetName(var), newbound);
4442 *used = TRUE;
4443 }
4444 else
4445 *used = FALSE;
4446 break;
4447 default:
4448 SCIPerrorMessage("invalid bound type %d\n", boundtype);
4449 SCIPABORT();
4450 *used = FALSE; /*lint !e527*/
4451 }
4452 }
4453
4454 return SCIP_OKAY;
4455}
4456
4457/** inserts variable's new bounds into bound change arrays */
4458static
4460 SCIP_SET* set, /**< global SCIP settings */
4461 SCIP_VAR* var, /**< variable to change the LP bounds for */
4462 SCIP_Real newlb, /**< new lower bound */
4463 SCIP_Real newub, /**< new upper bound */
4464 SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change */
4465 SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change */
4466 SCIP_LPI* lpi /**< pointer to LPi to access infinity of LP solver; necessary to set correct value */
4467 )
4468{
4469 assert(newlb <= newub);
4470 assert(oldlpbdchgs != NULL);
4471 assert(relaxedlpbdchgs != NULL);
4472
4474 {
4475 SCIP_COL* col;
4476 int idx;
4477 int c;
4478
4479 col = SCIPvarGetCol(var);
4480 c = SCIPcolGetLPPos(col);
4481
4482 if( c >= 0 )
4483 {
4484 /* store old bound change for resetting the LP later */
4485 if( !oldlpbdchgs->usedcols[c] )
4486 {
4487 idx = oldlpbdchgs->nbdchgs;
4488 oldlpbdchgs->usedcols[c] = TRUE;
4489 oldlpbdchgs->bdchgcolinds[c] = idx;
4490 oldlpbdchgs->nbdchgs++;
4491
4492 oldlpbdchgs->bdchginds[idx] = c;
4493 oldlpbdchgs->bdchglbs[idx] = SCIPvarGetLbLP(var, set);
4494 oldlpbdchgs->bdchgubs[idx] = SCIPvarGetUbLP(var, set);
4495 }
4496 assert(oldlpbdchgs->bdchginds[oldlpbdchgs->bdchgcolinds[c]] == c);
4497 assert((SCIPlpiIsInfinity(lpi, -oldlpbdchgs->bdchglbs[oldlpbdchgs->bdchgcolinds[c]]) && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var, set))) ||
4498 SCIPsetIsEQ(set, oldlpbdchgs->bdchglbs[oldlpbdchgs->bdchgcolinds[c]], SCIPvarGetLbLP(var, set)));
4499 assert((SCIPlpiIsInfinity(lpi, oldlpbdchgs->bdchgubs[oldlpbdchgs->bdchgcolinds[c]]) && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var, set))) ||
4500 SCIPsetIsEQ(set, oldlpbdchgs->bdchgubs[oldlpbdchgs->bdchgcolinds[c]], SCIPvarGetUbLP(var, set)));
4501
4502 /* store bound change for conflict analysis */
4503 if( !relaxedlpbdchgs->usedcols[c] )
4504 {
4505 idx = relaxedlpbdchgs->nbdchgs;
4506 relaxedlpbdchgs->usedcols[c] = TRUE;
4507 relaxedlpbdchgs->bdchgcolinds[c] = idx;
4508 relaxedlpbdchgs->nbdchgs++;
4509
4510 /* remember the positive for later further bound widenings */
4511 relaxedlpbdchgs->bdchginds[idx] = c;
4512 }
4513 else
4514 {
4515 idx = relaxedlpbdchgs->bdchgcolinds[c];
4516 assert(relaxedlpbdchgs->bdchginds[idx] == c);
4517
4518 /* the new bound should be the same or more relaxed */
4519 assert(relaxedlpbdchgs->bdchglbs[idx] >= newlb ||
4520 (SCIPlpiIsInfinity(lpi, -relaxedlpbdchgs->bdchglbs[idx]) && SCIPsetIsInfinity(set, -newlb)));
4521 assert(relaxedlpbdchgs->bdchgubs[idx] <= newub ||
4522 (SCIPlpiIsInfinity(lpi, relaxedlpbdchgs->bdchgubs[idx]) && SCIPsetIsInfinity(set, newub)));
4523 }
4524
4525 /* set the new bounds for the LP with the correct infinity value */
4526 relaxedlpbdchgs->bdchglbs[idx] = SCIPsetIsInfinity(set, -newlb) ? -SCIPlpiInfinity(lpi) : newlb;
4527 relaxedlpbdchgs->bdchgubs[idx] = SCIPsetIsInfinity(set, newub) ? SCIPlpiInfinity(lpi) : newub;
4528 if( SCIPsetIsInfinity(set, -oldlpbdchgs->bdchglbs[idx]) )
4529 oldlpbdchgs->bdchglbs[idx] = -SCIPlpiInfinity(lpi);
4530 if( SCIPsetIsInfinity(set, oldlpbdchgs->bdchgubs[idx]) )
4531 oldlpbdchgs->bdchgubs[idx] = SCIPlpiInfinity(lpi);
4532 }
4533 }
4534
4535 return SCIP_OKAY;
4536}
4537
4538/** adds variable to candidate list, if the current best bound corresponding to the proof coefficient is local;
4539 * returns the array position in the candidate list, where the new candidate was inserted, or -1 if the
4540 * variable can relaxed to global bounds immediately without increasing the proof's activity;
4541 * the candidates are sorted with respect to the following two criteria:
4542 * - prefer bound changes that have been applied deeper in the tree, to get a more global conflict
4543 * - prefer variables with small Farkas coefficient to get rid of as many bound changes as possible
4544 */
4545static
4547 SCIP_SET* set, /**< global SCIP settings */
4548 int currentdepth, /**< current depth in the tree */
4549 SCIP_VAR* var, /**< variable to add to candidate array */
4550 int lbchginfopos, /**< positions of currently active lower bound change information in variable's array */
4551 int ubchginfopos, /**< positions of currently active upper bound change information in variable's array */
4552 SCIP_Real proofcoef, /**< coefficient of variable in infeasibility/bound proof */
4553 SCIP_Real prooflhs, /**< left hand side of infeasibility/bound proof */
4554 SCIP_Real proofact, /**< activity of infeasibility/bound proof row */
4555 SCIP_VAR*** cands, /**< pointer to candidate array for undoing bound changes */
4556 SCIP_Real** candscores, /**< pointer to candidate score array for undoing bound changes */
4557 SCIP_Real** newbounds, /**< pointer to candidate new bounds array for undoing bound changes */
4558 SCIP_Real** proofactdeltas, /**< pointer to proof activity increase array for undoing bound changes */
4559 int* candssize, /**< pointer to size of cands arrays */
4560 int* ncands, /**< pointer to count number of candidates in bound change list */
4561 int firstcand /**< position of first unprocessed bound change candidate */
4562 )
4563{
4564 SCIP_Real oldbound;
4565 SCIP_Real newbound;
4566 SCIP_Real QUAD(proofactdelta);
4567 SCIP_Real score;
4568 int depth;
4569 int i;
4570 SCIP_Bool resolvable;
4571
4572 assert(set != NULL);
4573 assert(var != NULL);
4574 assert(-1 <= lbchginfopos && lbchginfopos <= var->nlbchginfos);
4575 assert(-1 <= ubchginfopos && ubchginfopos <= var->nubchginfos);
4576 assert(!SCIPsetIsZero(set, proofcoef));
4577 assert(SCIPsetIsGT(set, prooflhs, proofact));
4578 assert(cands != NULL);
4579 assert(candscores != NULL);
4580 assert(newbounds != NULL);
4581 assert(proofactdeltas != NULL);
4582 assert(candssize != NULL);
4583 assert(ncands != NULL);
4584 assert(*ncands <= *candssize);
4585 assert(0 <= firstcand && firstcand <= *ncands);
4586
4587 /* in the infeasibility or dual bound proof, the variable's bound is chosen to maximize the proof's activity */
4588 if( proofcoef > 0.0 )
4589 {
4590 assert(ubchginfopos >= 0); /* otherwise, undoBdchgsProof() should already have relaxed the local bound */
4591
4592 /* calculate the difference of current bound to the previous bound the variable was set to */
4593 if( ubchginfopos == var->nubchginfos )
4594 {
4595 /* current bound is the strong branching or diving bound */
4596 oldbound = SCIPvarGetUbLP(var, set);
4597 newbound = SCIPvarGetUbLocal(var);
4598 depth = currentdepth+1;
4599 resolvable = FALSE;
4600 }
4601 else
4602 {
4603 /* current bound is the result of a local bound change */
4604 resolvable = bdchginfoIsResolvable(&var->ubchginfos[ubchginfopos]);
4605 depth = var->ubchginfos[ubchginfopos].bdchgidx.depth;
4606 oldbound = var->ubchginfos[ubchginfopos].newbound;
4607 newbound = var->ubchginfos[ubchginfopos].oldbound;
4608 }
4609 }
4610 else
4611 {
4612 assert(lbchginfopos >= 0); /* otherwise, undoBdchgsProof() should already have relaxed the local bound */
4613
4614 /* calculate the difference of current bound to the previous bound the variable was set to */
4615 if( lbchginfopos == var->nlbchginfos )
4616 {
4617 /* current bound is the strong branching or diving bound */
4618 oldbound = SCIPvarGetLbLP(var, set);
4619 newbound = SCIPvarGetLbLocal(var);
4620 depth = currentdepth+1;
4621 resolvable = FALSE;
4622 }
4623 else
4624 {
4625 /* current bound is the result of a local bound change */
4626 resolvable = bdchginfoIsResolvable(&var->lbchginfos[lbchginfopos]);
4627 depth = var->lbchginfos[lbchginfopos].bdchgidx.depth;
4628 oldbound = var->lbchginfos[lbchginfopos].newbound;
4629 newbound = var->lbchginfos[lbchginfopos].oldbound;
4630 }
4631 }
4632
4633 /* calculate the increase in the proof's activity */
4634 SCIPquadprecSumDD(proofactdelta, newbound, -oldbound);
4635 SCIPquadprecProdQD(proofactdelta, proofactdelta, proofcoef);
4636 assert(QUAD_TO_DBL(proofactdelta) > 0.0);
4637
4638 /* calculate score for undoing the bound change */
4639 score = calcBdchgScore(prooflhs, proofact, QUAD_TO_DBL(proofactdelta), proofcoef, depth, currentdepth, var, set);
4640
4641 if( !resolvable )
4642 {
4643 score += 10.0;
4644 if( !SCIPvarIsBinary(var) )
4645 score += 10.0;
4646 }
4647
4648 /* get enough memory to store new candidate */
4649 SCIP_CALL( ensureCandsSize(set, cands, candscores, newbounds, proofactdeltas, candssize, (*ncands)+1) );
4650 assert(*cands != NULL);
4651 assert(*candscores != NULL);
4652 assert(*newbounds != NULL);
4653 assert(*proofactdeltas != NULL);
4654
4655 SCIPsetDebugMsg(set, " -> local <%s> %s %g, relax <%s> %s %g, proofcoef=%g, dpt=%d, resolve=%u, delta=%g, score=%g\n",
4656 SCIPvarGetName(var), proofcoef > 0.0 ? "<=" : ">=", oldbound,
4657 SCIPvarGetName(var), proofcoef > 0.0 ? "<=" : ">=", newbound,
4658 proofcoef, depth, resolvable, QUAD_TO_DBL(proofactdelta), score);
4659
4660 /* insert variable in candidate list without touching the already processed candidates */
4661 for( i = *ncands; i > firstcand && score > (*candscores)[i-1]; --i )
4662 {
4663 (*cands)[i] = (*cands)[i-1];
4664 (*candscores)[i] = (*candscores)[i-1];
4665 (*newbounds)[i] = (*newbounds)[i-1];
4666 (*proofactdeltas)[i] = (*proofactdeltas)[i-1];
4667 }
4668 (*cands)[i] = var;
4669 (*candscores)[i] = score;
4670 (*newbounds)[i] = newbound;
4671 (*proofactdeltas)[i] = QUAD_TO_DBL(proofactdelta);
4672 (*ncands)++;
4673
4674 return SCIP_OKAY;
4675}
4676
4677/** undoes bound changes on variables, still leaving the given infeasibility proof valid */
4679 SCIP_SET* set, /**< global SCIP settings */
4680 SCIP_PROB* prob, /**< problem data */
4681 int currentdepth, /**< current depth in the tree */
4682 SCIP_Real* proofcoefs, /**< coefficients in infeasibility proof */
4683 SCIP_Real prooflhs, /**< left hand side of proof */
4684 SCIP_Real* proofact, /**< current activity of proof */
4685 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
4686 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
4687 int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
4688 int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
4689 SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
4690 SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
4691 SCIP_Bool* resolve, /**< pointer to store whether the changed LP should be resolved again, or NULL */
4692 SCIP_LPI* lpi /**< pointer to LPi to access infinity of LP solver; necessary to set correct values */
4693 )
4694{
4695 SCIP_VAR** vars;
4696 SCIP_VAR** cands;
4697 SCIP_Real* candscores;
4698 SCIP_Real* newbounds;
4699 SCIP_Real* proofactdeltas;
4700 int nvars;
4701 int ncands;
4702 int candssize;
4703 int v;
4704 int i;
4705
4706 assert(prob != NULL);
4707 assert(proofcoefs != NULL);
4708 assert(SCIPsetIsFeasGT(set, prooflhs, (*proofact)));
4709 assert(curvarlbs != NULL);
4710 assert(curvarubs != NULL);
4711 assert(lbchginfoposs != NULL);
4712 assert(ubchginfoposs != NULL);
4713
4714 if( resolve != NULL )
4715 *resolve = FALSE;
4716
4717 vars = prob->vars;
4718 nvars = prob->nvars;
4719 assert(nvars == 0 || vars != NULL);
4720
4721 /* calculate the order in which the bound changes are tried to be undone, and relax all bounds if this doesn't
4722 * increase the proof's activity
4723 */
4724 SCIP_CALL( SCIPsetAllocBufferArray(set, &cands, nvars) );
4725 SCIP_CALL( SCIPsetAllocBufferArray(set, &candscores, nvars) );
4726 SCIP_CALL( SCIPsetAllocBufferArray(set, &newbounds, nvars) );
4727 SCIP_CALL( SCIPsetAllocBufferArray(set, &proofactdeltas, nvars) );
4728 ncands = 0;
4729 candssize = nvars;
4730 for( v = 0; v < nvars; ++v )
4731 {
4732 SCIP_VAR* var;
4733 SCIP_Bool relaxed;
4734
4735 var = vars[v];
4736
4737 /* after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
4738 * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
4739 * global bound and we can ignore it
4740 */
4741 skipRedundantBdchginfos(var, &lbchginfoposs[v], &ubchginfoposs[v]);
4742
4743 /* ignore variables already relaxed to global bounds */
4744 if( (lbchginfoposs[v] == -1 && ubchginfoposs[v] == -1) )
4745 {
4746 proofcoefs[v] = 0.0;
4747 continue;
4748 }
4749
4750 /* relax bounds that are not used in the proof to the global bounds */
4751 relaxed = FALSE;
4752 if( !SCIPsetIsNegative(set, proofcoefs[v]) )
4753 {
4754 /* the lower bound is not used */
4755 if( lbchginfoposs[v] >= 0 )
4756 {
4757 SCIPsetDebugMsg(set, " -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g\n",
4758 SCIPvarGetName(var), curvarlbs[v], curvarubs[v], SCIPvarGetLbGlobal(var), curvarubs[v],
4759 proofcoefs[v], prooflhs, (*proofact));
4760 curvarlbs[v] = SCIPvarGetLbGlobal(var);
4761 lbchginfoposs[v] = -1;
4762 relaxed = TRUE;
4763 }
4764 }
4765 if( !SCIPsetIsPositive(set, proofcoefs[v]) )
4766 {
4767 /* the upper bound is not used */
4768 if( ubchginfoposs[v] >= 0 )
4769 {
4770 SCIPsetDebugMsg(set, " -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g\n",
4771 SCIPvarGetName(var), curvarlbs[v], curvarubs[v], curvarlbs[v], SCIPvarGetUbGlobal(var),
4772 proofcoefs[v], prooflhs, (*proofact));
4773 curvarubs[v] = SCIPvarGetUbGlobal(var);
4774 ubchginfoposs[v] = -1;
4775 relaxed = TRUE;
4776 }
4777 }
4778 if( relaxed && oldlpbdchgs != NULL )
4779 {
4780 SCIP_CALL( addBdchg(set, var, curvarlbs[v], curvarubs[v], oldlpbdchgs, relaxedlpbdchgs, lpi) );
4781 }
4782
4783 /* add bound to candidate list */
4784 if( lbchginfoposs[v] >= 0 || ubchginfoposs[v] >= 0 )
4785 {
4786 SCIP_CALL( addCand(set, currentdepth, var, lbchginfoposs[v], ubchginfoposs[v], proofcoefs[v],
4787 prooflhs, (*proofact), &cands, &candscores, &newbounds, &proofactdeltas, &candssize, &ncands, 0) );
4788 }
4789 /* we can set the proof coefficient to zero, because the variable is not needed */
4790 else
4791 proofcoefs[v] = 0.0;
4792 }
4793
4794 /* try to undo remaining local bound changes while still keeping the proof row violated:
4795 * bound changes can be undone, if prooflhs > proofact + proofactdelta;
4796 * afterwards, the current proof activity has to be updated
4797 */
4798 for( i = 0; i < ncands; ++i )
4799 {
4800 assert(proofactdeltas[i] > 0.0);
4801 assert((lbchginfoposs[SCIPvarGetProbindex(cands[i])] >= 0) != (ubchginfoposs[SCIPvarGetProbindex(cands[i])] >= 0));
4802
4803 /* when relaxing a constraint we still need to stay infeasible; therefore we need to do the comparison in
4804 * feasibility tolerance because if 'prooflhs' is (feas-))equal to 'proofact + proofactdeltas[i]' it would mean
4805 * that there is no violation
4806 */
4807 if( SCIPsetIsFeasGT(set, prooflhs, (*proofact) + proofactdeltas[i]) )
4808 {
4809 v = SCIPvarGetProbindex(cands[i]);
4810 assert(0 <= v && v < nvars);
4811 assert((lbchginfoposs[v] >= 0) != (ubchginfoposs[v] >= 0));
4812
4813 SCIPsetDebugMsg(set, " -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g + %g\n",
4814 SCIPvarGetName(cands[i]), curvarlbs[v], curvarubs[v],
4815 proofcoefs[v] > 0.0 ? curvarlbs[v] : newbounds[i],
4816 proofcoefs[v] > 0.0 ? newbounds[i] : curvarubs[v],
4817 proofcoefs[v], prooflhs, (*proofact), proofactdeltas[i]);
4818
4819#ifndef NDEBUG
4820 {
4821 SCIP_Real QUAD(verifylb);
4822 SCIP_Real QUAD(verifyub);
4823
4824 SCIPquadprecSumDD(verifylb, newbounds[i], -curvarlbs[v]);
4825 SCIPquadprecProdQD(verifylb, verifylb, proofcoefs[v]);
4826
4827 SCIPquadprecSumDD(verifyub, newbounds[i], -curvarubs[v]);
4828 SCIPquadprecProdQD(verifyub, verifyub, proofcoefs[v]);
4829
4830 assert((SCIPsetIsPositive(set, proofcoefs[v]) && SCIPsetIsGT(set, newbounds[i], curvarubs[v]))
4831 || (SCIPsetIsNegative(set, proofcoefs[v]) && SCIPsetIsLT(set, newbounds[i], curvarlbs[v])));
4832 assert((SCIPsetIsPositive(set, proofcoefs[v])
4833 && SCIPsetIsEQ(set, proofactdeltas[i], QUAD_TO_DBL(verifyub)))
4834 || (SCIPsetIsNegative(set, proofcoefs[v])
4835 && SCIPsetIsEQ(set, proofactdeltas[i], QUAD_TO_DBL(verifylb))));
4836 assert(!SCIPsetIsZero(set, proofcoefs[v]));
4837 }
4838#endif
4839
4840 if( proofcoefs[v] > 0.0 )
4841 {
4842 assert(ubchginfoposs[v] >= 0);
4843 assert(lbchginfoposs[v] == -1);
4844 curvarubs[v] = newbounds[i];
4845 ubchginfoposs[v]--;
4846 }
4847 else
4848 {
4849 assert(lbchginfoposs[v] >= 0);
4850 assert(ubchginfoposs[v] == -1);
4851 curvarlbs[v] = newbounds[i];
4852 lbchginfoposs[v]--;
4853 }
4854 if( oldlpbdchgs != NULL )
4855 {
4856 SCIP_CALL( addBdchg(set, cands[i], curvarlbs[v], curvarubs[v], oldlpbdchgs, relaxedlpbdchgs, lpi) );
4857 }
4858 (*proofact) += proofactdeltas[i];
4859 if( resolve != NULL && SCIPvarIsInLP(cands[i]) )
4860 *resolve = TRUE;
4861
4862 /* after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
4863 * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
4864 * global bound and we can ignore it
4865 */
4866 skipRedundantBdchginfos(cands[i], &lbchginfoposs[v], &ubchginfoposs[v]);
4867
4868 /* insert the new local bound of the variable into the candidate list */
4869 if( lbchginfoposs[v] >= 0 || ubchginfoposs[v] >= 0 )
4870 {
4871 SCIP_CALL( addCand(set, currentdepth, cands[i], lbchginfoposs[v], ubchginfoposs[v], proofcoefs[v],
4872 prooflhs, (*proofact), &cands, &candscores, &newbounds, &proofactdeltas, &candssize, &ncands, i+1) );
4873 }
4874 else
4875 proofcoefs[v] = 0.0;
4876 }
4877 }
4878
4879 /* free the buffer for the sorted bound change candidates */
4880 SCIPsetFreeBufferArray(set, &proofactdeltas);
4881 SCIPsetFreeBufferArray(set, &newbounds);
4882 SCIPsetFreeBufferArray(set, &candscores);
4883 SCIPsetFreeBufferArray(set, &cands);
4884
4885 return SCIP_OKAY;
4886}
4887
4888/** analyzes an infeasible LP and undoes additional bound changes while staying infeasible */
4889static
4891 SCIP_SET* set, /**< global SCIP settings */
4892 SCIP_PROB* prob, /**< problem data */
4893 SCIP_LP* lp, /**< LP data */
4894 int currentdepth, /**< current depth in the tree */
4895 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
4896 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
4897 int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
4898 int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
4899 SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
4900 SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
4901 SCIP_Bool* valid, /**< pointer to store whether the unfixings are valid */
4902 SCIP_Bool* resolve, /**< pointer to store whether the changed LP should be resolved again */
4903 SCIP_Real* farkascoefs, /**< coefficients in the proof constraint */
4904 SCIP_Real farkaslhs, /**< lhs of the proof constraint */
4905 SCIP_Real* farkasactivity /**< maximal activity of the proof constraint */
4906 )
4907{
4908 SCIP_LPI* lpi;
4909
4910 assert(prob != NULL);
4911 assert(lp != NULL);
4912 assert(lp->flushed);
4913 assert(lp->solved);
4914 assert(curvarlbs != NULL);
4915 assert(curvarubs != NULL);
4916 assert(lbchginfoposs != NULL);
4917 assert(ubchginfoposs != NULL);
4918 assert(valid != NULL);
4919 assert(resolve != NULL);
4920
4921 SCIPsetDebugMsg(set, "undoing bound changes in infeasible LP: cutoff=%g\n", lp->cutoffbound);
4922
4923 *valid = FALSE;
4924 *resolve = FALSE;
4925
4926 lpi = SCIPlpGetLPI(lp);
4927
4928 /* check, if the Farkas row is still violated (using current bounds and ignoring local rows) */
4929 if( SCIPsetIsFeasGT(set, farkaslhs, *farkasactivity) )
4930 {
4931 /* undo bound changes while keeping the infeasibility proof valid */
4932 SCIP_CALL( SCIPundoBdchgsProof(set, prob, currentdepth, farkascoefs, farkaslhs, farkasactivity, \
4933 curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, resolve, lpi) );
4934
4935 *valid = TRUE;
4936
4937 /* resolving does not make sense: the old dual ray is still valid -> resolving will not change the solution */
4938 *resolve = FALSE;
4939 }
4940
4941 return SCIP_OKAY;
4942}
4943
4944
4945/*
4946 * Conflict LP Bound Changes
4947 */
4948
4949/** create conflict LP bound change data structure */
4950static
4952 SCIP_LPBDCHGS** lpbdchgs, /**< pointer to store the conflict LP bound change data structure */
4953 SCIP_SET* set, /**< global SCIP settings */
4954 int ncols /**< number of columns */
4955 )
4956{
4957 SCIP_CALL( SCIPsetAllocBuffer(set, lpbdchgs) );
4958
4959 SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchginds, ncols) );
4960 SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchglbs, ncols) );
4961 SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchgubs, ncols) );
4962 SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchgcolinds, ncols) );
4963 SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->usedcols, ncols) );
4964 BMSclearMemoryArray((*lpbdchgs)->usedcols, ncols);
4965
4966 (*lpbdchgs)->nbdchgs = 0;
4967
4968 return SCIP_OKAY;
4969}
4970
4971
4972/*
4973 * Propagation Conflict Analysis
4974 */
4975
4976/** ensures, that side change arrays can store at least num entries */
4977static
4979 SCIP_SET* set, /**< global SCIP settings */
4980 int** sidechginds, /**< pointer to side change index array */
4981 SCIP_Real** sidechgoldlhss, /**< pointer to side change old left hand sides array */
4982 SCIP_Real** sidechgoldrhss, /**< pointer to side change old right hand sides array */
4983 SCIP_Real** sidechgnewlhss, /**< pointer to side change new left hand sides array */
4984 SCIP_Real** sidechgnewrhss, /**< pointer to side change new right hand sides array */
4985 int* sidechgssize, /**< pointer to size of side change arrays */
4986 int num /**< minimal number of entries to be able to store in side change arrays */
4987 )
4988{
4989 assert(sidechginds != NULL);
4990 assert(sidechgoldlhss != NULL);
4991 assert(sidechgoldrhss != NULL);
4992 assert(sidechgnewlhss != NULL);
4993 assert(sidechgnewrhss != NULL);
4994 assert(sidechgssize != NULL);
4995
4996 if( num > *sidechgssize )
4997 {
4998 int newsize;
4999
5000 newsize = SCIPsetCalcMemGrowSize(set, num);
5001 SCIP_CALL( SCIPsetReallocBufferArray(set, sidechginds, newsize) );
5002 SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgoldlhss, newsize) );
5003 SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgoldrhss, newsize) );
5004 SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgnewlhss, newsize) );
5005 SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgnewrhss, newsize) );
5006 *sidechgssize = newsize;
5007 }
5008 assert(num <= *sidechgssize);
5009
5010 return SCIP_OKAY;
5011}
5012
5013/** adds removal of row's side to side change arrays; finite sides are only replaced by near infinite sides, such
5014 * that the row's sense in the LP solver is not changed
5015 */
5016static
5018 SCIP_SET* set, /**< global SCIP settings */
5019 SCIP_ROW* row, /**< LP row to change the sides for */
5020 SCIP_Real lpiinfinity, /**< value treated as infinity in LP solver */
5021 int** sidechginds, /**< pointer to side change index array */
5022 SCIP_Real** sidechgoldlhss, /**< pointer to side change old left hand sides array */
5023 SCIP_Real** sidechgoldrhss, /**< pointer to side change old right hand sides array */
5024 SCIP_Real** sidechgnewlhss, /**< pointer to side change new left hand sides array */
5025 SCIP_Real** sidechgnewrhss, /**< pointer to side change new right hand sides array */
5026 int* sidechgssize, /**< pointer to size of side change arrays */
5027 int* nsidechgs /**< pointer to number of used slots in side change arrays */
5028 )
5029{
5030 SCIP_Real lhs;
5031 SCIP_Real rhs;
5032 SCIP_Real constant;
5033
5034 assert(sidechginds != NULL);
5035 assert(sidechgoldlhss != NULL);
5036 assert(sidechgoldrhss != NULL);
5037 assert(sidechgnewlhss != NULL);
5038 assert(sidechgnewrhss != NULL);
5039 assert(sidechgssize != NULL);
5040 assert(nsidechgs != NULL);
5041
5042 lhs = SCIProwGetLhs(row);
5043 rhs = SCIProwGetRhs(row);
5044 constant = SCIProwGetConstant(row);
5045 assert(!SCIPsetIsInfinity(set, -lhs) || !SCIPsetIsInfinity(set, rhs));
5046
5047 /* get memory to store additional side change */
5048 SCIP_CALL( ensureSidechgsSize(set, sidechginds, sidechgoldlhss, sidechgoldrhss, sidechgnewlhss, sidechgnewrhss, \
5049 sidechgssize, (*nsidechgs)+1) );
5050 assert(*nsidechgs < *sidechgssize);
5051 assert(*sidechginds != NULL);
5052 assert(*sidechgoldlhss != NULL);
5053 assert(*sidechgoldrhss != NULL);
5054 assert(*sidechgnewlhss != NULL);
5055 assert(*sidechgnewrhss != NULL);
5056
5057 /* store side change */
5058 (*sidechginds)[*nsidechgs] = SCIProwGetLPPos(row);
5059 if( SCIPsetIsInfinity(set, -lhs) )
5060 {
5061 (*sidechgoldlhss)[*nsidechgs] = -lpiinfinity;
5062 (*sidechgnewlhss)[*nsidechgs] = -lpiinfinity;
5063 }
5064 else
5065 {
5066 (*sidechgoldlhss)[*nsidechgs] = lhs - constant;
5067 (*sidechgnewlhss)[*nsidechgs] = -lpiinfinity;
5068 }
5069 if( SCIPsetIsInfinity(set, rhs) )
5070 {
5071 (*sidechgoldrhss)[*nsidechgs] = lpiinfinity;
5072 (*sidechgnewrhss)[*nsidechgs] = lpiinfinity;
5073 }
5074 else
5075 {
5076 (*sidechgoldrhss)[*nsidechgs] = rhs - constant;
5077 (*sidechgnewrhss)[*nsidechgs] = lpiinfinity;
5078 }
5079 (*nsidechgs)++;
5080
5081 return SCIP_OKAY;
5082}
5083
5084
5085/*
5086 * Infeasible LP Conflict Analysis
5087 */
5088
5089/** reset conflict LP bound change data structure */
5090static
5092 SCIP_LPBDCHGS* lpbdchgs, /**< conflict LP bound change data structure */
5093 int ncols /**< number of columns */
5094 )
5095{
5096 assert(lpbdchgs != NULL);
5097
5098 BMSclearMemoryArray(lpbdchgs->usedcols, ncols);
5099 lpbdchgs->nbdchgs = 0;
5100}
5101
5102/** free conflict LP bound change data structure */
5103static
5105 SCIP_LPBDCHGS** lpbdchgs, /**< pointer to store the conflict LP bound change data structure */
5106 SCIP_SET* set /**< global SCIP settings */
5107 )
5108{
5109 SCIPsetFreeBufferArray(set, &(*lpbdchgs)->usedcols);
5110 SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchgcolinds);
5111 SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchgubs);
5112 SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchglbs);
5113 SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchginds);
5114
5115 SCIPsetFreeBuffer(set, lpbdchgs);
5116}
5117
5118/** analyzes an LP exceeding the objective limit and undoes additional bound changes while staying beyond the
5119 * objective limit
5120 */
5121static
5123 SCIP_SET* set, /**< global SCIP settings */
5124 SCIP_PROB* prob, /**< problem data */
5125 SCIP_LP* lp, /**< LP data */
5126 int currentdepth, /**< current depth in the tree */
5127 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
5128 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
5129 int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
5130 int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
5131 SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
5132 SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
5133 SCIP_Bool* valid, /**< pointer to store whether the unfixings are valid */
5134 SCIP_Bool* resolve, /**< pointer to store whether the changed LP should be resolved again */
5135 SCIP_Real* dualcoefs, /**< coefficients in the proof constraint */
5136 SCIP_Real duallhs, /**< lhs of the proof constraint */
5137 SCIP_Real* dualactivity /**< maximal activity of the proof constraint */
5138 )
5139{
5140 SCIP_LPI* lpi;
5141
5142 assert(set != NULL);
5143 assert(prob != NULL);
5144 assert(lp != NULL);
5145 assert(lp->flushed);
5146 assert(lp->solved);
5147 assert(curvarlbs != NULL);
5148 assert(curvarubs != NULL);
5149 assert(lbchginfoposs != NULL);
5150 assert(ubchginfoposs != NULL);
5151 assert(valid != NULL);
5152 assert(resolve != NULL);
5153
5154 *valid = FALSE;
5155 *resolve = FALSE;
5156
5157 SCIPsetDebugMsg(set, "undoing bound changes in LP exceeding cutoff: cutoff=%g\n", lp->cutoffbound);
5158
5159 /* get LP solver interface */
5160 lpi = SCIPlpGetLPI(lp);
5161
5162 /* check, if the dual row is still violated (using current bounds and ignoring local rows) */
5163 if( SCIPsetIsFeasGT(set, duallhs, *dualactivity) )
5164 {
5165 /* undo bound changes while keeping the infeasibility proof valid */
5166 SCIP_CALL( SCIPundoBdchgsProof(set, prob, currentdepth, dualcoefs, duallhs, dualactivity, curvarlbs, curvarubs, \
5167 lbchginfoposs, ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, resolve, lpi) );
5168
5169 *valid = TRUE;
5170 }
5171
5172 return SCIP_OKAY;
5173}
5174
5175/** try to find a subset of changed bounds leading to an infeasible LP
5176 *
5177 * 1. call undoBdchgsDualfarkas() or undoBdchgsDualsol()
5178 * -> update lb/ubchginfoposs arrays
5179 * -> store additional changes in bdchg and curvarlbs/ubs arrays
5180 * -> apply additional changes to the LPI
5181 * 2. (optional) if additional bound changes were undone:
5182 * -> resolve LP
5183 * -> goto 1.
5184 * 3. redo all bound changes in the LPI to restore the LPI to its original state
5185 * 4. analyze conflict
5186 * -> put remaining changed bounds (see lb/ubchginfoposs arrays) into starting conflict set
5187 */
5189 SCIP_CONFLICT* conflict, /**< conflict data */
5190 SCIP_SET* set, /**< global SCIP settings */
5191 SCIP_STAT* stat, /**< problem statistics */
5192 SCIP_PROB* origprob, /**< original problem */
5193 SCIP_PROB* transprob, /**< transformed problem */
5194 SCIP_TREE* tree, /**< branch and bound tree */
5195 SCIP_REOPT* reopt, /**< reoptimization data */
5196 SCIP_LP* lp, /**< LP data */
5197 SCIP_LPI* lpi, /**< LPI data */
5198 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
5199 BMS_BLKMEM* blkmem, /**< block memory */
5200 SCIP_Real* proofcoefs, /**< coefficients in the proof constraint */
5201 SCIP_Real* prooflhs, /**< lhs of the proof constraint */
5202 SCIP_Real* proofactivity, /**< maximal activity of the proof constraint */
5203 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
5204 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
5205 int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
5206 int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
5207 int* iterations, /**< pointer to store the total number of LP iterations used */
5208 SCIP_Bool marklpunsolved, /**< whether LP should be marked unsolved after analysis (needed for strong branching) */
5209 SCIP_Bool* dualproofsuccess, /**< pointer to store success result of dual proof analysis */
5210 SCIP_Bool* valid /**< pointer to store whether the result is still a valid proof */
5211 )
5212{
5213 SCIP_LPBDCHGS* oldlpbdchgs;
5214 SCIP_LPBDCHGS* relaxedlpbdchgs;
5215 SCIP_Bool solvelp;
5216 SCIP_Bool resolve;
5217 int ncols;
5218
5219 assert(set != NULL);
5220
5221 /* get number of columns in the LP */
5222 ncols = SCIPlpGetNCols(lp);
5223
5224 /* get temporary memory for remembering bound changes on LPI columns */
5225 SCIP_CALL( lpbdchgsCreate(&oldlpbdchgs, set, ncols) );
5226 SCIP_CALL( lpbdchgsCreate(&relaxedlpbdchgs, set, ncols) );
5227
5228 /* undo as many bound changes as possible with the current LP solution */
5229 resolve = FALSE;
5230 if( (*valid) )
5231 {
5232 int currentdepth;
5233 currentdepth = SCIPtreeGetCurrentDepth(tree);
5234
5235 if( SCIPlpiIsPrimalInfeasible(lpi) )
5236 {
5237 SCIP_CALL( undoBdchgsDualfarkas(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, \
5238 ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, *prooflhs, proofactivity) );
5239 }
5240 else
5241 {
5242 assert(SCIPlpiIsDualFeasible(lpi) || SCIPlpiIsObjlimExc(lpi));
5243 SCIP_CALL( undoBdchgsDualsol(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs, \
5244 oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, *prooflhs, proofactivity) );
5245 }
5246 }
5247
5248 /* check if we want to solve the LP */
5249 assert(SCIPprobAllColsInLP(transprob, set, lp));
5250 solvelp = (set->conf_maxlploops != 0 && set->conf_lpiterations != 0);
5251
5252 if( (*valid) && resolve && solvelp )
5253 {
5254 SCIP_RETCODE retcode;
5255 SCIP_ROW** rows;
5256 int* sidechginds;
5257 SCIP_Real* sidechgoldlhss;
5258 SCIP_Real* sidechgoldrhss;
5259 SCIP_Real* sidechgnewlhss;
5260 SCIP_Real* sidechgnewrhss;
5261 SCIP_Real lpiinfinity;
5262 SCIP_Bool globalinfeasible;
5263 int maxlploops;
5264 int lpiterations;
5265 int sidechgssize;
5266 int nsidechgs;
5267 int nrows;
5268 int nloops;
5269 int r;
5270
5271 /* get infinity value of LP solver */
5272 lpiinfinity = SCIPlpiInfinity(lpi);
5273
5274 /* temporarily disable objective limit and install an iteration limit */
5275 maxlploops = (set->conf_maxlploops >= 0 ? set->conf_maxlploops : INT_MAX);
5276 lpiterations = (set->conf_lpiterations >= 0 ? set->conf_lpiterations : INT_MAX);
5277 SCIP_CALL( SCIPlpiSetRealpar(lpi, SCIP_LPPAR_OBJLIM, lpiinfinity) );
5278 SCIP_CALL( SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, lpiterations) );
5279
5280 /* get LP rows */
5281 rows = SCIPlpGetRows(lp);
5282 nrows = SCIPlpGetNRows(lp);
5283 assert(nrows == 0 || rows != NULL);
5284
5285 /* get temporary memory for remembering side changes on LPI rows */
5286 SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechginds, nrows) );
5287 SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgoldlhss, nrows) );
5288 SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgoldrhss, nrows) );
5289 SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgnewlhss, nrows) );
5290 SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgnewrhss, nrows) );
5291 sidechgssize = nrows;
5292 nsidechgs = 0;
5293
5294 /* remove all local rows by setting their sides to infinity;
5295 * finite sides are only changed to near infinity, such that the row's sense in the LP solver
5296 * is not affected (e.g. CPLEX cannot handle free rows)
5297 */
5298 for( r = 0; r < nrows; ++r )
5299 {
5300 assert(SCIProwGetLPPos(rows[r]) == r);
5301
5302 if( SCIProwIsLocal(rows[r]) )
5303 {
5304 SCIPsetDebugMsg(set, " -> removing local row <%s> [%g,%g]\n",
5305 SCIProwGetName(rows[r]), SCIProwGetLhs(rows[r]), SCIProwGetRhs(rows[r]));
5306 SCIP_CALL( addSideRemoval(set, rows[r], lpiinfinity, &sidechginds, &sidechgoldlhss, &sidechgoldrhss,
5307 &sidechgnewlhss, &sidechgnewrhss, &sidechgssize, &nsidechgs) );
5308 }
5309 }
5310
5311 /* apply changes of local rows to the LP solver */
5312 if( nsidechgs > 0 )
5313 {
5314 SCIP_CALL( SCIPlpiChgSides(lpi, nsidechgs, sidechginds, sidechgnewlhss, sidechgnewrhss) );
5315 }
5316
5317 /* undo as many additional bound changes as possible by resolving the LP */
5318 assert((*valid));
5319 assert(resolve);
5320 nloops = 0;
5321 globalinfeasible = FALSE;
5322 while( (*valid) && resolve && nloops < maxlploops )
5323 {
5324 int iter;
5325
5326 assert(!globalinfeasible);
5327
5328 nloops++;
5329 resolve = FALSE;
5330
5331 SCIPsetDebugMsg(set, "infeasible LP conflict analysis loop %d (changed col bounds: %d)\n", nloops, relaxedlpbdchgs->nbdchgs);
5332
5333 /* apply bound changes to the LP solver */
5334 assert(relaxedlpbdchgs->nbdchgs >= 0);
5335 if( relaxedlpbdchgs->nbdchgs > 0 )
5336 {
5337 SCIPsetDebugMsg(set, " -> applying %d bound changes to the LP solver\n", relaxedlpbdchgs->nbdchgs);
5338 SCIP_CALL( SCIPlpiChgBounds(lpi, relaxedlpbdchgs->nbdchgs, relaxedlpbdchgs->bdchginds, \
5339 relaxedlpbdchgs->bdchglbs, relaxedlpbdchgs->bdchgubs) );
5340
5341 /* reset conflict LP bound change data structure */
5342 lpbdchgsReset(relaxedlpbdchgs, ncols);
5343 }
5344
5345 /* start LP timer */
5347
5348 /* resolve LP */
5349 retcode = SCIPlpiSolveDual(lpi);
5350
5351 /* stop LP timer */
5353
5354 /* check return code of LP solving call */
5355 if( retcode == SCIP_LPERROR )
5356 {
5357 (*valid) = FALSE;
5358 break;
5359 }
5360 SCIP_CALL( retcode );
5361
5362 /* count number of LP iterations */
5363 SCIP_CALL( SCIPlpiGetIterations(lpi, &iter) );
5364 (*iterations) += iter;
5365 stat->nconflictlps++;
5366 stat->nconflictlpiterations += iter;
5367 SCIPsetDebugMsg(set, " -> resolved LP in %d iterations (total: %" SCIP_LONGINT_FORMAT ") (infeasible:%u)\n",
5369
5370 /* evaluate result */
5371 if( SCIPlpiIsDualFeasible(lpi) || SCIPlpiIsObjlimExc(lpi) )
5372 {
5373 SCIP_Real objval;
5374
5375 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
5376 (*valid) = (objval >= lp->lpiobjlim && !SCIPlpDivingObjChanged(lp));
5377 }
5378 else
5379 (*valid) = SCIPlpiIsPrimalInfeasible(lpi);
5380
5381 if( (*valid) )
5382 {
5383 int currentdepth;
5384 currentdepth = SCIPtreeGetCurrentDepth(tree);
5385
5386 /* undo additional bound changes */
5387 if( SCIPlpiIsPrimalInfeasible(lpi) )
5388 {
5389 SCIP_AGGRROW* farkasrow;
5390 int* inds;
5391 int validdepth;
5392 int nnz;
5393 int v;
5394
5395#ifndef NDEBUG
5396 SCIP_VAR** vars = SCIPprobGetVars(transprob);
5397#endif
5398
5399 SCIP_CALL( SCIPaggrRowCreate(set->scip, &farkasrow) );
5400
5401 /* the original LP exceeds the current cutoff bound, thus, we have not constructed the Farkas proof */
5402 SCIP_CALL( SCIPgetFarkasProof(set, transprob, lp, lpi, tree, farkasrow, proofactivity, &validdepth,
5403 curvarlbs, curvarubs, valid) );
5404
5405 /* the constructed Farkas proof is not valid, we need to break here */
5406 if( !(*valid) )
5407 {
5408 SCIPaggrRowFree(set->scip, &farkasrow);
5409 break;
5410 }
5411
5412 /* start dual proof analysis */
5413 if( set->conf_useinflp == 'd' || set->conf_useinflp == 'b' )
5414 {
5415 /* change the conflict type */
5416 SCIP_Bool oldusescutoff = conflict->conflictset->usescutoffbound;
5417 SCIP_CONFTYPE oldconftype = conflict->conflictset->conflicttype;
5418 conflict->conflictset->usescutoffbound = FALSE;
5420
5421 /* start dual proof analysis */
5422 SCIP_CALL( SCIPconflictAnalyzeDualProof(conflict, set, stat, eventfilter, blkmem, origprob, transprob, tree, reopt,
5423 lp, farkasrow, validdepth, curvarlbs, curvarubs, FALSE, &globalinfeasible, dualproofsuccess) );
5424
5425 conflict->conflictset->usescutoffbound = oldusescutoff;
5426 conflict->conflictset->conflicttype = oldconftype;
5427 }
5428
5429 /* todo: in theory, we could apply conflict graph analysis for locally valid proofs, too, but this needs to be implemented */
5430 if( globalinfeasible || validdepth > SCIPtreeGetEffectiveRootDepth(tree) )
5431 {
5432 SCIPaggrRowFree(set->scip, &farkasrow);
5433 goto TERMINATE;
5434 }
5435
5436 BMSclearMemoryArray(proofcoefs, SCIPprobGetNVars(transprob));
5437 (*prooflhs) = -SCIPaggrRowGetRhs(farkasrow);
5438 (*proofactivity) = -(*proofactivity);
5439
5440 inds = SCIPaggrRowGetInds(farkasrow);
5441 nnz = SCIPaggrRowGetNNz(farkasrow);
5442
5443 for( v = 0; v < nnz; v++ )
5444 {
5445 int i = inds[v];
5446
5447 assert(SCIPvarGetProbindex(vars[i]) == inds[v]);
5448
5449 proofcoefs[i] = -SCIPaggrRowGetProbvarValue(farkasrow, i);
5450 }
5451
5452 /* free aggregation rows */
5453 SCIPaggrRowFree(set->scip, &farkasrow);
5454
5455 SCIP_CALL( undoBdchgsDualfarkas(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, \
5456 ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, (*prooflhs), proofactivity) );
5457 }
5458 else
5459 {
5460 SCIP_AGGRROW* proofrow;
5461 int* inds;
5462 int validdepth;
5463 int nnz;
5464 int v;
5465
5466#ifndef NDEBUG
5467 SCIP_VAR** vars = SCIPprobGetVars(transprob);
5468#endif
5469
5470 assert(SCIPlpiIsDualFeasible(lpi) || SCIPlpiIsObjlimExc(lpi));
5471
5472 SCIP_CALL( SCIPaggrRowCreate(set->scip, &proofrow) );
5473
5474 SCIP_CALL( SCIPgetDualProof(set, transprob, lp, lpi, tree, proofrow, proofactivity, &validdepth,
5475 curvarlbs, curvarubs, valid) );
5476
5477 /* the constructed dual proof is not valid, we need to break here */
5478 if( !(*valid) || validdepth > SCIPtreeGetEffectiveRootDepth(tree) )
5479 {
5480 SCIPaggrRowFree(set->scip, &proofrow);
5481 break;
5482 }
5483 /* in contrast to the infeasible case we don't want to analyze the (probably identical) proof again. */
5484
5485 BMSclearMemoryArray(proofcoefs, SCIPprobGetNVars(transprob));
5486 (*prooflhs) = -SCIPaggrRowGetRhs(proofrow);
5487 (*proofactivity) = -(*proofactivity);
5488
5489 inds = SCIPaggrRowGetInds(proofrow);
5490 nnz = SCIPaggrRowGetNNz(proofrow);
5491
5492 for( v = 0; v < nnz; v++ )
5493 {
5494 int i = inds[v];
5495
5496 assert(SCIPvarGetProbindex(vars[i]) == inds[v]);
5497
5498 proofcoefs[i] = -SCIPaggrRowGetProbvarValue(proofrow, i);
5499 }
5500
5501 /* free aggregation rows */
5502 SCIPaggrRowFree(set->scip, &proofrow);
5503
5504 SCIP_CALL( undoBdchgsDualsol(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, \
5505 ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, *prooflhs, proofactivity) );
5506 }
5507 }
5508 assert(!resolve || (*valid));
5509 assert(!resolve || relaxedlpbdchgs->nbdchgs > 0);
5510 SCIPsetDebugMsg(set, " -> finished infeasible LP conflict analysis loop %d (iter: %d, nbdchgs: %d)\n",
5511 nloops, iter, relaxedlpbdchgs->nbdchgs);
5512 }
5513
5514 SCIPsetDebugMsg(set, "finished undoing bound changes after %d loops (valid=%u, nbdchgs: %d)\n",
5515 nloops, (*valid), oldlpbdchgs->nbdchgs);
5516
5517 TERMINATE:
5518 /* reset variables to local bounds */
5519 if( oldlpbdchgs->nbdchgs > 0 )
5520 {
5521 SCIP_CALL( SCIPlpiChgBounds(lpi, oldlpbdchgs->nbdchgs, oldlpbdchgs->bdchginds, oldlpbdchgs->bdchglbs, oldlpbdchgs->bdchgubs) );
5522 }
5523
5524 /* reset changes of local rows */
5525 if( nsidechgs > 0 )
5526 {
5527 SCIP_CALL( SCIPlpiChgSides(lpi, nsidechgs, sidechginds, sidechgoldlhss, sidechgoldrhss) );
5528 }
5529
5530 /* mark the LP unsolved */
5531 if( oldlpbdchgs->nbdchgs > 0 || nsidechgs > 0 )
5532 {
5533 /* The LPI data are out of sync with LP data. Thus, the LP should be marked
5534 * unsolved. However, for strong branching calls, the LP has to have status 'solved'; in
5535 * this case, marklpunsolved is FALSE and synchronization is performed later. */
5536 if( marklpunsolved )
5537 {
5538 lp->solved = FALSE;
5539 lp->primalfeasible = FALSE;
5540 lp->primalchecked = FALSE;
5541 lp->dualfeasible = FALSE;
5542 lp->dualchecked = FALSE;
5543 lp->lpobjval = SCIP_INVALID;
5545 }
5546 }
5547
5548 /* reinstall old objective and iteration limits in LP solver */
5551
5552 /* free temporary memory */
5553 SCIPsetFreeBufferArray(set, &sidechgnewrhss);
5554 SCIPsetFreeBufferArray(set, &sidechgnewlhss);
5555 SCIPsetFreeBufferArray(set, &sidechgoldrhss);
5556 SCIPsetFreeBufferArray(set, &sidechgoldlhss);
5557 SCIPsetFreeBufferArray(set, &sidechginds);
5558 }
5559
5560 /* free temporary memory */
5561 lpbdchgsFree(&relaxedlpbdchgs, set);
5562 lpbdchgsFree(&oldlpbdchgs, set);
5563
5564 return SCIP_OKAY;
5565}
5566
5567/** analyzes conflicting bound changes that were added with calls to SCIPconflictAddBound(), and on success, calls the
5568 * conflict handlers to create a conflict constraint out of the resulting conflict set;
5569 * updates statistics for propagation conflict analysis
5570 */
5572 SCIP_CONFLICT* conflict, /**< conflict analysis data */
5573 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5574 SCIP_SET* set, /**< global SCIP settings */
5575 SCIP_STAT* stat, /**< problem statistics */
5576 SCIP_PROB* prob, /**< problem data */
5577 SCIP_TREE* tree, /**< branch and bound tree */
5578 int validdepth, /**< minimal depth level at which the initial conflict set is valid */
5579 SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
5580 )
5581{
5582 int nconss;
5583 int nliterals;
5584 int nreconvconss;
5585 int nreconvliterals;
5586
5587 assert(conflict != NULL);
5588 assert(conflict->conflictset != NULL);
5589 assert(set != NULL);
5590 assert(prob != NULL);
5591
5592 if( success != NULL )
5593 *success = FALSE;
5594
5595 /* check if the conflict analysis is applicable */
5597 return SCIP_OKAY;
5598
5599 /* check, if the conflict set will get too large with high probability */
5600 if( conflict->conflictset->nbdchginfos + SCIPpqueueNElems(conflict->bdchgqueue)
5601 + SCIPpqueueNElems(conflict->forcedbdchgqueue) >= 2*conflictCalcMaxsize(set, prob) )
5602 return SCIP_OKAY;
5603
5604 SCIPsetDebugMsg(set, "analyzing conflict after infeasible propagation in depth %d\n", SCIPtreeGetCurrentDepth(tree));
5605
5606 /* start timing */
5608
5609 conflict->npropcalls++;
5610
5611 /* setting this to true adds bound changes only to the conflict graph bdchg queue */
5612 conflict->bdchgonlyconfqueue = TRUE;
5613
5614 /* analyze the conflict set, and create a conflict constraint on success */
5615 SCIP_CALL( conflictAnalyze(conflict, blkmem, set, stat, prob, tree, FALSE, validdepth, TRUE, &nconss, &nliterals, \
5616 &nreconvconss, &nreconvliterals) );
5617 conflict->npropsuccess += (nconss > 0 ? 1 : 0);
5618 conflict->npropconfconss += nconss;
5619 conflict->npropconfliterals += nliterals;
5620 conflict->npropreconvconss += nreconvconss;
5621 conflict->npropreconvliterals += nreconvliterals;
5622 conflict->bdchgonlyconfqueue = FALSE;
5623
5624 if( success != NULL )
5625 *success = (nconss > 0);
5626
5627 /* stop timing */
5628 SCIPclockStop(conflict->propanalyzetime, set);
5629
5630 return SCIP_OKAY;
5631}
static long bound
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 SCIPclockEnableOrDisable(SCIP_CLOCK *clck, SCIP_Bool enable)
Definition: clock.c:260
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:290
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:438
void SCIPclockReset(SCIP_CLOCK *clck)
Definition: clock.c:209
void SCIPclockFree(SCIP_CLOCK **clck)
Definition: clock.c:185
SCIP_RETCODE SCIPclockCreate(SCIP_CLOCK **clck, SCIP_CLOCKTYPE clocktype)
Definition: clock.c:170
internal methods for clocks and timing issues
internal methods for conflict analysis
SCIP_RETCODE SCIPconflictAnalyzeDualProof(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_AGGRROW *proofrow, int validdepth, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_Bool initialproof, SCIP_Bool *globalinfeasible, SCIP_Bool *success)
internal methods for dual proof conflict analysis
SCIP_RETCODE SCIPgetFarkasProof(SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, SCIP_LPI *lpi, SCIP_TREE *tree, SCIP_AGGRROW *farkasrow, SCIP_Real *farkasact, int *validdepth, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_Bool *valid)
SCIP_RETCODE SCIPgetDualProof(SCIP_SET *set, SCIP_PROB *transprob, SCIP_LP *lp, SCIP_LPI *lpi, SCIP_TREE *tree, SCIP_AGGRROW *farkasrow, SCIP_Real *farkasact, int *validdepth, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_Bool *valid)
void SCIPconflictsetFree(SCIP_CONFLICTSET **conflictset, BMS_BLKMEM *blkmem)
static SCIP_Bool conflictsetIsRedundant(SCIP_CONFLICTSET *conflictset1, SCIP_CONFLICTSET *conflictset2)
SCIP_Bool SCIPconflictGraphApplicable(SCIP_SET *set)
static SCIP_RETCODE ensureSidechgsSize(SCIP_SET *set, int **sidechginds, SCIP_Real **sidechgoldlhss, SCIP_Real **sidechgoldrhss, SCIP_Real **sidechgnewlhss, SCIP_Real **sidechgnewrhss, int *sidechgssize, int num)
static void conflictClearResolution(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_PROB *prob)
static SCIP_RETCODE undoBdchgsDualsol(SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, int currentdepth, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, int *lbchginfoposs, int *ubchginfoposs, SCIP_LPBDCHGS *oldlpbdchgs, SCIP_LPBDCHGS *relaxedlpbdchgs, SCIP_Bool *valid, SCIP_Bool *resolve, SCIP_Real *dualcoefs, SCIP_Real duallhs, SCIP_Real *dualactivity)
static void conflictClear(SCIP_CONFLICT *conflict)
static SCIP_RETCODE detectImpliedBounds(SCIP_SET *set, SCIP_PROB *prob, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_PROB *origprob, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CONFLICTSET *conflictset, int *nbdchgs, int *nredvars, SCIP_Bool *redundant)
void SCIPconflicthdlrEnableOrDisableClocks(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_Bool enable)
SCIP_RETCODE conflictCreateTmpBdchginfo(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound, SCIP_BDCHGINFO **bdchginfo)
SCIP_RETCODE SCIPconflictAnalyzeRemainingBdchgs(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_Bool diving, int *lbchginfoposs, int *ubchginfoposs, int *nconss, int *nliterals, int *nreconvconss, int *nreconvliterals)
static SCIP_RETCODE conflictEnsureTmpbdchginfosMem(SCIP_CONFLICT *conflict, SCIP_SET *set, int num)
static SCIP_RETCODE conflictQueueBound(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd, SCIP_Bool *success)
static SCIP_Bool isBoundchgUseless(SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo)
SCIP_RETCODE SCIPrunBoundHeuristic(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_LPI *lpi, SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_Real *proofcoefs, SCIP_Real *prooflhs, SCIP_Real *proofactivity, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, int *lbchginfoposs, int *ubchginfoposs, int *iterations, SCIP_Bool marklpunsolved, SCIP_Bool *dualproofsuccess, SCIP_Bool *valid)
SCIP_RETCODE SCIPconflicthdlrCreate(SCIP_CONFLICTHDLR **conflicthdlr, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTCOPY((*conflictcopy)), SCIP_DECL_CONFLICTFREE((*conflictfree)), SCIP_DECL_CONFLICTINIT((*conflictinit)), SCIP_DECL_CONFLICTEXIT((*conflictexit)), SCIP_DECL_CONFLICTINITSOL((*conflictinitsol)), SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol)), SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
static void conflictsetCalcConflictDepth(SCIP_CONFLICTSET *conflictset)
SCIP_RETCODE SCIPconflicthdlrExit(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set)
static SCIP_Real calcBdchgScore(SCIP_Real prooflhs, SCIP_Real proofact, SCIP_Real proofactdelta, SCIP_Real proofcoef, int depth, int currentdepth, SCIP_VAR *var, SCIP_SET *set)
void SCIPconflicthdlrSetInit(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTINIT((*conflictinit)))
int conflictCalcMaxsize(SCIP_SET *set, SCIP_PROB *prob)
void SCIPconflicthdlrSetPriority(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set, int priority)
SCIP_RETCODE SCIPconflictAddBound(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPconflicthdlrFree(SCIP_CONFLICTHDLR **conflicthdlr, SCIP_SET *set)
SCIP_RETCODE SCIPconflictAnalyze(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, int validdepth, SCIP_Bool *success)
static SCIP_RETCODE undoBdchgsDualfarkas(SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, int currentdepth, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, int *lbchginfoposs, int *ubchginfoposs, SCIP_LPBDCHGS *oldlpbdchgs, SCIP_LPBDCHGS *relaxedlpbdchgs, SCIP_Bool *valid, SCIP_Bool *resolve, SCIP_Real *farkascoefs, SCIP_Real farkaslhs, SCIP_Real *farkasactivity)
static SCIP_RETCODE addCand(SCIP_SET *set, int currentdepth, SCIP_VAR *var, int lbchginfopos, int ubchginfopos, SCIP_Real proofcoef, SCIP_Real prooflhs, SCIP_Real proofact, SCIP_VAR ***cands, SCIP_Real **candscores, SCIP_Real **newbounds, SCIP_Real **proofactdeltas, int *candssize, int *ncands, int firstcand)
static SCIP_RETCODE addBdchg(SCIP_SET *set, SCIP_VAR *var, SCIP_Real newlb, SCIP_Real newub, SCIP_LPBDCHGS *oldlpbdchgs, SCIP_LPBDCHGS *relaxedlpbdchgs, SCIP_LPI *lpi)
static SCIP_RETCODE conflictCreateReconvergenceConss(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_Bool diving, int validdepth, SCIP_BDCHGINFO *firstuip, int *nreconvconss, int *nreconvliterals)
SCIP_RETCODE SCIPconflicthdlrExitsol(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set)
static SCIP_RETCODE conflictResolveBound(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd, int validdepth, SCIP_Bool *resolved)
static void conflictsetClear(SCIP_CONFLICTSET *conflictset)
SCIP_RETCODE SCIPconflictAddRelaxedBound(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedbd)
void SCIPconflicthdlrSetFree(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTFREE((*conflictfree)))
static SCIP_Real conflictsetCalcScore(SCIP_CONFLICTSET *conflictset, SCIP_SET *set)
void SCIPconflicthdlrSetExitsol(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol)))
static SCIP_RETCODE conflictAddConflictBound(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd)
static SCIP_RETCODE lpbdchgsCreate(SCIP_LPBDCHGS **lpbdchgs, SCIP_SET *set, int ncols)
static SCIP_RETCODE doConflicthdlrCreate(SCIP_CONFLICTHDLR **conflicthdlr, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTCOPY((*conflictcopy)), SCIP_DECL_CONFLICTFREE((*conflictfree)), SCIP_DECL_CONFLICTINIT((*conflictinit)), SCIP_DECL_CONFLICTEXIT((*conflictexit)), SCIP_DECL_CONFLICTINITSOL((*conflictinitsol)), SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol)), SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
static SCIP_RETCODE conflictsetCopy(SCIP_CONFLICTSET **targetconflictset, BMS_BLKMEM *blkmem, SCIP_CONFLICTSET *sourceconflictset, int nadditionalelems)
static SCIP_RETCODE conflictsetAddBound(SCIP_CONFLICTSET *conflictset, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd)
static SCIP_RETCODE conflictAddConflictCons(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_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_CONFLICTSET *conflictset, int insertdepth, SCIP_Bool *success)
static SCIP_Bool conflictMarkBoundCheckPresence(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd)
SCIP_RETCODE SCIPconflicthdlrCopyInclude(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set)
static SCIP_Bool betterBoundInResolutionQueue(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo)
void SCIPconflicthdlrSetExit(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTEXIT((*conflictexit)))
SCIP_RETCODE SCIPundoBdchgsProof(SCIP_SET *set, SCIP_PROB *prob, int currentdepth, SCIP_Real *proofcoefs, SCIP_Real prooflhs, SCIP_Real *proofact, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, int *lbchginfoposs, int *ubchginfoposs, SCIP_LPBDCHGS *oldlpbdchgs, SCIP_LPBDCHGS *relaxedlpbdchgs, SCIP_Bool *resolve, SCIP_LPI *lpi)
static SCIP_RETCODE conflictsetAddBounds(SCIP_CONFLICT *conflict, SCIP_CONFLICTSET *conflictset, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BDCHGINFO **bdchginfos, int nbdchginfos)
static SCIP_RETCODE addSideRemoval(SCIP_SET *set, SCIP_ROW *row, SCIP_Real lpiinfinity, int **sidechginds, SCIP_Real **sidechgoldlhss, SCIP_Real **sidechgoldrhss, SCIP_Real **sidechgnewlhss, SCIP_Real **sidechgnewrhss, int *sidechgssize, int *nsidechgs)
static SCIP_RETCODE convertToActiveVar(SCIP_VAR **var, SCIP_SET *set, SCIP_BOUNDTYPE *boundtype, SCIP_Real *bound)
static SCIP_RETCODE incVSIDS(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BOUNDTYPE boundtype, SCIP_Real value, SCIP_Real weight)
static SCIP_Bool bdchginfoIsResolvable(SCIP_BDCHGINFO *bdchginfo)
SCIP_RETCODE conflictAnalyze(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_Bool diving, int validdepth, SCIP_Bool mustresolve, int *nconss, int *nliterals, int *nreconvconss, int *nreconvliterals)
void SCIPconflicthdlrSetCopy(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTCOPY((*conflictcopy)))
static SCIP_Bool checkRedundancy(SCIP_SET *set, SCIP_CONFLICTSET *conflictset)
static void lpbdchgsReset(SCIP_LPBDCHGS *lpbdchgs, int ncols)
SCIP_RETCODE SCIPconflictIsVarUsed(SCIP_CONFLICT *conflict, SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool *used)
static SCIP_RETCODE conflictAddBound(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd)
SCIP_RETCODE SCIPconflictsetCreate(SCIP_CONFLICTSET **conflictset, BMS_BLKMEM *blkmem)
static SCIP_RETCODE conflictsetCalcInsertDepth(SCIP_CONFLICTSET *conflictset, SCIP_SET *set, SCIP_TREE *tree)
static SCIP_BDCHGINFO * conflictRemoveCand(SCIP_CONFLICT *conflict)
static SCIP_DECL_PARAMCHGD(paramChgdConflicthdlrPriority)
static SCIP_RETCODE conflictsetEnsureBdchginfosMem(SCIP_CONFLICTSET *conflictset, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
static SCIP_BDCHGINFO * conflictFirstCand(SCIP_CONFLICT *conflict)
SCIP_RETCODE SCIPconflictInit(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_CONFTYPE conftype, SCIP_Bool usescutoffbound)
static SCIP_RETCODE ensureCandsSize(SCIP_SET *set, SCIP_VAR ***cands, SCIP_Real **candscores, SCIP_Real **newbounds, SCIP_Real **proofactdeltas, int *candssize, int num)
SCIP_RETCODE SCIPconflicthdlrExec(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set, SCIP_NODE *node, SCIP_NODE *validnode, SCIP_BDCHGINFO **bdchginfos, SCIP_Real *relaxedbds, int nbdchginfos, SCIP_CONFTYPE conftype, SCIP_Bool usescutoffbound, SCIP_Bool resolved, SCIP_RESULT *result)
SCIP_RETCODE SCIPconflicthdlrInitsol(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set)
static void skipRedundantBdchginfos(SCIP_VAR *var, int *lbchginfopos, int *ubchginfopos)
static SCIP_RETCODE conflictInsertConflictset(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CONFLICTSET **conflictset)
static SCIP_RETCODE conflictEnsureConflictsetsMem(SCIP_CONFLICT *conflict, SCIP_SET *set, int num)
static void lpbdchgsFree(SCIP_LPBDCHGS **lpbdchgs, SCIP_SET *set)
SCIP_RETCODE SCIPconflicthdlrInit(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set)
static SCIP_RETCODE conflictAddConflictset(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, int validdepth, SCIP_Bool diving, SCIP_Bool repropagate, SCIP_Bool *success, int *nliterals)
static void conflictFreeTmpBdchginfos(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem)
void SCIPconflicthdlrSetInitsol(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTINITSOL((*conflictinitsol)))
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_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable)
static SCIP_RETCODE updateStatistics(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_CONFLICTSET *conflictset, int insertdepth)
SCIP_Bool bdchginfoIsInvalid(SCIP_CONFLICT *conflict, SCIP_BDCHGINFO *bdchginfo)
methods and datastructures for conflict analysis
void conflictsetPrint(SCIP_CONFLICTSET *conflictset)
SCIP_RETCODE SCIPconsResolvePropagation(SCIP_CONS *cons, SCIP_SET *set, SCIP_VAR *infervar, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT *result)
Definition: cons.c:7493
internal methods for constraints and constraint handlers
Constraint handler for linear constraints in their most general form, .
methods for the aggregation rows
#define SCIPquadprecProdQD(r, a, b)
Definition: dbldblarith.h:63
#define QUAD(x)
Definition: dbldblarith.h:47
#define SCIPquadprecSumDD(r, a, b)
Definition: dbldblarith.h:60
#define QUAD_TO_DBL(x)
Definition: dbldblarith.h:49
#define SCIPdebugCheckConflict(blkmem, set, node, bdchginfos, relaxedbds, nliterals)
Definition: debug.h:308
#define SCIPdebugCheckConflictFrontier(blkmem, set, node, bdchginfo, bdchginfos, relaxedbds, nliterals, bdchgqueue, forcedbdchgqueue)
Definition: debug.h:309
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_REAL_MAX
Definition: def.h:158
#define SCIP_INVALID
Definition: def.h:178
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_ALLOC(x)
Definition: def.h:366
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define SCIPABORT()
Definition: def.h:327
#define SCIP_REAL_MIN
Definition: def.h:159
#define SCIP_CALL(x)
Definition: def.h:355
#define SCIP_CALL_FINALLY(x, y)
Definition: def.h:397
void SCIPdotWriteOpening(FILE *file)
Definition: misc.c:715
void SCIPdotWriteClosing(FILE *file)
Definition: misc.c:753
void SCIPdotWriteArc(FILE *file, int source, int target, const char *color)
Definition: misc.c:740
void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition: misc.c:501
void SCIPgmlWriteClosing(FILE *file)
Definition: misc.c:703
void SCIPdotWriteNode(FILE *file, int node, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition: misc.c:725
void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
Definition: misc.c:687
void SCIPgmlWriteEdge(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:599
void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:643
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition: lpi_clp.cpp:1179
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:3947
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2718
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
Definition: lpi_clp.cpp:3959
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_clp.cpp:3861
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_clp.cpp:2794
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_clp.cpp:1096
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2637
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_clp.cpp:3720
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2530
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:1908
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_clp.cpp:2949
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
void ** SCIPpqueueElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1540
void SCIPpqueueClear(SCIP_PQUEUE *pqueue)
Definition: misc.c:1335
SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1396
int SCIPpqueueNElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1529
void * SCIPpqueueRemove(SCIP_PQUEUE *pqueue)
Definition: misc.c:1495
void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
Definition: misc.c:1515
int SCIPcolGetLPPos(SCIP_COL *col)
Definition: lp.c:17487
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:17520
SCIP_BOUNDTYPE SCIPboundtypeOpposite(SCIP_BOUNDTYPE boundtype)
Definition: lp.c:17597
SCIP_CONFLICTHDLRDATA * SCIPconflicthdlrGetData(SCIP_CONFLICTHDLR *conflicthdlr)
SCIP_DECL_SORTPTRCOMP(SCIPconflicthdlrComp)
int SCIPconflicthdlrGetPriority(SCIP_CONFLICTHDLR *conflicthdlr)
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
void SCIPconflicthdlrSetData(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
SCIP_Bool SCIPconflicthdlrIsInitialized(SCIP_CONFLICTHDLR *conflicthdlr)
SCIP_Real SCIPconflicthdlrGetTime(SCIP_CONFLICTHDLR *conflicthdlr)
SCIP_Real SCIPconflicthdlrGetSetupTime(SCIP_CONFLICTHDLR *conflicthdlr)
const char * SCIPconflicthdlrGetDesc(SCIP_CONFLICTHDLR *conflicthdlr)
SCIP_RETCODE SCIPsetConflicthdlrPriority(SCIP *scip, SCIP_CONFLICTHDLR *conflicthdlr, int priority)
int SCIPconsGetValidDepth(SCIP_CONS *cons)
Definition: cons.c:8472
SCIP_Bool SCIPconsIsGlobal(SCIP_CONS *cons)
Definition: cons.c:8618
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8389
SCIP_RETCODE SCIPaggrRowCreate(SCIP *scip, SCIP_AGGRROW **aggrrow)
Definition: cuts.c:2668
SCIP_Real SCIPaggrRowGetRhs(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:4068
void SCIPaggrRowFree(SCIP *scip, SCIP_AGGRROW **aggrrow)
Definition: cuts.c:2700
int * SCIPaggrRowGetInds(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:4028
int SCIPaggrRowGetNNz(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:4038
static INLINE SCIP_Real SCIPaggrRowGetProbvarValue(SCIP_AGGRROW *aggrrow, int probindex)
Definition: cuts.h:297
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:8493
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:951
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17686
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17696
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:17895
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:17795
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17745
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17652
SCIP_RETCODE SCIPshrinkDisjunctiveVarSet(SCIP *scip, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_Bool *boundtypes, SCIP_Bool *redundants, int nvars, int *nredvars, int *nglobalred, SCIP_Bool *setredundant, SCIP_Bool *glbinfeas, SCIP_Bool fullshortening)
Definition: presolve.c:995
SCIP_Real SCIPgetVarBdAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:3008
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:24482
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:23683
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:25057
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:23642
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:24889
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24979
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4386
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:25013
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24959
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:25024
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:23652
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:25001
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24969
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2872
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:23662
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24929
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:24524
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24909
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:25036
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:22741
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:23806
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:25082
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:23794
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:24642
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24939
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24989
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:25068
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:23600
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:24704
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2736
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24949
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24919
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4328
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:24724
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:23818
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:23706
void SCIPsortedvecInsertIntPtrReal(int *intarray, void **ptrarray, SCIP_Real *realarray, int keyval, void *field1val, SCIP_Real field2val, int *len, int *pos)
void SCIPsortIntPtrReal(int *intarray, void **ptrarray, SCIP_Real *realarray, int len)
void SCIPsortLongPtrRealRealBool(SCIP_Longint *longarray, void **ptrarray, SCIP_Real *realarray, SCIP_Real *realarray2, SCIP_Bool *boolarray, int len)
void SCIPsortedvecDelPosIntPtrReal(int *intarray, void **ptrarray, SCIP_Real *realarray, int pos, int *len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:674
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:649
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:635
internal methods for branching and inference history
SCIP_Bool SCIPlpDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:18261
SCIP_LPI * SCIPlpGetLPI(SCIP_LP *lp)
Definition: lp.c:18178
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:17979
SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
Definition: lp.c:18016
static const SCIP_Real scalars[]
Definition: lp.c:5959
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:18026
internal methods for LP management
interface methods for specific LP solvers
static const char * paramname[]
Definition: lpi_msk.c:5172
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:127
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:468
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:143
#define BMSclearMemory(ptr)
Definition: memory.h:129
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:148
#define BMSallocMemory(ptr)
Definition: memory.h:118
SCIP_PARAMDATA * SCIPparamGetData(SCIP_PARAM *param)
Definition: paramset.c:678
int SCIPparamGetInt(SCIP_PARAM *param)
Definition: paramset.c:733
methods commonly used for presolving
const char * SCIPprobGetName(SCIP_PROB *prob)
Definition: prob.c:2859
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2868
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2913
SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
Definition: prob.c:2825
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2803
internal methods for storing and manipulating the main problem
SCIP_RETCODE SCIPpropResolvePropagation(SCIP_PROP *prop, SCIP_SET *set, SCIP_VAR *infervar, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT *result)
Definition: prop.c:739
internal methods for propagators
public methods for conflict analysis handlers
public methods for managing constraints
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugMessage
Definition: pub_message.h:96
#define SCIPdebugPrintf
Definition: pub_message.h:99
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for handling parameter settings
public methods for propagators
public methods for branch and bound tree
public methods for problem variables
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for memory management
public methods for message handling
public methods for solutions
public methods for SCIP variables
SCIP_RETCODE SCIPsetAddIntParam(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: set.c:3229
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6617
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:7017
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6993
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6945
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6648
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6577
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6537
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6969
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6557
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6515
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6597
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6670
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6637
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:7041
void SCIPsetSortConflicthdlrs(SCIP_SET *set)
Definition: set.c:4308
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:6080
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6659
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1782
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1789
#define SCIPsetDebugMsgPrint
Definition: set.h:1812
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1775
#define SCIPsetFreeBuffer(set, ptr)
Definition: set.h:1780
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1786
#define SCIPsetDebugMsg
Definition: set.h:1811
#define SCIPsetAllocBuffer(set, ptr)
Definition: set.h:1773
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1779
internal methods for storing primal CIP solutions
SCIP_BDCHGIDX bdchgidx
Definition: struct_var.h:127
SCIP_Real newbound
Definition: struct_var.h:123
unsigned int boundtype
Definition: struct_var.h:130
SCIP_VAR * var
Definition: struct_var.h:125
unsigned int redundant
Definition: struct_var.h:132
SCIP_Real oldbound
Definition: struct_var.h:122
unsigned int pos
Definition: struct_var.h:128
SCIP_CONFTYPE conflicttype
unsigned int hasrelaxonlyvar
SCIP_BDCHGINFO ** bdchginfos
unsigned int repropagate
SCIP_Real * relaxedbds
SCIP_CONFTYPE conflicttype
unsigned int usescutoffbound
SCIP_Real * conflictvarsubs
SCIP_Real * conflictsetscores
SCIP_Longint nappliedglbconss
SCIP_Longint npropconfconss
SCIP_CLOCK * dIBclock
SCIP_PQUEUE * resbdchgqueue
SCIP_CLOCK * propanalyzetime
SCIP_PQUEUE * forcedbdchgqueue
SCIP_Longint nappliedglbliterals
SCIP_CONFLICTSET ** conflictsets
SCIP_Bool bdchgonlyconfqueue
SCIP_PQUEUE * bdchgqueue
SCIP_Longint npropsuccess
SCIP_Longint nappliedlocconss
SCIP_Longint npropcalls
SCIP_CONFLICTROW * conflictrow
SCIP_Longint npropreconvliterals
SCIP_Bool bdchgonlyresqueue
SCIP_BDCHGINFO ** tmpbdchginfos
SCIP_Longint npropconfliterals
SCIP_CONFLICTSET * conflictset
SCIP_Real * conflictvarslbs
SCIP_Longint nappliedlocliterals
SCIP_Longint npropreconvconss
SCIP_CONFLICTHDLRDATA * conflicthdlrdata
SCIP_CLOCK * setuptime
SCIP_CLOCK * conflicttime
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:140
unsigned int nboundchgs
Definition: struct_var.h:138
SCIP_Real * bdchgubs
SCIP_Bool * usedcols
SCIP_Real * bdchglbs
int lpiitlim
Definition: struct_lp.h:351
SCIP_Bool strongbranching
Definition: struct_lp.h:383
SCIP_Bool primalfeasible
Definition: struct_lp.h:374
SCIP_Real cutoffbound
Definition: struct_lp.h:289
SCIP_Bool dualfeasible
Definition: struct_lp.h:376
SCIP_Bool primalchecked
Definition: struct_lp.h:375
SCIP_LPSOLSTAT lpsolstat
Definition: struct_lp.h:359
SCIP_Real lpobjval
Definition: struct_lp.h:276
SCIP_Bool solved
Definition: struct_lp.h:373
SCIP_Bool dualchecked
Definition: struct_lp.h:377
SCIP_Bool diving
Definition: struct_lp.h:386
SCIP_Bool flushed
Definition: struct_lp.h:372
SCIP_Real lpiobjlim
Definition: struct_lp.h:291
SCIP_DOMCHG * domchg
Definition: struct_tree.h:160
unsigned int depth
Definition: struct_tree.h:161
int ncontvars
Definition: struct_prob.h:80
SCIP_VAR ** vars
Definition: struct_prob.h:67
SCIP_Longint nnodes
Definition: struct_stat.h:84
SCIP_Longint nconflictlps
Definition: struct_stat.h:228
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:195
SCIP_VISUAL * visual
Definition: struct_stat.h:198
SCIP_Real vsidsweight
Definition: struct_stat.h:134
SCIP_Longint lastconflictnode
Definition: struct_stat.h:114
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:196
SCIP_Longint nconflictlpiterations
Definition: struct_stat.h:81
SCIP_CLOCK * conflictlptime
Definition: struct_stat.h:179
SCIP_NODE * root
Definition: struct_tree.h:188
SCIP_NODE ** path
Definition: struct_tree.h:190
int nubchginfos
Definition: struct_var.h:325
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:304
int conflictubcount
Definition: struct_var.h:327
SCIP_Real conflictrelaxedub
Definition: struct_var.h:276
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:305
SCIP_Real conflictub
Definition: struct_var.h:274
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:275
int nlbchginfos
Definition: struct_var.h:323
SCIP_Real conflictlb
Definition: struct_var.h:273
int conflictlbcount
Definition: struct_var.h:326
datastructures for conflict analysis
data structures for LP management
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
int SCIPtreeGetFocusDepth(SCIP_TREE *tree)
Definition: tree.c:9404
SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, 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_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition: tree.c:2539
void SCIPnodePropagateAgain(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree)
Definition: tree.c:1368
SCIP_RETCODE SCIPnodeCutoff(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_REOPT *reopt, SCIP_LP *lp, BMS_BLKMEM *blkmem)
Definition: tree.c:1259
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:9529
int SCIPtreeGetEffectiveRootDepth(SCIP_TREE *tree)
Definition: tree.c:9518
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:9479
internal methods for branch and bound tree
@ SCIP_CLOCKTYPE_DEFAULT
Definition: type_clock.h:43
#define SCIP_DECL_CONFLICTEXIT(x)
#define SCIP_DECL_CONFLICTCOPY(x)
Definition: type_conflict.h:89
#define SCIP_DECL_CONFLICTEXEC(x)
#define SCIP_DECL_CONFLICTINITSOL(x)
#define SCIP_DECL_CONFLICTFREE(x)
Definition: type_conflict.h:97
@ SCIP_CONFTYPE_BNDEXCEEDING
Definition: type_conflict.h:64
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:62
@ SCIP_CONFTYPE_INFEASLP
Definition: type_conflict.h:63
@ SCIP_CONFTYPE_UNKNOWN
Definition: type_conflict.h:61
#define SCIP_DECL_CONFLICTINIT(x)
enum SCIP_ConflictType SCIP_CONFTYPE
Definition: type_conflict.h:68
struct SCIP_ConflicthdlrData SCIP_CONFLICTHDLRDATA
Definition: type_conflict.h:50
#define SCIP_DECL_CONFLICTEXITSOL(x)
@ SCIP_BRANCHDIR_DOWNWARDS
Definition: type_history.h:43
@ SCIP_BRANCHDIR_UPWARDS
Definition: type_history.h:44
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:48
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:60
@ SCIP_LPSOLSTAT_NOTSOLVED
Definition: type_lp.h:43
@ SCIP_LPPAR_LPITLIM
Definition: type_lpi.h:60
@ SCIP_LPPAR_OBJLIM
Definition: type_lpi.h:59
struct SCIP_ParamData SCIP_PARAMDATA
Definition: type_paramset.h:87
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_CONSADDED
Definition: type_result.h:52
@ SCIP_SUCCESS
Definition: type_result.h:58
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_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_WRITEERROR
Definition: type_retcode.h:46
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_INVALIDCALL
Definition: type_retcode.h:51
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_BOUNDCHGTYPE_PROPINFER
Definition: type_var.h:133
@ SCIP_BOUNDCHGTYPE_BRANCHING
Definition: type_var.h:131
@ SCIP_BOUNDCHGTYPE_CONSINFER
Definition: type_var.h:132
@ SCIP_VARSTATUS_FIXED
Definition: type_var.h:54
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:53
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition: type_var.h:57
@ SCIP_VARSTATUS_AGGREGATED
Definition: type_var.h:55
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:141
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:168
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:22615
SCIP_RETCODE SCIPvarIncVSIDS(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
Definition: var.c:21103
SCIP_RETCODE SCIPvarIncNActiveConflicts(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real length)
Definition: var.c:21239
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:9910
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:18568
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:21189
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:18638
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:24849
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:22585
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:18075
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:9961
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:25048
internal methods for problem variables
void SCIPvisualFoundConflict(SCIP_VISUAL *visual, SCIP_STAT *stat, SCIP_NODE *node)
Definition: visual.c:612
methods for creating output for visualization tools (VBC, BAK)