SCIP Doxygen Documentation
Loading...
Searching...
No Matches
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-2026 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
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);
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 {
668 {
670 bound += 1.0;
671 }
672
673 /* check if the bound is already fulfilled globally */
675 return TRUE;
676 }
677 else
678 {
680
682 {
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);
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 */
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))) ||
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
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 */
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 {
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 {
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",
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",
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 */
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)
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 */
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
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",
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),
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 {
2773 return TRUE;
2774 }
2775 }
2776 else
2777 {
2779
2780 if( var->conflictubcount != conflict->count || var->conflictub != SCIPbdchginfoGetNewbound(bdchginfo) ) /*lint !e777*/
2781 {
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 ++i;
2918 }
2919 else
2920 {
2921 /* both bound change are equivalent; hence, keep the worse relaxed bound and remove one of them */
2922 confrelaxedbds[k] = (confsortvals[k] % 2 == 0) ? MAX(confrelaxedbds[k], confrelaxedbds[i]) : MIN(confrelaxedbds[k], confrelaxedbds[i]);
2923 ++i;
2924 }
2925 }
2926 else
2927 {
2928 /* all bound change infos must be valid */
2929 assert(!bdchginfoIsInvalid(conflict, confbdchginfos[k]));
2930
2931 ++k;
2932 /* move next comparison element to the correct position */
2933 if( k != i )
2934 {
2935 confbdchginfos[k] = confbdchginfos[i];
2936 confrelaxedbds[k] = confrelaxedbds[i];
2937 confsortvals[k] = confsortvals[i];
2938 }
2939 ++i;
2940 }
2941 }
2942 /* last bound change infos must also be valid */
2943 assert(!bdchginfoIsInvalid(conflict, confbdchginfos[k]));
2944 /* the number of bound change infos cannot be decreased, it would mean that the conflict set was not merged
2945 * before
2946 */
2947 assert(conflictset->nbdchginfos <= k + 1 );
2948 assert(k + 1 <= confnbdchginfos);
2949
2950 conflictset->nbdchginfos = k + 1;
2951 }
2952
2953 return SCIP_OKAY;
2954}
2955
2956/** removes and returns next conflict analysis candidate from the candidate queue */
2957static
2959 SCIP_CONFLICT* conflict /**< conflict analysis data */
2960 )
2961{
2962 SCIP_BDCHGINFO* bdchginfo;
2963 SCIP_VAR* var;
2964
2965 assert(conflict != NULL);
2966
2967 if( SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0 )
2968 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->forcedbdchgqueue));
2969 else
2970 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->bdchgqueue));
2971
2972 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
2973
2974 /* if we have a candidate this one should be valid for the current conflict analysis */
2975 assert(!bdchginfoIsInvalid(conflict, bdchginfo));
2976
2977 /* mark the bound change to be no longer in the conflict (it will be either added again to the conflict set or
2978 * replaced by resolving, which might add a weaker change on the same bound to the queue)
2979 */
2980 var = SCIPbdchginfoGetVar(bdchginfo);
2982 {
2983 var->conflictlbcount = 0;
2984 var->conflictrelaxedlb = SCIP_REAL_MIN;
2985 }
2986 else
2987 {
2989 var->conflictubcount = 0;
2990 var->conflictrelaxedub = SCIP_REAL_MAX;
2991 }
2992
2993#if defined(SCIP_CONFGRAPH) || defined(SCIP_CONFGRAPH_DOT)
2994 confgraphSetCurrentBdchg(bdchginfo);
2995#endif
2996
2997 return bdchginfo;
2998}
2999
3000/** returns next conflict analysis candidate from the candidate queue without removing it */
3001static
3003 SCIP_CONFLICT* conflict /**< conflict analysis data */
3004 )
3005{
3006 SCIP_BDCHGINFO* bdchginfo;
3007
3008 assert(conflict != NULL);
3009
3010 if( SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0 )
3011 {
3012 /* get next potential candidate */
3013 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueFirst(conflict->forcedbdchgqueue));
3014
3015 /* check if this candidate is valid */
3016 if( bdchginfoIsInvalid(conflict, bdchginfo) )
3017 {
3018 SCIPdebugMessage("bound change info [%d:<%s> %s %g] is invalid -> pop it from the force queue\n", SCIPbdchginfoGetDepth(bdchginfo),
3020 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3021 SCIPbdchginfoGetNewbound(bdchginfo));
3022
3023 /* pop the invalid bound change info from the queue */
3024 (void)(SCIPpqueueRemove(conflict->forcedbdchgqueue));
3025
3026 /* call method recursively to get next conflict analysis candidate */
3027 bdchginfo = conflictFirstCand(conflict);
3028 }
3029 }
3030 else
3031 {
3032 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueFirst(conflict->bdchgqueue));
3033
3034 /* check if this candidate is valid */
3035 if( bdchginfo != NULL && bdchginfoIsInvalid(conflict, bdchginfo) )
3036 {
3037 SCIPdebugMessage("bound change info [%d:<%s> %s %g] is invalid -> pop it from the queue\n", SCIPbdchginfoGetDepth(bdchginfo),
3039 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3040 SCIPbdchginfoGetNewbound(bdchginfo));
3041
3042 /* pop the invalid bound change info from the queue */
3043 (void)(SCIPpqueueRemove(conflict->bdchgqueue));
3044
3045 /* call method recursively to get next conflict analysis candidate */
3046 bdchginfo = conflictFirstCand(conflict);
3047 }
3048 }
3049 assert(bdchginfo == NULL || !SCIPbdchginfoIsRedundant(bdchginfo));
3050
3051 return bdchginfo;
3052}
3053
3054/** adds the current conflict set (extended by all remaining bound changes in the queue) to the pool of conflict sets */
3055static
3057 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3058 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3059 SCIP_SET* set, /**< global SCIP settings */
3060 SCIP_STAT* stat, /**< dynamic problem statistics */
3061 SCIP_TREE* tree, /**< branch and bound tree */
3062 int validdepth, /**< minimal depth level at which the conflict set is valid */
3063 SCIP_Bool diving, /**< are we in strong branching or diving mode? */
3064 SCIP_Bool repropagate, /**< should the constraint trigger a repropagation? */
3065 SCIP_Bool* success, /**< pointer to store whether the conflict set is valid */
3066 int* nliterals /**< pointer to store the number of literals in the generated conflictset */
3067 )
3068{
3069 SCIP_CONFLICTSET* conflictset;
3070 SCIP_BDCHGINFO** bdchginfos;
3071 int nbdchginfos;
3072 int currentdepth;
3073 int focusdepth;
3074
3075 assert(conflict != NULL);
3076 assert(conflict->conflictset != NULL);
3077 assert(set != NULL);
3078 assert(stat != NULL);
3079 assert(tree != NULL);
3080 assert(success != NULL);
3081 assert(nliterals != NULL);
3082 assert(SCIPpqueueNElems(conflict->forcedbdchgqueue) == 0);
3083
3084 *success = FALSE;
3085 *nliterals = 0;
3086
3087 /* check, whether local conflicts are allowed */
3088 validdepth = MAX(validdepth, conflict->conflictset->validdepth);
3089 if( !set->conf_allowlocal && validdepth > 0 )
3090 return SCIP_OKAY;
3091
3092 focusdepth = SCIPtreeGetFocusDepth(tree);
3093 currentdepth = SCIPtreeGetCurrentDepth(tree);
3094 assert(currentdepth == tree->pathlen-1);
3095 assert(focusdepth <= currentdepth);
3096 assert(0 <= conflict->conflictset->validdepth && conflict->conflictset->validdepth <= currentdepth);
3097 assert(0 <= validdepth && validdepth <= currentdepth);
3098
3099 /* get the elements of the bound change queue */
3100 bdchginfos = (SCIP_BDCHGINFO**)SCIPpqueueElems(conflict->bdchgqueue);
3101 nbdchginfos = SCIPpqueueNElems(conflict->bdchgqueue);
3102
3103 /* create a copy of the current conflict set, allocating memory for the additional elements of the queue */
3104 SCIP_CALL( conflictsetCopy(&conflictset, blkmem, conflict->conflictset, nbdchginfos) );
3105 conflictset->validdepth = validdepth;
3106 conflictset->repropagate = repropagate;
3107
3108 /* add the valid queue elements to the conflict set */
3109 SCIPsetDebugMsg(set, "adding %d variables from the queue as temporary conflict variables\n", nbdchginfos);
3110 SCIP_CALL( conflictsetAddBounds(conflict, conflictset, blkmem, set, bdchginfos, nbdchginfos) );
3111
3112 /* calculate the depth, at which the conflictset should be inserted */
3113 SCIP_CALL( conflictsetCalcInsertDepth(conflictset, set, tree) );
3114 assert(conflictset->validdepth <= conflictset->insertdepth && conflictset->insertdepth <= currentdepth);
3115 SCIPsetDebugMsg(set, " -> conflict with %d literals found at depth %d is active in depth %d and valid in depth %d\n",
3116 conflictset->nbdchginfos, currentdepth, conflictset->insertdepth, conflictset->validdepth);
3117
3118 /* if all branching variables are in the conflict set, the conflict set is of no use;
3119 * don't use conflict sets that are only valid in the probing path but not in the problem tree
3120 */
3121 if( (diving || conflictset->insertdepth < currentdepth) && conflictset->insertdepth <= focusdepth )
3122 {
3123 /* if the conflict should not be located only in the subtree where it is useful, put it to its valid depth level */
3124 if( !set->conf_settlelocal )
3125 conflictset->insertdepth = conflictset->validdepth;
3126
3127 *nliterals = conflictset->nbdchginfos;
3128 SCIPsetDebugMsg(set, " -> final conflict set has %d literals\n", *nliterals);
3129
3130 /* check conflict set on debugging solution */
3131 SCIP_CALL( SCIPdebugCheckConflict(blkmem, set, tree->path[validdepth], \
3132 conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos) ); /*lint !e506 !e774*/
3133
3134 /* move conflictset to the conflictset storage */
3135 SCIP_CALL( conflictInsertConflictset(conflict, blkmem, set, &conflictset) );
3136 *success = TRUE;
3137 }
3138 else
3139 {
3140 /* free the temporary conflict set */
3141 SCIPconflictsetFree(&conflictset, blkmem);
3142 }
3143
3144 return SCIP_OKAY;
3145}
3146
3147/** tries to resolve given bound change
3148 * - resolutions on local constraints are only applied, if the constraint is valid at the
3149 * current minimal valid depth level, because this depth level is the topmost level to add the conflict
3150 * constraint to anyways
3151 *
3152 * @note it is sufficient to explain the relaxed bound change
3153 */
3154static
3156 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3157 SCIP_SET* set, /**< global SCIP settings */
3158 SCIP_BDCHGINFO* bdchginfo, /**< bound change to resolve */
3159 SCIP_Real relaxedbd, /**< the relaxed bound */
3160 int validdepth, /**< minimal depth level at which the conflict is valid */
3161 SCIP_Bool* resolved /**< pointer to store whether the bound change was resolved */
3162 )
3163{
3164 SCIP_VAR* actvar;
3165 SCIP_CONS* infercons;
3166 SCIP_PROP* inferprop;
3168
3169#ifndef NDEBUG
3170 int nforcedbdchgqueue;
3171 int nbdchgqueue;
3172
3173 /* store the current size of the conflict queues */
3174 assert(conflict != NULL);
3175 nforcedbdchgqueue = SCIPpqueueNElems(conflict->forcedbdchgqueue);
3176 nbdchgqueue = SCIPpqueueNElems(conflict->bdchgqueue);
3177#else
3178 assert(conflict != NULL);
3179#endif
3180
3181 assert(resolved != NULL);
3182 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3183
3184 *resolved = FALSE;
3185
3186 actvar = SCIPbdchginfoGetVar(bdchginfo);
3187 assert(actvar != NULL);
3188 assert(SCIPvarIsActive(actvar));
3189
3190#ifdef SCIP_DEBUG
3191 {
3192 int i;
3193 SCIPsetDebugMsg(set, "processing next conflicting bound (depth: %d, valid depth: %d, bdchgtype: %s [%s], vartype: %d): [<%s> %s %g(%g)]\n",
3194 SCIPbdchginfoGetDepth(bdchginfo), validdepth,
3196 : SCIPbdchginfoGetChgtype(bdchginfo) == SCIP_BOUNDCHGTYPE_CONSINFER ? "cons" : "prop",
3200 : SCIPbdchginfoGetInferProp(bdchginfo) == NULL ? "-"
3202 SCIPvarGetType(actvar), SCIPvarGetName(actvar),
3203 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3204 SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd);
3205 SCIPsetDebugMsg(set, " - conflict set :");
3206
3207 for( i = 0; i < conflict->conflictset->nbdchginfos; ++i )
3208 {
3209 SCIPsetDebugMsgPrint(set, " [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(conflict->conflictset->bdchginfos[i]),
3213 }
3215 SCIPsetDebugMsg(set, " - forced candidates :");
3216
3217 for( i = 0; i < SCIPpqueueNElems(conflict->forcedbdchgqueue); ++i )
3218 {
3221 bdchginfoIsInvalid(conflict, info) ? "<!>" : SCIPbdchginfoGetBoundtype(info) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3223 }
3225 SCIPsetDebugMsg(set, " - optional candidates:");
3226
3227 for( i = 0; i < SCIPpqueueNElems(conflict->bdchgqueue); ++i )
3228 {
3231 bdchginfoIsInvalid(conflict, info) ? "<!>" : SCIPbdchginfoGetBoundtype(info) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3233 }
3235 }
3236#endif
3237
3238 /* check, if the bound change can and should be resolved:
3239 * - resolutions on local constraints should only be applied, if the constraint is valid at the
3240 * current minimal valid depth level (which is initialized with the valid depth level of the initial
3241 * conflict set), because this depth level is the topmost level to add the conflict constraint to anyways
3242 */
3243 switch( SCIPbdchginfoGetChgtype(bdchginfo) )
3244 {
3246 infercons = SCIPbdchginfoGetInferCons(bdchginfo);
3247 assert(infercons != NULL);
3248
3249 if( SCIPconsIsGlobal(infercons) || SCIPconsGetValidDepth(infercons) <= validdepth )
3250 {
3251 SCIP_VAR* infervar;
3252 int inferinfo;
3253 SCIP_BOUNDTYPE inferboundtype;
3254 SCIP_BDCHGIDX* bdchgidx;
3255
3256 /* resolve bound change by asking the constraint that inferred the bound to put all bounds that were
3257 * the reasons for the conflicting bound change on the priority queue
3258 */
3259 infervar = SCIPbdchginfoGetInferVar(bdchginfo);
3260 inferinfo = SCIPbdchginfoGetInferInfo(bdchginfo);
3261 inferboundtype = SCIPbdchginfoGetInferBoundtype(bdchginfo);
3262 bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
3263 assert(infervar != NULL);
3264
3265 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",
3266 SCIPvarGetName(actvar),
3267 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3268 SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd,
3269 SCIPvarGetStatus(actvar), SCIPvarGetType(actvar),
3270 SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
3271 SCIPvarGetName(infervar),
3272 inferboundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3273 SCIPgetVarBdAtIndex(set->scip, infervar, inferboundtype, bdchgidx, TRUE),
3274 SCIPconsGetName(infercons),
3275 SCIPconsIsGlobal(infercons) ? "global" : "local",
3276 inferinfo);
3277
3278 /* in case the inference variables is not an active variables, we need to transform the relaxed bound */
3279 if( actvar != infervar )
3280 {
3281 SCIP_VAR* var;
3282 SCIP_Real scalar;
3283 SCIP_Real constant;
3284
3287 || (SCIPvarGetStatus(infervar) == SCIP_VARSTATUS_MULTAGGR && SCIPvarGetMultaggrNVars(infervar) == 1));
3288
3289 scalar = 1.0;
3290 constant = 0.0;
3291
3292 var = infervar;
3293
3294 /* transform given variable to active variable */
3295 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
3296 assert(var == actvar);
3297
3298 relaxedbd *= scalar;
3299 relaxedbd += constant;
3300 }
3301
3302 SCIP_CALL( SCIPconsResolvePropagation(infercons, set, infervar, inferinfo, inferboundtype, bdchgidx, relaxedbd, &result) );
3303 *resolved = (result == SCIP_SUCCESS);
3304 }
3305 break;
3306
3308 inferprop = SCIPbdchginfoGetInferProp(bdchginfo);
3309 if( inferprop != NULL )
3310 {
3311 SCIP_VAR* infervar;
3312 int inferinfo;
3313 SCIP_BOUNDTYPE inferboundtype;
3314 SCIP_BDCHGIDX* bdchgidx;
3315
3316 /* resolve bound change by asking the propagator that inferred the bound to put all bounds that were
3317 * the reasons for the conflicting bound change on the priority queue
3318 */
3319 infervar = SCIPbdchginfoGetInferVar(bdchginfo);
3320 inferinfo = SCIPbdchginfoGetInferInfo(bdchginfo);
3321 inferboundtype = SCIPbdchginfoGetInferBoundtype(bdchginfo);
3322 bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
3323 assert(infervar != NULL);
3324
3325 SCIPsetDebugMsg(set, "resolving bound <%s> %s %g(%g) [status:%d, depth:%d, pos:%d]: <%s> %s %g [prop:<%s>, info:%d]\n",
3326 SCIPvarGetName(actvar),
3327 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3328 SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd,
3329 SCIPvarGetStatus(actvar), SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
3330 SCIPvarGetName(infervar),
3331 inferboundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3332 SCIPgetVarBdAtIndex(set->scip, infervar, inferboundtype, bdchgidx, TRUE),
3333 SCIPpropGetName(inferprop), inferinfo);
3334
3335 SCIP_CALL( SCIPpropResolvePropagation(inferprop, set, infervar, inferinfo, inferboundtype, bdchgidx, relaxedbd, &result) );
3336 *resolved = (result == SCIP_SUCCESS);
3337 }
3338 break;
3339
3341 assert(!(*resolved));
3342 break;
3343
3344 default:
3345 SCIPerrorMessage("invalid bound change type <%d>\n", SCIPbdchginfoGetChgtype(bdchginfo));
3346 return SCIP_INVALIDDATA;
3347 }
3348
3349 SCIPsetDebugMsg(set, "resolving status: %u\n", *resolved);
3350
3351#ifndef NDEBUG
3352 /* subtract the size of the conflicq queues */
3353 nforcedbdchgqueue -= SCIPpqueueNElems(conflict->forcedbdchgqueue);
3354 nbdchgqueue -= SCIPpqueueNElems(conflict->bdchgqueue);
3355
3356 /* in case the bound change was not resolved, the conflict queues should have the same size (contents) */
3357 assert((*resolved) || (nforcedbdchgqueue == 0 && nbdchgqueue == 0));
3358#endif
3359
3360 return SCIP_OKAY;
3361}
3362
3363/** clears the conflict queue and the current conflict set */
3364static
3366 SCIP_CONFLICT* conflict /**< conflict analysis data */
3367 )
3368{
3369 assert(conflict != NULL);
3370
3371 SCIPpqueueClear(conflict->bdchgqueue);
3373 conflictsetClear(conflict->conflictset);
3374}
3375
3376
3377/** clears the resolution conflict analysis queues and the bounds leading to conflict */
3378static
3380 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3381 SCIP_SET* set, /**< global SCIP settings */
3382 SCIP_PROB* prob /**< problem data */
3383 )
3384{
3385 int nvars;
3386 int i;
3387
3388 assert(conflict != NULL);
3389 assert(set != NULL);
3390 assert(prob != NULL);
3391
3392 if( !set->conf_usegenres )
3393 return;
3394
3395 /* clear the resolution conflict analysis queues */
3396 SCIPpqueueClear(conflict->resbdchgqueue);
3397
3398 /* reset the current lower and upper bounds leading to conflict */
3399 nvars = SCIPprobGetNVars(prob);
3400
3401 /* allocate memory for the lower and upper bounds of variables used in the resolution conflict analysis */
3402 if(conflict->conflictprobnvars < nvars)
3403 {
3404 conflict->conflictprobnvars = nvars;
3407 }
3408
3409 for( i = 0; i < nvars; ++i )
3410 {
3411 conflict->conflictvarslbs[i] = SCIP_REAL_MIN;
3412 conflict->conflictvarsubs[i] = SCIP_REAL_MAX;
3413 }
3414}
3415
3416/** initializes propagation and resolution conflict analysis by clearing the conflict candidate queues */
3418 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3419 SCIP_SET* set, /**< global SCIP settings */
3420 SCIP_STAT* stat, /**< problem statistics */
3421 SCIP_PROB* prob, /**< problem data */
3422 SCIP_CONFTYPE conftype, /**< type of the conflict */
3423 SCIP_Bool usescutoffbound /**< depends the conflict on a cutoff bound? */
3424 )
3425{
3426 assert(conflict != NULL);
3427 assert(set != NULL);
3428 assert(stat != NULL);
3429 assert(prob != NULL);
3430
3431 SCIPsetDebugMsg(set, "initializing conflict analysis\n");
3432
3433 /* clear the conflict candidate queue and the conflict set */
3434 conflictClear(conflict);
3435
3436 /* clear the resolution conflict analysis queues and the bounds leading to conflict */
3437 conflictClearResolution(conflict, set, prob);
3438
3439 /* set conflict type */
3441 || conftype == SCIP_CONFTYPE_PROPAGATION);
3442 conflict->conflictset->conflicttype = conftype;
3443 conflict->conflictrow->conflicttype = conftype;
3444
3445 /* set whether a cutoff bound is involved */
3446 conflict->conflictset->usescutoffbound = usescutoffbound;
3447
3448 /* increase the conflict counter, such that binary variables of new conflict set and new conflict queue are labeled
3449 * with this new counter
3450 */
3451 conflict->count++;
3452 if( conflict->count == 0 ) /* make sure, 0 is not a valid conflict counter (may happen due to integer overflow) */
3453 conflict->count = 1;
3454
3455 /* increase the conflict score weight for history updates of future conflict reasons */
3456 if( stat->nnodes > stat->lastconflictnode )
3457 {
3458 assert(0.0 < set->conf_scorefac && set->conf_scorefac <= 1.0);
3459 stat->vsidsweight /= set->conf_scorefac;
3460 assert(stat->vsidsweight > 0.0);
3461
3462 /* if the conflict score for the next conflict exceeds 1000.0, rescale all history conflict scores */
3463 if( stat->vsidsweight >= 1000.0 )
3464 {
3465 int v;
3466
3467 for( v = 0; v < prob->nvars; ++v )
3468 {
3469 SCIP_CALL( SCIPvarScaleVSIDS(prob->vars[v], 1.0/stat->vsidsweight) );
3470 }
3473 stat->vsidsweight = 1.0;
3474 }
3475 stat->lastconflictnode = stat->nnodes;
3476 }
3477
3478#if defined(SCIP_CONFGRAPH) || defined(SCIP_CONFGRAPH_DOT)
3479 confgraphFree();
3480 SCIP_CALL( confgraphCreate(set, conflict) );
3481#endif
3482
3483 return SCIP_OKAY;
3484}
3485
3486/** convert variable and bound change to active variable */
3487static
3489 SCIP_VAR** var, /**< pointer to variable */
3490 SCIP_SET* set, /**< global SCIP settings */
3491 SCIP_BOUNDTYPE* boundtype, /**< pointer to type of bound that was changed: lower or upper bound */
3492 SCIP_Real* bound /**< pointer to bound to convert, or NULL */
3493 )
3494{
3495 SCIP_Real scalar;
3496 SCIP_Real constant;
3497
3498 scalar = 1.0;
3499 constant = 0.0;
3500
3501 /* transform given variable to active variable */
3502 SCIP_CALL( SCIPvarGetProbvarSum(var, set, &scalar, &constant) );
3503 assert(SCIPvarGetStatus(*var) == SCIP_VARSTATUS_FIXED || scalar != 0.0); /*lint !e777*/
3504
3506 return SCIP_OKAY;
3507
3508 /* if the scalar of the aggregation is negative, we have to switch the bound type */
3509 if( scalar < 0.0 )
3510 (*boundtype) = SCIPboundtypeOpposite(*boundtype);
3511
3512 if( bound != NULL )
3513 {
3514 (*bound) -= constant;
3515 (*bound) /= scalar;
3516 }
3517
3518 return SCIP_OKAY;
3519}
3520
3521/** returns whether bound change has a valid reason that can be resolved in conflict analysis */
3522static
3524 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
3525 )
3526{
3527 assert(bdchginfo != NULL);
3528 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3529
3532 && SCIPbdchginfoGetInferProp(bdchginfo) != NULL));
3533}
3534
3535
3536/** if only one conflicting bound change of the last depth level was used, and if this can be resolved,
3537 * creates GRASP-like reconvergence conflict constraints in the conflict graph up to the branching variable of this
3538 * depth level
3539 */
3540static
3542 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3543 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3544 SCIP_SET* set, /**< global SCIP settings */
3545 SCIP_STAT* stat, /**< problem statistics */
3546 SCIP_PROB* prob, /**< problem data */
3547 SCIP_TREE* tree, /**< branch and bound tree */
3548 SCIP_Bool diving, /**< are we in strong branching or diving mode? */
3549 int validdepth, /**< minimal depth level at which the initial conflict set is valid */
3550 SCIP_BDCHGINFO* firstuip, /**< first UIP of conflict graph */
3551 int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
3552 int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
3553 )
3554{
3555 SCIP_BDCHGINFO* uip;
3556 SCIP_CONFTYPE conftype;
3557 SCIP_Bool usescutoffbound;
3558 int firstuipdepth;
3559 int focusdepth;
3560 int currentdepth;
3561 int maxvaliddepth;
3562
3563 assert(conflict != NULL);
3564 assert(firstuip != NULL);
3565 assert(nreconvconss != NULL);
3566 assert(nreconvliterals != NULL);
3567 assert(!SCIPbdchginfoIsRedundant(firstuip));
3568
3569 focusdepth = SCIPtreeGetFocusDepth(tree);
3570 currentdepth = SCIPtreeGetCurrentDepth(tree);
3571 assert(currentdepth == tree->pathlen-1);
3572 assert(focusdepth <= currentdepth);
3573
3574 /* check, whether local constraints are allowed; however, don't generate reconvergence constraints that are only valid
3575 * in the probing path and not in the problem tree (i.e. that exceed the focusdepth)
3576 */
3577 maxvaliddepth = (set->conf_allowlocal ? MIN(currentdepth-1, focusdepth) : 0);
3578 if( validdepth > maxvaliddepth )
3579 return SCIP_OKAY;
3580
3581 firstuipdepth = SCIPbdchginfoGetDepth(firstuip);
3582
3583 conftype = conflict->conflictset->conflicttype;
3584 usescutoffbound = conflict->conflictset->usescutoffbound;
3585
3586 /* for each succeeding UIP pair of the last depth level, create one reconvergence constraint */
3587 uip = firstuip;
3588 while( uip != NULL && SCIPbdchginfoGetDepth(uip) == SCIPbdchginfoGetDepth(firstuip) && bdchginfoIsResolvable(uip) )
3589 {
3590 SCIP_BDCHGINFO* oppositeuip;
3591 SCIP_BDCHGINFO* bdchginfo;
3592 SCIP_BDCHGINFO* nextuip;
3593 SCIP_VAR* uipvar;
3594 SCIP_Real oppositeuipbound;
3595 SCIP_BOUNDTYPE oppositeuipboundtype;
3596 int nresolutions;
3597
3599
3600 SCIPsetDebugMsg(set, "creating reconvergence constraint for UIP <%s> %s %g in depth %d pos %d\n",
3603
3604 /* initialize conflict data */
3605 SCIP_CALL( SCIPconflictInit(conflict, set, stat, prob, conftype, usescutoffbound) );
3606
3607 conflict->conflictset->conflicttype = conftype;
3608 conflict->conflictset->usescutoffbound = usescutoffbound;
3609
3610 /* create a temporary bound change information for the negation of the UIP's bound change;
3611 * this bound change information is freed in the SCIPconflictFlushConss() call;
3612 * for reconvergence constraints for continuous variables we can only use the "negation" !(x <= u) == (x >= u);
3613 * during conflict analysis, we treat a continuous bound "x >= u" in the conflict set as "x > u", and in the
3614 * generated constraint this is negated again to "x <= u" which is correct.
3615 */
3616 uipvar = SCIPbdchginfoGetVar(uip);
3617 oppositeuipboundtype = SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(uip));
3618 oppositeuipbound = SCIPbdchginfoGetNewbound(uip);
3619 if( SCIPvarIsIntegral(uipvar) )
3620 {
3621 assert(SCIPsetIsIntegral(set, oppositeuipbound));
3622 oppositeuipbound += (oppositeuipboundtype == SCIP_BOUNDTYPE_LOWER ? +1.0 : -1.0);
3623 }
3624 SCIP_CALL( conflictCreateTmpBdchginfo(conflict, blkmem, set, uipvar, oppositeuipboundtype, \
3625 oppositeuipboundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_REAL_MIN : SCIP_REAL_MAX, oppositeuipbound, &oppositeuip) );
3626
3627 /* put the negated UIP into the conflict set */
3628 SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, oppositeuip, oppositeuipbound) );
3629
3630 /* put positive UIP into priority queue */
3632
3633 /* resolve the queue until the next UIP is reached */
3634 bdchginfo = conflictFirstCand(conflict);
3635 nextuip = NULL;
3636 nresolutions = 0;
3637 while( bdchginfo != NULL && validdepth <= maxvaliddepth )
3638 {
3639 SCIP_BDCHGINFO* nextbdchginfo;
3640 SCIP_Real relaxedbd;
3641 SCIP_Bool forceresolve;
3642 int bdchgdepth;
3643
3644 /* check if the next bound change must be resolved in every case */
3645 forceresolve = (SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0);
3646
3647 /* remove currently processed candidate and get next conflicting bound from the conflict candidate queue before
3648 * we remove the candidate we have to collect the relaxed bound since removing the candidate from the queue
3649 * invalidates the relaxed bound
3650 */
3651 assert(bdchginfo == conflictFirstCand(conflict));
3652 relaxedbd = SCIPbdchginfoGetRelaxedBound(bdchginfo);
3653 bdchginfo = conflictRemoveCand(conflict);
3654 nextbdchginfo = conflictFirstCand(conflict);
3655 bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
3656 assert(bdchginfo != NULL);
3657 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3658 assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(bdchginfo) >= SCIPbdchginfoGetDepth(nextbdchginfo)
3659 || forceresolve);
3660 assert(bdchgdepth <= firstuipdepth);
3661
3662 /* bound changes that are higher in the tree than the valid depth of the conflict can be ignored;
3663 * multiple insertions of the same bound change can be ignored
3664 */
3665 if( bdchgdepth > validdepth && bdchginfo != nextbdchginfo )
3666 {
3667 SCIP_VAR* actvar;
3668 SCIP_Bool resolved;
3669
3670 actvar = SCIPbdchginfoGetVar(bdchginfo);
3671 assert(actvar != NULL);
3672 assert(SCIPvarIsActive(actvar));
3673
3674 /* check if we have to resolve the bound change in this depth level
3675 * - the starting uip has to be resolved
3676 * - a bound change should be resolved, if it is in the fuip's depth level and not the
3677 * next uip (i.e., if it is not the last bound change in the fuip's depth level)
3678 * - a forced bound change must be resolved in any case
3679 */
3680 resolved = FALSE;
3681 if( bdchginfo == uip
3682 || (bdchgdepth == firstuipdepth
3683 && nextbdchginfo != NULL
3684 && SCIPbdchginfoGetDepth(nextbdchginfo) == bdchgdepth)
3685 || forceresolve )
3686 {
3687 SCIP_CALL( conflictResolveBound(conflict, set, bdchginfo, relaxedbd, validdepth, &resolved) );
3688 }
3689
3690 if( resolved )
3691 nresolutions++;
3692 else if( forceresolve )
3693 {
3694 /* variable cannot enter the conflict clause: we have to make the conflict clause local, s.t.
3695 * the unresolved bound change is active in the whole sub tree of the conflict clause
3696 */
3697 assert(bdchgdepth >= validdepth);
3698 validdepth = bdchgdepth;
3699
3700 SCIPsetDebugMsg(set, "couldn't resolve forced bound change on <%s> -> new valid depth: %d\n",
3701 SCIPvarGetName(actvar), validdepth);
3702 }
3703 else if( bdchginfo != uip )
3704 {
3705 assert(conflict->conflictset != NULL);
3706 assert(conflict->conflictset->nbdchginfos >= 1); /* starting UIP is already member of the conflict set */
3707
3708 /* if this is the first variable of the conflict set besides the current starting UIP, it is the next
3709 * UIP (or the first unresolvable bound change)
3710 */
3711 if( bdchgdepth == firstuipdepth && conflict->conflictset->nbdchginfos == 1 )
3712 {
3713 assert(nextuip == NULL);
3714 nextuip = bdchginfo;
3715 }
3716
3717 /* put bound change into the conflict set */
3718 SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, bdchginfo, relaxedbd) );
3719 assert(conflict->conflictset->nbdchginfos >= 2);
3720 }
3721 else
3722 assert(conflictFirstCand(conflict) == NULL); /* the starting UIP was not resolved */
3723 }
3724
3725 /* get next conflicting bound from the conflict candidate queue (this does not need to be nextbdchginfo, because
3726 * due to resolving the bound changes, a variable could be added to the queue which must be
3727 * resolved before nextbdchginfo)
3728 */
3729 bdchginfo = conflictFirstCand(conflict);
3730 }
3731 assert(nextuip != uip);
3732
3733 /* if only one propagation was resolved, the reconvergence constraint is already member of the constraint set
3734 * (it is exactly the constraint that produced the propagation)
3735 */
3736 if( nextuip != NULL && nresolutions >= 2 && bdchginfo == NULL && validdepth <= maxvaliddepth )
3737 {
3738 int nlits;
3739 SCIP_Bool success;
3740
3742
3743 /* check conflict graph frontier on debugging solution */
3744 SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth], \
3745 bdchginfo, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, \
3746 conflict->conflictset->nbdchginfos, conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
3747
3748 SCIPsetDebugMsg(set, "creating reconvergence constraint from UIP <%s> to UIP <%s> in depth %d with %d literals after %d resolutions\n",
3750 SCIPbdchginfoGetDepth(uip), conflict->conflictset->nbdchginfos, nresolutions);
3751
3752 /* call the conflict handlers to create a conflict set */
3753 SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, FALSE, &success, &nlits) );
3754 if( success )
3755 {
3756 (*nreconvconss)++;
3757 (*nreconvliterals) += nlits;
3758 }
3759 }
3760
3761 /* clear the conflict candidate queue and the conflict set (to make sure, oppositeuip is not referenced anymore) */
3762 conflictClear(conflict);
3763
3764 uip = nextuip;
3765 }
3766
3767 conflict->conflictset->conflicttype = conftype;
3768 conflict->conflictset->usescutoffbound = usescutoffbound;
3769
3770 return SCIP_OKAY;
3771}
3772
3773/** analyzes conflicting bound changes that were added with calls to SCIPconflictAddBound() and
3774 * SCIPconflictAddRelaxedBound(), and on success, calls the conflict handlers to create a conflict constraint out of
3775 * the resulting conflict set; afterwards the conflict queue and the conflict set is cleared
3776 */
3778 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3779 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3780 SCIP_SET* set, /**< global SCIP settings */
3781 SCIP_STAT* stat, /**< problem statistics */
3782 SCIP_PROB* prob, /**< problem data */
3783 SCIP_TREE* tree, /**< branch and bound tree */
3784 SCIP_Bool diving, /**< are we in strong branching or diving mode? */
3785 int validdepth, /**< minimal depth level at which the initial conflict set is valid */
3786 SCIP_Bool mustresolve, /**< should the conflict set only be used, if a resolution was applied? */
3787 int* nconss, /**< pointer to store the number of generated conflict constraints */
3788 int* nliterals, /**< pointer to store the number of literals in generated conflict constraints */
3789 int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
3790 int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
3791 )
3792{
3793 SCIP_BDCHGINFO* bdchginfo;
3794 SCIP_BDCHGINFO** firstuips;
3795 SCIP_CONFTYPE conftype;
3796 int nfirstuips;
3797 int focusdepth;
3798 int currentdepth;
3799 int maxvaliddepth;
3800 int resolvedepth;
3801 int nresolutions;
3802 int lastconsnresolutions;
3803 int lastconsresoldepth;
3804
3805 assert(conflict != NULL);
3806 assert(conflict->conflictset != NULL);
3807 assert(conflict->conflictset->nbdchginfos >= 0);
3808 assert(set != NULL);
3809 assert(stat != NULL);
3810 assert(0 <= validdepth && validdepth <= SCIPtreeGetCurrentDepth(tree));
3811 assert(nconss != NULL);
3812 assert(nliterals != NULL);
3813 assert(nreconvconss != NULL);
3814 assert(nreconvliterals != NULL);
3815
3816 focusdepth = SCIPtreeGetFocusDepth(tree);
3817 currentdepth = SCIPtreeGetCurrentDepth(tree);
3818 assert(currentdepth == tree->pathlen-1);
3819 assert(focusdepth <= currentdepth);
3820
3821 resolvedepth = ((set->conf_fuiplevels >= 0 && set->conf_fuiplevels <= currentdepth)
3822 ? currentdepth - set->conf_fuiplevels + 1 : 0);
3823 assert(0 <= resolvedepth && resolvedepth <= currentdepth + 1);
3824
3825 /* if we must resolve at least one bound change, find the first UIP at least in the last depth level */
3826 if( mustresolve )
3827 resolvedepth = MIN(resolvedepth, currentdepth);
3828
3829 SCIPsetDebugMsg(set, "analyzing conflict with %d+%d conflict candidates and starting conflict set of size %d in depth %d (resolvedepth=%d)\n",
3831 conflict->conflictset->nbdchginfos, currentdepth, resolvedepth);
3832
3833 *nconss = 0;
3834 *nliterals = 0;
3835 *nreconvconss = 0;
3836 *nreconvliterals = 0;
3837
3838 /* check, whether local conflicts are allowed; however, don't generate conflict constraints that are only valid in the
3839 * probing path and not in the problem tree (i.e. that exceed the focusdepth)
3840 */
3841 maxvaliddepth = (set->conf_allowlocal ? MIN(currentdepth-1, focusdepth) : 0);
3842 if( validdepth > maxvaliddepth )
3843 return SCIP_OKAY;
3844
3845 /* allocate temporary memory for storing first UIPs (in each depth level, at most two bound changes can be flagged
3846 * as UIP, namely a binary and a non-binary bound change)
3847 */
3848 SCIP_CALL( SCIPsetAllocBufferArray(set, &firstuips, 2*(currentdepth+1)) ); /*lint !e647*/
3849
3850 /* process all bound changes in the conflict candidate queue */
3851 nresolutions = 0;
3852 lastconsnresolutions = (mustresolve ? 0 : -1);
3853 lastconsresoldepth = (mustresolve ? currentdepth : INT_MAX);
3854 bdchginfo = conflictFirstCand(conflict);
3855 nfirstuips = 0;
3856
3857 /* check if the initial reason on debugging solution */
3858 SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth], \
3859 NULL, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, conflict->conflictset->nbdchginfos, \
3860 conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
3861
3862 while( bdchginfo != NULL && validdepth <= maxvaliddepth )
3863 {
3864 SCIP_BDCHGINFO* nextbdchginfo;
3865 SCIP_Real relaxedbd;
3866 SCIP_Bool forceresolve;
3867 int bdchgdepth;
3868
3869 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3870
3871 /* check if the next bound change must be resolved in every case */
3872 forceresolve = (SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0);
3873
3874 /* resolve next bound change in queue */
3875 bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
3876 assert(0 <= bdchgdepth && bdchgdepth <= currentdepth);
3878 assert(bdchgdepth < tree->pathlen);
3879 assert(tree->path[bdchgdepth] != NULL);
3880 assert(tree->path[bdchgdepth]->domchg != NULL);
3881 assert(SCIPbdchginfoGetPos(bdchginfo) < (int)tree->path[bdchgdepth]->domchg->domchgbound.nboundchgs);
3882 assert(tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].var
3883 == SCIPbdchginfoGetVar(bdchginfo));
3884 assert(tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].newbound
3885 == SCIPbdchginfoGetNewbound(bdchginfo)
3888 == SCIPbdchginfoGetNewbound(bdchginfo)); /*lint !e777*/
3889 assert((SCIP_BOUNDTYPE)tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].boundtype
3890 == SCIPbdchginfoGetBoundtype(bdchginfo));
3891
3892 /* create intermediate conflict constraint */
3893 assert(nresolutions >= lastconsnresolutions);
3894 if( !forceresolve )
3895 {
3896 if( nresolutions == lastconsnresolutions )
3897 lastconsresoldepth = bdchgdepth; /* all intermediate depth levels consisted of only unresolved bound changes */
3898 else if( bdchgdepth < lastconsresoldepth && (set->conf_interconss == -1 || *nconss < set->conf_interconss) )
3899 {
3900 int nlits;
3901 SCIP_Bool success;
3902
3903 /* call the conflict handlers to create a conflict set */
3904 SCIPsetDebugMsg(set, "creating intermediate conflictset after %d resolutions up to depth %d (valid at depth %d): %d conflict bounds, %d bounds in queue\n",
3905 nresolutions, bdchgdepth, validdepth, conflict->conflictset->nbdchginfos,
3906 SCIPpqueueNElems(conflict->bdchgqueue));
3907
3908 SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, TRUE, &success, &nlits) );
3909 lastconsnresolutions = nresolutions;
3910 lastconsresoldepth = bdchgdepth;
3911 if( success )
3912 {
3913 (*nconss)++;
3914 (*nliterals) += nlits;
3915 }
3916 }
3917 }
3918
3919 /* remove currently processed candidate and get next conflicting bound from the conflict candidate queue before
3920 * we remove the candidate we have to collect the relaxed bound since removing the candidate from the queue
3921 * invalidates the relaxed bound
3922 */
3923 assert(bdchginfo == conflictFirstCand(conflict));
3924 relaxedbd = SCIPbdchginfoGetRelaxedBound(bdchginfo);
3925 bdchginfo = conflictRemoveCand(conflict);
3926 nextbdchginfo = conflictFirstCand(conflict);
3927 assert(bdchginfo != NULL);
3928 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3929 assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(bdchginfo) >= SCIPbdchginfoGetDepth(nextbdchginfo)
3930 || forceresolve);
3931
3932 /* we don't need to resolve bound changes that are already active in the valid depth of the current conflict set,
3933 * because the conflict set can only be added locally at the valid depth, and all bound changes applied in this
3934 * depth or earlier can be removed from the conflict constraint, since they are already applied in the constraint's
3935 * subtree;
3936 * if the next bound change on the remaining queue is equal to the current bound change,
3937 * this is a multiple insertion in the conflict candidate queue and we can ignore the current
3938 * bound change
3939 */
3940 if( bdchgdepth > validdepth && bdchginfo != nextbdchginfo )
3941 {
3942 SCIP_VAR* actvar;
3943 SCIP_Bool resolved;
3944
3945 actvar = SCIPbdchginfoGetVar(bdchginfo);
3946 assert(actvar != NULL);
3947 assert(SCIPvarIsActive(actvar));
3948
3949 /* check if we want to resolve the bound change in this depth level
3950 * - bound changes should be resolved, if
3951 * (i) we must apply at least one resolution and didn't resolve a bound change yet, or
3952 * (ii) their depth level is at least equal to the minimal resolving depth, and
3953 * they are not the last remaining conflicting bound change in their depth level
3954 * (iii) the bound change resolving is forced (i.e., the forced queue was non-empty)
3955 */
3956 resolved = FALSE;
3957 if( (mustresolve && nresolutions == 0)
3958 || (bdchgdepth >= resolvedepth
3959 && nextbdchginfo != NULL
3960 && SCIPbdchginfoGetDepth(nextbdchginfo) == bdchgdepth)
3961 || forceresolve )
3962 {
3963 SCIP_CALL( conflictResolveBound(conflict, set, bdchginfo, relaxedbd, validdepth, &resolved) );
3964 }
3965
3966 if( resolved )
3967 nresolutions++;
3968 else if( forceresolve )
3969 {
3970 /* variable cannot enter the conflict clause: we have to make the conflict clause local, s.t.
3971 * the unresolved bound change is active in the whole sub tree of the conflict clause
3972 */
3973 assert(bdchgdepth >= validdepth);
3974 validdepth = bdchgdepth;
3975
3976 SCIPsetDebugMsg(set, "couldn't resolve forced bound change on <%s> -> new valid depth: %d\n",
3977 SCIPvarGetName(actvar), validdepth);
3978 }
3979 else
3980 {
3981 /* if this is a UIP (the last bound change in its depth level), it can be used to generate a
3982 * UIP reconvergence constraint
3983 */
3984 if( nextbdchginfo == NULL || SCIPbdchginfoGetDepth(nextbdchginfo) != bdchgdepth )
3985 {
3986 assert(nfirstuips < 2*(currentdepth+1));
3987 firstuips[nfirstuips] = bdchginfo;
3988 nfirstuips++;
3989 }
3990
3991 /* put variable into the conflict set, using the literal that is currently fixed to FALSE */
3992 SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, bdchginfo, relaxedbd) );
3993 }
3994 }
3995
3996 /* check conflict graph frontier on debugging solution */
3997 SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth], \
3998 bdchginfo, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, conflict->conflictset->nbdchginfos, \
3999 conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
4000
4001 /* get next conflicting bound from the conflict candidate queue (this needs not to be nextbdchginfo, because
4002 * due to resolving the bound changes, a bound change could be added to the queue which must be
4003 * resolved before nextbdchginfo)
4004 */
4005 bdchginfo = conflictFirstCand(conflict);
4006 }
4007
4008 /* check, if a valid conflict set was found */
4009 if( bdchginfo == NULL
4010 && nresolutions > lastconsnresolutions
4011 && validdepth <= maxvaliddepth
4012 && (!mustresolve || nresolutions > 0 || conflict->conflictset->nbdchginfos == 0)
4013 && SCIPpqueueNElems(conflict->forcedbdchgqueue) == 0 )
4014 {
4015 int nlits;
4016 SCIP_Bool success;
4017
4018 /* call the conflict handlers to create a conflict set */
4019 SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, TRUE, &success, &nlits) );
4020 if( success )
4021 {
4022 (*nconss)++;
4023 (*nliterals) += nlits;
4024 }
4025 }
4026
4027 /* produce reconvergence constraints defined by succeeding UIP's of the last depth level */
4028 if( set->conf_reconvlevels != 0 && validdepth <= maxvaliddepth )
4029 {
4030 int reconvlevels;
4031 int i;
4032
4033 reconvlevels = (set->conf_reconvlevels == -1 ? INT_MAX : set->conf_reconvlevels);
4034 for( i = 0; i < nfirstuips; ++i )
4035 {
4036 if( SCIPbdchginfoHasInferenceReason(firstuips[i])
4037 && currentdepth - SCIPbdchginfoGetDepth(firstuips[i]) < reconvlevels )
4038 {
4039 SCIP_CALL( conflictCreateReconvergenceConss(conflict, blkmem, set, stat, prob, tree, diving, \
4040 validdepth, firstuips[i], nreconvconss, nreconvliterals) );
4041 }
4042 }
4043 }
4044
4045 /* free the temporary memory */
4046 SCIPsetFreeBufferArray(set, &firstuips);
4047
4048 /* store last conflict type */
4049 conftype = conflict->conflictset->conflicttype;
4050
4051 /* clear the conflict candidate queue and the conflict set */
4052 conflictClear(conflict);
4053
4054 /* restore last conflict type */
4055 conflict->conflictset->conflicttype = conftype;
4056
4057 return SCIP_OKAY;
4058}
4059
4060/** calculates the score of a bound change within a conflict */
4061static
4063 SCIP_Real prooflhs, /**< lhs of proof constraint */
4064 SCIP_Real proofact, /**< activity of the proof constraint */
4065 SCIP_Real proofactdelta, /**< activity change */
4066 SCIP_Real proofcoef, /**< coefficient in proof constraint */
4067 int depth, /**< bound change depth */
4068 int currentdepth, /**< current depth */
4069 SCIP_VAR* var, /**< variable corresponding to bound change */
4070 SCIP_SET* set /**< global SCIP settings */
4071 )
4072{
4073 SCIP_COL* col;
4074 SCIP_Real score;
4075
4076 score = set->conf_proofscorefac * (1.0 - proofactdelta/(prooflhs - proofact));
4077 score = MAX(score, 0.0);
4078 score += set->conf_depthscorefac * (SCIP_Real)(depth+1)/(SCIP_Real)(currentdepth+1);
4079
4081 col = SCIPvarGetCol(var);
4082 else
4083 col = NULL;
4084
4085 if( proofcoef > 0.0 )
4086 {
4087 if( col != NULL && SCIPcolGetNNonz(col) > 0 )
4088 score += set->conf_uplockscorefac
4090 else
4091 score += set->conf_uplockscorefac * SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
4092 }
4093 else
4094 {
4095 if( col != NULL && SCIPcolGetNNonz(col) > 0 )
4096 score += set->conf_downlockscorefac
4098 else
4099 score += set->conf_downlockscorefac * SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL);
4100 }
4101
4102 return score;
4103}
4104
4105/** ensures, that candidate array can store at least num entries */
4106static
4108 SCIP_SET* set, /**< global SCIP settings */
4109 SCIP_VAR*** cands, /**< pointer to candidate array */
4110 SCIP_Real** candscores, /**< pointer to candidate score array */
4111 SCIP_Real** newbounds, /**< pointer to candidate new bounds array */
4112 SCIP_Real** proofactdeltas, /**< pointer to candidate proof delta array */
4113 int* candssize, /**< pointer to size of array */
4114 int num /**< minimal number of candidates to store in array */
4115 )
4116{
4117 assert(cands != NULL);
4118 assert(candssize != NULL);
4119
4120 if( num > *candssize )
4121 {
4122 int newsize;
4123
4124 newsize = SCIPsetCalcMemGrowSize(set, num);
4125 SCIP_CALL( SCIPsetReallocBufferArray(set, cands, newsize) );
4126 SCIP_CALL( SCIPsetReallocBufferArray(set, candscores, newsize) );
4127 SCIP_CALL( SCIPsetReallocBufferArray(set, newbounds, newsize) );
4128 SCIP_CALL( SCIPsetReallocBufferArray(set, proofactdeltas, newsize) );
4129 *candssize = newsize;
4130 }
4131 assert(num <= *candssize);
4132
4133 return SCIP_OKAY;
4134}
4135
4136/** after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
4137 * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
4138 * global bound and we can ignore it by installing a -1 as the corresponding bound change info position
4139 */
4140static
4142 SCIP_VAR* var, /**< problem variable */
4143 int* lbchginfopos, /**< pointer to lower bound change information position */
4144 int* ubchginfopos /**< pointer to upper bound change information position */
4145 )
4146{
4147 assert(var != NULL);
4148 assert(lbchginfopos != NULL);
4149 assert(ubchginfopos != NULL);
4150 assert(-1 <= *lbchginfopos && *lbchginfopos <= var->nlbchginfos);
4151 assert(-1 <= *ubchginfopos && *ubchginfopos <= var->nubchginfos);
4152 assert(*lbchginfopos == -1 || *lbchginfopos == var->nlbchginfos
4153 || var->lbchginfos[*lbchginfopos].redundant
4154 == (var->lbchginfos[*lbchginfopos].oldbound == var->lbchginfos[*lbchginfopos].newbound)); /*lint !e777*/
4155 assert(*ubchginfopos == -1 || *ubchginfopos == var->nubchginfos
4156 || var->ubchginfos[*ubchginfopos].redundant
4157 == (var->ubchginfos[*ubchginfopos].oldbound == var->ubchginfos[*ubchginfopos].newbound)); /*lint !e777*/
4158
4159 if( *lbchginfopos >= 0 && *lbchginfopos < var->nlbchginfos && var->lbchginfos[*lbchginfopos].redundant )
4160 {
4161 assert(SCIPvarGetLbGlobal(var) == var->lbchginfos[*lbchginfopos].oldbound); /*lint !e777*/
4162 *lbchginfopos = -1;
4163 }
4164 if( *ubchginfopos >= 0 && *ubchginfopos < var->nubchginfos && var->ubchginfos[*ubchginfopos].redundant )
4165 {
4166 assert(SCIPvarGetUbGlobal(var) == var->ubchginfos[*ubchginfopos].oldbound); /*lint !e777*/
4167 *ubchginfopos = -1;
4168 }
4169}
4170
4171/** adds variable's bound to conflict candidate queue */
4173 SCIP_CONFLICT* conflict, /**< conflict analysis data */
4174 BMS_BLKMEM* blkmem, /**< block memory */
4175 SCIP_SET* set, /**< global SCIP settings */
4176 SCIP_STAT* stat, /**< dynamic problem statistics */
4177 SCIP_VAR* var, /**< problem variable */
4178 SCIP_BOUNDTYPE boundtype, /**< type of bound that was changed: lower or upper bound */
4179 SCIP_BDCHGIDX* bdchgidx /**< bound change index (time stamp of bound change), or NULL for current time */
4180 )
4181{
4182 SCIP_BDCHGINFO* bdchginfo;
4183
4184 assert(conflict != NULL);
4185 assert(stat != NULL);
4186 assert(var != NULL);
4187
4188 /* convert bound to active problem variable */
4189 SCIP_CALL( convertToActiveVar(&var, set, &boundtype, NULL) );
4190
4191 /* we can ignore fixed variables */
4193 return SCIP_OKAY;
4194
4195 /* if the variable is multi-aggregated, add the bounds of all aggregation variables */
4197 {
4198 SCIP_VAR** vars;
4200 int nvars;
4201 int i;
4202
4206 for( i = 0; i < nvars; ++i )
4207 {
4208 SCIP_CALL( SCIPconflictAddBound(conflict, blkmem, set, stat, vars[i],
4209 (scalars[i] < 0.0 ? SCIPboundtypeOpposite(boundtype) : boundtype), bdchgidx) );
4210 }
4211
4212 return SCIP_OKAY;
4213 }
4215
4216 /* get bound change information */
4217 bdchginfo = SCIPvarGetBdchgInfo(var, boundtype, bdchgidx, FALSE);
4218
4219 /* if bound of variable was not changed (this means it is still the global bound), we can ignore the conflicting
4220 * bound
4221 */
4222 if( bdchginfo == NULL )
4223 return SCIP_OKAY;
4224
4225 assert(SCIPbdchgidxIsEarlier(SCIPbdchginfoGetIdx(bdchginfo), bdchgidx));
4226
4227 SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchginfo, SCIPbdchginfoGetNewbound(bdchginfo)) );
4228
4229 return SCIP_OKAY;
4230}
4231
4232/** adds variable's bound to conflict candidate queue */
4234 SCIP_CONFLICT* conflict, /**< conflict analysis data */
4235 BMS_BLKMEM* blkmem, /**< block memory */
4236 SCIP_SET* set, /**< global SCIP settings */
4237 SCIP_STAT* stat, /**< dynamic problem statistics */
4238 SCIP_VAR* var, /**< problem variable */
4239 SCIP_BOUNDTYPE boundtype, /**< type of bound that was changed: lower or upper bound */
4240 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4241 SCIP_Real relaxedbd /**< the relaxed bound */
4242 )
4243{
4244 SCIP_BDCHGINFO* bdchginfo;
4245 int nbdchgs;
4246
4247 assert(conflict != NULL);
4248 assert(stat != NULL);
4249 assert(var != NULL);
4250
4251 if( !SCIPvarIsActive(var) )
4252 {
4253 /* convert bound to active problem variable */
4254 SCIP_CALL( convertToActiveVar(&var, set, &boundtype, &relaxedbd) );
4255
4256 /* we can ignore fixed variables */
4258 return SCIP_OKAY;
4259
4260 /* if the variable is multi-aggregated, add the bounds of all aggregation variables */
4262 {
4263 SCIPsetDebugMsg(set, "ignoring relaxed bound information since variable <%s> is multi-aggregated active\n", SCIPvarGetName(var));
4264
4265 SCIP_CALL( SCIPconflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchgidx) );
4266
4267 return SCIP_OKAY;
4268 }
4269 }
4271
4272 /* get bound change information */
4273 bdchginfo = SCIPvarGetBdchgInfo(var, boundtype, bdchgidx, FALSE);
4274
4275 /* if bound of variable was not changed (this means it is still the global bound), we can ignore the conflicting
4276 * bound
4277 */
4278 if( bdchginfo == NULL )
4279 return SCIP_OKAY;
4280
4281 /* check that the bound change info is not a temporary one */
4282 assert(SCIPbdchgidxGetPos(&bdchginfo->bdchgidx) >= 0);
4283
4284 /* get the position of the bound change information within the bound change array of the variable */
4285 nbdchgs = (int) bdchginfo->pos;
4286 assert(nbdchgs >= 0);
4287
4288 /* if the relaxed bound should be ignored, set the relaxed bound to the bound given by the bdchgidx; that ensures
4289 * that the loop(s) below will be skipped
4290 */
4291 if( set->conf_ignorerelaxedbd )
4292 relaxedbd = SCIPbdchginfoGetNewbound(bdchginfo);
4293
4294 /* search for the bound change information which includes the relaxed bound */
4295 if( boundtype == SCIP_BOUNDTYPE_LOWER )
4296 {
4297 SCIP_Real newbound;
4298
4299 /* adjust relaxed lower bound w.r.t. variable type */
4300 SCIPvarAdjustLb(var, set, &relaxedbd);
4301
4302 /* due to numericis we compare the relaxed lower bound to the one present at the particular time point and take
4303 * the better one
4304 */
4305 newbound = SCIPbdchginfoGetNewbound(bdchginfo);
4306 relaxedbd = MIN(relaxedbd, newbound);
4307
4308 /* check if relaxed lower bound is smaller or equal to global lower bound; if so we can ignore the conflicting
4309 * bound
4310 */
4311 if( SCIPsetIsLE(set, relaxedbd, SCIPvarGetLbGlobal(var)) )
4312 return SCIP_OKAY;
4313
4314 while( nbdchgs > 0 )
4315 {
4316 assert(SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4317
4318 /* check if the old lower bound is greater than or equal to relaxed lower bound; if not we found the bound
4319 * change info which we need to report
4320 */
4321 if( SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) )
4322 break;
4323
4324 bdchginfo = SCIPvarGetBdchgInfoLb(var, nbdchgs-1);
4325
4326 SCIPsetDebugMsg(set, "lower bound change %d oldbd=%.15g, newbd=%.15g, depth=%d, pos=%d, redundant=%u\n",
4327 nbdchgs, SCIPbdchginfoGetOldbound(bdchginfo), SCIPbdchginfoGetNewbound(bdchginfo),
4328 SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
4329 SCIPbdchginfoIsRedundant(bdchginfo));
4330
4331 /* if bound change is redundant (this means it now a global bound), we can ignore the conflicting bound */
4332 if( SCIPbdchginfoIsRedundant(bdchginfo) )
4333 return SCIP_OKAY;
4334
4335 nbdchgs--;
4336 }
4337 assert(SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
4338 }
4339 else
4340 {
4341 SCIP_Real newbound;
4342
4343 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
4344
4345 /* adjust relaxed upper bound w.r.t. variable type */
4346 SCIPvarAdjustUb(var, set, &relaxedbd);
4347
4348 /* due to numericis we compare the relaxed upper bound to the one present at the particular time point and take
4349 * the better one
4350 */
4351 newbound = SCIPbdchginfoGetNewbound(bdchginfo);
4352 relaxedbd = MAX(relaxedbd, newbound);
4353
4354 /* check if relaxed upper bound is greater or equal to global upper bound; if so we can ignore the conflicting
4355 * bound
4356 */
4357 if( SCIPsetIsGE(set, relaxedbd, SCIPvarGetUbGlobal(var)) )
4358 return SCIP_OKAY;
4359
4360 while( nbdchgs > 0 )
4361 {
4362 assert(SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4363
4364 /* check if the old upper bound is smaller than or equal to the relaxed upper bound; if not we found the
4365 * bound change info which we need to report
4366 */
4367 if( SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) )
4368 break;
4369
4370 bdchginfo = SCIPvarGetBdchgInfoUb(var, nbdchgs-1);
4371
4372 SCIPsetDebugMsg(set, "upper bound change %d oldbd=%.15g, newbd=%.15g, depth=%d, pos=%d, redundant=%u\n",
4373 nbdchgs, SCIPbdchginfoGetOldbound(bdchginfo), SCIPbdchginfoGetNewbound(bdchginfo),
4374 SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
4375 SCIPbdchginfoIsRedundant(bdchginfo));
4376
4377 /* if bound change is redundant (this means it now a global bound), we can ignore the conflicting bound */
4378 if( SCIPbdchginfoIsRedundant(bdchginfo) )
4379 return SCIP_OKAY;
4380
4381 nbdchgs--;
4382 }
4383 assert(SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
4384 }
4385
4386 assert(SCIPbdchgidxIsEarlier(SCIPbdchginfoGetIdx(bdchginfo), bdchgidx));
4387
4388 /* put bound change information into priority queue */
4389 SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchginfo, relaxedbd) );
4390
4391 return SCIP_OKAY;
4392}
4393
4394/** checks if the given variable is already part of the current conflict set or queued for resolving with the same or
4395 * even stronger bound
4396 */
4398 SCIP_CONFLICT* conflict, /**< conflict analysis data */
4399 SCIP_VAR* var, /**< problem variable */
4400 SCIP_SET* set, /**< global SCIP settings */
4401 SCIP_BOUNDTYPE boundtype, /**< type of bound for which the score should be increased */
4402 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4403 SCIP_Bool* used /**< pointer to store if the variable is already used */
4404 )
4405{
4406 SCIP_Real newbound;
4407
4408 /* convert bound to active problem variable */
4409 SCIP_CALL( convertToActiveVar(&var, set, &boundtype, NULL) );
4410
4412 *used = FALSE;
4413 else
4414 {
4416 assert(var != NULL);
4417
4418 switch( boundtype )
4419 {
4421
4422 newbound = SCIPgetVarLbAtIndex(set->scip, var, bdchgidx, FALSE);
4423
4424 if( var->conflictlbcount == conflict->count && var->conflictlb >= newbound )
4425 {
4426 SCIPsetDebugMsg(set, "already queued bound change <%s> >= %g\n", SCIPvarGetName(var), newbound);
4427 *used = TRUE;
4428 }
4429 else
4430 *used = FALSE;
4431 break;
4433
4434 newbound = SCIPgetVarUbAtIndex(set->scip, var, bdchgidx, FALSE);
4435
4436 if( var->conflictubcount == conflict->count && var->conflictub <= newbound )
4437 {
4438 SCIPsetDebugMsg(set, "already queued bound change <%s> <= %g\n", SCIPvarGetName(var), newbound);
4439 *used = TRUE;
4440 }
4441 else
4442 *used = FALSE;
4443 break;
4444 default:
4445 SCIPerrorMessage("invalid bound type %d\n", boundtype);
4446 SCIPABORT();
4447 *used = FALSE; /*lint !e527*/
4448 }
4449 }
4450
4451 return SCIP_OKAY;
4452}
4453
4454/** inserts variable's new bounds into bound change arrays */
4455static
4457 SCIP_SET* set, /**< global SCIP settings */
4458 SCIP_VAR* var, /**< variable to change the LP bounds for */
4459 SCIP_Real newlb, /**< new lower bound */
4460 SCIP_Real newub, /**< new upper bound */
4461 SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change */
4462 SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change */
4463 SCIP_LPI* lpi /**< pointer to LPi to access infinity of LP solver; necessary to set correct value */
4464 )
4465{
4466 assert(newlb <= newub);
4467 assert(oldlpbdchgs != NULL);
4468 assert(relaxedlpbdchgs != NULL);
4469
4471 {
4472 SCIP_COL* col;
4473 int idx;
4474 int c;
4475
4476 col = SCIPvarGetCol(var);
4477 c = SCIPcolGetLPPos(col);
4478
4479 if( c >= 0 )
4480 {
4481 /* store old bound change for resetting the LP later */
4482 if( !oldlpbdchgs->usedcols[c] )
4483 {
4484 idx = oldlpbdchgs->nbdchgs;
4485 oldlpbdchgs->usedcols[c] = TRUE;
4486 oldlpbdchgs->bdchgcolinds[c] = idx;
4487 oldlpbdchgs->nbdchgs++;
4488
4489 oldlpbdchgs->bdchginds[idx] = c;
4490 oldlpbdchgs->bdchglbs[idx] = SCIPvarGetLbLP(var, set);
4491 oldlpbdchgs->bdchgubs[idx] = SCIPvarGetUbLP(var, set);
4492 }
4493 assert(oldlpbdchgs->bdchginds[oldlpbdchgs->bdchgcolinds[c]] == c);
4494 assert((SCIPlpiIsInfinity(lpi, -oldlpbdchgs->bdchglbs[oldlpbdchgs->bdchgcolinds[c]]) && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var, set))) ||
4495 SCIPsetIsEQ(set, oldlpbdchgs->bdchglbs[oldlpbdchgs->bdchgcolinds[c]], SCIPvarGetLbLP(var, set)));
4496 assert((SCIPlpiIsInfinity(lpi, oldlpbdchgs->bdchgubs[oldlpbdchgs->bdchgcolinds[c]]) && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var, set))) ||
4497 SCIPsetIsEQ(set, oldlpbdchgs->bdchgubs[oldlpbdchgs->bdchgcolinds[c]], SCIPvarGetUbLP(var, set)));
4498
4499 /* store bound change for conflict analysis */
4500 if( !relaxedlpbdchgs->usedcols[c] )
4501 {
4502 idx = relaxedlpbdchgs->nbdchgs;
4503 relaxedlpbdchgs->usedcols[c] = TRUE;
4504 relaxedlpbdchgs->bdchgcolinds[c] = idx;
4505 relaxedlpbdchgs->nbdchgs++;
4506
4507 /* remember the positive for later further bound widenings */
4508 relaxedlpbdchgs->bdchginds[idx] = c;
4509 }
4510 else
4511 {
4512 idx = relaxedlpbdchgs->bdchgcolinds[c];
4513 assert(relaxedlpbdchgs->bdchginds[idx] == c);
4514
4515 /* the new bound should be the same or more relaxed */
4516 assert(relaxedlpbdchgs->bdchglbs[idx] >= newlb ||
4517 (SCIPlpiIsInfinity(lpi, -relaxedlpbdchgs->bdchglbs[idx]) && SCIPsetIsInfinity(set, -newlb)));
4518 assert(relaxedlpbdchgs->bdchgubs[idx] <= newub ||
4519 (SCIPlpiIsInfinity(lpi, relaxedlpbdchgs->bdchgubs[idx]) && SCIPsetIsInfinity(set, newub)));
4520 }
4521
4522 /* set the new bounds for the LP with the correct infinity value */
4523 relaxedlpbdchgs->bdchglbs[idx] = SCIPsetIsInfinity(set, -newlb) ? -SCIPlpiInfinity(lpi) : newlb;
4524 relaxedlpbdchgs->bdchgubs[idx] = SCIPsetIsInfinity(set, newub) ? SCIPlpiInfinity(lpi) : newub;
4525 if( SCIPsetIsInfinity(set, -oldlpbdchgs->bdchglbs[idx]) )
4526 oldlpbdchgs->bdchglbs[idx] = -SCIPlpiInfinity(lpi);
4527 if( SCIPsetIsInfinity(set, oldlpbdchgs->bdchgubs[idx]) )
4528 oldlpbdchgs->bdchgubs[idx] = SCIPlpiInfinity(lpi);
4529 }
4530 }
4531
4532 return SCIP_OKAY;
4533}
4534
4535/** adds variable to candidate list, if the current best bound corresponding to the proof coefficient is local;
4536 * returns the array position in the candidate list, where the new candidate was inserted, or -1 if the
4537 * variable can relaxed to global bounds immediately without increasing the proof's activity;
4538 * the candidates are sorted with respect to the following two criteria:
4539 * - prefer bound changes that have been applied deeper in the tree, to get a more global conflict
4540 * - prefer variables with small Farkas coefficient to get rid of as many bound changes as possible
4541 */
4542static
4544 SCIP_SET* set, /**< global SCIP settings */
4545 int currentdepth, /**< current depth in the tree */
4546 SCIP_VAR* var, /**< variable to add to candidate array */
4547 int lbchginfopos, /**< positions of currently active lower bound change information in variable's array */
4548 int ubchginfopos, /**< positions of currently active upper bound change information in variable's array */
4549 SCIP_Real proofcoef, /**< coefficient of variable in infeasibility/bound proof */
4550 SCIP_Real prooflhs, /**< left hand side of infeasibility/bound proof */
4551 SCIP_Real proofact, /**< activity of infeasibility/bound proof row */
4552 SCIP_VAR*** cands, /**< pointer to candidate array for undoing bound changes */
4553 SCIP_Real** candscores, /**< pointer to candidate score array for undoing bound changes */
4554 SCIP_Real** newbounds, /**< pointer to candidate new bounds array for undoing bound changes */
4555 SCIP_Real** proofactdeltas, /**< pointer to proof activity increase array for undoing bound changes */
4556 int* candssize, /**< pointer to size of cands arrays */
4557 int* ncands, /**< pointer to count number of candidates in bound change list */
4558 int firstcand /**< position of first unprocessed bound change candidate */
4559 )
4560{
4561 SCIP_Real oldbound;
4562 SCIP_Real newbound;
4563 SCIP_Real QUAD(proofactdelta);
4564 SCIP_Real score;
4565 int depth;
4566 int i;
4567 SCIP_Bool resolvable;
4568
4569 assert(set != NULL);
4570 assert(var != NULL);
4571 assert(-1 <= lbchginfopos && lbchginfopos <= var->nlbchginfos);
4572 assert(-1 <= ubchginfopos && ubchginfopos <= var->nubchginfos);
4573 assert(!SCIPsetIsZero(set, proofcoef));
4574 assert(SCIPsetIsGT(set, prooflhs, proofact));
4575 assert(cands != NULL);
4576 assert(candscores != NULL);
4577 assert(newbounds != NULL);
4578 assert(proofactdeltas != NULL);
4579 assert(candssize != NULL);
4580 assert(ncands != NULL);
4581 assert(*ncands <= *candssize);
4582 assert(0 <= firstcand && firstcand <= *ncands);
4583
4584 /* in the infeasibility or dual bound proof, the variable's bound is chosen to maximize the proof's activity */
4585 if( proofcoef > 0.0 )
4586 {
4587 assert(ubchginfopos >= 0); /* otherwise, undoBdchgsProof() should already have relaxed the local bound */
4588
4589 /* calculate the difference of current bound to the previous bound the variable was set to */
4590 if( ubchginfopos == var->nubchginfos )
4591 {
4592 /* current bound is the strong branching or diving bound */
4593 oldbound = SCIPvarGetUbLP(var, set);
4594 newbound = SCIPvarGetUbLocal(var);
4595 depth = currentdepth+1;
4596 resolvable = FALSE;
4597 }
4598 else
4599 {
4600 /* current bound is the result of a local bound change */
4601 resolvable = bdchginfoIsResolvable(&var->ubchginfos[ubchginfopos]);
4602 depth = var->ubchginfos[ubchginfopos].bdchgidx.depth;
4603 oldbound = var->ubchginfos[ubchginfopos].newbound;
4604 newbound = var->ubchginfos[ubchginfopos].oldbound;
4605 }
4606 }
4607 else
4608 {
4609 assert(lbchginfopos >= 0); /* otherwise, undoBdchgsProof() should already have relaxed the local bound */
4610
4611 /* calculate the difference of current bound to the previous bound the variable was set to */
4612 if( lbchginfopos == var->nlbchginfos )
4613 {
4614 /* current bound is the strong branching or diving bound */
4615 oldbound = SCIPvarGetLbLP(var, set);
4616 newbound = SCIPvarGetLbLocal(var);
4617 depth = currentdepth+1;
4618 resolvable = FALSE;
4619 }
4620 else
4621 {
4622 /* current bound is the result of a local bound change */
4623 resolvable = bdchginfoIsResolvable(&var->lbchginfos[lbchginfopos]);
4624 depth = var->lbchginfos[lbchginfopos].bdchgidx.depth;
4625 oldbound = var->lbchginfos[lbchginfopos].newbound;
4626 newbound = var->lbchginfos[lbchginfopos].oldbound;
4627 }
4628 }
4629
4630 /* calculate the increase in the proof's activity */
4631 SCIPquadprecSumDD(proofactdelta, newbound, -oldbound);
4632 SCIPquadprecProdQD(proofactdelta, proofactdelta, proofcoef);
4633 assert(QUAD_TO_DBL(proofactdelta) > 0.0);
4634
4635 /* calculate score for undoing the bound change */
4636 score = calcBdchgScore(prooflhs, proofact, QUAD_TO_DBL(proofactdelta), proofcoef, depth, currentdepth, var, set);
4637
4638 if( !resolvable )
4639 {
4640 score += 10.0;
4641 if( !SCIPvarIsBinary(var) )
4642 score += 10.0;
4643 }
4644
4645 /* get enough memory to store new candidate */
4646 SCIP_CALL( ensureCandsSize(set, cands, candscores, newbounds, proofactdeltas, candssize, (*ncands)+1) );
4647 assert(*cands != NULL);
4648 assert(*candscores != NULL);
4649 assert(*newbounds != NULL);
4650 assert(*proofactdeltas != NULL);
4651
4652 SCIPsetDebugMsg(set, " -> local <%s> %s %g, relax <%s> %s %g, proofcoef=%g, dpt=%d, resolve=%u, delta=%g, score=%g\n",
4653 SCIPvarGetName(var), proofcoef > 0.0 ? "<=" : ">=", oldbound,
4654 SCIPvarGetName(var), proofcoef > 0.0 ? "<=" : ">=", newbound,
4655 proofcoef, depth, resolvable, QUAD_TO_DBL(proofactdelta), score);
4656
4657 /* insert variable in candidate list without touching the already processed candidates */
4658 for( i = *ncands; i > firstcand && score > (*candscores)[i-1]; --i )
4659 {
4660 (*cands)[i] = (*cands)[i-1];
4661 (*candscores)[i] = (*candscores)[i-1];
4662 (*newbounds)[i] = (*newbounds)[i-1];
4663 (*proofactdeltas)[i] = (*proofactdeltas)[i-1];
4664 }
4665 (*cands)[i] = var;
4666 (*candscores)[i] = score;
4667 (*newbounds)[i] = newbound;
4668 (*proofactdeltas)[i] = QUAD_TO_DBL(proofactdelta);
4669 (*ncands)++;
4670
4671 return SCIP_OKAY;
4672}
4673
4674/** undoes bound changes on variables, still leaving the given infeasibility proof valid */
4676 SCIP_SET* set, /**< global SCIP settings */
4677 SCIP_PROB* prob, /**< problem data */
4678 int currentdepth, /**< current depth in the tree */
4679 SCIP_Real* proofcoefs, /**< coefficients in infeasibility proof */
4680 SCIP_Real prooflhs, /**< left hand side of proof */
4681 SCIP_Real* proofact, /**< current activity of proof */
4682 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
4683 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
4684 int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
4685 int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
4686 SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
4687 SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
4688 SCIP_Bool* resolve, /**< pointer to store whether the changed LP should be resolved again, or NULL */
4689 SCIP_LPI* lpi /**< pointer to LPi to access infinity of LP solver; necessary to set correct values */
4690 )
4691{
4692 SCIP_VAR** vars;
4693 SCIP_VAR** cands;
4694 SCIP_Real* candscores;
4695 SCIP_Real* newbounds;
4696 SCIP_Real* proofactdeltas;
4697 int nvars;
4698 int ncands;
4699 int candssize;
4700 int v;
4701 int i;
4702
4703 assert(prob != NULL);
4704 assert(proofcoefs != NULL);
4705 assert(SCIPsetIsFeasGT(set, prooflhs, (*proofact)));
4706 assert(curvarlbs != NULL);
4707 assert(curvarubs != NULL);
4708 assert(lbchginfoposs != NULL);
4709 assert(ubchginfoposs != NULL);
4710
4711 if( resolve != NULL )
4712 *resolve = FALSE;
4713
4714 vars = prob->vars;
4715 nvars = prob->nvars;
4716 assert(nvars == 0 || vars != NULL);
4717
4718 /* calculate the order in which the bound changes are tried to be undone, and relax all bounds if this doesn't
4719 * increase the proof's activity
4720 */
4722 SCIP_CALL( SCIPsetAllocBufferArray(set, &candscores, nvars) );
4723 SCIP_CALL( SCIPsetAllocBufferArray(set, &newbounds, nvars) );
4724 SCIP_CALL( SCIPsetAllocBufferArray(set, &proofactdeltas, nvars) );
4725 ncands = 0;
4726 candssize = nvars;
4727 for( v = 0; v < nvars; ++v )
4728 {
4729 SCIP_VAR* var;
4730 SCIP_Bool relaxed;
4731
4732 var = vars[v];
4733
4734 /* after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
4735 * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
4736 * global bound and we can ignore it
4737 */
4738 skipRedundantBdchginfos(var, &lbchginfoposs[v], &ubchginfoposs[v]);
4739
4740 /* ignore variables already relaxed to global bounds */
4741 if( (lbchginfoposs[v] == -1 && ubchginfoposs[v] == -1) )
4742 {
4743 proofcoefs[v] = 0.0;
4744 continue;
4745 }
4746
4747 /* relax bounds that are not used in the proof to the global bounds */
4748 relaxed = FALSE;
4749 if( !SCIPsetIsNegative(set, proofcoefs[v]) )
4750 {
4751 /* the lower bound is not used */
4752 if( lbchginfoposs[v] >= 0 )
4753 {
4754 SCIPsetDebugMsg(set, " -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g\n",
4755 SCIPvarGetName(var), curvarlbs[v], curvarubs[v], SCIPvarGetLbGlobal(var), curvarubs[v],
4756 proofcoefs[v], prooflhs, (*proofact));
4757 curvarlbs[v] = SCIPvarGetLbGlobal(var);
4758 lbchginfoposs[v] = -1;
4759 relaxed = TRUE;
4760 }
4761 }
4762 if( !SCIPsetIsPositive(set, proofcoefs[v]) )
4763 {
4764 /* the upper bound is not used */
4765 if( ubchginfoposs[v] >= 0 )
4766 {
4767 SCIPsetDebugMsg(set, " -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g\n",
4768 SCIPvarGetName(var), curvarlbs[v], curvarubs[v], curvarlbs[v], SCIPvarGetUbGlobal(var),
4769 proofcoefs[v], prooflhs, (*proofact));
4770 curvarubs[v] = SCIPvarGetUbGlobal(var);
4771 ubchginfoposs[v] = -1;
4772 relaxed = TRUE;
4773 }
4774 }
4775 if( relaxed && oldlpbdchgs != NULL )
4776 {
4777 SCIP_CALL( addBdchg(set, var, curvarlbs[v], curvarubs[v], oldlpbdchgs, relaxedlpbdchgs, lpi) );
4778 }
4779
4780 /* add bound to candidate list */
4781 if( lbchginfoposs[v] >= 0 || ubchginfoposs[v] >= 0 )
4782 {
4783 SCIP_CALL( addCand(set, currentdepth, var, lbchginfoposs[v], ubchginfoposs[v], proofcoefs[v],
4784 prooflhs, (*proofact), &cands, &candscores, &newbounds, &proofactdeltas, &candssize, &ncands, 0) );
4785 }
4786 /* we can set the proof coefficient to zero, because the variable is not needed */
4787 else
4788 proofcoefs[v] = 0.0;
4789 }
4790
4791 /* try to undo remaining local bound changes while still keeping the proof row violated:
4792 * bound changes can be undone, if prooflhs > proofact + proofactdelta;
4793 * afterwards, the current proof activity has to be updated
4794 */
4795 for( i = 0; i < ncands; ++i )
4796 {
4797 assert(proofactdeltas[i] > 0.0);
4798 assert((lbchginfoposs[SCIPvarGetProbindex(cands[i])] >= 0) != (ubchginfoposs[SCIPvarGetProbindex(cands[i])] >= 0));
4799
4800 /* when relaxing a constraint we still need to stay infeasible; therefore we need to do the comparison in
4801 * feasibility tolerance because if 'prooflhs' is (feas-))equal to 'proofact + proofactdeltas[i]' it would mean
4802 * that there is no violation
4803 */
4804 if( SCIPsetIsFeasGT(set, prooflhs, (*proofact) + proofactdeltas[i]) )
4805 {
4806 v = SCIPvarGetProbindex(cands[i]);
4807 assert(0 <= v && v < nvars);
4808 assert((lbchginfoposs[v] >= 0) != (ubchginfoposs[v] >= 0));
4809
4810 SCIPsetDebugMsg(set, " -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g + %g\n",
4811 SCIPvarGetName(cands[i]), curvarlbs[v], curvarubs[v],
4812 proofcoefs[v] > 0.0 ? curvarlbs[v] : newbounds[i],
4813 proofcoefs[v] > 0.0 ? newbounds[i] : curvarubs[v],
4814 proofcoefs[v], prooflhs, (*proofact), proofactdeltas[i]);
4815
4816#ifndef NDEBUG
4817 {
4818 SCIP_Real QUAD(verifylb);
4819 SCIP_Real QUAD(verifyub);
4820
4821 SCIPquadprecSumDD(verifylb, newbounds[i], -curvarlbs[v]);
4822 SCIPquadprecProdQD(verifylb, verifylb, proofcoefs[v]);
4823
4824 SCIPquadprecSumDD(verifyub, newbounds[i], -curvarubs[v]);
4825 SCIPquadprecProdQD(verifyub, verifyub, proofcoefs[v]);
4826
4827 assert((SCIPsetIsPositive(set, proofcoefs[v]) && SCIPsetIsGT(set, newbounds[i], curvarubs[v]))
4828 || (SCIPsetIsNegative(set, proofcoefs[v]) && SCIPsetIsLT(set, newbounds[i], curvarlbs[v])));
4829 assert((SCIPsetIsPositive(set, proofcoefs[v])
4830 && SCIPsetIsEQ(set, proofactdeltas[i], QUAD_TO_DBL(verifyub)))
4831 || (SCIPsetIsNegative(set, proofcoefs[v])
4832 && SCIPsetIsEQ(set, proofactdeltas[i], QUAD_TO_DBL(verifylb))));
4833 assert(!SCIPsetIsZero(set, proofcoefs[v]));
4834 }
4835#endif
4836
4837 if( proofcoefs[v] > 0.0 )
4838 {
4839 assert(ubchginfoposs[v] >= 0);
4840 assert(lbchginfoposs[v] == -1);
4841 curvarubs[v] = newbounds[i];
4842 ubchginfoposs[v]--;
4843 }
4844 else
4845 {
4846 assert(lbchginfoposs[v] >= 0);
4847 assert(ubchginfoposs[v] == -1);
4848 curvarlbs[v] = newbounds[i];
4849 lbchginfoposs[v]--;
4850 }
4851 if( oldlpbdchgs != NULL )
4852 {
4853 SCIP_CALL( addBdchg(set, cands[i], curvarlbs[v], curvarubs[v], oldlpbdchgs, relaxedlpbdchgs, lpi) );
4854 }
4855 (*proofact) += proofactdeltas[i];
4856 if( resolve != NULL && SCIPvarIsInLP(cands[i]) )
4857 *resolve = TRUE;
4858
4859 /* after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
4860 * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
4861 * global bound and we can ignore it
4862 */
4863 skipRedundantBdchginfos(cands[i], &lbchginfoposs[v], &ubchginfoposs[v]);
4864
4865 /* insert the new local bound of the variable into the candidate list */
4866 if( lbchginfoposs[v] >= 0 || ubchginfoposs[v] >= 0 )
4867 {
4868 SCIP_CALL( addCand(set, currentdepth, cands[i], lbchginfoposs[v], ubchginfoposs[v], proofcoefs[v],
4869 prooflhs, (*proofact), &cands, &candscores, &newbounds, &proofactdeltas, &candssize, &ncands, i+1) );
4870 }
4871 else
4872 proofcoefs[v] = 0.0;
4873 }
4874 }
4875
4876 /* free the buffer for the sorted bound change candidates */
4877 SCIPsetFreeBufferArray(set, &proofactdeltas);
4878 SCIPsetFreeBufferArray(set, &newbounds);
4879 SCIPsetFreeBufferArray(set, &candscores);
4880 SCIPsetFreeBufferArray(set, &cands);
4881
4882 return SCIP_OKAY;
4883}
4884
4885/** analyzes an infeasible LP and undoes additional bound changes while staying infeasible */
4886static
4888 SCIP_SET* set, /**< global SCIP settings */
4889 SCIP_PROB* prob, /**< problem data */
4890 SCIP_LP* lp, /**< LP data */
4891 int currentdepth, /**< current depth in the tree */
4892 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
4893 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
4894 int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
4895 int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
4896 SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
4897 SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
4898 SCIP_Bool* valid, /**< pointer to store whether the unfixings are valid */
4899 SCIP_Bool* resolve, /**< pointer to store whether the changed LP should be resolved again */
4900 SCIP_Real* farkascoefs, /**< coefficients in the proof constraint */
4901 SCIP_Real farkaslhs, /**< lhs of the proof constraint */
4902 SCIP_Real* farkasactivity /**< maximal activity of the proof constraint */
4903 )
4904{
4905 SCIP_LPI* lpi;
4906
4907 assert(prob != NULL);
4908 assert(lp != NULL);
4909 assert(lp->flushed);
4910 assert(lp->solved);
4911 assert(curvarlbs != NULL);
4912 assert(curvarubs != NULL);
4913 assert(lbchginfoposs != NULL);
4914 assert(ubchginfoposs != NULL);
4915 assert(valid != NULL);
4916 assert(resolve != NULL);
4917
4918 SCIPsetDebugMsg(set, "undoing bound changes in infeasible LP: cutoff=%g\n", lp->cutoffbound);
4919
4920 *valid = FALSE;
4921 *resolve = FALSE;
4922
4923 lpi = SCIPlpGetLPI(lp);
4924
4925 /* check, if the Farkas row is still violated (using current bounds and ignoring local rows) */
4926 if( SCIPsetIsFeasGT(set, farkaslhs, *farkasactivity) )
4927 {
4928 /* undo bound changes while keeping the infeasibility proof valid */
4929 SCIP_CALL( SCIPundoBdchgsProof(set, prob, currentdepth, farkascoefs, farkaslhs, farkasactivity, \
4930 curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, resolve, lpi) );
4931
4932 *valid = TRUE;
4933
4934 /* resolving does not make sense: the old dual ray is still valid -> resolving will not change the solution */
4935 *resolve = FALSE;
4936 }
4937
4938 return SCIP_OKAY;
4939}
4940
4941
4942/*
4943 * Conflict LP Bound Changes
4944 */
4945
4946/** create conflict LP bound change data structure */
4947static
4949 SCIP_LPBDCHGS** lpbdchgs, /**< pointer to store the conflict LP bound change data structure */
4950 SCIP_SET* set, /**< global SCIP settings */
4951 int ncols /**< number of columns */
4952 )
4953{
4954 SCIP_CALL( SCIPsetAllocBuffer(set, lpbdchgs) );
4955
4956 SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchginds, ncols) );
4957 SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchglbs, ncols) );
4958 SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchgubs, ncols) );
4959 SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchgcolinds, ncols) );
4960 SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->usedcols, ncols) );
4961 BMSclearMemoryArray((*lpbdchgs)->usedcols, ncols);
4962
4963 (*lpbdchgs)->nbdchgs = 0;
4964
4965 return SCIP_OKAY;
4966}
4967
4968
4969/*
4970 * Propagation Conflict Analysis
4971 */
4972
4973/** ensures, that side change arrays can store at least num entries */
4974static
4976 SCIP_SET* set, /**< global SCIP settings */
4977 int** sidechginds, /**< pointer to side change index array */
4978 SCIP_Real** sidechgoldlhss, /**< pointer to side change old left hand sides array */
4979 SCIP_Real** sidechgoldrhss, /**< pointer to side change old right hand sides array */
4980 SCIP_Real** sidechgnewlhss, /**< pointer to side change new left hand sides array */
4981 SCIP_Real** sidechgnewrhss, /**< pointer to side change new right hand sides array */
4982 int* sidechgssize, /**< pointer to size of side change arrays */
4983 int num /**< minimal number of entries to be able to store in side change arrays */
4984 )
4985{
4986 assert(sidechginds != NULL);
4987 assert(sidechgoldlhss != NULL);
4988 assert(sidechgoldrhss != NULL);
4989 assert(sidechgnewlhss != NULL);
4990 assert(sidechgnewrhss != NULL);
4991 assert(sidechgssize != NULL);
4992
4993 if( num > *sidechgssize )
4994 {
4995 int newsize;
4996
4997 newsize = SCIPsetCalcMemGrowSize(set, num);
4998 SCIP_CALL( SCIPsetReallocBufferArray(set, sidechginds, newsize) );
4999 SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgoldlhss, newsize) );
5000 SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgoldrhss, newsize) );
5001 SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgnewlhss, newsize) );
5002 SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgnewrhss, newsize) );
5003 *sidechgssize = newsize;
5004 }
5005 assert(num <= *sidechgssize);
5006
5007 return SCIP_OKAY;
5008}
5009
5010/** adds removal of row's side to side change arrays; finite sides are only replaced by near infinite sides, such
5011 * that the row's sense in the LP solver is not changed
5012 */
5013static
5015 SCIP_SET* set, /**< global SCIP settings */
5016 SCIP_ROW* row, /**< LP row to change the sides for */
5017 SCIP_Real lpiinfinity, /**< value treated as infinity in LP solver */
5018 int** sidechginds, /**< pointer to side change index array */
5019 SCIP_Real** sidechgoldlhss, /**< pointer to side change old left hand sides array */
5020 SCIP_Real** sidechgoldrhss, /**< pointer to side change old right hand sides array */
5021 SCIP_Real** sidechgnewlhss, /**< pointer to side change new left hand sides array */
5022 SCIP_Real** sidechgnewrhss, /**< pointer to side change new right hand sides array */
5023 int* sidechgssize, /**< pointer to size of side change arrays */
5024 int* nsidechgs /**< pointer to number of used slots in side change arrays */
5025 )
5026{
5027 SCIP_Real lhs;
5028 SCIP_Real rhs;
5029 SCIP_Real constant;
5030
5031 assert(sidechginds != NULL);
5032 assert(sidechgoldlhss != NULL);
5033 assert(sidechgoldrhss != NULL);
5034 assert(sidechgnewlhss != NULL);
5035 assert(sidechgnewrhss != NULL);
5036 assert(sidechgssize != NULL);
5037 assert(nsidechgs != NULL);
5038
5039 lhs = SCIProwGetLhs(row);
5040 rhs = SCIProwGetRhs(row);
5041 constant = SCIProwGetConstant(row);
5043
5044 /* get memory to store additional side change */
5045 SCIP_CALL( ensureSidechgsSize(set, sidechginds, sidechgoldlhss, sidechgoldrhss, sidechgnewlhss, sidechgnewrhss, \
5046 sidechgssize, (*nsidechgs)+1) );
5047 assert(*nsidechgs < *sidechgssize);
5048 assert(*sidechginds != NULL);
5049 assert(*sidechgoldlhss != NULL);
5050 assert(*sidechgoldrhss != NULL);
5051 assert(*sidechgnewlhss != NULL);
5052 assert(*sidechgnewrhss != NULL);
5053
5054 /* store side change */
5055 (*sidechginds)[*nsidechgs] = SCIProwGetLPPos(row);
5056 if( SCIPsetIsInfinity(set, -lhs) )
5057 {
5058 (*sidechgoldlhss)[*nsidechgs] = -lpiinfinity;
5059 (*sidechgnewlhss)[*nsidechgs] = -lpiinfinity;
5060 }
5061 else
5062 {
5063 (*sidechgoldlhss)[*nsidechgs] = lhs - constant;
5064 (*sidechgnewlhss)[*nsidechgs] = -lpiinfinity;
5065 }
5066 if( SCIPsetIsInfinity(set, rhs) )
5067 {
5068 (*sidechgoldrhss)[*nsidechgs] = lpiinfinity;
5069 (*sidechgnewrhss)[*nsidechgs] = lpiinfinity;
5070 }
5071 else
5072 {
5073 (*sidechgoldrhss)[*nsidechgs] = rhs - constant;
5074 (*sidechgnewrhss)[*nsidechgs] = lpiinfinity;
5075 }
5076 (*nsidechgs)++;
5077
5078 return SCIP_OKAY;
5079}
5080
5081
5082/*
5083 * Infeasible LP Conflict Analysis
5084 */
5085
5086/** reset conflict LP bound change data structure */
5087static
5089 SCIP_LPBDCHGS* lpbdchgs, /**< conflict LP bound change data structure */
5090 int ncols /**< number of columns */
5091 )
5092{
5093 assert(lpbdchgs != NULL);
5094
5095 BMSclearMemoryArray(lpbdchgs->usedcols, ncols);
5096 lpbdchgs->nbdchgs = 0;
5097}
5098
5099/** free conflict LP bound change data structure */
5100static
5102 SCIP_LPBDCHGS** lpbdchgs, /**< pointer to store the conflict LP bound change data structure */
5103 SCIP_SET* set /**< global SCIP settings */
5104 )
5105{
5106 SCIPsetFreeBufferArray(set, &(*lpbdchgs)->usedcols);
5107 SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchgcolinds);
5108 SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchgubs);
5109 SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchglbs);
5110 SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchginds);
5111
5112 SCIPsetFreeBuffer(set, lpbdchgs);
5113}
5114
5115/** analyzes an LP exceeding the objective limit and undoes additional bound changes while staying beyond the
5116 * objective limit
5117 */
5118static
5120 SCIP_SET* set, /**< global SCIP settings */
5121 SCIP_PROB* prob, /**< problem data */
5122 SCIP_LP* lp, /**< LP data */
5123 int currentdepth, /**< current depth in the tree */
5124 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
5125 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
5126 int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
5127 int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
5128 SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
5129 SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
5130 SCIP_Bool* valid, /**< pointer to store whether the unfixings are valid */
5131 SCIP_Bool* resolve, /**< pointer to store whether the changed LP should be resolved again */
5132 SCIP_Real* dualcoefs, /**< coefficients in the proof constraint */
5133 SCIP_Real duallhs, /**< lhs of the proof constraint */
5134 SCIP_Real* dualactivity /**< maximal activity of the proof constraint */
5135 )
5136{
5137 SCIP_LPI* lpi;
5138
5139 assert(set != NULL);
5140 assert(prob != NULL);
5141 assert(lp != NULL);
5142 assert(lp->flushed);
5143 assert(lp->solved);
5144 assert(curvarlbs != NULL);
5145 assert(curvarubs != NULL);
5146 assert(lbchginfoposs != NULL);
5147 assert(ubchginfoposs != NULL);
5148 assert(valid != NULL);
5149 assert(resolve != NULL);
5150
5151 *valid = FALSE;
5152 *resolve = FALSE;
5153
5154 SCIPsetDebugMsg(set, "undoing bound changes in LP exceeding cutoff: cutoff=%g\n", lp->cutoffbound);
5155
5156 /* get LP solver interface */
5157 lpi = SCIPlpGetLPI(lp);
5158
5159 /* check, if the dual row is still violated (using current bounds and ignoring local rows) */
5160 if( SCIPsetIsFeasGT(set, duallhs, *dualactivity) )
5161 {
5162 /* undo bound changes while keeping the infeasibility proof valid */
5163 SCIP_CALL( SCIPundoBdchgsProof(set, prob, currentdepth, dualcoefs, duallhs, dualactivity, curvarlbs, curvarubs, \
5164 lbchginfoposs, ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, resolve, lpi) );
5165
5166 *valid = TRUE;
5167 }
5168
5169 return SCIP_OKAY;
5170}
5171
5172/** try to find a subset of changed bounds leading to an infeasible LP
5173 *
5174 * 1. call undoBdchgsDualfarkas() or undoBdchgsDualsol()
5175 * -> update lb/ubchginfoposs arrays
5176 * -> store additional changes in bdchg and curvarlbs/ubs arrays
5177 * -> apply additional changes to the LPI
5178 * 2. (optional) if additional bound changes were undone:
5179 * -> resolve LP
5180 * -> goto 1.
5181 * 3. redo all bound changes in the LPI to restore the LPI to its original state
5182 * 4. analyze conflict
5183 * -> put remaining changed bounds (see lb/ubchginfoposs arrays) into starting conflict set
5184 */
5186 SCIP_CONFLICT* conflict, /**< conflict data */
5187 SCIP_SET* set, /**< global SCIP settings */
5188 SCIP_STAT* stat, /**< problem statistics */
5189 SCIP_PROB* origprob, /**< original problem */
5190 SCIP_PROB* transprob, /**< transformed problem */
5191 SCIP_TREE* tree, /**< branch and bound tree */
5192 SCIP_REOPT* reopt, /**< reoptimization data */
5193 SCIP_LP* lp, /**< LP data */
5194 SCIP_LPI* lpi, /**< LPI data */
5195 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
5196 BMS_BLKMEM* blkmem, /**< block memory */
5197 SCIP_Real* proofcoefs, /**< coefficients in the proof constraint */
5198 SCIP_Real* prooflhs, /**< lhs of the proof constraint */
5199 SCIP_Real* proofactivity, /**< maximal activity of the proof constraint */
5200 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
5201 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
5202 int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
5203 int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
5204 int* iterations, /**< pointer to store the total number of LP iterations used */
5205 SCIP_Bool marklpunsolved, /**< whether LP should be marked unsolved after analysis (needed for strong branching) */
5206 SCIP_Bool* dualproofsuccess, /**< pointer to store success result of dual proof analysis */
5207 SCIP_Bool* valid /**< pointer to store whether the result is still a valid proof */
5208 )
5209{
5210 SCIP_LPBDCHGS* oldlpbdchgs;
5211 SCIP_LPBDCHGS* relaxedlpbdchgs;
5212 SCIP_Bool solvelp;
5213 SCIP_Bool resolve;
5214 int ncols;
5215
5216 assert(set != NULL);
5217
5218 /* get number of columns in the LP */
5219 ncols = SCIPlpGetNCols(lp);
5220
5221 /* get temporary memory for remembering bound changes on LPI columns */
5222 SCIP_CALL( lpbdchgsCreate(&oldlpbdchgs, set, ncols) );
5223 SCIP_CALL( lpbdchgsCreate(&relaxedlpbdchgs, set, ncols) );
5224
5225 /* undo as many bound changes as possible with the current LP solution */
5226 resolve = FALSE;
5227 if( (*valid) )
5228 {
5229 int currentdepth;
5230 currentdepth = SCIPtreeGetCurrentDepth(tree);
5231
5232 if( SCIPlpiIsPrimalInfeasible(lpi) )
5233 {
5234 SCIP_CALL( undoBdchgsDualfarkas(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, \
5235 ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, *prooflhs, proofactivity) );
5236 }
5237 else
5238 {
5240 SCIP_CALL( undoBdchgsDualsol(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs, \
5241 oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, *prooflhs, proofactivity) );
5242 }
5243 }
5244
5245 /* check if we want to solve the LP */
5246 assert(SCIPprobAllColsInLP(transprob, set, lp));
5247 solvelp = (set->conf_maxlploops != 0 && set->conf_lpiterations != 0);
5248
5249 if( (*valid) && resolve && solvelp )
5250 {
5251 SCIP_RETCODE retcode;
5252 SCIP_ROW** rows;
5253 int* sidechginds;
5254 SCIP_Real* sidechgoldlhss;
5255 SCIP_Real* sidechgoldrhss;
5256 SCIP_Real* sidechgnewlhss;
5257 SCIP_Real* sidechgnewrhss;
5258 SCIP_Real lpiinfinity;
5259 SCIP_Bool globalinfeasible;
5260 int maxlploops;
5261 int lpiterations;
5262 int sidechgssize;
5263 int nsidechgs;
5264 int nrows;
5265 int nloops;
5266 int r;
5267
5268 /* get infinity value of LP solver */
5269 lpiinfinity = SCIPlpiInfinity(lpi);
5270
5271 /* temporarily disable objective limit and install an iteration limit */
5272 maxlploops = (set->conf_maxlploops >= 0 ? set->conf_maxlploops : INT_MAX);
5273 lpiterations = (set->conf_lpiterations >= 0 ? set->conf_lpiterations : INT_MAX);
5274 SCIP_CALL( SCIPlpiSetRealpar(lpi, SCIP_LPPAR_OBJLIM, lpiinfinity) );
5275 SCIP_CALL( SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, lpiterations) );
5276
5277 /* get LP rows */
5278 rows = SCIPlpGetRows(lp);
5279 nrows = SCIPlpGetNRows(lp);
5280 assert(nrows == 0 || rows != NULL);
5281
5282 /* get temporary memory for remembering side changes on LPI rows */
5283 SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechginds, nrows) );
5284 SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgoldlhss, nrows) );
5285 SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgoldrhss, nrows) );
5286 SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgnewlhss, nrows) );
5287 SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgnewrhss, nrows) );
5288 sidechgssize = nrows;
5289 nsidechgs = 0;
5290
5291 /* remove all local rows by setting their sides to infinity;
5292 * finite sides are only changed to near infinity, such that the row's sense in the LP solver
5293 * is not affected (e.g. CPLEX cannot handle free rows)
5294 */
5295 for( r = 0; r < nrows; ++r )
5296 {
5297 assert(SCIProwGetLPPos(rows[r]) == r);
5298
5299 if( SCIProwIsLocal(rows[r]) )
5300 {
5301 SCIPsetDebugMsg(set, " -> removing local row <%s> [%g,%g]\n",
5302 SCIProwGetName(rows[r]), SCIProwGetLhs(rows[r]), SCIProwGetRhs(rows[r]));
5303 SCIP_CALL( addSideRemoval(set, rows[r], lpiinfinity, &sidechginds, &sidechgoldlhss, &sidechgoldrhss,
5304 &sidechgnewlhss, &sidechgnewrhss, &sidechgssize, &nsidechgs) );
5305 }
5306 }
5307
5308 /* apply changes of local rows to the LP solver */
5309 if( nsidechgs > 0 )
5310 {
5311 SCIP_CALL( SCIPlpiChgSides(lpi, nsidechgs, sidechginds, sidechgnewlhss, sidechgnewrhss) );
5312 }
5313
5314 /* undo as many additional bound changes as possible by resolving the LP */
5315 assert((*valid));
5316 assert(resolve);
5317 nloops = 0;
5318 globalinfeasible = FALSE;
5319 while( (*valid) && resolve && nloops < maxlploops )
5320 {
5321 int iter;
5322
5323 assert(!globalinfeasible);
5324
5325 nloops++;
5326 resolve = FALSE;
5327
5328 SCIPsetDebugMsg(set, "infeasible LP conflict analysis loop %d (changed col bounds: %d)\n", nloops, relaxedlpbdchgs->nbdchgs);
5329
5330 /* apply bound changes to the LP solver */
5331 assert(relaxedlpbdchgs->nbdchgs >= 0);
5332 if( relaxedlpbdchgs->nbdchgs > 0 )
5333 {
5334 SCIPsetDebugMsg(set, " -> applying %d bound changes to the LP solver\n", relaxedlpbdchgs->nbdchgs);
5335 SCIP_CALL( SCIPlpiChgBounds(lpi, relaxedlpbdchgs->nbdchgs, relaxedlpbdchgs->bdchginds, \
5336 relaxedlpbdchgs->bdchglbs, relaxedlpbdchgs->bdchgubs) );
5337
5338 /* reset conflict LP bound change data structure */
5339 lpbdchgsReset(relaxedlpbdchgs, ncols);
5340 }
5341
5342 /* start LP timer */
5344
5345 /* resolve LP */
5346 retcode = SCIPlpiSolveDual(lpi);
5347
5348 /* stop LP timer */
5350
5351 /* check return code of LP solving call */
5352 if( retcode == SCIP_LPERROR )
5353 {
5354 (*valid) = FALSE;
5355 break;
5356 }
5357 SCIP_CALL( retcode );
5358
5359 /* count number of LP iterations */
5360 SCIP_CALL( SCIPlpiGetIterations(lpi, &iter) );
5361 (*iterations) += iter;
5362 stat->nconflictlps++;
5363 stat->nconflictlpiterations += iter;
5364 SCIPsetDebugMsg(set, " -> resolved LP in %d iterations (total: %" SCIP_LONGINT_FORMAT ") (infeasible:%u)\n",
5366
5367 /* evaluate result */
5368 if( SCIPlpiIsDualFeasible(lpi) || SCIPlpiIsObjlimExc(lpi) )
5369 {
5371
5373 (*valid) = (objval >= lp->lpiobjlim && !SCIPlpDivingObjChanged(lp));
5374 }
5375 else
5377
5378 if( (*valid) )
5379 {
5380 int currentdepth;
5381 currentdepth = SCIPtreeGetCurrentDepth(tree);
5382
5383 /* undo additional bound changes */
5384 if( SCIPlpiIsPrimalInfeasible(lpi) )
5385 {
5386 SCIP_AGGRROW* farkasrow;
5387 int* inds;
5388 int validdepth;
5389 int nnz;
5390 int v;
5391
5392#ifndef NDEBUG
5393 SCIP_VAR** vars = SCIPprobGetVars(transprob);
5394#endif
5395
5396 SCIP_CALL( SCIPaggrRowCreate(set->scip, &farkasrow) );
5397
5398 /* the original LP exceeds the current cutoff bound, thus, we have not constructed the Farkas proof */
5399 SCIP_CALL( SCIPgetFarkasProof(set, transprob, lp, lpi, tree, farkasrow, proofactivity, &validdepth,
5400 curvarlbs, curvarubs, valid) );
5401
5402 /* the constructed Farkas proof is not valid, we need to break here */
5403 if( !(*valid) )
5404 {
5405 SCIPaggrRowFree(set->scip, &farkasrow);
5406 break;
5407 }
5408
5409 /* start dual proof analysis */
5410 if( set->conf_useinflp == 'd' || set->conf_useinflp == 'b' )
5411 {
5412 /* change the conflict type */
5413 SCIP_Bool oldusescutoff = conflict->conflictset->usescutoffbound;
5414 SCIP_CONFTYPE oldconftype = conflict->conflictset->conflicttype;
5415 conflict->conflictset->usescutoffbound = FALSE;
5417
5418 /* start dual proof analysis */
5419 SCIP_CALL( SCIPconflictAnalyzeDualProof(conflict, set, stat, eventfilter, blkmem, origprob, transprob, tree, reopt,
5420 lp, farkasrow, validdepth, curvarlbs, curvarubs, FALSE, &globalinfeasible, dualproofsuccess) );
5421
5422 conflict->conflictset->usescutoffbound = oldusescutoff;
5423 conflict->conflictset->conflicttype = oldconftype;
5424 }
5425
5426 /* todo: in theory, we could apply conflict graph analysis for locally valid proofs, too, but this needs to be implemented */
5427 if( globalinfeasible || validdepth > SCIPtreeGetEffectiveRootDepth(tree) )
5428 {
5429 SCIPaggrRowFree(set->scip, &farkasrow);
5430 goto TERMINATE;
5431 }
5432
5433 BMSclearMemoryArray(proofcoefs, SCIPprobGetNVars(transprob));
5434 (*prooflhs) = -SCIPaggrRowGetRhs(farkasrow);
5435 (*proofactivity) = -(*proofactivity);
5436
5437 inds = SCIPaggrRowGetInds(farkasrow);
5438 nnz = SCIPaggrRowGetNNz(farkasrow);
5439
5440 for( v = 0; v < nnz; v++ )
5441 {
5442 int i = inds[v];
5443
5444 assert(SCIPvarGetProbindex(vars[i]) == inds[v]);
5445
5446 proofcoefs[i] = -SCIPaggrRowGetProbvarValue(farkasrow, i);
5447 }
5448
5449 /* free aggregation rows */
5450 SCIPaggrRowFree(set->scip, &farkasrow);
5451
5452 SCIP_CALL( undoBdchgsDualfarkas(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, \
5453 ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, (*prooflhs), proofactivity) );
5454 }
5455 else
5456 {
5457 SCIP_AGGRROW* proofrow;
5458 int* inds;
5459 int validdepth;
5460 int nnz;
5461 int v;
5462
5463#ifndef NDEBUG
5464 SCIP_VAR** vars = SCIPprobGetVars(transprob);
5465#endif
5466
5468
5469 SCIP_CALL( SCIPaggrRowCreate(set->scip, &proofrow) );
5470
5471 SCIP_CALL( SCIPgetDualProof(set, transprob, lp, lpi, tree, proofrow, proofactivity, &validdepth,
5472 curvarlbs, curvarubs, valid) );
5473
5474 /* the constructed dual proof is not valid, we need to break here */
5475 if( !(*valid) || validdepth > SCIPtreeGetEffectiveRootDepth(tree) )
5476 {
5477 SCIPaggrRowFree(set->scip, &proofrow);
5478 break;
5479 }
5480 /* in contrast to the infeasible case we don't want to analyze the (probably identical) proof again. */
5481
5482 BMSclearMemoryArray(proofcoefs, SCIPprobGetNVars(transprob));
5483 (*prooflhs) = -SCIPaggrRowGetRhs(proofrow);
5484 (*proofactivity) = -(*proofactivity);
5485
5486 inds = SCIPaggrRowGetInds(proofrow);
5487 nnz = SCIPaggrRowGetNNz(proofrow);
5488
5489 for( v = 0; v < nnz; v++ )
5490 {
5491 int i = inds[v];
5492
5493 assert(SCIPvarGetProbindex(vars[i]) == inds[v]);
5494
5495 proofcoefs[i] = -SCIPaggrRowGetProbvarValue(proofrow, i);
5496 }
5497
5498 /* free aggregation rows */
5499 SCIPaggrRowFree(set->scip, &proofrow);
5500
5501 SCIP_CALL( undoBdchgsDualsol(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, \
5502 ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, *prooflhs, proofactivity) );
5503 }
5504 }
5505 assert(!resolve || (*valid));
5506 assert(!resolve || relaxedlpbdchgs->nbdchgs > 0);
5507 SCIPsetDebugMsg(set, " -> finished infeasible LP conflict analysis loop %d (iter: %d, nbdchgs: %d)\n",
5508 nloops, iter, relaxedlpbdchgs->nbdchgs);
5509 }
5510
5511 SCIPsetDebugMsg(set, "finished undoing bound changes after %d loops (valid=%u, nbdchgs: %d)\n",
5512 nloops, (*valid), oldlpbdchgs->nbdchgs);
5513
5514 TERMINATE:
5515 /* reset variables to local bounds */
5516 if( oldlpbdchgs->nbdchgs > 0 )
5517 {
5518 SCIP_CALL( SCIPlpiChgBounds(lpi, oldlpbdchgs->nbdchgs, oldlpbdchgs->bdchginds, oldlpbdchgs->bdchglbs, oldlpbdchgs->bdchgubs) );
5519 }
5520
5521 /* reset changes of local rows */
5522 if( nsidechgs > 0 )
5523 {
5524 SCIP_CALL( SCIPlpiChgSides(lpi, nsidechgs, sidechginds, sidechgoldlhss, sidechgoldrhss) );
5525 }
5526
5527 /* mark the LP unsolved */
5528 if( oldlpbdchgs->nbdchgs > 0 || nsidechgs > 0 )
5529 {
5530 /* The LPI data are out of sync with LP data. Thus, the LP should be marked
5531 * unsolved. However, for strong branching calls, the LP has to have status 'solved'; in
5532 * this case, marklpunsolved is FALSE and synchronization is performed later. */
5533 if( marklpunsolved )
5534 {
5535 lp->solved = FALSE;
5536 lp->primalfeasible = FALSE;
5537 lp->primalchecked = FALSE;
5538 lp->dualfeasible = FALSE;
5539 lp->dualchecked = FALSE;
5540 lp->lpobjval = SCIP_INVALID;
5542 }
5543 }
5544
5545 /* reinstall old objective and iteration limits in LP solver */
5548
5549 /* free temporary memory */
5550 SCIPsetFreeBufferArray(set, &sidechgnewrhss);
5551 SCIPsetFreeBufferArray(set, &sidechgnewlhss);
5552 SCIPsetFreeBufferArray(set, &sidechgoldrhss);
5553 SCIPsetFreeBufferArray(set, &sidechgoldlhss);
5554 SCIPsetFreeBufferArray(set, &sidechginds);
5555 }
5556
5557 /* free temporary memory */
5558 lpbdchgsFree(&relaxedlpbdchgs, set);
5559 lpbdchgsFree(&oldlpbdchgs, set);
5560
5561 return SCIP_OKAY;
5562}
5563
5564/** analyzes conflicting bound changes that were added with calls to SCIPconflictAddBound(), and on success, calls the
5565 * conflict handlers to create a conflict constraint out of the resulting conflict set;
5566 * updates statistics for propagation conflict analysis
5567 */
5569 SCIP_CONFLICT* conflict, /**< conflict analysis data */
5570 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5571 SCIP_SET* set, /**< global SCIP settings */
5572 SCIP_STAT* stat, /**< problem statistics */
5573 SCIP_PROB* prob, /**< problem data */
5574 SCIP_TREE* tree, /**< branch and bound tree */
5575 int validdepth, /**< minimal depth level at which the initial conflict set is valid */
5576 SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
5577 )
5578{
5579 int nconss;
5580 int nliterals;
5581 int nreconvconss;
5582 int nreconvliterals;
5583
5584 assert(conflict != NULL);
5585 assert(conflict->conflictset != NULL);
5586 assert(set != NULL);
5587 assert(prob != NULL);
5588
5589 if( success != NULL )
5590 *success = FALSE;
5591
5592 /* check if the conflict analysis is applicable */
5594 return SCIP_OKAY;
5595
5596 /* check, if the conflict set will get too large with high probability */
5597 if( conflict->conflictset->nbdchginfos + SCIPpqueueNElems(conflict->bdchgqueue)
5598 + SCIPpqueueNElems(conflict->forcedbdchgqueue) >= 2*conflictCalcMaxsize(set, prob) )
5599 return SCIP_OKAY;
5600
5601 SCIPsetDebugMsg(set, "analyzing conflict after infeasible propagation in depth %d\n", SCIPtreeGetCurrentDepth(tree));
5602
5603 /* start timing */
5605
5606 conflict->npropcalls++;
5607
5608 /* setting this to true adds bound changes only to the conflict graph bdchg queue */
5609 conflict->bdchgonlyconfqueue = TRUE;
5610
5611 /* analyze the conflict set, and create a conflict constraint on success */
5612 SCIP_CALL( conflictAnalyze(conflict, blkmem, set, stat, prob, tree, FALSE, validdepth, TRUE, &nconss, &nliterals, \
5613 &nreconvconss, &nreconvliterals) );
5614 conflict->npropsuccess += (nconss > 0 ? 1 : 0);
5615 conflict->npropconfconss += nconss;
5616 conflict->npropconfliterals += nliterals;
5617 conflict->npropreconvconss += nreconvconss;
5618 conflict->npropreconvliterals += nreconvliterals;
5619 conflict->bdchgonlyconfqueue = FALSE;
5620
5621 if( success != NULL )
5622 *success = (nconss > 0);
5623
5624 /* stop timing */
5625 SCIPclockStop(conflict->propanalyzetime, set);
5626
5627 return SCIP_OKAY;
5628}
static long bound
SCIP_VAR * h
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)
void SCIPconflicthdlrSetExitsol(SCIP_CONFLICTHDLR *conflicthdlr,)
static void conflictsetCalcConflictDepth(SCIP_CONFLICTSET *conflictset)
SCIP_RETCODE SCIPconflicthdlrExit(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set)
void SCIPconflicthdlrSetFree(SCIP_CONFLICTHDLR *conflicthdlr,)
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)
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)
void SCIPconflicthdlrSetCopy(SCIP_CONFLICTHDLR *conflicthdlr,)
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)
static SCIP_Real conflictsetCalcScore(SCIP_CONFLICTSET *conflictset, SCIP_SET *set)
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)
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)
void SCIPconflicthdlrSetExit(SCIP_CONFLICTHDLR *conflicthdlr,)
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)
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_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)
void SCIPconflicthdlrSetInit(SCIP_CONFLICTHDLR *conflicthdlr,)
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)
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)
void SCIPconflicthdlrSetInitsol(SCIP_CONFLICTHDLR *conflicthdlr,)
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:7497
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:255
#define SCIP_MAXSTRLEN
Definition def.h:276
#define SCIP_Longint
Definition def.h:148
#define SCIP_REAL_MAX
Definition def.h:165
#define SCIP_INVALID
Definition def.h:185
#define SCIP_Bool
Definition def.h:98
#define MIN(x, y)
Definition def.h:231
#define SCIP_ALLOC(x)
Definition def.h:373
#define SCIP_Real
Definition def.h:163
#define TRUE
Definition def.h:100
#define FALSE
Definition def.h:101
#define MAX(x, y)
Definition def.h:227
#define SCIP_LONGINT_FORMAT
Definition def.h:155
#define SCIPABORT()
Definition def.h:334
#define SCIP_REAL_MIN
Definition def.h:166
#define SCIP_CALL(x)
Definition def.h:362
#define SCIP_CALL_FINALLY(x, y)
Definition def.h:404
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,...)
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)
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:8476
SCIP_Bool SCIPconsIsGlobal(SCIP_CONS *cons)
Definition cons.c:8622
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8393
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:8523
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:24483
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition var.c:23684
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25058
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23643
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23479
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition var.c:24890
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24980
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23387
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4386
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24269
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25014
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23454
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24143
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24960
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25025
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23653
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25002
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24970
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:23663
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23268
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24930
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition var.c:24525
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24910
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23491
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25037
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:22742
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition var.c:23807
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition var.c:25083
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition var.c:23795
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24643
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24940
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24235
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24990
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25069
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition var.c:23601
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24121
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition var.c:24705
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:24950
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24920
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4328
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition var.c:24725
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition var.c:23819
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition var.c:23707
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
return SCIP_OKAY
int c
int maxdepth
int depth
SCIP_Real objval
int r
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
static SCIP_VAR ** vars
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:2856
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition prob.c:2865
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition prob.c:2910
SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
Definition prob.c:2822
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition prob.c:2800
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
unsigned int boundtype
Definition struct_var.h:130
SCIP_VAR * var
Definition struct_var.h:125
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
unsigned int depth
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
SCIP_HISTORY * glbhistory
SCIP_VISUAL * visual
SCIP_Real vsidsweight
SCIP_Longint lastconflictnode
SCIP_HISTORY * glbhistorycrun
SCIP_Longint nconflictlpiterations
Definition struct_stat.h:81
SCIP_CLOCK * conflictlptime
SCIP_NODE * root
SCIP_NODE ** path
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
int SCIPtreeGetFocusDepth(SCIP_TREE *tree)
Definition tree.c:9434
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:9559
int SCIPtreeGetEffectiveRootDepth(SCIP_TREE *tree)
Definition tree.c:9548
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition tree.c:9509
internal methods for branch and bound tree
struct SCIP_BranchCand SCIP_BRANCHCAND
Definition type_branch.h:55
@ SCIP_CLOCKTYPE_DEFAULT
Definition type_clock.h:43
struct SCIP_Conflicthdlr SCIP_CONFLICTHDLR
#define SCIP_DECL_CONFLICTEXIT(x)
#define SCIP_DECL_CONFLICTCOPY(x)
struct SCIP_ConflictSet SCIP_CONFLICTSET
struct SCIP_Conflict SCIP_CONFLICT
#define SCIP_DECL_CONFLICTEXEC(x)
#define SCIP_DECL_CONFLICTINITSOL(x)
#define SCIP_DECL_CONFLICTFREE(x)
struct SCIP_LPBdChgs SCIP_LPBDCHGS
@ SCIP_CONFTYPE_BNDEXCEEDING
@ SCIP_CONFTYPE_PROPAGATION
@ SCIP_CONFTYPE_INFEASLP
@ SCIP_CONFTYPE_UNKNOWN
#define SCIP_DECL_CONFLICTINIT(x)
enum SCIP_ConflictType SCIP_CONFTYPE
struct SCIP_ConflicthdlrData SCIP_CONFLICTHDLRDATA
#define SCIP_DECL_CONFLICTEXITSOL(x)
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
struct SCIP_AggrRow SCIP_AGGRROW
Definition type_cuts.h:37
struct SCIP_EventFilter SCIP_EVENTFILTER
Definition type_event.h:180
struct SCIP_EventQueue SCIP_EVENTQUEUE
Definition type_event.h:181
@ SCIP_BRANCHDIR_DOWNWARDS
@ SCIP_BRANCHDIR_UPWARDS
enum SCIP_BranchDir SCIP_BRANCHDIR
struct SCIP_CliqueTable SCIP_CLIQUETABLE
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
struct SCIP_Lp SCIP_LP
Definition type_lp.h:111
@ SCIP_BOUNDTYPE_UPPER
Definition type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition type_lp.h:57
struct SCIP_Col SCIP_COL
Definition type_lp.h:99
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition type_lp.h:60
@ SCIP_LPSOLSTAT_NOTSOLVED
Definition type_lp.h:43
struct SCIP_LPi SCIP_LPI
Definition type_lpi.h:106
@ SCIP_LPPAR_LPITLIM
Definition type_lpi.h:60
@ SCIP_LPPAR_OBJLIM
Definition type_lpi.h:59
struct SCIP_Messagehdlr SCIP_MESSAGEHDLR
#define SCIP_DECL_SORTPTRCOMP(x)
Definition type_misc.h:189
struct SCIP_ParamData SCIP_PARAMDATA
#define SCIP_DECL_PARAMCHGD(x)
struct SCIP_Prob SCIP_PROB
Definition type_prob.h:52
struct SCIP_Prop SCIP_PROP
Definition type_prop.h:51
struct SCIP_Reopt SCIP_REOPT
Definition type_reopt.h:39
@ 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
@ SCIP_INVALIDRESULT
@ SCIP_INVALIDDATA
@ SCIP_WRITEERROR
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct SCIP_Set SCIP_SET
Definition type_set.h:71
struct SCIP_Stat SCIP_STAT
Definition type_stat.h:66
struct SCIP_Node SCIP_NODE
Definition type_tree.h:63
struct SCIP_Tree SCIP_TREE
Definition type_tree.h:65
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
struct SCIP_BdChgIdx SCIP_BDCHGIDX
Definition type_var.h:151
@ 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
struct SCIP_BdChgInfo SCIP_BDCHGINFO
Definition type_var.h:152
@ 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:22616
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:21104
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:21240
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition var.c:9911
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:18569
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition var.c:21190
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:18639
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition var.c:24850
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition var.c:22586
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:18076
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition var.c:9962
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25049
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)