Scippy

SCIP

Solving Constraint Integer Programs

conflict.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-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file conflict.c
17  * @brief methods and datastructures for conflict analysis
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Stefan Heinz
21  * @author Marc Pfetsch
22  * @author Michael Winkler
23  *
24  * This file implements a conflict analysis method like the one used in modern
25  * SAT solvers like zchaff. The algorithm works as follows:
26  *
27  * Given is a set of bound changes that are not allowed being applied simultaneously, because they
28  * render the current node infeasible (e.g. because a single constraint is infeasible in the these
29  * bounds, or because the LP relaxation is infeasible). The goal is to deduce a clause on variables
30  * -- a conflict clause -- representing the "reason" for this conflict, i.e., the branching decisions
31  * or the deductions (applied e.g. in domain propagation) that lead to the conflict. This clause can
32  * then be added to the constraint set to help cutting off similar parts of the branch and bound
33  * tree, that would lead to the same conflict. A conflict clause can also be generated, if the
34  * conflict was detected by a locally valid constraint. In this case, the resulting conflict clause
35  * is also locally valid in the same depth as the conflict detecting constraint. If all involved
36  * variables are binary, a linear (set covering) constraint can be generated, otherwise a bound
37  * disjunction constraint is generated. Details are given in
38  *
39  * Tobias Achterberg, Conflict Analysis in Mixed Integer Programming@n
40  * Discrete Optimization, 4, 4-20 (2007)
41  *
42  * See also @ref CONF. Here is an outline of the algorithm:
43  *
44  * -# Put all the given bound changes to a priority queue, which is ordered,
45  * such that the bound change that was applied last due to branching or deduction
46  * is at the top of the queue. The variables in the queue are always active
47  * problem variables. Because binary variables are preferred over general integer
48  * variables, integer variables are put on the priority queue prior to the binary
49  * variables. Create an empty conflict set.
50  * -# Remove the top bound change b from the priority queue.
51  * -# Perform the following case distinction:
52  * -# If the remaining queue is non-empty, and bound change b' (the one that is now
53  * on the top of the queue) was applied at the same depth level as b, and if
54  * b was a deduction with known inference reason, and if the inference constraint's
55  * valid depth is smaller or equal to the conflict detecting constraint's valid
56  * depth:
57  * - Resolve bound change b by asking the constraint that inferred the
58  * bound change to put all the bound changes on the priority queue, that
59  * lead to the deduction of b.
60  * Note that these bound changes have at most the same inference depth
61  * level as b, and were deduced earlier than b.
62  * -# Otherwise, the bound change b was a branching decision or a deduction with
63  * missing inference reason, or the inference constraint's validity is more local
64  * than the one of the conflict detecting constraint.
65  * - If a the bound changed corresponds to a binary variable, add it or its
66  * negation to the conflict set, depending on which of them is currently fixed to
67  * FALSE (i.e., the conflict set consists of literals that cannot be FALSE
68  * altogether at the same time).
69  * - Otherwise put the bound change into the conflict set.
70  * Note that if the bound change was a branching, all deduced bound changes
71  * remaining in the priority queue have smaller inference depth level than b,
72  * since deductions are always applied after the branching decisions. However,
73  * there is the possibility, that b was a deduction, where the inference
74  * reason was not given or the inference constraint was too local.
75  * With this lack of information, we must treat the deduced bound change like
76  * a branching, and there may exist other deduced bound changes of the same
77  * inference depth level in the priority queue.
78  * -# If priority queue is non-empty, goto step 2.
79  * -# The conflict set represents the conflict clause saying that at least one
80  * of the conflict variables must take a different value. The conflict set is then passed
81  * to the conflict handlers, that may create a corresponding constraint (e.g. a logicor
82  * constraint or bound disjunction constraint) out of these conflict variables and
83  * add it to the problem.
84  *
85  * If all deduced bound changes come with (global) inference information, depending on
86  * the conflict analyzing strategy, the resulting conflict set has the following property:
87  * - 1-FirstUIP: In the depth level where the conflict was found, at most one variable
88  * assigned at that level is member of the conflict set. This conflict variable is the
89  * first unique implication point of its depth level (FUIP).
90  * - All-FirstUIP: For each depth level, at most one variable assigned at that level is
91  * member of the conflict set. This conflict variable is the first unique implication
92  * point of its depth level (FUIP).
93  *
94  * The user has to do the following to get the conflict analysis running in its
95  * current implementation:
96  * - A constraint handler or propagator supporting the conflict analysis must implement
97  * the CONSRESPROP/PROPRESPROP call, that processes a bound change inference b and puts all
98  * the reason bounds leading to the application of b with calls to
99  * SCIPaddConflictBound() on the conflict queue (algorithm step 3.(a)).
100  * - If the current bounds lead to a deduction of a bound change (e.g. in domain
101  * propagation), a constraint handler should call SCIPinferVarLbCons() or
102  * SCIPinferVarUbCons(), thus providing the constraint that infered the bound change.
103  * A propagator should call SCIPinferVarLbProp() or SCIPinferVarUbProp() instead,
104  * thus providing a pointer to itself.
105  * - If (in the current bounds) an infeasibility is detected, the constraint handler or
106  * propagator should
107  * 1. call SCIPinitConflictAnalysis() to initialize the conflict queue,
108  * 2. call SCIPaddConflictBound() for each bound that lead to the conflict,
109  * 3. call SCIPanalyzeConflictCons() or SCIPanalyzeConflict() to analyze the conflict
110  * and add an appropriate conflict constraint.
111  */
112 
113 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
114 
115 #include <assert.h>
116 #include <string.h>
117 
118 #include "scip/def.h"
119 #include "scip/set.h"
120 #include "scip/stat.h"
121 #include "scip/clock.h"
122 #include "scip/vbc.h"
123 #include "scip/history.h"
124 #include "scip/paramset.h"
125 #include "scip/lp.h"
126 #include "scip/var.h"
127 #include "scip/prob.h"
128 #include "scip/tree.h"
129 #include "scip/scip.h"
130 #include "scip/conflict.h"
131 #include "scip/cons.h"
132 #include "scip/prop.h"
133 #include "scip/presolve.h"
134 #include "scip/debug.h"
135 #include "scip/pub_message.h"
136 #include "scip/pub_misc.h"
137 #include "lpi/lpi.h"
138 
139 #include "scip/struct_conflict.h"
140 
141 
142 
143 #define CONFLICTSETSCORE(conflictset) (-(conflictset)->nbdchginfos - 100*(conflictset)->repropdepth \
144  - 1000*(conflictset)->validdepth)
145 
146 
147 /*#define SCIP_CONFGRAPH*/
148 
149 
150 #ifdef SCIP_CONFGRAPH
151 /*
152  * Output of Conflict Graph
153  */
154 
155 #include <stdio.h>
156 
157 static FILE* confgraphfile = NULL; /**< output file for current conflict graph */
158 static SCIP_BDCHGINFO* confgraphcurrentbdchginfo = NULL; /**< currently resolved bound change */
159 static int confgraphnconflictsets = 0; /**< number of conflict sets marked in the graph */
160 
161 /** writes a node section to the conflict graph file */
162 static
163 void confgraphWriteNode(
164  void* idptr, /**< id of the node */
165  const char* label, /**< label of the node */
166  const char* nodetype, /**< type of the node */
167  const char* fillcolor, /**< color of the node's interior */
168  const char* bordercolor /**< color of the node's border */
169  )
170 {
171  assert(confgraphfile != NULL);
172 
173  SCIPgmlWriteNode(confgraphfile, (unsigned int)(size_t)idptr, label, nodetype, fillcolor, bordercolor);
174 }
175 
176 /** writes an edge section to the conflict graph file */
177 static
178 void confgraphWriteEdge(
179  void* source, /**< source node of the edge */
180  void* target, /**< target node of the edge */
181  const char* color /**< color of the edge */
182  )
183 {
184  assert(confgraphfile != NULL);
185 
186 #ifndef SCIP_CONFGRAPH_EDGE
187  SCIPgmlWriteArc(confgraphfile, (unsigned int)(size_t)source, (unsigned int)(size_t)target, NULL, color);
188 #else
189  SCIPgmlWriteEdge(confgraphfile, (unsigned int)(size_t)source, (unsigned int)(size_t)target, NULL, color);
190 #endif
191 }
192 
193 /** creates a file to output the current conflict graph into; adds the conflict vertex to the graph */
194 static
195 SCIP_RETCODE confgraphCreate(
196  SCIP_SET* set, /**< global SCIP settings */
197  SCIP_CONFLICT* conflict /**< conflict analysis data */
198  )
199 {
200  char fname[SCIP_MAXSTRLEN];
201 
202  assert(conflict != NULL);
203  assert(confgraphfile == NULL);
204 
205  (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "conf%p%d.gml", conflict, conflict->count);
206  SCIPinfoMessage(set->scip, NULL, "storing conflict graph in file <%s>\n", fname);
207 
208  confgraphfile = fopen(fname, "w");
209 
210  if( confgraphfile == NULL )
211  {
212  SCIPerrorMessage("cannot open graph file <%s>\n", fname);
213  SCIPABORT(); /*lint !e527*/
214  return SCIP_WRITEERROR;
215  }
216 
217  SCIPgmlWriteOpening(confgraphfile, TRUE);
218 
219  confgraphWriteNode(NULL, "conflict", "ellipse", "#ff0000", "#000000");
220 
221  confgraphcurrentbdchginfo = NULL;
222 
223  return SCIP_OKAY;
224 }
225 
226 /** closes conflict graph file */
227 static
228 void confgraphFree(
229  void
230  )
231 {
232  if( confgraphfile != NULL )
233  {
234  SCIPgmlWriteClosing(confgraphfile);
235 
236  fclose(confgraphfile);
237 
238  confgraphfile = NULL;
239  confgraphnconflictsets = 0;
240  }
241 }
242 
243 /** adds a bound change node to the conflict graph and links it to the currently resolved bound change */
244 static
245 void confgraphAddBdchg(
246  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict graph */
247  )
248 {
249  const char* colors[] = {
250  "#8888ff", /**< blue for constraint resolving */
251  "#ffff00", /**< yellow for propagator resolving */
252  "#55ff55" /**< green branching decision */
253  };
254  char label[SCIP_MAXSTRLEN];
255  char depth[SCIP_MAXSTRLEN];
256  int col;
257 
258 
259  switch( SCIPbdchginfoGetChgtype(bdchginfo) )
260  {
262  col = 2;
263  break;
265  col = 0;
266  break;
268  col = (SCIPbdchginfoGetInferProp(bdchginfo) == NULL ? 1 : 0);
269  break;
270  default:
271  SCIPerrorMessage("invalid bound change type\n");
272  col = 0;
273  SCIPABORT();
274  break;
275  }
276 
277  if( SCIPbdchginfoGetDepth(bdchginfo) == INT_MAX )
278  (void) SCIPsnprintf(depth, SCIP_MAXSTRLEN, "dive");
279  else
280  (void) SCIPsnprintf(depth, SCIP_MAXSTRLEN, "%d", SCIPbdchginfoGetDepth(bdchginfo));
281  (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "%s %s %g\n[%s:%d]", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
282  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
283  SCIPbdchginfoGetNewbound(bdchginfo), depth, SCIPbdchginfoGetPos(bdchginfo));
284  confgraphWriteNode(bdchginfo, label, "ellipse", colors[col], "#000000");
285  confgraphWriteEdge(bdchginfo, confgraphcurrentbdchginfo, "#000000");
286 }
287 
288 /** links the already existing bound change node to the currently resolved bound change */
289 static
290 void confgraphLinkBdchg(
291  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict graph */
292  )
293 {
294  confgraphWriteEdge(bdchginfo, confgraphcurrentbdchginfo, "#000000");
295 }
296 
297 /** marks the given bound change to be the currently resolved bound change */
298 static
299 void confgraphSetCurrentBdchg(
300  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict graph */
301  )
302 {
303  confgraphcurrentbdchginfo = bdchginfo;
304 }
305 
306 /** marks given conflict set in the conflict graph */
307 static
308 void confgraphMarkConflictset(
309  SCIP_CONFLICTSET* conflictset /**< conflict set */
310  )
311 {
312  char label[SCIP_MAXSTRLEN];
313  int i;
314 
315  assert(conflictset != NULL);
316 
317  confgraphnconflictsets++;
318  (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "conf %d (%d)", confgraphnconflictsets, conflictset->validdepth);
319  confgraphWriteNode((void*)(size_t)confgraphnconflictsets, label, "rectangle", "#ff00ff", "#000000");
320  for( i = 0; i < conflictset->nbdchginfos; ++i )
321  confgraphWriteEdge((void*)(size_t)confgraphnconflictsets, conflictset->bdchginfos[i], "#ff00ff");
322 }
323 
324 #endif
325 
326 
327 
328 /*
329  * Conflict Handler
330  */
331 
332 /** compares two conflict handlers w. r. to their priority */
333 SCIP_DECL_SORTPTRCOMP(SCIPconflicthdlrComp)
334 { /*lint --e{715}*/
335  return ((SCIP_CONFLICTHDLR*)elem2)->priority - ((SCIP_CONFLICTHDLR*)elem1)->priority;
336 }
337 
338 /** comparison method for sorting conflict handler w.r.t. to their name */
339 SCIP_DECL_SORTPTRCOMP(SCIPconflicthdlrCompName)
340 {
342 }
343 
344 /** method to call, when the priority of a conflict handler was changed */
345 static
346 SCIP_DECL_PARAMCHGD(paramChgdConflicthdlrPriority)
347 { /*lint --e{715}*/
348  SCIP_PARAMDATA* paramdata;
349 
350  paramdata = SCIPparamGetData(param);
351  assert(paramdata != NULL);
352 
353  /* use SCIPsetConflicthdlrPriority() to mark the conflicthdlrs unsorted */
354  SCIP_CALL( SCIPsetConflicthdlrPriority(scip, (SCIP_CONFLICTHDLR*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
355 
356  return SCIP_OKAY;
357 }
358 
359 /** copies the given conflict handler to a new scip */
361  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
362  SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
363  )
364 {
365  assert(conflicthdlr != NULL);
366  assert(set != NULL);
367  assert(set->scip != NULL);
368 
369  if( conflicthdlr->conflictcopy != NULL )
370  {
371  SCIPdebugMessage("including conflict handler %s in subscip %p\n", SCIPconflicthdlrGetName(conflicthdlr), (void*)set->scip);
372  SCIP_CALL( conflicthdlr->conflictcopy(set->scip, conflicthdlr) );
373  }
374 
375  return SCIP_OKAY;
376 }
377 
378 /** creates a conflict handler */
380  SCIP_CONFLICTHDLR** conflicthdlr, /**< pointer to conflict handler data structure */
381  SCIP_SET* set, /**< global SCIP settings */
382  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
383  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
384  const char* name, /**< name of conflict handler */
385  const char* desc, /**< description of conflict handler */
386  int priority, /**< priority of the conflict handler */
387  SCIP_DECL_CONFLICTCOPY((*conflictcopy)), /**< copy method of conflict handler or NULL if you don't want to copy your plugin into sub-SCIPs */
388  SCIP_DECL_CONFLICTFREE((*conflictfree)), /**< destructor of conflict handler */
389  SCIP_DECL_CONFLICTINIT((*conflictinit)), /**< initialize conflict handler */
390  SCIP_DECL_CONFLICTEXIT((*conflictexit)), /**< deinitialize conflict handler */
391  SCIP_DECL_CONFLICTINITSOL((*conflictinitsol)),/**< solving process initialization method of conflict handler */
392  SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol)),/**< solving process deinitialization method of conflict handler */
393  SCIP_DECL_CONFLICTEXEC((*conflictexec)), /**< conflict processing method of conflict handler */
394  SCIP_CONFLICTHDLRDATA* conflicthdlrdata /**< conflict handler data */
395  )
396 {
398  char paramdesc[SCIP_MAXSTRLEN];
399 
400  assert(conflicthdlr != NULL);
401  assert(name != NULL);
402  assert(desc != NULL);
403 
404  SCIP_ALLOC( BMSallocMemory(conflicthdlr) );
405  SCIP_ALLOC( BMSduplicateMemoryArray(&(*conflicthdlr)->name, name, strlen(name)+1) );
406  SCIP_ALLOC( BMSduplicateMemoryArray(&(*conflicthdlr)->desc, desc, strlen(desc)+1) );
407  (*conflicthdlr)->priority = priority;
408  (*conflicthdlr)->conflictcopy = conflictcopy;
409  (*conflicthdlr)->conflictfree = conflictfree;
410  (*conflicthdlr)->conflictinit = conflictinit;
411  (*conflicthdlr)->conflictexit = conflictexit;
412  (*conflicthdlr)->conflictinitsol = conflictinitsol;
413  (*conflicthdlr)->conflictexitsol = conflictexitsol;
414  (*conflicthdlr)->conflictexec = conflictexec;
415  (*conflicthdlr)->conflicthdlrdata = conflicthdlrdata;
416  (*conflicthdlr)->initialized = FALSE;
417 
418  SCIP_CALL( SCIPclockCreate(&(*conflicthdlr)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
419  SCIP_CALL( SCIPclockCreate(&(*conflicthdlr)->conflicttime, SCIP_CLOCKTYPE_DEFAULT) );
420 
421  /* add parameters */
422  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "conflict/%s/priority", name);
423  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of conflict handler <%s>", name);
424  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
425  &(*conflicthdlr)->priority, TRUE, priority, INT_MIN, INT_MAX,
426  paramChgdConflicthdlrPriority, (SCIP_PARAMDATA*)(*conflicthdlr)) ); /*lint !e740*/
427 
428  return SCIP_OKAY;
429 }
430 
431 /** calls destructor and frees memory of conflict handler */
433  SCIP_CONFLICTHDLR** conflicthdlr, /**< pointer to conflict handler data structure */
434  SCIP_SET* set /**< global SCIP settings */
435  )
436 {
437  assert(conflicthdlr != NULL);
438  assert(*conflicthdlr != NULL);
439  assert(!(*conflicthdlr)->initialized);
440  assert(set != NULL);
441 
442  /* call destructor of conflict handler */
443  if( (*conflicthdlr)->conflictfree != NULL )
444  {
445  SCIP_CALL( (*conflicthdlr)->conflictfree(set->scip, *conflicthdlr) );
446  }
447 
448  SCIPclockFree(&(*conflicthdlr)->conflicttime);
449  SCIPclockFree(&(*conflicthdlr)->setuptime);
450 
451  BMSfreeMemoryArray(&(*conflicthdlr)->name);
452  BMSfreeMemoryArray(&(*conflicthdlr)->desc);
453  BMSfreeMemory(conflicthdlr);
454 
455  return SCIP_OKAY;
456 }
457 
458 /** calls initialization method of conflict handler */
460  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
461  SCIP_SET* set /**< global SCIP settings */
462  )
463 {
464  assert(conflicthdlr != NULL);
465  assert(set != NULL);
466 
467  if( conflicthdlr->initialized )
468  {
469  SCIPerrorMessage("conflict handler <%s> already initialized\n", conflicthdlr->name);
470  return SCIP_INVALIDCALL;
471  }
472 
473  if( set->misc_resetstat )
474  {
475  SCIPclockReset(conflicthdlr->setuptime);
476  SCIPclockReset(conflicthdlr->conflicttime);
477  }
478 
479  /* call initialization method of conflict handler */
480  if( conflicthdlr->conflictinit != NULL )
481  {
482  /* start timing */
483  SCIPclockStart(conflicthdlr->setuptime, set);
484 
485  SCIP_CALL( conflicthdlr->conflictinit(set->scip, conflicthdlr) );
486 
487  /* stop timing */
488  SCIPclockStop(conflicthdlr->setuptime, set);
489  }
490  conflicthdlr->initialized = TRUE;
491 
492  return SCIP_OKAY;
493 }
494 
495 /** calls exit method of conflict handler */
497  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
498  SCIP_SET* set /**< global SCIP settings */
499  )
500 {
501  assert(conflicthdlr != NULL);
502  assert(set != NULL);
503 
504  if( !conflicthdlr->initialized )
505  {
506  SCIPerrorMessage("conflict handler <%s> not initialized\n", conflicthdlr->name);
507  return SCIP_INVALIDCALL;
508  }
509 
510  /* call deinitialization method of conflict handler */
511  if( conflicthdlr->conflictexit != NULL )
512  {
513  /* start timing */
514  SCIPclockStart(conflicthdlr->setuptime, set);
515 
516  SCIP_CALL( conflicthdlr->conflictexit(set->scip, conflicthdlr) );
517 
518  /* stop timing */
519  SCIPclockStop(conflicthdlr->setuptime, set);
520  }
521  conflicthdlr->initialized = FALSE;
522 
523  return SCIP_OKAY;
524 }
525 
526 /** informs conflict handler that the branch and bound process is being started */
528  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
529  SCIP_SET* set /**< global SCIP settings */
530  )
531 {
532  assert(conflicthdlr != NULL);
533  assert(set != NULL);
534 
535  /* call solving process initialization method of conflict handler */
536  if( conflicthdlr->conflictinitsol != NULL )
537  {
538  /* start timing */
539  SCIPclockStart(conflicthdlr->setuptime, set);
540 
541  SCIP_CALL( conflicthdlr->conflictinitsol(set->scip, conflicthdlr) );
542 
543  /* stop timing */
544  SCIPclockStop(conflicthdlr->setuptime, set);
545  }
546 
547  return SCIP_OKAY;
548 }
549 
550 /** informs conflict handler that the branch and bound process data is being freed */
552  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
553  SCIP_SET* set /**< global SCIP settings */
554  )
555 {
556  assert(conflicthdlr != NULL);
557  assert(set != NULL);
558 
559  /* call solving process deinitialization method of conflict handler */
560  if( conflicthdlr->conflictexitsol != NULL )
561  {
562  /* start timing */
563  SCIPclockStart(conflicthdlr->setuptime, set);
564 
565  SCIP_CALL( conflicthdlr->conflictexitsol(set->scip, conflicthdlr) );
566 
567  /* stop timing */
568  SCIPclockStop(conflicthdlr->setuptime, set);
569  }
570 
571  return SCIP_OKAY;
572 }
573 
574 /** calls execution method of conflict handler */
576  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
577  SCIP_SET* set, /**< global SCIP settings */
578  SCIP_NODE* node, /**< node to add conflict constraint to */
579  SCIP_NODE* validnode, /**< node at which the constraint is valid */
580  SCIP_BDCHGINFO** bdchginfos, /**< bound change resembling the conflict set */
581  SCIP_Real* relaxedbds, /**< array with relaxed bounds which are efficient to create a valid conflict */
582  int nbdchginfos, /**< number of bound changes in the conflict set */
583  SCIP_Bool resolved, /**< was the conflict set already used to create a constraint? */
584  SCIP_RESULT* result /**< pointer to store the result of the callback method */
585  )
586 {
587  assert(conflicthdlr != NULL);
588  assert(set != NULL);
589  assert(bdchginfos != NULL || nbdchginfos == 0);
590  assert(result != NULL);
591 
592  /* call solution start method of conflict handler */
593  *result = SCIP_DIDNOTRUN;
594  if( conflicthdlr->conflictexec != NULL )
595  {
596  /* start timing */
597  SCIPclockStart(conflicthdlr->conflicttime, set);
598 
599  SCIP_CALL( conflicthdlr->conflictexec(set->scip, conflicthdlr, node, validnode, bdchginfos, relaxedbds, nbdchginfos,
600  set->conf_seperate, (SCIPnodeGetDepth(validnode) > 0), set->conf_dynamic, set->conf_removable, resolved, result) );
601 
602  /* stop timing */
603  SCIPclockStop(conflicthdlr->conflicttime, set);
604 
605  if( *result != SCIP_CONSADDED
606  && *result != SCIP_DIDNOTFIND
607  && *result != SCIP_DIDNOTRUN )
608  {
609  SCIPerrorMessage("execution method of conflict handler <%s> returned invalid result <%d>\n",
610  conflicthdlr->name, *result);
611  return SCIP_INVALIDRESULT;
612  }
613  }
614 
615  return SCIP_OKAY;
616 }
617 
618 /** gets user data of conflict handler */
620  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
621  )
622 {
623  assert(conflicthdlr != NULL);
624 
625  return conflicthdlr->conflicthdlrdata;
626 }
627 
628 /** sets user data of conflict handler; user has to free old data in advance! */
630  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
631  SCIP_CONFLICTHDLRDATA* conflicthdlrdata /**< new conflict handler user data */
632  )
633 {
634  assert(conflicthdlr != NULL);
635 
636  conflicthdlr->conflicthdlrdata = conflicthdlrdata;
637 }
638 
639 /** set copy method of conflict handler */
641  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
642  SCIP_DECL_CONFLICTCOPY((*conflictcopy)) /**< copy method of the conflict handler */
643  )
644 {
645  assert(conflicthdlr != NULL);
646 
647  conflicthdlr->conflictcopy = conflictcopy;
648 }
649 
650 /** set destructor of conflict handler */
652  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
653  SCIP_DECL_CONFLICTFREE((*conflictfree)) /**< destructor of conflict handler */
654  )
655 {
656  assert(conflicthdlr != NULL);
657 
658  conflicthdlr->conflictfree = conflictfree;
659 }
660 
661 /** set initialization method of conflict handler */
663  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
664  SCIP_DECL_CONFLICTINIT((*conflictinit)) /**< initialization method conflict handler */
665  )
666 {
667  assert(conflicthdlr != NULL);
668 
669  conflicthdlr->conflictinit = conflictinit;
670 }
671 
672 /** set deinitialization method of conflict handler */
674  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
675  SCIP_DECL_CONFLICTEXIT((*conflictexit)) /**< deinitialization method conflict handler */
676  )
677 {
678  assert(conflicthdlr != NULL);
679 
680  conflicthdlr->conflictexit = conflictexit;
681 }
682 
683 /** set solving process initialization method of conflict handler */
685  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
686  SCIP_DECL_CONFLICTINITSOL((*conflictinitsol))/**< solving process initialization method of conflict handler */
687  )
688 {
689  assert(conflicthdlr != NULL);
690 
691  conflicthdlr->conflictinitsol = conflictinitsol;
692 }
693 
694 /** set solving process deinitialization method of conflict handler */
696  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
697  SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol))/**< solving process deinitialization method of conflict handler */
698  )
699 {
700  assert(conflicthdlr != NULL);
701 
702  conflicthdlr->conflictexitsol = conflictexitsol;
703 }
704 
705 /** gets name of conflict handler */
707  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
708  )
709 {
710  assert(conflicthdlr != NULL);
711 
712  return conflicthdlr->name;
713 }
714 
715 /** gets description of conflict handler */
717  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
718  )
719 {
720  assert(conflicthdlr != NULL);
721 
722  return conflicthdlr->desc;
723 }
724 
725 /** gets priority of conflict handler */
727  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
728  )
729 {
730  assert(conflicthdlr != NULL);
731 
732  return conflicthdlr->priority;
733 }
734 
735 /** sets priority of conflict handler */
737  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
738  SCIP_SET* set, /**< global SCIP settings */
739  int priority /**< new priority of the conflict handler */
740  )
741 {
742  assert(conflicthdlr != NULL);
743  assert(set != NULL);
744 
745  conflicthdlr->priority = priority;
746  set->conflicthdlrssorted = FALSE;
747 }
748 
749 /** is conflict handler initialized? */
751  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
752  )
753 {
754  assert(conflicthdlr != NULL);
755 
756  return conflicthdlr->initialized;
757 }
758 
759 
760 /** gets time in seconds used in this conflict handler for setting up for next stages */
762  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
763  )
764 {
765  assert(conflicthdlr != NULL);
766 
767  return SCIPclockGetTime(conflicthdlr->setuptime);
768 }
769 
770 /** gets time in seconds used in this conflict handler */
772  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
773  )
774 {
775  assert(conflicthdlr != NULL);
776 
777  return SCIPclockGetTime(conflicthdlr->conflicttime);
778 }
779 
780 /*
781  * Conflict LP Bound Changes
782  */
783 
784 
785 /** create conflict LP bound change data structure */
786 static
788  SCIP_LPBDCHGS** lpbdchgs, /**< pointer to store the conflict LP bound change data structure */
789  SCIP_SET* set, /**< global SCIP settings */
790  int ncols /**< number of columns */
791  )
792 {
793  SCIP_CALL( SCIPsetAllocBuffer(set, lpbdchgs) );
794 
795  SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchginds, ncols) );
796  SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchglbs, ncols) );
797  SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchgubs, ncols) );
798  SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchgcolinds, ncols) );
799  SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->usedcols, ncols) );
800  BMSclearMemoryArray((*lpbdchgs)->usedcols, ncols);
801 
802  (*lpbdchgs)->nbdchgs = 0;
803 
804  return SCIP_OKAY;
805 }
806 
807 /** reset conflict LP bound change data structure */
808 static
810  SCIP_LPBDCHGS* lpbdchgs /**< conflict LP bound change data structure */
811  )
812 {
813  assert(lpbdchgs != NULL);
814 
815  BMSclearMemoryArray(lpbdchgs->usedcols, lpbdchgs->nbdchgs);
816  lpbdchgs->nbdchgs = 0;
817 }
818 
819 /** free conflict LP bound change data structure */
820 static
822  SCIP_LPBDCHGS** lpbdchgs, /**< pointer to store the conflict LP bound change data structure */
823  SCIP_SET* set /**< global SCIP settings */
824  )
825 {
826  SCIPsetFreeBufferArray(set, &(*lpbdchgs)->usedcols);
827  SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchgcolinds);
828  SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchgubs);
829  SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchglbs);
830  SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchginds);
831 
832  SCIPsetFreeBuffer(set, lpbdchgs);
833 }
834 
835 /*
836  * Conflict Sets
837  */
838 
839 /** resizes the array of the temporary bound change informations to be able to store at least num bound change entries */
840 static
842  SCIP_CONFLICT* conflict, /**< conflict analysis data */
843  SCIP_SET* set, /**< global SCIP settings */
844  int num /**< minimal number of slots in arrays */
845  )
846 {
847  assert(conflict != NULL);
848  assert(set != NULL);
849 
850  if( num > conflict->tmpbdchginfossize )
851  {
852  int newsize;
853 
854  newsize = SCIPsetCalcMemGrowSize(set, num);
855  SCIP_ALLOC( BMSreallocMemoryArray(&conflict->tmpbdchginfos, newsize) );
856  conflict->tmpbdchginfossize = newsize;
857  }
858  assert(num <= conflict->tmpbdchginfossize);
859 
860  return SCIP_OKAY;
861 }
862 
863 /** creates a temporary bound change information object that is destroyed after the conflict sets are flushed */
864 static
866  SCIP_CONFLICT* conflict, /**< conflict analysis data */
867  BMS_BLKMEM* blkmem, /**< block memory */
868  SCIP_SET* set, /**< global SCIP settings */
869  SCIP_VAR* var, /**< active variable that changed the bounds */
870  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
871  SCIP_Real oldbound, /**< old value for bound */
872  SCIP_Real newbound, /**< new value for bound */
873  SCIP_BDCHGINFO** bdchginfo /**< pointer to store bound change information */
874  )
875 {
876  assert(conflict != NULL);
877 
878  SCIP_CALL( conflictEnsureTmpbdchginfosMem(conflict, set, conflict->ntmpbdchginfos+1) );
879  SCIP_CALL( SCIPbdchginfoCreate(&conflict->tmpbdchginfos[conflict->ntmpbdchginfos], blkmem,
880  var, boundtype, oldbound, newbound) );
881  *bdchginfo = conflict->tmpbdchginfos[conflict->ntmpbdchginfos];
882  conflict->ntmpbdchginfos++;
883 
884  return SCIP_OKAY;
885 }
886 
887 /** frees all temporarily created bound change information data */
888 static
890  SCIP_CONFLICT* conflict, /**< conflict analysis data */
891  BMS_BLKMEM* blkmem /**< block memory */
892  )
893 {
894  int i;
895 
896  assert(conflict != NULL);
897 
898  for( i = 0; i < conflict->ntmpbdchginfos; ++i )
899  SCIPbdchginfoFree(&conflict->tmpbdchginfos[i], blkmem);
900  conflict->ntmpbdchginfos = 0;
901 }
902 
903 /** clears the given conflict set */
904 static
906  SCIP_CONFLICTSET* conflictset /**< conflict set */
907  )
908 {
909  assert(conflictset != NULL);
910 
911  conflictset->nbdchginfos = 0;
912  conflictset->validdepth = 0;
913  conflictset->insertdepth = 0;
914  conflictset->conflictdepth = 0;
915  conflictset->repropdepth = 0;
916  conflictset->repropagate = TRUE;
917 }
918 
919 /** creates an empty conflict set */
920 static
922  SCIP_CONFLICTSET** conflictset, /**< pointer to store the conflict set */
923  BMS_BLKMEM* blkmem /**< block memory of transformed problem */
924  )
925 {
926  assert(conflictset != NULL);
927 
928  SCIP_ALLOC( BMSallocBlockMemory(blkmem, conflictset) );
929  (*conflictset)->bdchginfos = NULL;
930  (*conflictset)->relaxedbds = NULL;
931  (*conflictset)->sortvals = NULL;
932  (*conflictset)->bdchginfossize = 0;
933 
934  conflictsetClear(*conflictset);
935 
936  return SCIP_OKAY;
937 }
938 
939 /** creates a copy of the given conflict set, allocating an additional amount of memory */
940 static
942  SCIP_CONFLICTSET** targetconflictset, /**< pointer to store the conflict set */
943  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
944  SCIP_CONFLICTSET* sourceconflictset, /**< source conflict set */
945  int nadditionalelems /**< number of additional elements to allocate memory for */
946  )
947 {
948  int targetsize;
949 
950  assert(targetconflictset != NULL);
951  assert(sourceconflictset != NULL);
952 
953  targetsize = sourceconflictset->nbdchginfos + nadditionalelems;
954  SCIP_ALLOC( BMSallocBlockMemory(blkmem, targetconflictset) );
955  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetconflictset)->bdchginfos, targetsize) );
956  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetconflictset)->relaxedbds, targetsize) );
957  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetconflictset)->sortvals, targetsize) );
958  (*targetconflictset)->bdchginfossize = targetsize;
959 
960  BMScopyMemoryArray((*targetconflictset)->bdchginfos, sourceconflictset->bdchginfos, sourceconflictset->nbdchginfos);
961  BMScopyMemoryArray((*targetconflictset)->relaxedbds, sourceconflictset->relaxedbds, sourceconflictset->nbdchginfos);
962  BMScopyMemoryArray((*targetconflictset)->sortvals, sourceconflictset->sortvals, sourceconflictset->nbdchginfos);
963 
964  (*targetconflictset)->nbdchginfos = sourceconflictset->nbdchginfos;
965  (*targetconflictset)->validdepth = sourceconflictset->validdepth;
966  (*targetconflictset)->insertdepth = sourceconflictset->insertdepth;
967  (*targetconflictset)->conflictdepth = sourceconflictset->conflictdepth;
968  (*targetconflictset)->repropdepth = sourceconflictset->repropdepth;
969 
970  return SCIP_OKAY;
971 }
972 
973 /** frees a conflict set */
974 static
976  SCIP_CONFLICTSET** conflictset, /**< pointer to the conflict set */
977  BMS_BLKMEM* blkmem /**< block memory of transformed problem */
978  )
979 {
980  assert(conflictset != NULL);
981  assert(*conflictset != NULL);
982 
983  BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->bdchginfos, (*conflictset)->bdchginfossize);
984  BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->relaxedbds, (*conflictset)->bdchginfossize);
985  BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->sortvals, (*conflictset)->bdchginfossize);
986  BMSfreeBlockMemory(blkmem, conflictset);
987 }
988 
989 /** resizes the arrays of the conflict set to be able to store at least num bound change entries */
990 static
992  SCIP_CONFLICTSET* conflictset, /**< conflict set */
993  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
994  SCIP_SET* set, /**< global SCIP settings */
995  int num /**< minimal number of slots in arrays */
996  )
997 {
998  assert(conflictset != NULL);
999  assert(set != NULL);
1000 
1001  if( num > conflictset->bdchginfossize )
1002  {
1003  int newsize;
1004 
1005  newsize = SCIPsetCalcMemGrowSize(set, num);
1006  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->bdchginfos, conflictset->bdchginfossize, newsize) );
1007  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->relaxedbds, conflictset->bdchginfossize, newsize) );
1008  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->sortvals, conflictset->bdchginfossize, newsize) );
1009  conflictset->bdchginfossize = newsize;
1010  }
1011  assert(num <= conflictset->bdchginfossize);
1012 
1013  return SCIP_OKAY;
1014 }
1015 
1016 /** updates the score of the conflict set */
1017 static
1019  SCIP_CONFLICTSET* conflictset /**< conflict set */
1020  )
1021 {
1022  assert(conflictset != NULL);
1023 
1024  return (SCIP_Real)CONFLICTSETSCORE(conflictset); /*lint !e790*/
1025 }
1026 
1027 /** check if the bound change info (which is the potential next candidate which is queued) is valid for the current
1028  * conflict analysis; a bound change info can get invalid if after this one was added to the queue, a weaker bound
1029  * change was added to the queue (due the bound widening idea) which immediately makes this bound change redundant; due
1030  * to the priority we did not removed that bound change info since that cost O(log(n)); hence we have to skip/ignore it
1031  * now
1032  *
1033  * The following situations can occur before for example the bound change info (x >= 3) is potentially popped from the
1034  * queue.
1035  *
1036  * Postcondition: the reason why (x >= 3) was queued is that at this time point no lower bound of x was involved yet in
1037  * the current conflict or the lower bound which was involved until then was stronger, e.g., (x >= 2).
1038  *
1039  * 1) during the time until (x >= 3) gets potentially popped no weaker lower bound was added to the queue, in that case
1040  * the conflictlbcount is valid and conflictlb is 3; that is (var->conflictlbcount == conflict->count &&
1041  * var->conflictlb == 3)
1042  *
1043  * 2) a weaker bound change info gets queued (e.g., x >= 4); this bound change is popped before (x >= 3) since it has
1044  * higher priority (which is the time stamp of the bound change info and (x >= 4) has to be done after (x >= 3)
1045  * during propagation or branching)
1046  *
1047  * a) if (x >= 4) is popped and added to the conflict set the conflictlbcount is still valid and conflictlb is at
1048  * most 4; that is (var->conflictlbcount == conflict->count && var->conflictlb >= 4); it follows that any bound
1049  * change info which is stronger than (x >= 4) gets ignored (for example x >= 2)
1050  *
1051  * b) if (x >= 4) is popped and resolved without introducing a new lower bound on x until (x >= 3) is a potentially
1052  * candidate the conflictlbcount indicates that bound change is currently not present; that is
1053  * (var->conflictlbcount != conflict->count)
1054  *
1055  * 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
1056  * pooped, the conflictlbcount indicates that bound change is currently present; that is (var->conflictlbcount ==
1057  * conflict->count); however the (x >= 3) only has be explained if conflictlb matches that one; that is
1058  * (var->conflictlb == bdchginfo->newbound); otherwise it redundant/invalid.
1059  */
1060 static
1062  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1063  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
1064  )
1065 {
1066  SCIP_VAR* var;
1067 
1068  assert(bdchginfo != NULL);
1069 
1070  var = SCIPbdchginfoGetVar(bdchginfo);
1071  assert(var != NULL);
1072 
1073  /* the bound change info of a binary (domained) variable can never be invalid since the concepts of relaxed bounds
1074  * and bound widening do not make sense for these type of variables
1075  */
1076  if( SCIPvarIsBinary(var) )
1077  return FALSE;
1078 
1079  /* check if the bdchginfo is invaild since a tight/weaker bound change was already explained */
1081  {
1082  if( var->conflictlbcount != conflict->count || var->conflictlb != SCIPbdchginfoGetNewbound(bdchginfo) ) /*lint !e777*/
1083  {
1084  assert(!SCIPvarIsBinary(var));
1085  return TRUE;
1086  }
1087  }
1088  else
1089  {
1090  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER);
1091 
1092  if( var->conflictubcount != conflict->count || var->conflictub != SCIPbdchginfoGetNewbound(bdchginfo) ) /*lint !e777*/
1093  {
1094  assert(!SCIPvarIsBinary(var));
1095  return TRUE;
1096  }
1097  }
1098 
1099  return FALSE;
1100 }
1101 
1102 /** adds a bound change to a conflict set */
1103 static
1105  SCIP_CONFLICTSET* conflictset, /**< conflict set */
1106  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
1107  SCIP_SET* set, /**< global SCIP settings */
1108  SCIP_BDCHGINFO* bdchginfo, /**< bound change to add to the conflict set */
1109  SCIP_Real relaxedbd /**< relaxed bound */
1110  )
1111 {
1112  SCIP_BDCHGINFO** bdchginfos;
1113  SCIP_Real* relaxedbds;
1114  int* sortvals;
1115  SCIP_VAR* var;
1116  SCIP_BOUNDTYPE boundtype;
1117  int idx;
1118  int sortval;
1119  int pos;
1120 
1121  assert(conflictset != NULL);
1122  assert(bdchginfo != NULL);
1123 
1124  /* allocate memory for additional element */
1125  SCIP_CALL( conflictsetEnsureBdchginfosMem(conflictset, blkmem, set, conflictset->nbdchginfos+1) );
1126 
1127  /* insert the new bound change in the arrays sorted by increasing variable index and by bound type */
1128  bdchginfos = conflictset->bdchginfos;
1129  relaxedbds = conflictset->relaxedbds;
1130  sortvals = conflictset->sortvals;
1131  var = SCIPbdchginfoGetVar(bdchginfo);
1132  boundtype = SCIPbdchginfoGetBoundtype(bdchginfo);
1133  idx = SCIPvarGetIndex(var);
1134  assert(idx < INT_MAX/2);
1135  assert((int)boundtype == 0 || (int)boundtype == 1);
1136  sortval = 2*idx + (int)boundtype; /* first sorting criteria: variable index, second criteria: boundtype */
1137 
1138  /* insert new element into the sorted arrays; if an element exits with the same value insert the new element afterwards
1139  *
1140  * @todo check if it better (faster) to first search for the position O(log n) and compare the sort values and if
1141  * they are equal just replace the element and if not run the insert method O(n)
1142  */
1143 
1144  SCIPsortedvecInsertIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, sortval, (void*)bdchginfo, relaxedbd, &conflictset->nbdchginfos, &pos);
1145  assert(pos == conflictset->nbdchginfos - 1 || sortval < sortvals[pos+1]);
1146 
1147  /* merge multiple bound changes */
1148  if( pos > 0 && sortval == sortvals[pos-1] )
1149  {
1150  /* this is a multiple bound change */
1151  if( SCIPbdchginfoIsTighter(bdchginfo, bdchginfos[pos-1]) )
1152  {
1153  /* remove the "old" bound change since the "new" one in tighter */
1154  SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos-1, &conflictset->nbdchginfos);
1155  }
1156  else if( SCIPbdchginfoIsTighter(bdchginfos[pos-1], bdchginfo) )
1157  {
1158  /* remove the "new" bound change since the "old" one is tighter */
1159  SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos, &conflictset->nbdchginfos);
1160  }
1161  else
1162  {
1163  /* both bound change are equivalent; hence, keep the worse relaxed bound and remove one of them */
1164  relaxedbds[pos-1] = boundtype == SCIP_BOUNDTYPE_LOWER ? MAX(relaxedbds[pos-1], relaxedbd) : MIN(relaxedbds[pos-1], relaxedbd);
1165  SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos, &conflictset->nbdchginfos);
1166  }
1167  }
1168 
1169  return SCIP_OKAY;
1170 }
1171 
1172 /** adds given bound changes to a conflict set */
1173 static
1175  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1176  SCIP_CONFLICTSET* conflictset, /**< conflict set */
1177  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
1178  SCIP_SET* set, /**< global SCIP settings */
1179  SCIP_BDCHGINFO** bdchginfos, /**< bound changes to add to the conflict set */
1180  int nbdchginfos /**< number of bound changes to add */
1181  )
1182 {
1183  SCIP_BDCHGINFO** confbdchginfos;
1184  SCIP_BDCHGINFO* bdchginfo;
1185  SCIP_Real* confrelaxedbds;
1186  int* confsortvals;
1187  int confnbdchginfos;
1188  int idx;
1189  int sortval;
1190  int i;
1191  SCIP_BOUNDTYPE boundtype;
1192 
1193  assert(conflict != NULL);
1194  assert(conflictset != NULL);
1195  assert(blkmem != NULL);
1196  assert(set != NULL);
1197  assert(bdchginfos != NULL || nbdchginfos == 0);
1198 
1199  /* nothing to add */
1200  if( nbdchginfos == 0 )
1201  return SCIP_OKAY;
1202 
1203  assert(bdchginfos != NULL);
1204 
1205  /* only one element to add, use the single insertion method */
1206  if( nbdchginfos == 1 )
1207  {
1208  bdchginfo = bdchginfos[0];
1209  assert(bdchginfo != NULL);
1210 
1211  if( !bdchginfoIsInvalid(conflict, bdchginfo) )
1212  {
1213  SCIP_CALL( conflictsetAddBound(conflictset, blkmem, set, bdchginfo, SCIPbdchginfoGetRelaxedBound(bdchginfo)) );
1214  }
1215  else
1216  {
1217  SCIPdebugMessage("-> bound change info [%d:<%s> %s %g] is invaild -> ignore it\n", SCIPbdchginfoGetDepth(bdchginfo),
1218  SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
1219  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
1220  SCIPbdchginfoGetNewbound(bdchginfo));
1221  }
1222 
1223  return SCIP_OKAY;
1224  }
1225 
1226  confnbdchginfos = conflictset->nbdchginfos;
1227 
1228  /* allocate memory for additional element */
1229  SCIP_CALL( conflictsetEnsureBdchginfosMem(conflictset, blkmem, set, confnbdchginfos + nbdchginfos) );
1230 
1231  confbdchginfos = conflictset->bdchginfos;
1232  confrelaxedbds = conflictset->relaxedbds;
1233  confsortvals = conflictset->sortvals;
1234 
1235  assert(SCIP_BOUNDTYPE_LOWER == FALSE);/*lint !e641*/
1236  assert(SCIP_BOUNDTYPE_UPPER == TRUE);/*lint !e641*/
1237 
1238  for( i = 0; i < nbdchginfos; ++i )
1239  {
1240  bdchginfo = bdchginfos[i];
1241  assert(bdchginfo != NULL);
1242 
1243  /* add only valid bound change infos */
1244  if( !bdchginfoIsInvalid(conflict, bdchginfo) )
1245  {
1246  /* calculate sorting value */
1247  boundtype = SCIPbdchginfoGetBoundtype(bdchginfo);
1248  assert(SCIPbdchginfoGetVar(bdchginfo) != NULL);
1249 
1250  idx = SCIPvarGetIndex(SCIPbdchginfoGetVar(bdchginfo));
1251  assert(idx < INT_MAX/2);
1252 
1253  assert((int)boundtype == 0 || (int)boundtype == 1);
1254  sortval = 2*idx + (int)boundtype; /* first sorting criteria: variable index, second criteria: boundtype */
1255 
1256  /* add new element */
1257  confbdchginfos[confnbdchginfos] = bdchginfo;
1258  confrelaxedbds[confnbdchginfos] = SCIPbdchginfoGetRelaxedBound(bdchginfo);
1259  confsortvals[confnbdchginfos] = sortval;
1260  ++confnbdchginfos;
1261  }
1262  else
1263  {
1264  SCIPdebugMessage("-> bound change info [%d:<%s> %s %g] is invaild -> ignore it\n", SCIPbdchginfoGetDepth(bdchginfo),
1265  SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
1266  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
1267  SCIPbdchginfoGetNewbound(bdchginfo));
1268  }
1269  }
1270  assert(confnbdchginfos <= conflictset->nbdchginfos + nbdchginfos);
1271 
1272  /* sort and merge the new conflict set */
1273  if( confnbdchginfos > conflictset->nbdchginfos )
1274  {
1275  int k = 0;
1276 
1277  /* sort array */
1278  SCIPsortIntPtrReal(confsortvals, (void**)confbdchginfos, confrelaxedbds, confnbdchginfos);
1279 
1280  i = 1;
1281  /* merge multiple bound changes */
1282  while( i < confnbdchginfos )
1283  {
1284  assert(i > k);
1285 
1286  /* is this a multiple bound change */
1287  if( confsortvals[k] == confsortvals[i] )
1288  {
1289  if( SCIPbdchginfoIsTighter(confbdchginfos[k], confbdchginfos[i]) )
1290  ++i;
1291  else if( SCIPbdchginfoIsTighter(confbdchginfos[i], confbdchginfos[k]) )
1292  {
1293  /* replace worse bound change info by tighter bound change info */
1294  confbdchginfos[k] = confbdchginfos[i];
1295  confrelaxedbds[k] = confrelaxedbds[i];
1296  confsortvals[k] = confsortvals[i];
1297  ++i;
1298  }
1299  else
1300  {
1301  assert(confsortvals[k] == confsortvals[i]);
1302 
1303  /* both bound change are equivalent; hence, keep the worse relaxed bound and remove one of them */
1304  confrelaxedbds[k] = (confsortvals[k] % 2 == 0) ? MAX(confrelaxedbds[k], confrelaxedbds[i]) : MIN(confrelaxedbds[k], confrelaxedbds[i]);
1305  ++i;
1306  }
1307  }
1308  else
1309  {
1310  /* all bound change infos must be valid */
1311  assert(!bdchginfoIsInvalid(conflict, confbdchginfos[k]));
1312 
1313  ++k;
1314  /* move next comparison element to the correct position */
1315  if( k != i )
1316  {
1317  confbdchginfos[k] = confbdchginfos[i];
1318  confrelaxedbds[k] = confrelaxedbds[i];
1319  confsortvals[k] = confsortvals[i];
1320  }
1321  ++i;
1322  }
1323  }
1324  /* last bound change infos must also be valid */
1325  assert(!bdchginfoIsInvalid(conflict, confbdchginfos[k]));
1326  /* the number of bound change infos cannot be decreased, it would mean that the conflict set was not merged
1327  * before
1328  */
1329  assert(conflictset->nbdchginfos <= k + 1 );
1330  assert(k + 1 <= confnbdchginfos);
1331 
1332  conflictset->nbdchginfos = k + 1;
1333  }
1334 
1335  return SCIP_OKAY;
1336 }
1337 
1338 /** calculates the conflict and the repropagation depths of the conflict set */
1339 static
1341  SCIP_CONFLICTSET* conflictset /**< conflict set */
1342  )
1343 {
1344  int maxdepth[2];
1345  int i;
1346 
1347  assert(conflictset != NULL);
1348  assert(conflictset->validdepth <= conflictset->insertdepth);
1349 
1350  /* get the depth of the last and last but one bound change */
1351  maxdepth[0] = conflictset->validdepth;
1352  maxdepth[1] = conflictset->validdepth;
1353  for( i = 0; i < conflictset->nbdchginfos; ++i )
1354  {
1355  int depth;
1356 
1357  depth = SCIPbdchginfoGetDepth(conflictset->bdchginfos[i]);
1358  assert(depth >= 0);
1359  if( depth > maxdepth[0] )
1360  {
1361  maxdepth[1] = maxdepth[0];
1362  maxdepth[0] = depth;
1363  }
1364  else if( depth > maxdepth[1] )
1365  maxdepth[1] = depth;
1366  }
1367  assert(maxdepth[0] >= maxdepth[1]);
1368 
1369  conflictset->conflictdepth = maxdepth[0];
1370  conflictset->repropdepth = maxdepth[1];
1371 }
1372 
1373 /** identifies the depth, at which the conflict set should be added:
1374  * - if the branching rule operates on variables only, and if all branching variables up to a certain
1375  * depth level are member of the conflict, the conflict constraint can only be violated in the subtree
1376  * of the node at that depth, because in all other nodes, at least one of these branching variables
1377  * violates its conflicting bound, such that the conflict constraint is feasible
1378  * - if there is at least one branching variable in a node, we assume, that this branching was performed
1379  * on variables, and that the siblings of this node are disjunct w.r.t. the branching variables' fixings
1380  * - we have to add the conflict set at least in the valid depth of the initial conflict set,
1381  * so we start searching at the first branching after this depth level, i.e. validdepth+1
1382  */
1383 static
1385  SCIP_CONFLICTSET* conflictset, /**< conflict set */
1386  SCIP_SET* set, /**< global SCIP settings */
1387  SCIP_TREE* tree /**< branch and bound tree */
1388  )
1389 {
1390  SCIP_Bool* branchingincluded;
1391  int currentdepth;
1392  int i;
1393 
1394  assert(conflictset != NULL);
1395  assert(set != NULL);
1396  assert(tree != NULL);
1397 
1398  /* the conflict set must not be inserted prior to its valid depth */
1399  conflictset->insertdepth = conflictset->validdepth;
1400  assert(conflictset->insertdepth >= 0);
1401 
1402  currentdepth = SCIPtreeGetCurrentDepth(tree);
1403  assert(currentdepth == tree->pathlen-1);
1404 
1405  /* mark the levels for which a branching variable is included in the conflict set */
1406  SCIP_CALL( SCIPsetAllocBufferArray(set, &branchingincluded, currentdepth+2) );
1407  BMSclearMemoryArray(branchingincluded, currentdepth+2);
1408  for( i = 0; i < conflictset->nbdchginfos; ++i )
1409  {
1410  int depth;
1411 
1412  depth = SCIPbdchginfoGetDepth(conflictset->bdchginfos[i]);
1413  depth = MIN(depth, currentdepth+1); /* put diving/probing/strong branching changes in this depth level */
1414  branchingincluded[depth] = TRUE;
1415  }
1416 
1417  /* skip additional depth levels where branching on the conflict variables was applied */
1418  while( conflictset->insertdepth < currentdepth && branchingincluded[conflictset->insertdepth+1] )
1419  conflictset->insertdepth++;
1420 
1421  /* free temporary memory */
1422  SCIPsetFreeBufferArray(set, &branchingincluded);
1423 
1424  assert(conflictset->validdepth <= conflictset->insertdepth && conflictset->insertdepth <= currentdepth);
1425 
1426  return SCIP_OKAY;
1427 }
1428 
1429 /** checks whether the first conflict set is redundant to the second one */
1430 static
1432  SCIP_CONFLICTSET* conflictset1, /**< first conflict conflict set */
1433  SCIP_CONFLICTSET* conflictset2 /**< second conflict conflict set */
1434  )
1435 {
1436  int i1;
1437  int i2;
1438 
1439  assert(conflictset1 != NULL);
1440  assert(conflictset2 != NULL);
1441 
1442  /* if conflictset1 has smaller validdepth, it is definitely not redundant to conflictset2 */
1443  if( conflictset1->validdepth < conflictset2->validdepth )
1444  return FALSE;
1445 
1446  /* check, if all bound changes in conflictset2 are also present at least as tight in conflictset1;
1447  * we can stop immediately, if more bound changes are remaining in conflictset2 than in conflictset1
1448  */
1449  for( i1 = 0, i2 = 0; i2 < conflictset2->nbdchginfos && conflictset1->nbdchginfos - i1 >= conflictset2->nbdchginfos - i2;
1450  ++i1, ++i2 )
1451  {
1452  int sortval;
1453 
1454  assert(i2 == 0 || conflictset2->sortvals[i2-1] < conflictset2->sortvals[i2]);
1455 
1456  sortval = conflictset2->sortvals[i2];
1457  for( ; i1 < conflictset1->nbdchginfos && conflictset1->sortvals[i1] < sortval; ++i1 )
1458  {
1459  /* while scanning conflictset1, check consistency */
1460  assert(i1 == 0 || conflictset1->sortvals[i1-1] < conflictset1->sortvals[i1]);
1461  }
1462  if( i1 >= conflictset1->nbdchginfos || conflictset1->sortvals[i1] > sortval
1463  || SCIPbdchginfoIsTighter(conflictset2->bdchginfos[i2], conflictset1->bdchginfos[i1]) )
1464  return FALSE;
1465  }
1466 
1467  return (i2 == conflictset2->nbdchginfos);
1468 }
1469 
1470 #ifdef SCIP_DEBUG
1471 /** prints a conflict set to the screen */
1472 static
1473 void conflictsetPrint(
1474  SCIP_CONFLICTSET* conflictset /**< conflict set */
1475  )
1476 {
1477  int i;
1478 
1479  assert(conflictset != NULL);
1480  for( i = 0; i < conflictset->nbdchginfos; ++i )
1481  {
1482  SCIPdebugPrintf(" [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(conflictset->bdchginfos[i]),
1483  SCIPvarGetName(SCIPbdchginfoGetVar(conflictset->bdchginfos[i])),
1484  SCIPbdchginfoGetBoundtype(conflictset->bdchginfos[i]) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
1485  SCIPbdchginfoGetNewbound(conflictset->bdchginfos[i]), conflictset->relaxedbds[i]);
1486  }
1487  SCIPdebugPrintf("\n");
1488 }
1489 #endif
1490 
1491 /** resizes conflictsets array to be able to store at least num entries */
1492 static
1494  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1495  SCIP_SET* set, /**< global SCIP settings */
1496  int num /**< minimal number of slots in array */
1497  )
1498 {
1499  assert(conflict != NULL);
1500  assert(set != NULL);
1501 
1502  if( num > conflict->conflictsetssize )
1503  {
1504  int newsize;
1505 
1506  newsize = SCIPsetCalcMemGrowSize(set, num);
1507  SCIP_ALLOC( BMSreallocMemoryArray(&conflict->conflictsets, newsize) );
1508  SCIP_ALLOC( BMSreallocMemoryArray(&conflict->conflictsetscores, newsize) );
1509  conflict->conflictsetssize = newsize;
1510  }
1511  assert(num <= conflict->conflictsetssize);
1512 
1513  return SCIP_OKAY;
1514 }
1515 
1516 /** inserts conflict set into sorted conflictsets array and deletes the conflict set pointer */
1517 static
1519  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1520  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
1521  SCIP_SET* set, /**< global SCIP settings */
1522  SCIP_CONFLICTSET** conflictset /**< pointer to conflict set to insert */
1523  )
1524 {
1525  SCIP_Real score;
1526  int pos;
1527  int i;
1528  int j;
1529 
1530  assert(conflict != NULL);
1531  assert(set != NULL);
1532  assert(conflictset != NULL);
1533  assert(*conflictset != NULL);
1534  assert((*conflictset)->validdepth <= (*conflictset)->insertdepth);
1535  assert(set->conf_allowlocal || (*conflictset)->validdepth == 0);
1536 
1537  /* calculate conflict and repropagation depth */
1538  conflictsetCalcConflictDepth(*conflictset);
1539 
1540  /* if we apply repropagations, the conflict set should be inserted at most at its repropdepth */
1541  if( set->conf_repropagate )
1542  (*conflictset)->insertdepth = MIN((*conflictset)->insertdepth, (*conflictset)->repropdepth);
1543  else
1544  (*conflictset)->repropdepth = INT_MAX;
1545  assert((*conflictset)->insertdepth <= (*conflictset)->repropdepth);
1546 
1547  SCIPdebugMessage("inserting conflict set (valid: %d, insert: %d, conf: %d, reprop: %d):",
1548  (*conflictset)->validdepth, (*conflictset)->insertdepth, (*conflictset)->conflictdepth, (*conflictset)->repropdepth);
1549  SCIPdebug(conflictsetPrint(*conflictset));
1550 
1551  /* get the score of the conflict set */
1552  score = conflictsetCalcScore(*conflictset);
1553 
1554  /* check, if conflict set is redundant to a better conflict set */
1555  for( pos = 0; pos < conflict->nconflictsets && score < conflict->conflictsetscores[pos]; ++pos )
1556  {
1557  /* check if conflict set is redundant with respect to conflictsets[pos] */
1558  if( conflictsetIsRedundant(*conflictset, conflict->conflictsets[pos]) )
1559  {
1560  SCIPdebugMessage(" -> conflict set is redundant to: ");
1561  SCIPdebug(conflictsetPrint(conflict->conflictsets[pos]));
1562  conflictsetFree(conflictset, blkmem);
1563  return SCIP_OKAY;
1564  }
1565 
1566  /**@todo like in sepastore.c: calculate overlap between conflictsets -> large overlap reduces score */
1567 
1568  }
1569 
1570  /* insert conflictset into the sorted conflictsets array */
1571  SCIP_CALL( conflictEnsureConflictsetsMem(conflict, set, conflict->nconflictsets + 1) );
1572  for( i = conflict->nconflictsets; i > pos; --i )
1573  {
1574  assert(score >= conflict->conflictsetscores[i-1]);
1575  conflict->conflictsets[i] = conflict->conflictsets[i-1];
1576  conflict->conflictsetscores[i] = conflict->conflictsetscores[i-1];
1577  }
1578  conflict->conflictsets[pos] = *conflictset;
1579  conflict->conflictsetscores[pos] = score;
1580  conflict->nconflictsets++;
1581 
1582  /* remove worse conflictsets that are redundant to the new conflictset */
1583  for( i = pos+1, j = pos+1; i < conflict->nconflictsets; ++i )
1584  {
1585  if( conflictsetIsRedundant(conflict->conflictsets[i], *conflictset) )
1586  {
1587  SCIPdebugMessage(" -> conflict set dominates: ");
1588  SCIPdebug(conflictsetPrint(conflict->conflictsets[i]));
1589  conflictsetFree(&conflict->conflictsets[i], blkmem);
1590  }
1591  else
1592  {
1593  assert(j <= i);
1594  conflict->conflictsets[j] = conflict->conflictsets[i];
1595  conflict->conflictsetscores[j] = conflict->conflictsetscores[i];
1596  j++;
1597  }
1598  }
1599  assert(j <= conflict->nconflictsets);
1600  conflict->nconflictsets = j;
1601 
1602 #ifdef SCIP_CONFGRAPH
1603  confgraphMarkConflictset(*conflictset);
1604 #endif
1605 
1606  *conflictset = NULL; /* ownership of pointer is now in the conflictsets array */
1607 
1608  return SCIP_OKAY;
1609 }
1610 
1611 /** calculates the maximal size of conflict sets to be used */
1612 static
1614  SCIP_SET* set, /**< global SCIP settings */
1615  SCIP_PROB* prob /**< problem data */
1616  )
1617 {
1618  int maxsize;
1619 
1620  assert(set != NULL);
1621  assert(prob != NULL);
1622 
1623  maxsize = (int)(set->conf_maxvarsfac * (prob->nvars - prob->ncontvars));
1624  maxsize = MAX(maxsize, set->conf_minmaxvars);
1625 
1626  return maxsize;
1627 }
1628 
1629 /** increases the conflict score of the variable in the given direction */
1630 static
1632  SCIP_VAR* var, /**< problem variable */
1633  BMS_BLKMEM* blkmem, /**< block memory */
1634  SCIP_SET* set, /**< global SCIP settings */
1635  SCIP_STAT* stat, /**< dynamic problem statistics */
1636  SCIP_BOUNDTYPE boundtype, /**< type of bound for which the score should be increased */
1637  SCIP_Real value, /**< value of the bound */
1638  SCIP_Real weight /**< weight of this VSIDS updates */
1639  )
1640 {
1641  SCIP_BRANCHDIR branchdir;
1642 
1643  assert(var != NULL);
1644  assert(stat != NULL);
1645 
1646  /* weight the VSIDS by the given weight */
1647  weight *= stat->vsidsweight;
1648 
1649  if( SCIPsetIsZero(set, weight) )
1650  return SCIP_OKAY;
1651 
1652  branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
1653  SCIP_CALL( SCIPvarIncVSIDS(var, blkmem, set, stat, branchdir, value, weight) );
1654  SCIPhistoryIncVSIDS(stat->glbhistory, branchdir, weight);
1655  SCIPhistoryIncVSIDS(stat->glbhistorycrun, branchdir, weight);
1656 
1657  return SCIP_OKAY;
1658 }
1659 
1660 /** update conflict statistics */
1661 static
1663  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1664  BMS_BLKMEM* blkmem, /**< block memory */
1665  SCIP_SET* set, /**< global SCIP settings */
1666  SCIP_STAT* stat, /**< dynamic problem statistics */
1667  SCIP_CONFLICTSET* conflictset, /**< conflict set to add to the tree */
1668  int insertdepth /**< depth level at which the conflict set should be added */
1669  )
1670 {
1671  if( insertdepth > 0 )
1672  {
1673  conflict->nappliedlocconss++;
1674  conflict->nappliedlocliterals += conflictset->nbdchginfos;
1675  }
1676  else
1677  {
1678  int i;
1679  int conflictlength;
1680  conflictlength = conflictset->nbdchginfos;
1681 
1682  for( i = 0; i < conflictlength; i++ )
1683  {
1684  SCIP_VAR* var;
1685  SCIP_BRANCHDIR branchdir;
1686  SCIP_BOUNDTYPE boundtype;
1687  SCIP_Real bound;
1688 
1689  assert(stat != NULL);
1690 
1691  var = conflictset->bdchginfos[i]->var;
1692  boundtype = SCIPbdchginfoGetBoundtype(conflictset->bdchginfos[i]);
1693  bound = conflictset->relaxedbds[i];
1694 
1695  branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
1696 
1697  SCIP_CALL( SCIPvarIncNActiveConflicts(var, blkmem, set, stat, branchdir, bound, (SCIP_Real)conflictlength) );
1698  SCIPhistoryIncNActiveConflicts(stat->glbhistory, branchdir, (SCIP_Real)conflictlength);
1699  SCIPhistoryIncNActiveConflicts(stat->glbhistorycrun, branchdir, (SCIP_Real)conflictlength);
1700 
1701  /* each variable which is part of the conflict gets an increase in the VSIDS */
1702  SCIP_CALL( incVSIDS(var, blkmem, set, stat, boundtype, bound, set->conf_conflictweight) );
1703  }
1704  conflict->nappliedglbconss++;
1705  conflict->nappliedglbliterals += conflictset->nbdchginfos;
1706  }
1707 
1708  return SCIP_OKAY;
1709 }
1710 
1711 
1712 /** check conflict set for redundancy, other conflicts in the same conflict analysis could have led to global reductions
1713  * an made this conflict set redundant
1714  */
1715 static
1717  SCIP_SET* set, /**< global SCIP settings */
1718  SCIP_CONFLICTSET* conflictset /**< conflict set */
1719  )
1720 {
1721  SCIP_BDCHGINFO** bdchginfos;
1722  SCIP_VAR* var;
1723  SCIP_Real* relaxedbds;
1724  SCIP_Real bound;
1725  int v;
1726 
1727  assert(set != NULL);
1728  assert(conflictset != NULL);
1729 
1730  bdchginfos = conflictset->bdchginfos;
1731  relaxedbds = conflictset->relaxedbds;
1732  assert(bdchginfos != NULL);
1733  assert(relaxedbds != NULL);
1734 
1735  /* check all boundtypes and bounds for redundancy */
1736  for( v = conflictset->nbdchginfos - 1; v >= 0; --v )
1737  {
1738  var = SCIPbdchginfoGetVar(bdchginfos[v]);
1739  assert(var != NULL);
1740  assert(SCIPvarGetProbindex(var) >= 0);
1741 
1742  /* check if the relaxed bound is really a relaxed bound */
1743  assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
1744  assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
1745 
1746  bound = relaxedbds[v];
1747 
1748  if( SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_UPPER )
1749  {
1751  {
1752  assert(SCIPsetIsIntegral(set, bound));
1753  bound += 1.0;
1754  }
1755 
1756  /* check if the bound is already fulfilled globally */
1757  if( SCIPsetIsFeasGE(set, SCIPvarGetLbGlobal(var), bound) )
1758  return TRUE;
1759  }
1760  else
1761  {
1762  assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_LOWER);
1763 
1765  {
1766  assert(SCIPsetIsIntegral(set, bound));
1767  bound -= 1.0;
1768  }
1769 
1770  /* check if the bound is already fulfilled globally */
1771  if( SCIPsetIsFeasLE(set, SCIPvarGetUbGlobal(var), bound) )
1772  return TRUE;
1773  }
1774  }
1775 
1776  return FALSE;
1777 }
1778 
1779 /** find global fixings which can be derived from the new conflict set */
1780 static
1782  SCIP_SET* set, /**< global SCIP settings */
1783  SCIP_PROB* prob, /**< transformed problem after presolve */
1784  SCIP_CONFLICTSET* conflictset, /**< conflict set to add to the tree */
1785  int* nbdchgs, /**< number of global deducted bound changes due to the conflict set */
1786  int* nredvars, /**< number of redundant and removed variables from conflict set */
1787  SCIP_Bool* redundant /**< did we found a gloabl reduction on a conflict set variable, which makes this conflict redundant */
1788  )
1789 {
1790  SCIP_BDCHGINFO** bdchginfos;
1791  SCIP_Real* relaxedbds;
1792  SCIP_VAR* var;
1793  SCIP_Bool* boundtypes;
1794  SCIP_Real* bounds;
1795  SCIP_Longint* nbinimpls;
1796  int* sortvals;
1797  SCIP_Real bound;
1798  SCIP_Bool isupper;
1799  int ntrivialredvars;
1800  int nbdchginfos;
1801  int nzeroimpls;
1802  int v;
1803 
1804  assert(set != NULL);
1805  assert(prob != NULL);
1806  assert(SCIPprobIsTransformed(prob));
1807  assert(conflictset != NULL);
1808  assert(nbdchgs != NULL);
1809  assert(nredvars != NULL);
1810  /* only check conflict sets with more than one variable */
1811  assert(conflictset->nbdchginfos > 1);
1812 
1813  *nbdchgs = 0;
1814  *nredvars = 0;
1815 
1816  /* due to other conflict in the same conflict analysis, this conflict set might have become redundant */
1817  *redundant = checkRedundancy(set, conflictset);
1818 
1819  if( *redundant )
1820  return SCIP_OKAY;
1821 
1822  bdchginfos = conflictset->bdchginfos;
1823  relaxedbds = conflictset->relaxedbds;
1824  nbdchginfos = conflictset->nbdchginfos;
1825  sortvals = conflictset->sortvals;
1826 
1827  assert(bdchginfos != NULL);
1828  assert(relaxedbds != NULL);
1829  assert(sortvals != NULL);
1830 
1831  /* check if the boolean representation of boundtypes matches the 'standard' definition */
1832  assert(SCIP_BOUNDTYPE_LOWER == FALSE); /*lint !e641*/
1833  assert(SCIP_BOUNDTYPE_UPPER == TRUE); /*lint !e641*/
1834 
1835  ntrivialredvars = 0;
1836 
1837  /* due to multiple conflict sets for one conflict, it can happen, that we already have redundant information in the
1838  * conflict set
1839  */
1840  for( v = nbdchginfos - 1; v >= 0; --v )
1841  {
1842  var = SCIPbdchginfoGetVar(bdchginfos[v]);
1843  bound = relaxedbds[v];
1844  isupper = (SCIP_Bool) SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(bdchginfos[v]));
1845 
1846  /* for integral variable we can increase/decrease the conflicting bound */
1847  if( SCIPvarIsIntegral(var) )
1848  bound += (isupper ? -1.0 : +1.0);
1849 
1850  /* if conflict variable cannot fulfill the conflict we can remove it */
1851  if( (isupper && SCIPsetIsFeasLT(set, bound, SCIPvarGetLbGlobal(var))) ||
1852  (!isupper && SCIPsetIsFeasGT(set, bound, SCIPvarGetUbGlobal(var))) )
1853  {
1854  SCIPdebugMessage("remove redundant variable <%s> from conflict set\n", SCIPvarGetName(var));
1855 
1856  bdchginfos[v] = bdchginfos[nbdchginfos - 1];
1857  relaxedbds[v] = relaxedbds[nbdchginfos - 1];
1858  sortvals[v] = sortvals[nbdchginfos - 1];
1859 
1860  --nbdchginfos;
1861  ++ntrivialredvars;
1862  }
1863  }
1864  assert(ntrivialredvars + nbdchginfos == conflictset->nbdchginfos);
1865 
1866  SCIPdebugMessage("trivially removed %d redundant of %d variables from conflictset (%p)\n", ntrivialredvars, conflictset->nbdchginfos, (void*)conflictset);
1867  conflictset->nbdchginfos = nbdchginfos;
1868  assert(conflictset->nbdchginfos > 0);
1869 
1870  /* do not check to big or trivial conflicts */
1871  if( conflictset->nbdchginfos > set->conf_maxvarsdetectimpliedbounds || conflictset->nbdchginfos == 1 )
1872  {
1873  *nredvars = ntrivialredvars;
1874  return SCIP_OKAY;
1875  }
1876 
1877  /* create array of boundtypes, and bound values in conflict set */
1878  SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtypes, nbdchginfos) );
1879  SCIP_CALL( SCIPsetAllocBufferArray(set, &bounds, nbdchginfos) );
1880  /* memory for the estimates for binary implications used for sorting */
1881  SCIP_CALL( SCIPsetAllocBufferArray(set, &nbinimpls, nbdchginfos) );
1882 
1883  nzeroimpls = 0;
1884 
1885  /* collect estimates and initialize variables, boundtypes, and bounds array */
1886  for( v = 0; v < nbdchginfos; ++v )
1887  {
1888  var = SCIPbdchginfoGetVar(bdchginfos[v]);
1889  boundtypes[v] = (SCIP_Bool) SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(bdchginfos[v]));
1890  bounds[v] = relaxedbds[v];
1891 
1892  assert(SCIPvarGetProbindex(var) >= 0);
1893 
1894  /* check if the relaxed bound is really a relaxed bound */
1895  assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
1896  assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
1897 
1898  /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
1899  if( SCIPvarIsBinary(var) )
1900  {
1901  if( !boundtypes[v] )
1902  {
1903  assert(SCIPsetIsZero(set, bounds[v]));
1904  bounds[v] = 1.0;
1905  nbinimpls[v] = SCIPvarGetNBinImpls(var, TRUE) + (SCIP_Longint)SCIPvarGetNCliques(var, TRUE) * 2;
1906  }
1907  else
1908  {
1909  assert(SCIPsetIsEQ(set, bounds[v], 1.0));
1910  bounds[v] = 0.0;
1911  nbinimpls[v] = SCIPvarGetNBinImpls(var, FALSE) + (SCIP_Longint)SCIPvarGetNCliques(var, FALSE) * 2;
1912  }
1913  }
1914  else if( SCIPvarIsIntegral(var) )
1915  {
1916  assert(SCIPsetIsIntegral(set, bounds[v]));
1917 
1918  bounds[v] += ((!boundtypes[v]) ? +1.0 : -1.0);
1919  nbinimpls[v] = (boundtypes[v] ? SCIPvarGetNVlbs(var) : SCIPvarGetNVubs(var));
1920  }
1921  else if( ((!boundtypes[v]) && SCIPsetIsFeasEQ(set, SCIPvarGetLbGlobal(var), bounds[v]))
1922  || ((boundtypes[v]) && SCIPsetIsFeasEQ(set, SCIPvarGetUbGlobal(var), bounds[v])) )
1923  {
1924  /* the literal is satisfied in global bounds (may happen due to weak "negation" of continuous variables)
1925  * -> discard the conflict constraint
1926  */
1927  break;
1928  }
1929  else
1930  {
1931  nbinimpls[v] = (boundtypes[v] ? SCIPvarGetNVlbs(var) : SCIPvarGetNVubs(var));
1932  }
1933 
1934  if( nbinimpls[v] == 0 )
1935  ++nzeroimpls;
1936  }
1937 
1938  /* starting to derive global bound changes */
1939  if( v == nbdchginfos && ((!set->conf_fullshortenconflict && nzeroimpls < 2) || (set->conf_fullshortenconflict && nzeroimpls < nbdchginfos)) )
1940  {
1941  SCIP_VAR** vars;
1942  SCIP_Bool* redundants;
1943 
1944  /* sort variables in increasing order of binary implications to gain speed later on */
1945  SCIPsortLongPtrRealRealBool(nbinimpls, (void**)bdchginfos, relaxedbds, bounds, boundtypes, v);
1946 
1947  SCIPdebugMessage("checking for global reductions and redundant conflict variables(in %s) on conflict:\n", SCIPprobGetName(prob));
1948  SCIPdebugMessage("[");
1949  for( v = 0; v < nbdchginfos; ++v )
1950  {
1951  SCIPdebugPrintf("%s %s %g", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfos[v])), (!boundtypes[v]) ? ">=" : "<=", bounds[v]);
1952  if( v < nbdchginfos - 1 )
1953  SCIPdebugPrintf(", ");
1954  }
1955  SCIPdebugPrintf("]\n");
1956 
1957  SCIP_CALL( SCIPsetAllocBufferArray(set, &vars, v) );
1958  SCIP_CALL( SCIPsetAllocBufferArray(set, &redundants, v) );
1959 
1960  /* initialize conflict variable data */
1961  for( v = 0; v < nbdchginfos; ++v )
1962  vars[v] = SCIPbdchginfoGetVar(bdchginfos[v]);
1963 
1964  SCIP_CALL( SCIPshrinkDisjunctiveVarSet(set->scip, vars, bounds, boundtypes, redundants, nbdchginfos, nredvars, nbdchgs, redundant, set->conf_fullshortenconflict) );
1965 
1966 #ifdef SCIP_DEBUG
1967  if( *nbdchgs > 0 )
1968  {
1969  SCIPdebugMessage("conflict set (%p) led to %d global bound reductions\n", (void*) conflictset, *nbdchgs);
1970  }
1971 #endif
1972 
1973  /* remove as redundant marked variables */
1974  if( *redundant )
1975  {
1976  SCIPdebugMessage("conflict set (%p) is redundant because at least one global reduction, fulfills the conflict constraint\n", (void*)conflictset);
1977  }
1978  else if( *nredvars > 0 )
1979  {
1980 #ifdef SCIP_DEBUG
1981  int nvars;
1982 #endif
1983 
1984  assert(bdchginfos == conflictset->bdchginfos);
1985  assert(relaxedbds == conflictset->relaxedbds);
1986  assert(sortvals == conflictset->sortvals);
1987 
1988  for( v = nbdchginfos - 1; v >= 0; --v )
1989  {
1990  /* if conflict variable was marked to be redundant remove it */
1991  if( redundants[v] )
1992  {
1993  SCIPdebugMessage("remove redundant variable <%s> from conflict set\n", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfos[v])));
1994 
1995  bdchginfos[v] = bdchginfos[nbdchginfos - 1];
1996  relaxedbds[v] = relaxedbds[nbdchginfos - 1];
1997  sortvals[v] = sortvals[nbdchginfos - 1];
1998 
1999  --nbdchginfos;
2000  }
2001  }
2002  assert((*nredvars) + nbdchginfos == conflictset->nbdchginfos);
2003 
2004  SCIPdebugMessage("removed %d redundant of %d variables from conflictset (%p)\n", (*nredvars), conflictset->nbdchginfos, (void*)conflictset);
2005  conflictset->nbdchginfos = nbdchginfos;
2006 
2007 #ifdef SCIP_DEBUG
2008  nvars = SCIPprobGetNVars(prob);
2009 
2010  SCIPdebugMessage("could shorten conflict (in %s) to:\n", SCIPprobGetName(prob));
2011  SCIPdebugMessage("[");
2012  for( v = 0; v < nbdchginfos; ++v )
2013  {
2014  int confidx;
2015 
2016  var = SCIPbdchginfoGetVar(bdchginfos[v]);;
2017 
2018  confidx = SCIPvarGetProbindex(var);
2019  assert(confidx >= 0);
2020 
2021  if( boundtypes[v] )
2022  confidx += nvars;
2023 
2024  /* if conflict variable was marked to be redundant remove it */
2025  if( redundants[confidx] > 0 )
2026  {
2027  SCIPdebugPrintf("%s %s %g", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfos[v])), (!boundtypes[v]) ? ">=" : "<=", bounds[v]);
2028  if( v < nbdchginfos - 1 )
2029  SCIPdebugPrintf(", ");
2030  }
2031  }
2032  SCIPdebugPrintf("]\n");
2033 #endif
2034 
2035  }
2036 
2037  SCIPsetFreeBufferArray(set, &redundants);
2038  SCIPsetFreeBufferArray(set, &vars);
2039  }
2040 
2041  /* free temporary memory */
2042  SCIPsetFreeBufferArray(set, &nbinimpls);
2043  SCIPsetFreeBufferArray(set, &bounds);
2044  SCIPsetFreeBufferArray(set, &boundtypes);
2045 
2046  *nredvars += ntrivialredvars;
2047 
2048  return SCIP_OKAY;
2049 }
2050 
2051 /** adds the given conflict set as conflict constraint to the problem */
2052 static
2054  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2055  BMS_BLKMEM* blkmem, /**< block memory */
2056  SCIP_SET* set, /**< global SCIP settings */
2057  SCIP_STAT* stat, /**< dynamic problem statistics */
2058  SCIP_PROB* transprob, /**< transformed problem after presolve */
2059  SCIP_PROB* origprob, /**< original problem */
2060  SCIP_TREE* tree, /**< branch and bound tree */
2061  SCIP_LP* lp, /**< current LP data */
2062  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2063  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2064  SCIP_CONFLICTSET* conflictset, /**< conflict set to add to the tree */
2065  int insertdepth, /**< depth level at which the conflict set should be added */
2066  SCIP_Bool* success /**< pointer to store whether the addition was successful */
2067  )
2068 {
2069  SCIP_Bool redundant;
2070  int h;
2071 
2072  assert(conflict != NULL);
2073  assert(tree != NULL);
2074  assert(tree->path != NULL);
2075  assert(conflictset != NULL);
2076  assert(conflictset->validdepth <= insertdepth);
2077  assert(success != NULL);
2078 
2079  *success = FALSE;
2080  redundant = FALSE;
2081 
2082  /* try to derive global bound changes and shorten the conflictset by using implication and clique and variable bound
2083  * information
2084  */
2085  if( conflictset->nbdchginfos > 1 && insertdepth == 0 )
2086  {
2087  int nbdchgs;
2088  int nredvars;
2089  int oldnbdchginfos = conflictset->nbdchginfos;
2090 
2091  assert(conflictset->validdepth == 0);
2092 
2093  SCIPclockStart(conflict->dIBclock, set);
2094 
2095  /* find global bound changes which can be derived from the new conflict set */
2096  SCIP_CALL( detectImpliedBounds(set, transprob, conflictset, &nbdchgs, &nredvars, &redundant) );
2097 
2098  /* debug check for reduced conflict set */
2099  if( nredvars > 0 )
2100  {
2101  /* check conflict set on debugging solution */
2102  SCIP_CALL( SCIPdebugCheckConflict(blkmem, set, tree->root, conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos) ); /*lint !e506 !e774*/
2103  }
2104 
2105  SCIPdebugMessage(" -> conflict set removed %d redundant variables (old nvars %d, new nvars = %d)\n", nredvars, oldnbdchginfos, conflictset->nbdchginfos);
2106  SCIPdebugMessage(" -> conflict set led to %d global bound changes %s(cdpt:%d, fdpt:%d, confdpt:%d, len:%d):\n",
2107  nbdchgs, redundant ? "(conflict became redundant) " : "", SCIPtreeGetCurrentDepth(tree), SCIPtreeGetFocusDepth(tree),
2108  conflictset->conflictdepth, conflictset->nbdchginfos);
2109  SCIPdebug(conflictsetPrint(conflictset));
2110 
2111  SCIPclockStop(conflict->dIBclock, set);
2112 
2113  if( redundant )
2114  {
2115  if( nbdchgs > 0 )
2116  *success = TRUE;
2117 
2118  return SCIP_OKAY;
2119  }
2120  }
2121 
2122  /* in case the conflict set contains only one bound change which is globally valid we apply that bound change
2123  * directly (except if we are in strong branching or diving - in this case a bound change would yield an unflushed LP
2124  * and is not handled when restoring the information)
2125  *
2126  * @note A bound change can only be applied if it is are related to the active node or if is a global bound
2127  * change. Bound changes which are related to any other node cannot be handled at point due to the internal
2128  * data structure
2129  */
2130  if( conflictset->nbdchginfos == 1 && insertdepth == 0 && !lp->strongbranching && !lp->diving )
2131  {
2132  SCIP_VAR* var;
2133  SCIP_Real bound;
2134  SCIP_BOUNDTYPE boundtype;
2135 
2136  var = conflictset->bdchginfos[0]->var;
2137  assert(var != NULL);
2138 
2139  boundtype = SCIPboundtypeOpposite((SCIP_BOUNDTYPE) conflictset->bdchginfos[0]->boundtype);
2140  bound = conflictset->relaxedbds[0];
2141 
2142  /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
2143  if( SCIPvarIsIntegral(var) )
2144  {
2145  assert(SCIPsetIsIntegral(set, bound));
2146  bound += (boundtype == SCIP_BOUNDTYPE_LOWER ? +1.0 : -1.0);
2147  }
2148 
2149  SCIPdebugMessage(" -> apply global bound change: <%s> %s %g\n",
2150  SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", bound);
2151 
2152  SCIP_CALL( SCIPnodeAddBoundchg(tree->path[conflictset->validdepth], blkmem, set, stat, transprob, origprob, tree, lp, branchcand,
2153  eventqueue, var, bound, boundtype, FALSE) );
2154 
2155  *success = TRUE;
2156  SCIP_CALL( updateStatistics(conflict, blkmem, set, stat, conflictset, insertdepth) );
2157  }
2158  else
2159  {
2160  /* sort conflict handlers by priority */
2162 
2163  /* call conflict handlers to create a conflict constraint */
2164  for( h = 0; h < set->nconflicthdlrs; ++h )
2165  {
2166  SCIP_RESULT result;
2167 
2168  SCIP_CALL( SCIPconflicthdlrExec(set->conflicthdlrs[h], set, tree->path[insertdepth],
2169  tree->path[conflictset->validdepth], conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos, *success, &result) );
2170  if( result == SCIP_CONSADDED )
2171  {
2172  *success = TRUE;
2173  SCIP_CALL( updateStatistics(conflict, blkmem, set, stat, conflictset, insertdepth) );
2174  }
2175 
2176  SCIPdebugMessage(" -> call conflict handler <%s> (prio=%d) to create conflict set with %d bounds returned result %d\n",
2177  SCIPconflicthdlrGetName(set->conflicthdlrs[h]), SCIPconflicthdlrGetPriority(set->conflicthdlrs[h]),
2178  conflictset->nbdchginfos, result);
2179  }
2180  }
2181 
2182  return SCIP_OKAY;
2183 }
2184 
2185 /** adds the collected conflict constraints to the corresponding nodes; the best set->conf_maxconss conflict constraints
2186  * are added to the node of their validdepth; additionally (if not yet added, and if repropagation is activated), the
2187  * conflict constraint that triggers the earliest repropagation is added to the node of its validdepth
2188  */
2190  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2191  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2192  SCIP_SET* set, /**< global SCIP settings */
2193  SCIP_STAT* stat, /**< dynamic problem statistics */
2194  SCIP_PROB* transprob, /**< transformed problem */
2195  SCIP_PROB* origprob, /**< original problem */
2196  SCIP_TREE* tree, /**< branch and bound tree */
2197  SCIP_LP* lp, /**< current LP data */
2198  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2199  SCIP_EVENTQUEUE* eventqueue /**< event queue */
2200  )
2201 {
2202  assert(conflict != NULL);
2203  assert(set != NULL);
2204  assert(stat != NULL);
2205  assert(transprob != NULL);
2206  assert(tree != NULL);
2207 
2208  /* is there anything to do? */
2209  if( conflict->nconflictsets > 0 )
2210  {
2211  SCIP_CONFLICTSET* repropconflictset;
2212  int nconflictsetsused;
2213  int focusdepth;
2214 #ifndef NDEBUG
2215  int currentdepth;
2216 #endif
2217  int cutoffdepth;
2218  int repropdepth;
2219  int maxconflictsets;
2220  int maxsize;
2221  int i;
2222 
2223  /* calculate the maximal number of conflict sets to accept, and the maximal size of each accepted conflict set */
2224  maxconflictsets = (set->conf_maxconss == -1 ? INT_MAX : set->conf_maxconss);
2225  maxsize = conflictCalcMaxsize(set, transprob);
2226 
2227  focusdepth = SCIPtreeGetFocusDepth(tree);
2228 #ifndef NDEBUG
2229  currentdepth = SCIPtreeGetCurrentDepth(tree);
2230  assert(focusdepth <= currentdepth);
2231  assert(currentdepth == tree->pathlen-1);
2232 #endif
2233 
2234  SCIPdebugMessage("flushing %d conflict sets at focus depth %d (maxconflictsets: %d, maxsize: %d)\n",
2235  conflict->nconflictsets, focusdepth, maxconflictsets, maxsize);
2236 
2237  /* mark the focus node to have produced conflict sets in the VBC tool output */
2238  SCIPvbcFoundConflict(stat->vbc, stat, tree->path[focusdepth]);
2239 
2240  /* insert the conflict sets at the corresponding nodes */
2241  nconflictsetsused = 0;
2242  cutoffdepth = INT_MAX;
2243  repropdepth = INT_MAX;
2244  repropconflictset = NULL;
2245  for( i = 0; i < conflict->nconflictsets && nconflictsetsused < maxconflictsets; ++i )
2246  {
2247  SCIP_CONFLICTSET* conflictset;
2248 
2249  conflictset = conflict->conflictsets[i];
2250  assert(conflictset != NULL);
2251  assert(0 <= conflictset->validdepth);
2252  assert(conflictset->validdepth <= conflictset->insertdepth);
2253  assert(conflictset->insertdepth <= focusdepth);
2254  assert(conflictset->insertdepth <= conflictset->repropdepth);
2255  assert(conflictset->repropdepth <= currentdepth || conflictset->repropdepth == INT_MAX); /* INT_MAX for dive/probing/strong */
2256  assert(conflictset->conflictdepth <= currentdepth || conflictset->conflictdepth == INT_MAX); /* INT_MAX for dive/probing/strong */
2257 
2258  /* ignore conflict sets that are only valid at a node that was already cut off */
2259  if( conflictset->insertdepth >= cutoffdepth )
2260  {
2261  SCIPdebugMessage(" -> ignoring conflict set with insertdepth %d >= cutoffdepth %d\n",
2262  conflictset->validdepth, cutoffdepth);
2263  continue;
2264  }
2265 
2266  /* if no conflict bounds exist, the node and its sub tree in the conflict set's valid depth can be
2267  * cut off completely
2268  */
2269  if( conflictset->nbdchginfos == 0 )
2270  {
2271  SCIPdebugMessage(" -> empty conflict set in depth %d cuts off sub tree at depth %d\n",
2272  focusdepth, conflictset->validdepth);
2273 
2274  SCIPnodeCutoff(tree->path[conflictset->validdepth], set, stat, tree);
2275  cutoffdepth = conflictset->validdepth;
2276  continue;
2277  }
2278 
2279  /* if the conflict set is too long, use the conflict set only if it decreases the repropagation depth */
2280  if( conflictset->nbdchginfos > maxsize )
2281  {
2282  SCIPdebugMessage(" -> conflict set is too long: %d > %d literals\n", conflictset->nbdchginfos, maxsize);
2283  if( set->conf_keepreprop && conflictset->repropagate && conflictset->repropdepth < repropdepth )
2284  {
2285  repropdepth = conflictset->repropdepth;
2286  repropconflictset = conflictset;
2287  }
2288  }
2289  else
2290  {
2291  SCIP_Bool success;
2292 
2293  /* call conflict handlers to create a conflict constraint */
2294  SCIP_CALL( conflictAddConflictCons(conflict, blkmem, set, stat, transprob, origprob,
2295  tree, lp, branchcand, eventqueue, conflictset, conflictset->insertdepth, &success) );
2296 
2297  if( success )
2298  {
2299  SCIPdebugMessage(" -> conflict set %d/%d added (cdpt:%d, fdpt:%d, insert:%d, valid:%d, conf:%d, reprop:%d, len:%d):\n",
2300  nconflictsetsused+1, maxconflictsets, SCIPtreeGetCurrentDepth(tree), SCIPtreeGetFocusDepth(tree),
2301  conflictset->insertdepth, conflictset->validdepth, conflictset->conflictdepth, conflictset->repropdepth,
2302  conflictset->nbdchginfos);
2303  SCIPdebug(conflictsetPrint(conflictset));
2304 
2305  if( conflictset->repropagate && conflictset->repropdepth <= repropdepth )
2306  {
2307  repropdepth = conflictset->repropdepth;
2308  repropconflictset = NULL;
2309  }
2310  nconflictsetsused++;
2311  }
2312  }
2313  }
2314 
2315  /* reactivate propagation on the first node where one of the new conflict sets trigger a deduction */
2316  if( set->conf_repropagate && repropdepth < cutoffdepth && repropdepth < tree->pathlen )
2317  {
2318  assert(0 <= repropdepth && repropdepth < tree->pathlen);
2319  assert((int) tree->path[repropdepth]->depth == repropdepth);
2320 
2321  /* if the conflict constraint of smallest repropagation depth was not yet added, insert it now */
2322  if( repropconflictset != NULL )
2323  {
2324  SCIP_Bool success;
2325 
2326  assert(repropconflictset->repropagate);
2327  assert(repropconflictset->repropdepth == repropdepth);
2328 
2329  SCIP_CALL( conflictAddConflictCons(conflict, blkmem, set, stat, transprob, origprob,
2330  tree, lp, branchcand, eventqueue, repropconflictset, repropdepth, &success) );
2331 #ifdef SCIP_DEBUG
2332  if( success )
2333  {
2334  SCIPdebugMessage(" -> additional reprop conflict set added (cdpt:%d, fdpt:%d, insert:%d, valid:%d, conf:%d, reprop:%d, len:%d):\n",
2336  repropconflictset->insertdepth, repropconflictset->validdepth, repropconflictset->conflictdepth,
2337  repropconflictset->repropdepth, repropconflictset->nbdchginfos);
2338  SCIPdebug(conflictsetPrint(repropconflictset));
2339  }
2340 #endif
2341  }
2342 
2343  /* mark the node in the repropdepth to be propagated again */
2344  SCIPnodePropagateAgain(tree->path[repropdepth], set, stat, tree);
2345 
2346  SCIPdebugMessage("marked node %p in depth %d to be repropagated due to conflicts found in depth %d\n",
2347  (void*)tree->path[repropdepth], repropdepth, focusdepth);
2348  }
2349 
2350  /* free the conflict storage */
2351  for( i = 0; i < conflict->nconflictsets; ++i )
2352  {
2353  conflictsetFree(&conflict->conflictsets[i], blkmem);
2354  }
2355  conflict->nconflictsets = 0;
2356  }
2357 
2358  /* free all temporarily created bound change information data */
2359  conflictFreeTmpBdchginfos(conflict, blkmem);
2360 
2361  return SCIP_OKAY;
2362 }
2363 
2364 /** returns the current number of conflict sets in the conflict set storage */
2366  SCIP_CONFLICT* conflict /**< conflict analysis data */
2367  )
2368 {
2369  assert(conflict != NULL);
2370 
2371  return conflict->nconflictsets;
2372 }
2373 
2374 /** returns the total number of conflict constraints that were added to the problem */
2376  SCIP_CONFLICT* conflict /**< conflict analysis data */
2377  )
2378 {
2379  assert(conflict != NULL);
2380 
2381  return conflict->nappliedglbconss + conflict->nappliedlocconss;
2382 }
2383 
2384 /** returns the total number of literals in conflict constraints that were added to the problem */
2386  SCIP_CONFLICT* conflict /**< conflict analysis data */
2387  )
2388 {
2389  assert(conflict != NULL);
2390 
2391  return conflict->nappliedglbliterals + conflict->nappliedlocliterals;
2392 }
2393 
2394 /** returns the total number of global bound changes applied by the conflict analysis */
2396  SCIP_CONFLICT* conflict /**< conflict analysis data */
2397  )
2398 {
2399  assert(conflict != NULL);
2400 
2401  return conflict->nglbchgbds;
2402 }
2403 
2404 /** returns the total number of conflict constraints that were added globally to the problem */
2406  SCIP_CONFLICT* conflict /**< conflict analysis data */
2407  )
2408 {
2409  assert(conflict != NULL);
2410 
2411  return conflict->nappliedglbconss;
2412 }
2413 
2414 /** returns the total number of literals in conflict constraints that were added globally to the problem */
2416  SCIP_CONFLICT* conflict /**< conflict analysis data */
2417  )
2418 {
2419  assert(conflict != NULL);
2420 
2421  return conflict->nappliedglbliterals;
2422 }
2423 
2424 /** returns the total number of local bound changes applied by the conflict analysis */
2426  SCIP_CONFLICT* conflict /**< conflict analysis data */
2427  )
2428 {
2429  assert(conflict != NULL);
2430 
2431  return conflict->nlocchgbds;
2432 }
2433 
2434 /** returns the total number of conflict constraints that were added locally to the problem */
2436  SCIP_CONFLICT* conflict /**< conflict analysis data */
2437  )
2438 {
2439  assert(conflict != NULL);
2440 
2441  return conflict->nappliedlocconss;
2442 }
2443 
2444 /** returns the total number of literals in conflict constraints that were added locally to the problem */
2446  SCIP_CONFLICT* conflict /**< conflict analysis data */
2447  )
2448 {
2449  assert(conflict != NULL);
2450 
2451  return conflict->nappliedlocliterals;
2452 }
2453 
2454 
2455 
2456 
2457 /*
2458  * Propagation Conflict Analysis
2459  */
2460 
2461 /** returns whether bound change has a valid reason that can be resolved in conflict analysis */
2462 static
2464  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
2465  )
2466 {
2467  assert(bdchginfo != NULL);
2468  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
2469 
2472  && SCIPbdchginfoGetInferProp(bdchginfo) != NULL));
2473 }
2474 
2475 /** compares two conflict set entries, such that bound changes infered later are
2476  * ordered prior to ones that were infered earlier
2477  */
2478 static
2479 SCIP_DECL_SORTPTRCOMP(conflictBdchginfoComp)
2480 { /*lint --e{715}*/
2481  SCIP_BDCHGINFO* bdchginfo1;
2482  SCIP_BDCHGINFO* bdchginfo2;
2483 
2484  bdchginfo1 = (SCIP_BDCHGINFO*)elem1;
2485  bdchginfo2 = (SCIP_BDCHGINFO*)elem2;
2486  assert(bdchginfo1 != NULL);
2487  assert(bdchginfo2 != NULL);
2488  assert(!SCIPbdchginfoIsRedundant(bdchginfo1));
2489  assert(!SCIPbdchginfoIsRedundant(bdchginfo2));
2490 
2492  return -1;
2493  else
2494  return +1;
2495 }
2496 
2497 /** return TRUE if conflict analysis is applicable; In case the function return FALSE there is no need to initialize the
2498  * conflict analysis since it will not be applied
2499  */
2501  SCIP_SET* set /**< global SCIP settings */
2502  )
2503 {
2504  /* check, if propagation conflict analysis is enabled */
2505  if( !set->conf_enable || !set->conf_useprop )
2506  return FALSE;
2507 
2508  /* check, if there are any conflict handlers to use a conflict set */
2509  if( set->nconflicthdlrs == 0 )
2510  return FALSE;
2511 
2512  return TRUE;
2513 }
2514 
2515 /** creates conflict analysis data for propagation conflicts */
2517  SCIP_CONFLICT** conflict, /**< pointer to conflict analysis data */
2518  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2519  SCIP_SET* set /**< global SCIP settings */
2520  )
2521 {
2522  assert(conflict != NULL);
2523 
2524  SCIP_ALLOC( BMSallocMemory(conflict) );
2525 
2526  SCIP_CALL( SCIPclockCreate(&(*conflict)->dIBclock, SCIP_CLOCKTYPE_DEFAULT) );
2527  SCIP_CALL( SCIPclockCreate(&(*conflict)->propanalyzetime, SCIP_CLOCKTYPE_DEFAULT) );
2528  SCIP_CALL( SCIPclockCreate(&(*conflict)->inflpanalyzetime, SCIP_CLOCKTYPE_DEFAULT) );
2529  SCIP_CALL( SCIPclockCreate(&(*conflict)->boundlpanalyzetime, SCIP_CLOCKTYPE_DEFAULT) );
2530  SCIP_CALL( SCIPclockCreate(&(*conflict)->sbanalyzetime, SCIP_CLOCKTYPE_DEFAULT) );
2531  SCIP_CALL( SCIPclockCreate(&(*conflict)->pseudoanalyzetime, SCIP_CLOCKTYPE_DEFAULT) );
2532  SCIP_CALL( SCIPpqueueCreate(&(*conflict)->bdchgqueue, set->mem_arraygrowinit, set->mem_arraygrowfac,
2533  conflictBdchginfoComp) );
2534  SCIP_CALL( SCIPpqueueCreate(&(*conflict)->forcedbdchgqueue, set->mem_arraygrowinit, set->mem_arraygrowfac,
2535  conflictBdchginfoComp) );
2536  SCIP_CALL( conflictsetCreate(&(*conflict)->conflictset, blkmem) );
2537  (*conflict)->conflictsets = NULL;
2538  (*conflict)->conflictsetscores = NULL;
2539  (*conflict)->tmpbdchginfos = NULL;
2540  (*conflict)->conflictsetssize = 0;
2541  (*conflict)->nconflictsets = 0;
2542  (*conflict)->tmpbdchginfossize = 0;
2543  (*conflict)->ntmpbdchginfos = 0;
2544  (*conflict)->count = 0;
2545  (*conflict)->nglbchgbds = 0;
2546  (*conflict)->nappliedglbconss = 0;
2547  (*conflict)->nappliedglbliterals = 0;
2548  (*conflict)->nlocchgbds = 0;
2549  (*conflict)->nappliedlocconss = 0;
2550  (*conflict)->nappliedlocliterals = 0;
2551  (*conflict)->npropcalls = 0;
2552  (*conflict)->npropsuccess = 0;
2553  (*conflict)->npropconfconss = 0;
2554  (*conflict)->npropconfliterals = 0;
2555  (*conflict)->npropreconvconss = 0;
2556  (*conflict)->npropreconvliterals = 0;
2557  (*conflict)->ninflpcalls = 0;
2558  (*conflict)->ninflpsuccess = 0;
2559  (*conflict)->ninflpconfconss = 0;
2560  (*conflict)->ninflpconfliterals = 0;
2561  (*conflict)->ninflpreconvconss = 0;
2562  (*conflict)->ninflpreconvliterals = 0;
2563  (*conflict)->ninflpiterations = 0;
2564  (*conflict)->nboundlpcalls = 0;
2565  (*conflict)->nboundlpsuccess = 0;
2566  (*conflict)->nboundlpconfconss = 0;
2567  (*conflict)->nboundlpconfliterals = 0;
2568  (*conflict)->nboundlpreconvconss = 0;
2569  (*conflict)->nboundlpreconvliterals = 0;
2570  (*conflict)->nboundlpiterations = 0;
2571  (*conflict)->nsbcalls = 0;
2572  (*conflict)->nsbsuccess = 0;
2573  (*conflict)->nsbconfconss = 0;
2574  (*conflict)->nsbconfliterals = 0;
2575  (*conflict)->nsbreconvconss = 0;
2576  (*conflict)->nsbreconvliterals = 0;
2577  (*conflict)->nsbiterations = 0;
2578  (*conflict)->npseudocalls = 0;
2579  (*conflict)->npseudosuccess = 0;
2580  (*conflict)->npseudoconfconss = 0;
2581  (*conflict)->npseudoconfliterals = 0;
2582  (*conflict)->npseudoreconvconss = 0;
2583  (*conflict)->npseudoreconvliterals = 0;
2584 
2585  return SCIP_OKAY;
2586 }
2587 
2588 /** frees conflict analysis data for propagation conflicts */
2590  SCIP_CONFLICT** conflict, /**< pointer to conflict analysis data */
2591  BMS_BLKMEM* blkmem /**< block memory of transformed problem */
2592  )
2593 {
2594  assert(conflict != NULL);
2595  assert(*conflict != NULL);
2596  assert((*conflict)->nconflictsets == 0);
2597  assert((*conflict)->ntmpbdchginfos == 0);
2598 
2599 #ifdef SCIP_CONFGRAPH
2600  confgraphFree();
2601 #endif
2602 
2603  SCIPclockFree(&(*conflict)->dIBclock);
2604  SCIPclockFree(&(*conflict)->propanalyzetime);
2605  SCIPclockFree(&(*conflict)->inflpanalyzetime);
2606  SCIPclockFree(&(*conflict)->boundlpanalyzetime);
2607  SCIPclockFree(&(*conflict)->sbanalyzetime);
2608  SCIPclockFree(&(*conflict)->pseudoanalyzetime);
2609  SCIPpqueueFree(&(*conflict)->bdchgqueue);
2610  SCIPpqueueFree(&(*conflict)->forcedbdchgqueue);
2611  conflictsetFree(&(*conflict)->conflictset, blkmem);
2612  BMSfreeMemoryArrayNull(&(*conflict)->conflictsets);
2613  BMSfreeMemoryArrayNull(&(*conflict)->conflictsetscores);
2614  BMSfreeMemoryArrayNull(&(*conflict)->tmpbdchginfos);
2615  BMSfreeMemory(conflict);
2616 
2617  return SCIP_OKAY;
2618 }
2619 
2620 /** clears the conflict queue and the current conflict set */
2621 static
2623  SCIP_CONFLICT* conflict /**< conflict analysis data */
2624  )
2625 {
2626  assert(conflict != NULL);
2627 
2628  SCIPpqueueClear(conflict->bdchgqueue);
2629  SCIPpqueueClear(conflict->forcedbdchgqueue);
2630  conflictsetClear(conflict->conflictset);
2631 }
2632 
2633 /** initializes the propagation conflict analysis by clearing the conflict candidate queue */
2635  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2636  SCIP_SET* set, /**< global SCIP settings */
2637  SCIP_STAT* stat, /**< problem statistics */
2638  SCIP_PROB* prob /**< problem data */
2639  )
2640 {
2641  assert(conflict != NULL);
2642  assert(set != NULL);
2643  assert(stat != NULL);
2644  assert(prob != NULL);
2645 
2646  SCIPdebugMessage("initializing conflict analysis\n");
2647 
2648  /* clear the conflict candidate queue and the conflict set */
2649  conflictClear(conflict);
2650 
2651  /* increase the conflict counter, such that binary variables of new conflict set and new conflict queue are labeled
2652  * with this new counter
2653  */
2654  conflict->count++;
2655  if( conflict->count == 0 ) /* make sure, 0 is not a valid conflict counter (may happen due to integer overflow) */
2656  conflict->count = 1;
2657 
2658  /* increase the conflict score weight for history updates of future conflict reasons */
2659  if( stat->nnodes > stat->lastconflictnode )
2660  {
2661  assert(0.0 < set->conf_scorefac && set->conf_scorefac <= 1.0);
2662  stat->vsidsweight /= set->conf_scorefac;
2663  assert(stat->vsidsweight > 0.0);
2664 
2665  /* if the conflict score for the next conflict exceeds 1000.0, rescale all history conflict scores */
2666  if( stat->vsidsweight >= 1000.0 )
2667  {
2668  int v;
2669 
2670  for( v = 0; v < prob->nvars; ++v )
2671  {
2672  SCIP_CALL( SCIPvarScaleVSIDS(prob->vars[v], 1.0/stat->vsidsweight) );
2673  }
2674  SCIPhistoryScaleVSIDS(stat->glbhistory, 1.0/stat->vsidsweight);
2676  stat->vsidsweight = 1.0;
2677  }
2678  stat->lastconflictnode = stat->nnodes;
2679  }
2680 
2681 #ifdef SCIP_CONFGRAPH
2682  confgraphFree();
2683  SCIP_CALL( confgraphCreate(set, conflict) );
2684 #endif
2685 
2686  return SCIP_OKAY;
2687 }
2688 
2689 /** marks bound to be present in the current conflict and returns whether a bound which is at least as tight was already
2690  * member of the current conflict (i.e., the given bound change does not need to be added)
2691  */
2692 static
2694  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2695  SCIP_BDCHGINFO* bdchginfo, /**< bound change to add to the conflict set */
2696  SCIP_Real relaxedbd /**< relaxed bound */
2697  )
2698 {
2699  SCIP_VAR* var;
2700  SCIP_Real newbound;
2701 
2702  assert(conflict != NULL);
2703 
2704  var = SCIPbdchginfoGetVar(bdchginfo);
2705  newbound = SCIPbdchginfoGetNewbound(bdchginfo);
2706  assert(var != NULL);
2707 
2708  switch( SCIPbdchginfoGetBoundtype(bdchginfo) )
2709  {
2710  case SCIP_BOUNDTYPE_LOWER:
2711  /* check if the variables lower bound is already member of the conflict */
2712  if( var->conflictlbcount == conflict->count )
2713  {
2714  /* the variable is already member of the conflict; hence check if the new bound is redundant */
2715  if( var->conflictlb > newbound )
2716  {
2717  SCIPdebugMessage("ignoring redundant bound change <%s> >= %g since a stronger lower bound exist <%s> >= %g\n",
2718  SCIPvarGetName(var), newbound, SCIPvarGetName(var), var->conflictlb);
2719  return TRUE;
2720  }
2721  else if( var->conflictlb == newbound ) /*lint !e777*/
2722  {
2723  SCIPdebugMessage("ignoring redundant bound change <%s> >= %g since this lower bound is already present\n", SCIPvarGetName(var), newbound);
2724  SCIPdebugMessage("adjust relaxed lower bound <%g> -> <%g>\n", var->conflictlb, relaxedbd);
2725  var->conflictrelaxedlb = MAX(var->conflictrelaxedlb, relaxedbd);
2726  return TRUE;
2727  }
2728  }
2729 
2730  /* add the variable lower bound to the current conflict */
2731  var->conflictlbcount = conflict->count;
2732 
2733  /* remember the lower bound and relaxed bound to allow only better/tighter lower bounds for that variables
2734  * w.r.t. this conflict
2735  */
2736  var->conflictlb = newbound;
2737  var->conflictrelaxedlb = relaxedbd;
2738 
2739  return FALSE;
2740 
2741  case SCIP_BOUNDTYPE_UPPER:
2742  /* check if the variables upper bound is already member of the conflict */
2743  if( var->conflictubcount == conflict->count )
2744  {
2745  /* the variable is already member of the conflict; hence check if the new bound is redundant */
2746  if( var->conflictub < newbound )
2747  {
2748  SCIPdebugMessage("ignoring redundant bound change <%s> <= %g since a stronger upper bound exist <%s> <= %g\n",
2749  SCIPvarGetName(var), newbound, SCIPvarGetName(var), var->conflictub);
2750  return TRUE;
2751  }
2752  else if( var->conflictub == newbound ) /*lint !e777*/
2753  {
2754  SCIPdebugMessage("ignoring redundant bound change <%s> <= %g since this upper bound is already present\n", SCIPvarGetName(var), newbound);
2755  SCIPdebugMessage("adjust relaxed upper bound <%g> -> <%g>\n", var->conflictub, relaxedbd);
2756  var->conflictrelaxedub = MIN(var->conflictrelaxedub, relaxedbd);
2757  return TRUE;
2758  }
2759  }
2760 
2761  /* add the variable upper bound to the current conflict */
2762  var->conflictubcount = conflict->count;
2763 
2764  /* remember the upper bound and relaxed bound to allow only better/tighter upper bounds for that variables
2765  * w.r.t. this conflict
2766  */
2767  var->conflictub = newbound;
2768  var->conflictrelaxedub = relaxedbd;
2769 
2770  return FALSE;
2771 
2772  default:
2773  SCIPerrorMessage("invalid bound type %d\n", SCIPbdchginfoGetBoundtype(bdchginfo));
2774  SCIPABORT();
2775  return FALSE; /*lint !e527*/
2776  }
2777 }
2778 
2779 /** puts bound change into the current conflict set */
2780 static
2782  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2783  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2784  SCIP_SET* set, /**< global SCIP settings */
2785  SCIP_BDCHGINFO* bdchginfo, /**< bound change to add to the conflict set */
2786  SCIP_Real relaxedbd /**< relaxed bound */
2787  )
2788 {
2789  assert(conflict != NULL);
2790  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
2791 
2792  /* check if the relaxed bound is really a relaxed bound */
2793  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
2794  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
2795 
2796  SCIPdebugMessage("putting bound change <%s> %s %g(%g) at depth %d to current conflict set\n",
2797  SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
2798  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", SCIPbdchginfoGetNewbound(bdchginfo),
2799  relaxedbd, SCIPbdchginfoGetDepth(bdchginfo));
2800 
2801  /* mark the bound to be member of the conflict and check if a bound which is at least as tight is already member of
2802  * the conflict
2803  */
2804  if( !conflictMarkBoundCheckPresence(conflict, bdchginfo, relaxedbd) )
2805  {
2806  /* add the bound change to the current conflict set */
2807  SCIP_CALL( conflictsetAddBound(conflict->conflictset, blkmem, set, bdchginfo, relaxedbd) );
2808 
2809 #ifdef SCIP_CONFGRAPH
2810  if( bdchginfo != confgraphcurrentbdchginfo )
2811  confgraphAddBdchg(bdchginfo);
2812 #endif
2813  }
2814 #ifdef SCIP_CONFGRAPH
2815  else
2816  confgraphLinkBdchg(bdchginfo);
2817 #endif
2818 
2819  return SCIP_OKAY;
2820 }
2821 
2822 /** returns whether the negation of the given bound change would lead to a globally valid literal */
2823 static
2825  SCIP_SET* set, /**< global SCIP settings */
2826  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
2827  )
2828 {
2829  SCIP_VAR* var;
2830  SCIP_BOUNDTYPE boundtype;
2831  SCIP_Real bound;
2832 
2833  var = SCIPbdchginfoGetVar(bdchginfo);
2834  boundtype = SCIPbdchginfoGetBoundtype(bdchginfo);
2835  bound = SCIPbdchginfoGetNewbound(bdchginfo);
2836 
2837  return (SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS
2838  && ((boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGE(set, bound, SCIPvarGetUbGlobal(var)))
2839  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLE(set, bound, SCIPvarGetLbGlobal(var)))));
2840 }
2841 
2842 /** adds given bound change information to the conflict candidate queue */
2843 static
2845  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2846  SCIP_SET* set, /**< global SCIP settings */
2847  SCIP_BDCHGINFO* bdchginfo, /**< bound change information */
2848  SCIP_Real relaxedbd /**< relaxed bound */
2849  )
2850 {
2851  assert(conflict != NULL);
2852  assert(set != NULL);
2853  assert(bdchginfo != NULL);
2854  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
2855 
2856  /* check if the relaxed bound is really a relaxed bound */
2857  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
2858  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
2859 
2860  /* mark the bound to be member of the conflict and check if a bound which is at least as tight is already member of
2861  * the conflict
2862  */
2863  if( !conflictMarkBoundCheckPresence(conflict, bdchginfo, relaxedbd) )
2864  {
2865  /* insert the bound change into the conflict queue */
2866  if( (!set->conf_preferbinary || SCIPvarIsBinary(SCIPbdchginfoGetVar(bdchginfo)))
2867  && !isBoundchgUseless(set, bdchginfo) )
2868  {
2869  SCIP_CALL( SCIPpqueueInsert(conflict->bdchgqueue, (void*)bdchginfo) );
2870  }
2871  else
2872  {
2873  SCIP_CALL( SCIPpqueueInsert(conflict->forcedbdchgqueue, (void*)bdchginfo) );
2874  }
2875 
2876 #ifdef SCIP_CONFGRAPH
2877  confgraphAddBdchg(bdchginfo);
2878 #endif
2879  }
2880 #ifdef SCIP_CONFGRAPH
2881  else
2882  confgraphLinkBdchg(bdchginfo);
2883 #endif
2884 
2885  return SCIP_OKAY;
2886 }
2887 
2888 /** convert variable and bound change to active variable */
2889 static
2891  SCIP_VAR** var, /**< pointer to variable */
2892  SCIP_SET* set, /**< global SCIP settings */
2893  SCIP_BOUNDTYPE* boundtype, /**< pointer to type of bound that was changed: lower or upper bound */
2894  SCIP_Real* bound /**< pointer to bound to convert, or NULL */
2895  )
2896 {
2897  SCIP_Real scalar;
2898  SCIP_Real constant;
2899 
2900  scalar = 1.0;
2901  constant = 0.0;
2902 
2903  /* transform given varibale to active varibale */
2904  SCIP_CALL( SCIPvarGetProbvarSum(var, set, &scalar, &constant) );
2905  assert(SCIPvarGetStatus(*var) == SCIP_VARSTATUS_FIXED || scalar != 0.0); /*lint !e777*/
2906 
2907  if( SCIPvarGetStatus(*var) == SCIP_VARSTATUS_FIXED )
2908  return SCIP_OKAY;
2909 
2910  /* if the scalar of the aggregation is negative, we have to switch the bound type */
2911  if( scalar < 0.0 )
2912  (*boundtype) = SCIPboundtypeOpposite(*boundtype);
2913 
2914  if( bound != NULL )
2915  {
2916  (*bound) -= constant;
2917  (*bound) /= scalar;
2918  }
2919 
2920  return SCIP_OKAY;
2921 }
2922 
2923 /** adds variable's bound to conflict candidate queue */
2924 static
2926  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2927  BMS_BLKMEM* blkmem, /**< block memory */
2928  SCIP_SET* set, /**< global SCIP settings */
2929  SCIP_STAT* stat, /**< dynamic problem statistics */
2930  SCIP_VAR* var, /**< problem variable */
2931  SCIP_BOUNDTYPE boundtype, /**< type of bound that was changed: lower or upper bound */
2932  SCIP_BDCHGINFO* bdchginfo, /**< bound change info, or NULL */
2933  SCIP_Real relaxedbd /**< relaxed bound */
2934  )
2935 {
2936  assert(SCIPvarIsActive(var));
2937  assert(bdchginfo != NULL);
2938  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
2939 
2940  SCIPdebugMessage(" -> adding bound <%s> %s %.15g(%.15g) [status:%d, type:%d, depth:%d, pos:%d, reason:<%s>, info:%d] to candidates\n",
2941  SCIPvarGetName(var),
2942  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
2943  SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd,
2944  SCIPvarGetStatus(var), SCIPvarGetType(var),
2945  SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
2946  SCIPbdchginfoGetChgtype(bdchginfo) == SCIP_BOUNDCHGTYPE_BRANCHING ? "branch"
2950  : "none")),
2952 
2953  /* the local bound change may be resolved and has to be put on the candidate queue;
2954  * we even put bound changes without inference information on the queue in order to automatically
2955  * eliminate multiple insertions of the same bound change
2956  */
2957  assert(SCIPbdchginfoGetVar(bdchginfo) == var);
2958  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == boundtype);
2959  assert(SCIPbdchginfoGetDepth(bdchginfo) >= 0);
2960  assert(SCIPbdchginfoGetPos(bdchginfo) >= 0);
2961 
2962  /* the relaxed bound should be a relaxation */
2963  assert(boundtype == SCIP_BOUNDTYPE_LOWER ? SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)) : SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
2964 
2965  /* the relaxed bound should be worse then the old bound of the bound change info */
2966  assert(boundtype == SCIP_BOUNDTYPE_LOWER ? SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) : SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
2967 
2968  /* put bound change information into priority queue */
2969  SCIP_CALL( conflictQueueBound(conflict, set, bdchginfo, relaxedbd) );
2970 
2971  /* each variable which is add to the conflict graph gets an increase in the VSIDS
2972  *
2973  * @note That is different to the VSIDS preseted in the literature
2974  */
2975  SCIP_CALL( incVSIDS(var, blkmem, set, stat, boundtype, relaxedbd, set->conf_conflictgraphweight) );
2976 
2977  return SCIP_OKAY;
2978 }
2979 
2980 /** adds variable's bound to conflict candidate queue */
2982  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2983  BMS_BLKMEM* blkmem, /**< block memory */
2984  SCIP_SET* set, /**< global SCIP settings */
2985  SCIP_STAT* stat, /**< dynamic problem statistics */
2986  SCIP_VAR* var, /**< problem variable */
2987  SCIP_BOUNDTYPE boundtype, /**< type of bound that was changed: lower or upper bound */
2988  SCIP_BDCHGIDX* bdchgidx /**< bound change index (time stamp of bound change), or NULL for current time */
2989  )
2990 {
2991  SCIP_BDCHGINFO* bdchginfo;
2992 
2993  assert(conflict != NULL);
2994  assert(stat != NULL);
2995  assert(var != NULL);
2996 
2997  /* convert bound to active problem variable */
2998  SCIP_CALL( convertToActiveVar(&var, set, &boundtype, NULL) );
2999 
3000  /* we can ignore fixed variables */
3002  return SCIP_OKAY;
3003 
3004  /* if the variable is multi-aggregated, add the bounds of all aggregation variables */
3006  {
3007  SCIP_VAR** vars;
3008  SCIP_Real* scalars;
3009  int nvars;
3010  int i;
3011 
3012  vars = SCIPvarGetMultaggrVars(var);
3013  scalars = SCIPvarGetMultaggrScalars(var);
3014  nvars = SCIPvarGetMultaggrNVars(var);
3015  for( i = 0; i < nvars; ++i )
3016  {
3017  SCIP_CALL( SCIPconflictAddBound(conflict, blkmem, set, stat, vars[i],
3018  (scalars[i] < 0.0 ? SCIPboundtypeOpposite(boundtype) : boundtype), bdchgidx) );
3019  }
3020 
3021  return SCIP_OKAY;
3022  }
3023  assert(SCIPvarIsActive(var));
3024 
3025  /* get bound change information */
3026  bdchginfo = SCIPvarGetBdchgInfo(var, boundtype, bdchgidx, FALSE);
3027 
3028  /* if bound of variable was not changed (this means it is still the global bound), we can ignore the conflicting
3029  * bound
3030  */
3031  if( bdchginfo == NULL )
3032  return SCIP_OKAY;
3033 
3034  assert(SCIPbdchgidxIsEarlier(SCIPbdchginfoGetIdx(bdchginfo), bdchgidx));
3035 
3036  SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchginfo, SCIPbdchginfoGetNewbound(bdchginfo)) );
3037 
3038  return SCIP_OKAY;
3039 }
3040 
3041 /** adds variable's bound to conflict candidate queue */
3043  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3044  BMS_BLKMEM* blkmem, /**< block memory */
3045  SCIP_SET* set, /**< global SCIP settings */
3046  SCIP_STAT* stat, /**< dynamic problem statistics */
3047  SCIP_VAR* var, /**< problem variable */
3048  SCIP_BOUNDTYPE boundtype, /**< type of bound that was changed: lower or upper bound */
3049  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
3050  SCIP_Real relaxedbd /**< the relaxed bound */
3051  )
3052 {
3053  SCIP_BDCHGINFO* bdchginfo;
3054  int nbdchgs;
3055 
3056  assert(conflict != NULL);
3057  assert(stat != NULL);
3058  assert(var != NULL);
3059 
3060  if( !SCIPvarIsActive(var) )
3061  {
3062  /* convert bound to active problem variable */
3063  SCIP_CALL( convertToActiveVar(&var, set, &boundtype, &relaxedbd) );
3064 
3065  /* we can ignore fixed variables */
3067  return SCIP_OKAY;
3068 
3069  /* if the variable is multi-aggregated, add the bounds of all aggregation variables */
3071  {
3072  SCIPdebugMessage("ignoring relaxed bound information since variable <%s> is multi-aggregated active\n", SCIPvarGetName(var));
3073 
3074  SCIP_CALL( SCIPconflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchgidx) );
3075 
3076  return SCIP_OKAY;
3077  }
3078  }
3079  assert(SCIPvarIsActive(var));
3080 
3081  /* get bound change information */
3082  bdchginfo = SCIPvarGetBdchgInfo(var, boundtype, bdchgidx, FALSE);
3083 
3084  /* if bound of variable was not changed (this means it is still the global bound), we can ignore the conflicting
3085  * bound
3086  */
3087  if( bdchginfo == NULL )
3088  return SCIP_OKAY;
3089 
3090  /* check that the bound change info is not a temporary one */
3091  assert(SCIPbdchgidxGetPos(&bdchginfo->bdchgidx) >= 0);
3092 
3093  /* get the position of the bound change information within the bound change array of the variable */
3094  nbdchgs = (int) bdchginfo->pos;
3095  assert(nbdchgs >= 0);
3096 
3097  /* if the relaxed bound should be ignored, set the relaxed bound to the bound given by the bdchgidx; that ensures
3098  * that the loop(s) below will be skipped
3099  */
3100  if( set->conf_ignorerelaxedbd )
3101  relaxedbd = SCIPbdchginfoGetNewbound(bdchginfo);
3102 
3103  /* search for the bound change information which includes the relaxed bound */
3104  if( boundtype == SCIP_BOUNDTYPE_LOWER )
3105  {
3106  SCIP_Real newbound;
3107 
3108  /* adjust relaxed lower bound w.r.t. variable type */
3109  SCIPvarAdjustLb(var, set, &relaxedbd);
3110 
3111  /* due to numericis we compare the relaxed lower bound to the one present at the particular time point and take
3112  * the better one
3113  */
3114  newbound = SCIPbdchginfoGetNewbound(bdchginfo);
3115  relaxedbd = MIN(relaxedbd, newbound);
3116 
3117  /* check if relaxed lower bound is smaller or equal to global lower bound; if so we can ignore the conflicting
3118  * bound
3119  */
3120  if( SCIPsetIsLE(set, relaxedbd, SCIPvarGetLbGlobal(var)) )
3121  return SCIP_OKAY;
3122 
3123  while( nbdchgs > 0 )
3124  {
3125  assert(SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
3126 
3127  /* check if the old lower bound is greater than or equal to relaxed lower bound; if not we found the bound
3128  * change info which we need to report
3129  */
3130  if( SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) )
3131  break;
3132 
3133  bdchginfo = SCIPvarGetBdchgInfoLb(var, nbdchgs-1);
3134 
3135  SCIPdebugMessage("lower bound change %d oldbd=%.15g, newbd=%.15g, depth=%d, pos=%d, redundant=%u\n",
3136  nbdchgs, SCIPbdchginfoGetOldbound(bdchginfo), SCIPbdchginfoGetNewbound(bdchginfo),
3137  SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
3138  SCIPbdchginfoIsRedundant(bdchginfo));
3139 
3140  /* if bound change is redundant (this means it now a global bound), we can ignore the conflicting bound */
3141  if( SCIPbdchginfoIsRedundant(bdchginfo) )
3142  return SCIP_OKAY;
3143 
3144  nbdchgs--;
3145  }
3146  assert(SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
3147  }
3148  else
3149  {
3150  SCIP_Real newbound;
3151 
3152  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
3153 
3154  /* adjust relaxed upper bound w.r.t. variable type */
3155  SCIPvarAdjustUb(var, set, &relaxedbd);
3156 
3157  /* due to numericis we compare the relaxed upper bound to the one present at the particular time point and take
3158  * the better one
3159  */
3160  newbound = SCIPbdchginfoGetNewbound(bdchginfo);
3161  relaxedbd = MAX(relaxedbd, newbound);
3162 
3163  /* check if relaxed upper bound is greater or equal to global upper bound; if so we can ignore the conflicting
3164  * bound
3165  */
3166  if( SCIPsetIsGE(set, relaxedbd, SCIPvarGetUbGlobal(var)) )
3167  return SCIP_OKAY;
3168 
3169  while( nbdchgs > 0 )
3170  {
3171  assert(SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
3172 
3173  /* check if the old upper bound is smaller than or equal to the relaxed upper bound; if not we found the
3174  * bound change info which we need to report
3175  */
3176  if( SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) )
3177  break;
3178 
3179  bdchginfo = SCIPvarGetBdchgInfoUb(var, nbdchgs-1);
3180 
3181  SCIPdebugMessage("upper bound change %d oldbd=%.15g, newbd=%.15g, depth=%d, pos=%d, redundant=%u\n",
3182  nbdchgs, SCIPbdchginfoGetOldbound(bdchginfo), SCIPbdchginfoGetNewbound(bdchginfo),
3183  SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
3184  SCIPbdchginfoIsRedundant(bdchginfo));
3185 
3186  /* if bound change is redundant (this means it now a global bound), we can ignore the conflicting bound */
3187  if( SCIPbdchginfoIsRedundant(bdchginfo) )
3188  return SCIP_OKAY;
3189 
3190  nbdchgs--;
3191  }
3192  assert(SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
3193  }
3194 
3195  assert(SCIPbdchgidxIsEarlier(SCIPbdchginfoGetIdx(bdchginfo), bdchgidx));
3196 
3197  /* put bound change information into priority queue */
3198  SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchginfo, relaxedbd) );
3199 
3200  return SCIP_OKAY;
3201 }
3202 
3203 /** checks if the given variable is already part of the current conflict set or queued for resolving with the same or
3204  * even stronger bound
3205  */
3207  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3208  SCIP_VAR* var, /**< problem variable */
3209  SCIP_SET* set, /**< global SCIP settings */
3210  SCIP_BOUNDTYPE boundtype, /**< type of bound for which the score should be increased */
3211  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
3212  SCIP_Bool* used /**< pointer to store if the variable is already used */
3213  )
3214 {
3215  SCIP_Real newbound;
3216 
3217  /* convert bound to active problem variable */
3218  SCIP_CALL( convertToActiveVar(&var, set, &boundtype, NULL) );
3219 
3221  *used = FALSE;
3222  else
3223  {
3224  assert(SCIPvarIsActive(var));
3225  assert(var != NULL);
3226 
3227  switch( boundtype )
3228  {
3229  case SCIP_BOUNDTYPE_LOWER:
3230 
3231  newbound = SCIPvarGetLbAtIndex(var, bdchgidx, FALSE);
3232 
3233  if( var->conflictlbcount == conflict->count && var->conflictlb >= newbound )
3234  {
3235  SCIPdebugMessage("already queued bound change <%s> >= %g\n", SCIPvarGetName(var), newbound);
3236  *used = TRUE;
3237  }
3238  else
3239  *used = FALSE;
3240  break;
3241  case SCIP_BOUNDTYPE_UPPER:
3242 
3243  newbound = SCIPvarGetUbAtIndex(var, bdchgidx, FALSE);
3244 
3245  if( var->conflictubcount == conflict->count && var->conflictub <= newbound )
3246  {
3247  SCIPdebugMessage("already queued bound change <%s> <= %g\n", SCIPvarGetName(var), newbound);
3248  *used = TRUE;
3249  }
3250  else
3251  *used = FALSE;
3252  break;
3253  default:
3254  SCIPerrorMessage("invalid bound type %d\n", boundtype);
3255  SCIPABORT();
3256  *used = FALSE; /*lint !e527*/
3257  }
3258  }
3259 
3260  return SCIP_OKAY;
3261 }
3262 
3263 /** returns the conflict lower bound if the variable is present in the current conflict set; otherwise the global lower
3264  * bound
3265  */
3267  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3268  SCIP_VAR* var /**< problem variable */
3269  )
3270 {
3271  if( var->conflictlbcount == conflict->count )
3272  {
3273  assert(EPSGE(var->conflictlb, var->conflictrelaxedlb, 1e-09));
3274  return var->conflictrelaxedlb;
3275  }
3276 
3277  return SCIPvarGetLbGlobal(var);
3278 }
3279 
3280 /** returns the conflict upper bound if the variable is present in the current conflict set; otherwise the global upper
3281  * bound
3282  */
3284  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3285  SCIP_VAR* var /**< problem variable */
3286  )
3287 {
3288  if( var->conflictubcount == conflict->count )
3289  {
3290  assert(EPSLE(var->conflictub, var->conflictrelaxedub, 1e-09));
3291  return var->conflictrelaxedub;
3292  }
3293 
3294  return SCIPvarGetUbGlobal(var);
3295 }
3296 
3297 /** removes and returns next conflict analysis candidate from the candidate queue */
3298 static
3300  SCIP_CONFLICT* conflict /**< conflict analysis data */
3301  )
3302 {
3303  SCIP_BDCHGINFO* bdchginfo;
3304  SCIP_VAR* var;
3305 
3306  assert(conflict != NULL);
3307 
3308  if( SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0 )
3309  bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->forcedbdchgqueue));
3310  else
3311  bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->bdchgqueue));
3312 
3313  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3314 
3315  /* if we have a candidate this one should be valid for the current conflict analysis */
3316  assert(!bdchginfoIsInvalid(conflict, bdchginfo));
3317 
3318  /* mark the bound change to be no longer in the conflict (it will be either added again to the conflict set or
3319  * replaced by resolving, which might add a weaker change on the same bound to the queue)
3320  */
3321  var = SCIPbdchginfoGetVar(bdchginfo);
3323  {
3324  var->conflictlbcount = 0;
3326  }
3327  else
3328  {
3329  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER);
3330  var->conflictubcount = 0;
3332  }
3333 
3334 #ifdef SCIP_CONFGRAPH
3335  confgraphSetCurrentBdchg(bdchginfo);
3336 #endif
3337 
3338  return bdchginfo;
3339 }
3340 
3341 /** returns next conflict analysis candidate from the candidate queue without removing it */
3342 static
3344  SCIP_CONFLICT* conflict /**< conflict analysis data */
3345  )
3346 {
3347  SCIP_BDCHGINFO* bdchginfo;
3348 
3349  assert(conflict != NULL);
3350 
3351  if( SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0 )
3352  {
3353  /* get next potetioal candidate */
3354  bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueFirst(conflict->forcedbdchgqueue));
3355 
3356  /* check if this candidate is valid */
3357  if( bdchginfoIsInvalid(conflict, bdchginfo) )
3358  {
3359  SCIPdebugMessage("bound change info [%d:<%s> %s %g] is invaild -> pop it from the force queue\n", SCIPbdchginfoGetDepth(bdchginfo),
3360  SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
3361  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3362  SCIPbdchginfoGetNewbound(bdchginfo));
3363 
3364  /* pop the invalid bound change info from the queue */
3365  (void)(SCIPpqueueRemove(conflict->forcedbdchgqueue));
3366 
3367  /* call method recursively to get next conflict analysis candidate */
3368  bdchginfo = conflictFirstCand(conflict);
3369  }
3370  }
3371  else
3372  {
3373  bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueFirst(conflict->bdchgqueue));
3374 
3375  /* check if this candidate is valid */
3376  if( bdchginfo != NULL && bdchginfoIsInvalid(conflict, bdchginfo) )
3377  {
3378  SCIPdebugMessage("bound change info [%d:<%s> %s %g] is invaild -> pop it from the queue\n", SCIPbdchginfoGetDepth(bdchginfo),
3379  SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
3380  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3381  SCIPbdchginfoGetNewbound(bdchginfo));
3382 
3383  /* pop the invalid bound change info from the queue */
3384  (void)(SCIPpqueueRemove(conflict->bdchgqueue));
3385 
3386  /* call method recursively to get next conflict analysis candidate */
3387  bdchginfo = conflictFirstCand(conflict);
3388  }
3389  }
3390  assert(bdchginfo == NULL || !SCIPbdchginfoIsRedundant(bdchginfo));
3391 
3392  return bdchginfo;
3393 }
3394 
3395 /** adds the current conflict set (extended by all remaining bound changes in the queue) to the pool of conflict sets */
3396 static
3398  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3399  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3400  SCIP_SET* set, /**< global SCIP settings */
3401  SCIP_STAT* stat, /**< dynamic problem statistics */
3402  SCIP_TREE* tree, /**< branch and bound tree */
3403  int validdepth, /**< minimal depth level at which the conflict set is valid */
3404  SCIP_Bool diving, /**< are we in strong branching or diving mode? */
3405  SCIP_Bool repropagate, /**< should the constraint trigger a repropagation? */
3406  SCIP_Bool* success, /**< pointer to store whether the conflict set is valid */
3407  int* nliterals /**< pointer to store the number of literals in the generated conflictset */
3408  )
3409 {
3410  SCIP_CONFLICTSET* conflictset;
3411  SCIP_BDCHGINFO** bdchginfos;
3412  int nbdchginfos;
3413  int currentdepth;
3414  int focusdepth;
3415 
3416  assert(conflict != NULL);
3417  assert(conflict->conflictset != NULL);
3418  assert(set != NULL);
3419  assert(stat != NULL);
3420  assert(tree != NULL);
3421  assert(success != NULL);
3422  assert(nliterals != NULL);
3423  assert(SCIPpqueueNElems(conflict->forcedbdchgqueue) == 0);
3424 
3425  *success = FALSE;
3426  *nliterals = 0;
3427 
3428  /* check, whether local conflicts are allowed */
3429  validdepth = MAX(validdepth, conflict->conflictset->validdepth);
3430  if( !set->conf_allowlocal && validdepth > 0 )
3431  return SCIP_OKAY;
3432 
3433  focusdepth = SCIPtreeGetFocusDepth(tree);
3434  currentdepth = SCIPtreeGetCurrentDepth(tree);
3435  assert(currentdepth == tree->pathlen-1);
3436  assert(focusdepth <= currentdepth);
3437  assert(0 <= conflict->conflictset->validdepth && conflict->conflictset->validdepth <= currentdepth);
3438  assert(0 <= validdepth && validdepth <= currentdepth);
3439 
3440  /* get the elements of the bound change queue */
3441  bdchginfos = (SCIP_BDCHGINFO**)SCIPpqueueElems(conflict->bdchgqueue);
3442  nbdchginfos = SCIPpqueueNElems(conflict->bdchgqueue);
3443 
3444  /* create a copy of the current conflict set, allocating memory for the additional elements of the queue */
3445  SCIP_CALL( conflictsetCopy(&conflictset, blkmem, conflict->conflictset, nbdchginfos) );
3446  conflictset->validdepth = validdepth;
3447  conflictset->repropagate = repropagate;
3448 
3449  /* add the valid queue elements to the conflict set */
3450  SCIPdebugMessage("adding %d variables from the queue as temporary conflict variables\n", nbdchginfos);
3451  SCIP_CALL( conflictsetAddBounds(conflict, conflictset, blkmem, set, bdchginfos, nbdchginfos) );
3452 
3453  /* calculate the depth, at which the conflictset should be inserted */
3454  SCIP_CALL( conflictsetCalcInsertDepth(conflictset, set, tree) );
3455  assert(conflictset->validdepth <= conflictset->insertdepth && conflictset->insertdepth <= currentdepth);
3456  SCIPdebugMessage(" -> conflict with %d literals found at depth %d is active in depth %d and valid in depth %d\n",
3457  conflictset->nbdchginfos, currentdepth, conflictset->insertdepth, conflictset->validdepth);
3458 
3459  /* if all branching variables are in the conflict set, the conflict set is of no use;
3460  * don't use conflict sets that are only valid in the probing path but not in the problem tree
3461  */
3462  if( (diving || conflictset->insertdepth < currentdepth) && conflictset->insertdepth <= focusdepth )
3463  {
3464  /* if the conflict should not be located only in the subtree where it is useful, put it to its valid depth level */
3465  if( !set->conf_settlelocal )
3466  conflictset->insertdepth = conflictset->validdepth;
3467 
3468  *nliterals = conflictset->nbdchginfos;
3469  SCIPdebugMessage(" -> final conflict set has %d literals\n", *nliterals);
3470 
3471  /* check conflict set on debugging solution */
3472  SCIP_CALL( SCIPdebugCheckConflict(blkmem, set, tree->path[validdepth],
3473  conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos) ); /*lint !e506 !e774*/
3474 
3475  /* move conflictset to the conflictset storage */
3476  SCIP_CALL( conflictInsertConflictset(conflict, blkmem, set, &conflictset) );
3477  *success = TRUE;
3478  }
3479  else
3480  {
3481  /* free the temporary conflict set */
3482  conflictsetFree(&conflictset, blkmem);
3483  }
3484 
3485  return SCIP_OKAY;
3486 }
3487 
3488 /** tries to resolve given bound change
3489  * - resolutions on local constraints are only applied, if the constraint is valid at the
3490  * current minimal valid depth level, because this depth level is the topmost level to add the conflict
3491  * constraint to anyways
3492  *
3493  * @note it is sufficient to explain the relaxed bound change
3494  */
3495 static
3497  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3498  SCIP_SET* set, /**< global SCIP settings */
3499  SCIP_BDCHGINFO* bdchginfo, /**< bound change to resolve */
3500  SCIP_Real relaxedbd, /**< the relaxed bound */
3501  int validdepth, /**< minimal depth level at which the conflict is valid */
3502  SCIP_Bool* resolved /**< pointer to store whether the bound change was resolved */
3503  )
3504 {
3505  SCIP_VAR* actvar;
3506  SCIP_CONS* infercons;
3507  SCIP_PROP* inferprop;
3508  SCIP_RESULT result;
3509 
3510 #ifndef NDEBUG
3511  int nforcedbdchgqueue;
3512  int nbdchgqueue;
3513  int i;
3514 
3515  /* store the current size of the conflict queues */
3516  nforcedbdchgqueue = SCIPpqueueNElems(conflict->forcedbdchgqueue);
3517  nbdchgqueue = SCIPpqueueNElems(conflict->bdchgqueue);
3518 #endif
3519 
3520  assert(conflict != NULL);
3521  assert(resolved != NULL);
3522  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3523 
3524  *resolved = FALSE;
3525 
3526  actvar = SCIPbdchginfoGetVar(bdchginfo);
3527  assert(actvar != NULL);
3528  assert(SCIPvarIsActive(actvar));
3529 
3530  SCIPdebugMessage("processing next conflicting bound (depth: %d, valid depth: %d, bdchgtype: %s [%s], vartype: %d): [<%s> %s %g(%g)]\n",
3531  SCIPbdchginfoGetDepth(bdchginfo), validdepth,
3532  SCIPbdchginfoGetChgtype(bdchginfo) == SCIP_BOUNDCHGTYPE_BRANCHING ? "branch"
3533  : SCIPbdchginfoGetChgtype(bdchginfo) == SCIP_BOUNDCHGTYPE_CONSINFER ? "cons" : "prop",
3537  : SCIPbdchginfoGetInferProp(bdchginfo) == NULL ? "-"
3539  SCIPvarGetType(actvar), SCIPvarGetName(actvar),
3540  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3541  SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd);
3542  SCIPdebugMessage(" - conflict set :");
3543 
3544 #ifndef NDEBUG
3545  for( i = 0; i < conflict->conflictset->nbdchginfos; ++i )
3546  {
3547  SCIPdebugPrintf(" [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(conflict->conflictset->bdchginfos[i]),
3549  SCIPbdchginfoGetBoundtype(conflict->conflictset->bdchginfos[i]) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3550  SCIPbdchginfoGetNewbound(conflict->conflictset->bdchginfos[i]), conflict->conflictset->relaxedbds[i]);
3551  }
3552  SCIPdebugPrintf("\n");
3553  SCIPdebugMessage(" - forced candidates :");
3554 
3555  for( i = 0; i < nforcedbdchgqueue; ++i )
3556  {
3558  SCIPdebugPrintf(" [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(info), SCIPvarGetName(SCIPbdchginfoGetVar(info)),
3559  bdchginfoIsInvalid(conflict, info) ? "<!>" : SCIPbdchginfoGetBoundtype(info) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3561  }
3562  SCIPdebugPrintf("\n");
3563  SCIPdebugMessage(" - optional candidates:");
3564 
3565  for( i = 0; i < nbdchgqueue; ++i )
3566  {
3567  SCIP_BDCHGINFO* info = (SCIP_BDCHGINFO*)(SCIPpqueueElems(conflict->bdchgqueue)[i]);
3568  SCIPdebugPrintf(" [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(info), SCIPvarGetName(SCIPbdchginfoGetVar(info)),
3569  bdchginfoIsInvalid(conflict, info) ? "<!>" : SCIPbdchginfoGetBoundtype(info) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3571  }
3572  SCIPdebugPrintf("\n");
3573 #endif
3574 
3575  /* check, if the bound change can and should be resolved:
3576  * - resolutions on local constraints should only be applied, if the constraint is valid at the
3577  * current minimal valid depth level (which is initialized with the valid depth level of the initial
3578  * conflict set), because this depth level is the topmost level to add the conflict constraint to anyways
3579  */
3580  switch( SCIPbdchginfoGetChgtype(bdchginfo) )
3581  {
3583  infercons = SCIPbdchginfoGetInferCons(bdchginfo);
3584  assert(infercons != NULL);
3585 
3586  if( SCIPconsIsGlobal(infercons) || SCIPconsGetValidDepth(infercons) <= validdepth )
3587  {
3588  SCIP_VAR* infervar;
3589  int inferinfo;
3590  SCIP_BOUNDTYPE inferboundtype;
3591  SCIP_BDCHGIDX* bdchgidx;
3592 
3593  /* resolve bound change by asking the constraint that infered the bound to put all bounds that were
3594  * the reasons for the conflicting bound change on the priority queue
3595  */
3596  infervar = SCIPbdchginfoGetInferVar(bdchginfo);
3597  inferinfo = SCIPbdchginfoGetInferInfo(bdchginfo);
3598  inferboundtype = SCIPbdchginfoGetInferBoundtype(bdchginfo);
3599  bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
3600  assert(infervar != NULL);
3601 
3602  SCIPdebugMessage("resolving bound <%s> %s %g(%g) [status:%d, type:%d, depth:%d, pos:%d]: <%s> %s %g [cons:<%s>(%s), info:%d]\n",
3603  SCIPvarGetName(actvar),
3604  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3605  SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd,
3606  SCIPvarGetStatus(actvar), SCIPvarGetType(actvar),
3607  SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
3608  SCIPvarGetName(infervar),
3609  inferboundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3610  SCIPvarGetBdAtIndex(infervar, inferboundtype, bdchgidx, TRUE),
3611  SCIPconsGetName(infercons),
3612  SCIPconsIsGlobal(infercons) ? "global" : "local",
3613  inferinfo);
3614 
3615  /* in case the inference variables is not an active variables, we need to transform the relaxed bound */
3616  if( actvar != infervar )
3617  {
3618  SCIP_VAR* var;
3619  SCIP_Real scalar;
3620  SCIP_Real constant;
3621 
3622  assert(SCIPvarGetStatus(infervar) == SCIP_VARSTATUS_AGGREGATED
3623  || SCIPvarGetStatus(infervar) == SCIP_VARSTATUS_NEGATED);
3624 
3625  scalar = 1.0;
3626  constant = 0.0;
3627 
3628  var = infervar;
3629 
3630  /* transform given varibale to active varibale */
3631  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
3632  assert(var == actvar);
3633 
3634  relaxedbd *= scalar;
3635  relaxedbd += constant;
3636  }
3637 
3638  SCIP_CALL( SCIPconsResolvePropagation(infercons, set, infervar, inferinfo, inferboundtype, bdchgidx, relaxedbd, &result) );
3639  *resolved = (result == SCIP_SUCCESS);
3640  }
3641  break;
3642 
3644  inferprop = SCIPbdchginfoGetInferProp(bdchginfo);
3645  if( inferprop != NULL )
3646  {
3647  SCIP_VAR* infervar;
3648  int inferinfo;
3649  SCIP_BOUNDTYPE inferboundtype;
3650  SCIP_BDCHGIDX* bdchgidx;
3651 
3652  /* resolve bound change by asking the propagator that infered the bound to put all bounds that were
3653  * the reasons for the conflicting bound change on the priority queue
3654  */
3655  infervar = SCIPbdchginfoGetInferVar(bdchginfo);
3656  inferinfo = SCIPbdchginfoGetInferInfo(bdchginfo);
3657  inferboundtype = SCIPbdchginfoGetInferBoundtype(bdchginfo);
3658  bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
3659  assert(infervar != NULL);
3660 
3661  SCIPdebugMessage("resolving bound <%s> %s %g(%g) [status:%d, depth:%d, pos:%d]: <%s> %s %g [prop:<%s>, info:%d]\n",
3662  SCIPvarGetName(actvar),
3663  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3664  SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd,
3665  SCIPvarGetStatus(actvar), SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
3666  SCIPvarGetName(infervar),
3667  inferboundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
3668  SCIPvarGetBdAtIndex(infervar, inferboundtype, bdchgidx, TRUE),
3669  SCIPpropGetName(inferprop), inferinfo);
3670 
3671  SCIP_CALL( SCIPpropResolvePropagation(inferprop, set, infervar, inferinfo, inferboundtype, bdchgidx, relaxedbd, &result) );
3672  *resolved = (result == SCIP_SUCCESS);
3673  }
3674  break;
3675 
3677  assert(!(*resolved));
3678  break;
3679 
3680  default:
3681  SCIPerrorMessage("invalid bound change type <%d>\n", SCIPbdchginfoGetChgtype(bdchginfo));
3682  return SCIP_INVALIDDATA;
3683  }
3684 
3685  SCIPdebugMessage("resolving status: %u\n", *resolved);
3686 
3687 #ifndef NDEBUG
3688  /* subract the size of the conflicq queues */
3689  nforcedbdchgqueue -= SCIPpqueueNElems(conflict->forcedbdchgqueue);
3690  nbdchgqueue -= SCIPpqueueNElems(conflict->bdchgqueue);
3691 
3692  /* in case the bound change was not resolved, the conflict queues should have the same size (contents) */
3693  assert((*resolved) || (nforcedbdchgqueue == 0 && nbdchgqueue == 0));
3694 #endif
3695 
3696  return SCIP_OKAY;
3697 }
3698 
3699 /** if only one conflicting bound change of the last depth level was used, and if this can be resolved,
3700  * creates GRASP-like reconvergence conflict constraints in the conflict graph up to the branching variable of this
3701  * depth level
3702  */
3703 static
3705  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3706  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3707  SCIP_SET* set, /**< global SCIP settings */
3708  SCIP_STAT* stat, /**< problem statistics */
3709  SCIP_PROB* prob, /**< problem data */
3710  SCIP_TREE* tree, /**< branch and bound tree */
3711  SCIP_Bool diving, /**< are we in strong branching or diving mode? */
3712  int validdepth, /**< minimal depth level at which the initial conflict set is valid */
3713  SCIP_BDCHGINFO* firstuip, /**< first UIP of conflict graph */
3714  int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
3715  int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
3716  )
3717 {
3718  SCIP_BDCHGINFO* uip;
3719  int firstuipdepth;
3720  int focusdepth;
3721  int currentdepth;
3722  int maxvaliddepth;
3723 
3724  assert(conflict != NULL);
3725  assert(firstuip != NULL);
3726  assert(nreconvconss != NULL);
3727  assert(nreconvliterals != NULL);
3728  assert(!SCIPbdchginfoIsRedundant(firstuip));
3729 
3730  focusdepth = SCIPtreeGetFocusDepth(tree);
3731  currentdepth = SCIPtreeGetCurrentDepth(tree);
3732  assert(currentdepth == tree->pathlen-1);
3733  assert(focusdepth <= currentdepth);
3734 
3735  /* check, whether local constraints are allowed; however, don't generate reconvergence constraints that are only valid
3736  * in the probing path and not in the problem tree (i.e. that exceed the focusdepth)
3737  */
3738  maxvaliddepth = (set->conf_allowlocal ? MIN(currentdepth-1, focusdepth) : 0);
3739  if( validdepth > maxvaliddepth )
3740  return SCIP_OKAY;
3741 
3742  firstuipdepth = SCIPbdchginfoGetDepth(firstuip);
3743 
3744  /* for each succeeding UIP pair of the last depth level, create one reconvergence constraint */
3745  uip = firstuip;
3746  while( uip != NULL && SCIPbdchginfoGetDepth(uip) == SCIPbdchginfoGetDepth(firstuip) && bdchginfoIsResolvable(uip) )
3747  {
3748  SCIP_BDCHGINFO* oppositeuip;
3749  SCIP_BDCHGINFO* bdchginfo;
3750  SCIP_BDCHGINFO* nextuip;
3751  SCIP_VAR* uipvar;
3752  SCIP_Real oppositeuipbound;
3753  SCIP_BOUNDTYPE oppositeuipboundtype;
3754  int nresolutions;
3755 
3756  assert(!SCIPbdchginfoIsRedundant(uip));
3757 
3758  SCIPdebugMessage("creating reconvergence constraint for UIP <%s> %s %g in depth %d pos %d\n",
3761 
3762  /* initialize conflict data */
3763  SCIP_CALL( SCIPconflictInit(conflict, set, stat, prob) );
3764 
3765  /* create a temporary bound change information for the negation of the UIP's bound change;
3766  * this bound change information is freed in the SCIPconflictFlushConss() call;
3767  * for reconvergence constraints for continuous variables we can only use the "negation" !(x <= u) == (x >= u);
3768  * during conflict analysis, we treat a continuous bound "x >= u" in the conflict set as "x > u", and in the
3769  * generated constraint this is negated again to "x <= u" which is correct.
3770  */
3771  uipvar = SCIPbdchginfoGetVar(uip);
3772  oppositeuipboundtype = SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(uip));
3773  oppositeuipbound = SCIPbdchginfoGetNewbound(uip);
3774  if( SCIPvarIsIntegral(uipvar) )
3775  {
3776  assert(SCIPsetIsIntegral(set, oppositeuipbound));
3777  oppositeuipbound += (oppositeuipboundtype == SCIP_BOUNDTYPE_LOWER ? +1.0 : -1.0);
3778  }
3779  SCIP_CALL( conflictCreateTmpBdchginfo(conflict, blkmem, set, uipvar,
3780  oppositeuipboundtype, oppositeuipboundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_REAL_MIN : SCIP_REAL_MAX,
3781  oppositeuipbound, &oppositeuip) );
3782 
3783  /* put the negated UIP into the conflict set */
3784  SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, oppositeuip, oppositeuipbound) );
3785 
3786  /* put positive UIP into priority queue */
3787  SCIP_CALL( conflictQueueBound(conflict, set, uip, SCIPbdchginfoGetNewbound(uip) ) );
3788 
3789  /* resolve the queue until the next UIP is reached */
3790  bdchginfo = conflictFirstCand(conflict);
3791  nextuip = NULL;
3792  nresolutions = 0;
3793  while( bdchginfo != NULL && validdepth <= maxvaliddepth )
3794  {
3795  SCIP_BDCHGINFO* nextbdchginfo;
3796  SCIP_Real relaxedbd;
3797  SCIP_Bool forceresolve;
3798  int bdchgdepth;
3799 
3800  /* check if the next bound change must be resolved in every case */
3801  forceresolve = (SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0);
3802 
3803  /* remove currently processed candidate and get next conflicting bound from the conflict candidate queue before
3804  * we remove the candidate we have to collect the relaxed bound since removing the candidate from the queue
3805  * invalidates the relaxed bound
3806  */
3807  assert(bdchginfo == conflictFirstCand(conflict));
3808  relaxedbd = SCIPbdchginfoGetRelaxedBound(bdchginfo);
3809  bdchginfo = conflictRemoveCand(conflict);
3810  nextbdchginfo = conflictFirstCand(conflict);
3811  bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
3812  assert(bdchginfo != NULL);
3813  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3814  assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(bdchginfo) >= SCIPbdchginfoGetDepth(nextbdchginfo)
3815  || forceresolve);
3816  assert(bdchgdepth <= firstuipdepth);
3817 
3818  /* bound changes that are higher in the tree than the valid depth of the conflict can be ignored;
3819  * multiple insertions of the same bound change can be ignored
3820  */
3821  if( bdchgdepth > validdepth && bdchginfo != nextbdchginfo )
3822  {
3823  SCIP_VAR* actvar;
3824  SCIP_Bool resolved;
3825 
3826  actvar = SCIPbdchginfoGetVar(bdchginfo);
3827  assert(actvar != NULL);
3828  assert(SCIPvarIsActive(actvar));
3829 
3830  /* check if we have to resolve the bound change in this depth level
3831  * - the starting uip has to be resolved
3832  * - a bound change should be resolved, if it is in the fuip's depth level and not the
3833  * next uip (i.e., if it is not the last bound change in the fuip's depth level)
3834  * - a forced bound change must be resolved in any case
3835  */
3836  resolved = FALSE;
3837  if( bdchginfo == uip
3838  || (bdchgdepth == firstuipdepth
3839  && nextbdchginfo != NULL
3840  && SCIPbdchginfoGetDepth(nextbdchginfo) == bdchgdepth)
3841  || forceresolve )
3842  {
3843  SCIP_CALL( conflictResolveBound(conflict, set, bdchginfo, relaxedbd, validdepth, &resolved) );
3844  }
3845 
3846  if( resolved )
3847  nresolutions++;
3848  else if( forceresolve )
3849  {
3850  /* variable cannot enter the conflict clause: we have to make the conflict clause local, s.t.
3851  * the unresolved bound change is active in the whole sub tree of the conflict clause
3852  */
3853  assert(bdchgdepth >= validdepth);
3854  validdepth = bdchgdepth;
3855 
3856  SCIPdebugMessage("couldn't resolve forced bound change on <%s> -> new valid depth: %d\n",
3857  SCIPvarGetName(actvar), validdepth);
3858  }
3859  else if( bdchginfo != uip )
3860  {
3861  assert(conflict->conflictset != NULL);
3862  assert(conflict->conflictset->nbdchginfos >= 1); /* starting UIP is already member of the conflict set */
3863 
3864  /* if this is the first variable of the conflict set besides the current starting UIP, it is the next
3865  * UIP (or the first unresolvable bound change)
3866  */
3867  if( bdchgdepth == firstuipdepth && conflict->conflictset->nbdchginfos == 1 )
3868  {
3869  assert(nextuip == NULL);
3870  nextuip = bdchginfo;
3871  }
3872 
3873  /* put bound change into the conflict set */
3874  SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, bdchginfo, relaxedbd) );
3875  assert(conflict->conflictset->nbdchginfos >= 2);
3876  }
3877  else
3878  assert(conflictFirstCand(conflict) == NULL); /* the starting UIP was not resolved */
3879  }
3880 
3881  /* check conflict graph frontier on debugging solution */
3882  SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth],
3883  bdchginfo, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, conflict->conflictset->nbdchginfos,
3884  conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
3885 
3886  /* get next conflicting bound from the conflict candidate queue (this does not need to be nextbdchginfo, because
3887  * due to resolving the bound changes, a variable could be added to the queue which must be
3888  * resolved before nextbdchginfo)
3889  */
3890  bdchginfo = conflictFirstCand(conflict);
3891  }
3892  assert(nextuip != uip);
3893 
3894  /* if only one propagation was resolved, the reconvergence constraint is already member of the constraint set
3895  * (it is exactly the constraint that produced the propagation)
3896  */
3897  if( nextuip != NULL && nresolutions >= 2 && bdchginfo == NULL && validdepth <= maxvaliddepth )
3898  {
3899  int nlits;
3900  SCIP_Bool success;
3901 
3902  assert(SCIPbdchginfoGetDepth(nextuip) == SCIPbdchginfoGetDepth(uip));
3903 
3904  SCIPdebugMessage("creating reconvergence constraint from UIP <%s> to UIP <%s> in depth %d with %d literals after %d resolutions\n",
3906  SCIPbdchginfoGetDepth(uip), conflict->conflictset->nbdchginfos, nresolutions);
3907 
3908  /* call the conflict handlers to create a conflict set */
3909  SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, FALSE,
3910  &success, &nlits) );
3911  if( success )
3912  {
3913  (*nreconvconss)++;
3914  (*nreconvliterals) += nlits;
3915  }
3916  }
3917 
3918  /* clear the conflict candidate queue and the conflict set (to make sure, oppositeuip is not referenced anymore) */
3919  conflictClear(conflict);
3920 
3921  uip = nextuip;
3922  }
3923 
3924  return SCIP_OKAY;
3925 }
3926 
3927 /** analyzes conflicting bound changes that were added with calls to SCIPconflictAddBound() and
3928  * SCIPconflictAddRelaxedBound(), and on success, calls the conflict handlers to create a conflict constraint out of
3929  * the resulting conflict set; afterwards the conflict queue and the conflict set is cleared
3930  */
3931 static
3933  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3934  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3935  SCIP_SET* set, /**< global SCIP settings */
3936  SCIP_STAT* stat, /**< problem statistics */
3937  SCIP_PROB* prob, /**< problem data */
3938  SCIP_TREE* tree, /**< branch and bound tree */
3939  SCIP_Bool diving, /**< are we in strong branching or diving mode? */
3940  int validdepth, /**< minimal depth level at which the initial conflict set is valid */
3941  SCIP_Bool mustresolve, /**< should the conflict set only be used, if a resolution was applied? */
3942  int* nconss, /**< pointer to store the number of generated conflict constraints */
3943  int* nliterals, /**< pointer to store the number of literals in generated conflict constraints */
3944  int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
3945  int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
3946  )
3947 {
3948  SCIP_BDCHGINFO* bdchginfo;
3949  SCIP_BDCHGINFO** firstuips;
3950  int nfirstuips;
3951  int focusdepth;
3952  int currentdepth;
3953  int maxvaliddepth;
3954  int resolvedepth;
3955  int nresolutions;
3956  int lastconsnresolutions;
3957  int lastconsresoldepth;
3958 
3959  assert(conflict != NULL);
3960  assert(conflict->conflictset != NULL);
3961  assert(conflict->conflictset->nbdchginfos >= 0);
3962  assert(set != NULL);
3963  assert(stat != NULL);
3964  assert(0 <= validdepth && validdepth <= SCIPtreeGetCurrentDepth(tree));
3965  assert(nconss != NULL);
3966  assert(nliterals != NULL);
3967  assert(nreconvconss != NULL);
3968  assert(nreconvliterals != NULL);
3969 
3970  focusdepth = SCIPtreeGetFocusDepth(tree);
3971  currentdepth = SCIPtreeGetCurrentDepth(tree);
3972  assert(currentdepth == tree->pathlen-1);
3973  assert(focusdepth <= currentdepth);
3974 
3975  resolvedepth = ((set->conf_fuiplevels >= 0 && set->conf_fuiplevels <= currentdepth)
3976  ? currentdepth - set->conf_fuiplevels + 1 : 0);
3977  assert(0 <= resolvedepth && resolvedepth <= currentdepth + 1);
3978 
3979  /* if we must resolve at least one bound change, find the first UIP at least in the last depth level */
3980  if( mustresolve )
3981  resolvedepth = MIN(resolvedepth, currentdepth);
3982 
3983  SCIPdebugMessage("analyzing conflict with %d+%d conflict candidates and starting conflict set of size %d in depth %d (resolvedepth=%d)\n",
3985  conflict->conflictset->nbdchginfos, currentdepth, resolvedepth);
3986 
3987  *nconss = 0;
3988  *nliterals = 0;
3989  *nreconvconss = 0;
3990  *nreconvliterals = 0;
3991 
3992  /* check, whether local conflicts are allowed; however, don't generate conflict constraints that are only valid in the
3993  * probing path and not in the problem tree (i.e. that exceed the focusdepth)
3994  */
3995  maxvaliddepth = (set->conf_allowlocal ? MIN(currentdepth-1, focusdepth) : 0);
3996  if( validdepth > maxvaliddepth )
3997  return SCIP_OKAY;
3998 
3999  /* allocate temporary memory for storing first UIPs (in each depth level, at most two bound changes can be flagged
4000  * as UIP, namely a binary and a non-binary bound change)
4001  */
4002  SCIP_CALL( SCIPsetAllocBufferArray(set, &firstuips, 2*(currentdepth+1)) );
4003 
4004  /* process all bound changes in the conflict candidate queue */
4005  nresolutions = 0;
4006  lastconsnresolutions = (mustresolve ? 0 : -1);
4007  lastconsresoldepth = (mustresolve ? currentdepth : INT_MAX);
4008  bdchginfo = conflictFirstCand(conflict);
4009  nfirstuips = 0;
4010 
4011  /* check if the initial reason on debugging solution */
4012  SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth],
4013  NULL, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, conflict->conflictset->nbdchginfos,
4014  conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
4015 
4016  while( bdchginfo != NULL && validdepth <= maxvaliddepth )
4017  {
4018  SCIP_BDCHGINFO* nextbdchginfo;
4019  SCIP_Real relaxedbd;
4020  SCIP_Bool forceresolve;
4021  int bdchgdepth;
4022 
4023  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
4024 
4025  /* check if the next bound change must be resolved in every case */
4026  forceresolve = (SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0);
4027 
4028  /* resolve next bound change in queue */
4029  bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
4030  assert(0 <= bdchgdepth && bdchgdepth <= currentdepth);
4031  assert(SCIPvarIsActive(SCIPbdchginfoGetVar(bdchginfo)));
4032  assert(bdchgdepth < tree->pathlen);
4033  assert(tree->path[bdchgdepth] != NULL);
4034  assert(tree->path[bdchgdepth]->domchg != NULL);
4035  assert(SCIPbdchginfoGetPos(bdchginfo) < (int)tree->path[bdchgdepth]->domchg->domchgbound.nboundchgs);
4036  assert(tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].var
4037  == SCIPbdchginfoGetVar(bdchginfo));
4038  assert(tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].newbound
4039  == SCIPbdchginfoGetNewbound(bdchginfo)
4042  == SCIPbdchginfoGetNewbound(bdchginfo)); /*lint !e777*/
4043  assert((SCIP_BOUNDTYPE)tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].boundtype
4044  == SCIPbdchginfoGetBoundtype(bdchginfo));
4045 
4046  /* create intermediate conflict constraint */
4047  assert(nresolutions >= lastconsnresolutions);
4048  if( !forceresolve )
4049  {
4050  if( nresolutions == lastconsnresolutions )
4051  lastconsresoldepth = bdchgdepth; /* all intermediate depth levels consisted of only unresolved bound changes */
4052  else if( bdchgdepth < lastconsresoldepth && (set->conf_interconss == -1 || *nconss < set->conf_interconss) )
4053  {
4054  int nlits;
4055  SCIP_Bool success;
4056 
4057  /* call the conflict handlers to create a conflict set */
4058  SCIPdebugMessage("creating intermediate conflictset after %d resolutions up to depth %d (valid at depth %d): %d conflict bounds, %d bounds in queue\n",
4059  nresolutions, bdchgdepth, validdepth, conflict->conflictset->nbdchginfos,
4060  SCIPpqueueNElems(conflict->bdchgqueue));
4061  SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, TRUE,
4062  &success, &nlits) );
4063  lastconsnresolutions = nresolutions;
4064  lastconsresoldepth = bdchgdepth;
4065  if( success )
4066  {
4067  (*nconss)++;
4068  (*nliterals) += nlits;
4069  }
4070  }
4071  }
4072 
4073  /* remove currently processed candidate and get next conflicting bound from the conflict candidate queue before
4074  * we remove the candidate we have to collect the relaxed bound since removing the candidate from the queue
4075  * invalidates the relaxed bound
4076  */
4077  assert(bdchginfo == conflictFirstCand(conflict));
4078  relaxedbd = SCIPbdchginfoGetRelaxedBound(bdchginfo);
4079  bdchginfo = conflictRemoveCand(conflict);
4080  nextbdchginfo = conflictFirstCand(conflict);
4081  assert(bdchginfo != NULL);
4082  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
4083  assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(bdchginfo) >= SCIPbdchginfoGetDepth(nextbdchginfo)
4084  || forceresolve);
4085 
4086  /* we don't need to resolve bound changes that are already active in the valid depth of the current conflict set,
4087  * because the conflict set can only be added locally at the valid depth, and all bound changes applied in this
4088  * depth or earlier can be removed from the conflict constraint, since they are already applied in the constraint's
4089  * subtree;
4090  * if the next bound change on the remaining queue is equal to the current bound change,
4091  * this is a multiple insertion in the conflict candidate queue and we can ignore the current
4092  * bound change
4093  */
4094  if( bdchgdepth > validdepth && bdchginfo != nextbdchginfo )
4095  {
4096  SCIP_VAR* actvar;
4097  SCIP_Bool resolved;
4098 
4099  actvar = SCIPbdchginfoGetVar(bdchginfo);
4100  assert(actvar != NULL);
4101  assert(SCIPvarIsActive(actvar));
4102 
4103  /* check if we want to resolve the bound change in this depth level
4104  * - bound changes should be resolved, if
4105  * (i) we must apply at least one resolution and didn't resolve a bound change yet, or
4106  * (ii) their depth level is at least equal to the minimal resolving depth, and
4107  * they are not the last remaining conflicting bound change in their depth level
4108  * (iii) the bound change resolving is forced (i.e., the forced queue was non-empty)
4109  */
4110  resolved = FALSE;
4111  if( (mustresolve && nresolutions == 0)
4112  || (bdchgdepth >= resolvedepth
4113  && nextbdchginfo != NULL
4114  && SCIPbdchginfoGetDepth(nextbdchginfo) == bdchgdepth)
4115  || forceresolve )
4116  {
4117  SCIP_CALL( conflictResolveBound(conflict, set, bdchginfo, relaxedbd, validdepth, &resolved) );
4118  }
4119 
4120  if( resolved )
4121  nresolutions++;
4122  else if( forceresolve )
4123  {
4124  /* variable cannot enter the conflict clause: we have to make the conflict clause local, s.t.
4125  * the unresolved bound change is active in the whole sub tree of the conflict clause
4126  */
4127  assert(bdchgdepth >= validdepth);
4128  validdepth = bdchgdepth;
4129 
4130  SCIPdebugMessage("couldn't resolve forced bound change on <%s> -> new valid depth: %d\n",
4131  SCIPvarGetName(actvar), validdepth);
4132  }
4133  else
4134  {
4135  /* if this is a UIP (the last bound change in its depth level), it can be used to generate a
4136  * UIP reconvergence constraint
4137  */
4138  if( nextbdchginfo == NULL || SCIPbdchginfoGetDepth(nextbdchginfo) != bdchgdepth )
4139  {
4140  assert(nfirstuips < 2*(currentdepth+1));
4141  firstuips[nfirstuips] = bdchginfo;
4142  nfirstuips++;
4143  }
4144 
4145  /* put variable into the conflict set, using the literal that is currently fixed to FALSE */
4146  SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, bdchginfo, relaxedbd) );
4147  }
4148  }
4149 
4150  /* check conflict graph frontier on debugging solution */
4151  SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth],
4152  bdchginfo, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, conflict->conflictset->nbdchginfos,
4153  conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
4154 
4155  /* get next conflicting bound from the conflict candidate queue (this needs not to be nextbdchginfo, because
4156  * due to resolving the bound changes, a bound change could be added to the queue which must be
4157  * resolved before nextbdchginfo)
4158  */
4159  bdchginfo = conflictFirstCand(conflict);
4160  }
4161 
4162  /* check, if a valid conflict set was found */
4163  if( bdchginfo == NULL
4164  && nresolutions > lastconsnresolutions
4165  && validdepth <= maxvaliddepth
4166  && (!mustresolve || nresolutions > 0 || conflict->conflictset->nbdchginfos == 0)
4167  && SCIPpqueueNElems(conflict->forcedbdchgqueue) == 0 )
4168  {
4169  int nlits;
4170  SCIP_Bool success;
4171 
4172  /* call the conflict handlers to create a conflict set */
4173  SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, TRUE, &success, &nlits) );
4174  if( success )
4175  {
4176  (*nconss)++;
4177  (*nliterals) += nlits;
4178  }
4179  }
4180 
4181  /* produce reconvergence constraints defined by succeeding UIP's of the last depth level */
4182  if( set->conf_reconvlevels != 0 && validdepth <= maxvaliddepth )
4183  {
4184  int reconvlevels;
4185  int i;
4186 
4187  reconvlevels = (set->conf_reconvlevels == -1 ? INT_MAX : set->conf_reconvlevels);
4188  for( i = 0; i < nfirstuips; ++i )
4189  {
4190  if( SCIPbdchginfoHasInferenceReason(firstuips[i])
4191  && currentdepth - SCIPbdchginfoGetDepth(firstuips[i]) < reconvlevels )
4192  {
4193  SCIP_CALL( conflictCreateReconvergenceConss(conflict, blkmem, set, stat, prob, tree, diving,
4194  validdepth, firstuips[i], nreconvconss, nreconvliterals) );
4195  }
4196  }
4197  }
4198 
4199  /* free the temporary memory */
4200  SCIPsetFreeBufferArray(set, &firstuips);
4201 
4202  /* clear the conflict candidate queue and the conflict set */
4203  conflictClear(conflict);
4204 
4205  return SCIP_OKAY;
4206 }
4207 
4208 /** analyzes conflicting bound changes that were added with calls to SCIPconflictAddBound(), and on success, calls the
4209  * conflict handlers to create a conflict constraint out of the resulting conflict set;
4210  * updates statistics for propagation conflict analysis
4211  */
4213  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4214  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
4215  SCIP_SET* set, /**< global SCIP settings */
4216  SCIP_STAT* stat, /**< problem statistics */
4217  SCIP_PROB* prob, /**< problem data */
4218  SCIP_TREE* tree, /**< branch and bound tree */
4219  int validdepth, /**< minimal depth level at which the initial conflict set is valid */
4220  SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
4221  )
4222 {
4223  int nconss;
4224  int nliterals;
4225  int nreconvconss;
4226  int nreconvliterals;
4227 
4228  assert(conflict != NULL);
4229  assert(conflict->conflictset != NULL);
4230  assert(set != NULL);
4231  assert(prob != NULL);
4232 
4233 
4234  if( success != NULL )
4235  *success = FALSE;
4236 
4237  /* check if the conflict analysis is applicable */
4238  if( !SCIPconflictApplicable(set) )
4239  return SCIP_OKAY;
4240 
4241  /* check, if the conflict set will get too large with high probability */
4242  if( conflict->conflictset->nbdchginfos + SCIPpqueueNElems(conflict->bdchgqueue)
4243  + SCIPpqueueNElems(conflict->forcedbdchgqueue) >= 2*conflictCalcMaxsize(set, prob) )
4244  return SCIP_OKAY;
4245 
4246  SCIPdebugMessage("analyzing conflict after infeasible propagation in depth %d\n", SCIPtreeGetCurrentDepth(tree));
4247 
4248  /* start timing */
4249  SCIPclockStart(conflict->propanalyzetime, set);
4250 
4251  conflict->npropcalls++;
4252 
4253  /* analyze the conflict set, and create a conflict constraint on success */
4254  SCIP_CALL( conflictAnalyze(conflict, blkmem, set, stat, prob, tree, FALSE, validdepth, TRUE,
4255  &nconss, &nliterals, &nreconvconss, &nreconvliterals) );
4256  conflict->npropsuccess += (nconss > 0 ? 1 : 0);
4257  conflict->npropconfconss += nconss;
4258  conflict->npropconfliterals += nliterals;
4259  conflict->npropreconvconss += nreconvconss;
4260  conflict->npropreconvliterals += nreconvliterals;
4261  if( success != NULL )
4262  *success = (nconss > 0);
4263 
4264  /* stop timing */
4265  SCIPclockStop(conflict->propanalyzetime, set);
4266 
4267  return SCIP_OKAY;
4268 }
4269 
4270 /** gets time in seconds used for preprocessing global conflict constraint before appliance */
4272  SCIP_CONFLICT* conflict /**< conflict analysis data */
4273  )
4274 {
4275  assert(conflict != NULL);
4276 
4277  return SCIPclockGetTime(conflict->dIBclock);
4278 }
4279 
4280 /** gets time in seconds used for analyzing propagation conflicts */
4282  SCIP_CONFLICT* conflict /**< conflict analysis data */
4283  )
4284 {
4285  assert(conflict != NULL);
4286 
4287  return SCIPclockGetTime(conflict->propanalyzetime);
4288 }
4289 
4290 /** gets number of calls to propagation conflict analysis */
4292  SCIP_CONFLICT* conflict /**< conflict analysis data */
4293  )
4294 {
4295  assert(conflict != NULL);
4296 
4297  return conflict->npropcalls;
4298 }
4299 
4300 /** gets number of calls to propagation conflict analysis that yield at least one conflict constraint */
4302  SCIP_CONFLICT* conflict /**< conflict analysis data */
4303  )
4304 {
4305  assert(conflict != NULL);
4306 
4307  return conflict->npropsuccess;
4308 }
4309 
4310 /** gets number of conflict constraints detected in propagation conflict analysis */
4312  SCIP_CONFLICT* conflict /**< conflict analysis data */
4313  )
4314 {
4315  assert(conflict != NULL);
4316 
4317  return conflict->npropconfconss;
4318 }
4319 
4320 /** gets total number of literals in conflict constraints created in propagation conflict analysis */
4322  SCIP_CONFLICT* conflict /**< conflict analysis data */
4323  )
4324 {
4325  assert(conflict != NULL);
4326 
4327  return conflict->npropconfliterals;
4328 }
4329 
4330 /** gets number of reconvergence constraints detected in propagation conflict analysis */
4332  SCIP_CONFLICT* conflict /**< conflict analysis data */
4333  )
4334 {
4335  assert(conflict != NULL);
4336 
4337  return conflict->npropreconvconss;
4338 }
4339 
4340 /** gets total number of literals in reconvergence constraints created in propagation conflict analysis */
4342  SCIP_CONFLICT* conflict /**< conflict analysis data */
4343  )
4344 {
4345  assert(conflict != NULL);
4346 
4347  return conflict->npropreconvliterals;
4348 }
4349 
4350 
4351 
4352 
4353 /*
4354  * Infeasible LP Conflict Analysis
4355  */
4356 
4357 /** ensures, that side change arrays can store at least num entries */
4358 static
4360  SCIP_SET* set, /**< global SCIP settings */
4361  int** sidechginds, /**< pointer to side change index array */
4362  SCIP_Real** sidechgoldlhss, /**< pointer to side change old left hand sides array */
4363  SCIP_Real** sidechgoldrhss, /**< pointer to side change old right hand sides array */
4364  SCIP_Real** sidechgnewlhss, /**< pointer to side change new left hand sides array */
4365  SCIP_Real** sidechgnewrhss, /**< pointer to side change new right hand sides array */
4366  int* sidechgssize, /**< pointer to size of side change arrays */
4367  int num /**< minimal number of entries to be able to store in side change arrays */
4368  )
4369 {
4370  assert(sidechginds != NULL);
4371  assert(sidechgoldlhss != NULL);
4372  assert(sidechgoldrhss != NULL);
4373  assert(sidechgnewlhss != NULL);
4374  assert(sidechgnewrhss != NULL);
4375  assert(sidechgssize != NULL);
4376 
4377  if( num > *sidechgssize )
4378  {
4379  int newsize;
4380 
4381  newsize = SCIPsetCalcMemGrowSize(set, num);
4382  SCIP_CALL( SCIPsetReallocBufferArray(set, sidechginds, newsize) );
4383  SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgoldlhss, newsize) );
4384  SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgoldrhss, newsize) );
4385  SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgnewlhss, newsize) );
4386  SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgnewrhss, newsize) );
4387  *sidechgssize = newsize;
4388  }
4389  assert(num <= *sidechgssize);
4390 
4391  return SCIP_OKAY;
4392 }
4393 
4394 /** adds removal of row's side to side change arrays; finite sides are only replaced by near infinite sides, such
4395  * that the row's sense in the LP solver is not changed
4396  */
4397 static
4399  SCIP_SET* set, /**< global SCIP settings */
4400  SCIP_ROW* row, /**< LP row to change the sides for */
4401  SCIP_Real lpiinfinity, /**< value treated as infinity in LP solver */
4402  int** sidechginds, /**< pointer to side change index array */
4403  SCIP_Real** sidechgoldlhss, /**< pointer to side change old left hand sides array */
4404  SCIP_Real** sidechgoldrhss, /**< pointer to side change old right hand sides array */
4405  SCIP_Real** sidechgnewlhss, /**< pointer to side change new left hand sides array */
4406  SCIP_Real** sidechgnewrhss, /**< pointer to side change new right hand sides array */
4407  int* sidechgssize, /**< pointer to size of side change arrays */
4408  int* nsidechgs /**< pointer to number of used slots in side change arrays */
4409  )
4410 {
4411  SCIP_Real lhs;
4412  SCIP_Real rhs;
4413  SCIP_Real constant;
4414 
4415  assert(sidechginds != NULL);
4416  assert(sidechgoldlhss != NULL);
4417  assert(sidechgoldrhss != NULL);
4418  assert(sidechgnewlhss != NULL);
4419  assert(sidechgnewrhss != NULL);
4420  assert(sidechgssize != NULL);
4421  assert(nsidechgs != NULL);
4422 
4423  lhs = SCIProwGetLhs(row);
4424  rhs = SCIProwGetRhs(row);
4425  constant = SCIProwGetConstant(row);
4426  assert(!SCIPsetIsInfinity(set, -lhs) || !SCIPsetIsInfinity(set, rhs));
4427 
4428  /* get memory to store additional side change */
4429  SCIP_CALL( ensureSidechgsSize(set, sidechginds, sidechgoldlhss, sidechgoldrhss, sidechgnewlhss, sidechgnewrhss,
4430  sidechgssize, (*nsidechgs)+1) );
4431  assert(*nsidechgs < *sidechgssize);
4432  assert(*sidechginds != NULL);
4433  assert(*sidechgoldlhss != NULL);
4434  assert(*sidechgoldrhss != NULL);
4435  assert(*sidechgnewlhss != NULL);
4436  assert(*sidechgnewrhss != NULL);
4437 
4438  /* store side change */
4439  (*sidechginds)[*nsidechgs] = SCIProwGetLPPos(row);
4440  if( SCIPsetIsInfinity(set, -lhs) )
4441  {
4442  (*sidechgoldlhss)[*nsidechgs] = -lpiinfinity;
4443  (*sidechgnewlhss)[*nsidechgs] = -lpiinfinity;
4444  }
4445  else
4446  {
4447  (*sidechgoldlhss)[*nsidechgs] = lhs - constant;
4448  (*sidechgnewlhss)[*nsidechgs] = -lpiinfinity/2;
4449  }
4450  if( SCIPsetIsInfinity(set, rhs) )
4451  {
4452  (*sidechgoldrhss)[*nsidechgs] = lpiinfinity;
4453  (*sidechgnewrhss)[*nsidechgs] = lpiinfinity;
4454  }
4455  else
4456  {
4457  (*sidechgoldrhss)[*nsidechgs] = rhs - constant;
4458  (*sidechgnewrhss)[*nsidechgs] = lpiinfinity/2;
4459  }
4460  (*nsidechgs)++;
4461 
4462  return SCIP_OKAY;
4463 }
4464 
4465 /** inserts variable's new bounds into bound change arrays */
4466 static
4468  SCIP_SET* set, /**< global SCIP settings */
4469  SCIP_VAR* var, /**< variable to change the LP bounds for */
4470  SCIP_Real newlb, /**< new lower bound */
4471  SCIP_Real newub, /**< new upper bound */
4472  SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
4473  SCIP_LPBDCHGS* relaxedlpbdchgs /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
4474  )
4475 {
4476  assert(newlb <= newub);
4477  assert(oldlpbdchgs != NULL);
4478  assert(relaxedlpbdchgs != NULL);
4479 
4481  {
4482  SCIP_COL* col;
4483  int idx;
4484  int c;
4485 
4486  col = SCIPvarGetCol(var);
4487  c = SCIPcolGetLPPos(col);
4488 
4489  if( c >= 0 )
4490  {
4491  /* store old bound change for reseting the LP later */
4492  if( !oldlpbdchgs->usedcols[c] )
4493  {
4494  idx = oldlpbdchgs->nbdchgs;
4495  oldlpbdchgs->usedcols[c] = TRUE;
4496  oldlpbdchgs->bdchgcolinds[c] = idx;
4497  oldlpbdchgs->nbdchgs++;
4498 
4499  oldlpbdchgs->bdchginds[idx] = c;
4500  oldlpbdchgs->bdchglbs[idx] = SCIPvarGetLbLP(var, set);
4501  oldlpbdchgs->bdchgubs[idx] = SCIPvarGetUbLP(var, set);
4502  }
4503  assert(oldlpbdchgs->bdchginds[oldlpbdchgs->bdchgcolinds[c]] == c);
4504  assert(oldlpbdchgs->bdchglbs[oldlpbdchgs->bdchgcolinds[c]] == SCIPvarGetLbLP(var, set)); /*lint !e777*/
4505  assert(oldlpbdchgs->bdchgubs[oldlpbdchgs->bdchgcolinds[c]] == SCIPvarGetUbLP(var, set)); /*lint !e777*/
4506 
4507  /* store bound change for conflict analysis */
4508  if( !relaxedlpbdchgs->usedcols[c] )
4509  {
4510  idx = relaxedlpbdchgs->nbdchgs;
4511  relaxedlpbdchgs->usedcols[c] = TRUE;
4512  relaxedlpbdchgs->bdchgcolinds[c] = idx;
4513  relaxedlpbdchgs->nbdchgs++;
4514 
4515  /* remember the positive for later further bound widenings */
4516  relaxedlpbdchgs->bdchginds[idx] = c;
4517  }
4518  else
4519  {
4520  idx = relaxedlpbdchgs->bdchgcolinds[c];
4521  assert(relaxedlpbdchgs->bdchginds[idx] == c);
4522 
4523  /* the new bound should be the same or nore relexed */
4524  assert(relaxedlpbdchgs->bdchglbs[idx] >= newlb);
4525  assert(relaxedlpbdchgs->bdchgubs[idx] <= newub);
4526  }
4527 
4528  /* set the new bounds for the LP */
4529  relaxedlpbdchgs->bdchglbs[idx] = newlb;
4530  relaxedlpbdchgs->bdchgubs[idx] = newub;
4531  }
4532  }
4533 
4534  return SCIP_OKAY;
4535 }
4536 
4537 /** ensures, that candidate array can store at least num entries */
4538 static
4540  SCIP_SET* set, /**< global SCIP settings */
4541  SCIP_VAR*** cands, /**< pointer to candidate array */
4542  SCIP_Real** candscores, /**< pointer to candidate score array */
4543  SCIP_Real** newbounds, /**< pointer to candidate new bounds array */
4544  SCIP_Real** proofactdeltas, /**< pointer to candidate proof delta array */
4545  int* candssize, /**< pointer to size of array */
4546  int num /**< minimal number of candidates to store in array */
4547  )
4548 {
4549  assert(cands != NULL);
4550  assert(candssize != NULL);
4551 
4552  if( num > *candssize )
4553  {
4554  int newsize;
4555 
4556  newsize = SCIPsetCalcMemGrowSize(set, num);
4557  SCIP_CALL( SCIPsetReallocBufferArray(set, cands, newsize) );
4558  SCIP_CALL( SCIPsetReallocBufferArray(set, candscores, newsize) );
4559  SCIP_CALL( SCIPsetReallocBufferArray(set, newbounds, newsize) );
4560  SCIP_CALL( SCIPsetReallocBufferArray(set, proofactdeltas, newsize) );
4561  *candssize = newsize;
4562  }
4563  assert(num <= *candssize);
4564 
4565  return SCIP_OKAY;
4566 }
4567 
4568 /** adds variable to candidate list, if the current best bound corresponding to the proof coefficient is local;
4569  * returns the array position in the candidate list, where the new candidate was inserted, or -1 if the
4570  * variable can relaxed to global bounds immediately without increasing the proof's activity;
4571  * the candidates are sorted with respect to the following two criteria:
4572  * - prefer bound changes that have been applied deeper in the tree, to get a more global conflict
4573  * - prefer variables with small Farkas coefficient to get rid of as many bound changes as possible
4574  */
4575 static
4577  SCIP_SET* set, /**< global SCIP settings */
4578  int currentdepth, /**< current depth in the tree */
4579  SCIP_VAR* var, /**< variable to add to candidate array */
4580  int lbchginfopos, /**< positions of currently active lower bound change information in variable's array */
4581  int ubchginfopos, /**< positions of currently active upper bound change information in variable's array */
4582  SCIP_Real proofcoef, /**< coefficient of variable in infeasibility/bound proof */
4583  SCIP_Real prooflhs, /**< left hand side of infeasibility/bound proof */
4584  SCIP_Real proofact, /**< activity of infeasibility/bound proof row */
4585  SCIP_VAR*** cands, /**< pointer to candidate array for undoing bound changes */
4586  SCIP_Real** candscores, /**< pointer to candidate score array for undoing bound changes */
4587  SCIP_Real** newbounds, /**< pointer to candidate new bounds array for undoing bound changes */
4588  SCIP_Real** proofactdeltas, /**< pointer to proof activity increase array for undoing bound changes */
4589  int* candssize, /**< pointer to size of cands arrays */
4590  int* ncands, /**< pointer to count number of candidates in bound change list */
4591  int firstcand /**< position of first unprocessed bound change candidate */
4592  )
4593 {
4594  SCIP_Real oldbound;
4595  SCIP_Real newbound;
4596  SCIP_Real proofactdelta;
4597  SCIP_Real score;
4598  int depth;
4599  int i;
4600  SCIP_Bool resolvable;
4601 
4602  assert(set != NULL);
4603  assert(var != NULL);
4604  assert(-1 <= lbchginfopos && lbchginfopos <= var->nlbchginfos);
4605  assert(-1 <= ubchginfopos && ubchginfopos <= var->nubchginfos);
4606  assert(!SCIPsetIsZero(set, proofcoef));
4607  assert(SCIPsetIsGT(set, prooflhs, proofact));
4608  assert(cands != NULL);
4609  assert(candscores != NULL);
4610  assert(newbounds != NULL);
4611  assert(proofactdeltas != NULL);
4612  assert(candssize != NULL);
4613  assert(ncands != NULL);
4614  assert(*ncands <= *candssize);
4615  assert(0 <= firstcand && firstcand <= *ncands);
4616 
4617  /* in the infeasibility or dual bound proof, the variable's bound is chosen to maximize the proof's activity */
4618  if( proofcoef > 0.0 )
4619  {
4620  assert(ubchginfopos >= 0); /* otherwise, undoBdchgsProof() should already have relaxed the local bound */
4621 
4622  /* calculate the difference of current bound to the previous bound the variable was set to */
4623  if( ubchginfopos == var->nubchginfos )
4624  {
4625  /* current bound is the strong branching or diving bound */
4626  oldbound = SCIPvarGetUbLP(var, set);
4627  newbound = SCIPvarGetUbLocal(var);
4628  depth = currentdepth+1;
4629  resolvable = FALSE;
4630  }
4631  else
4632  {
4633  /* current bound is the result of a local bound change */
4634  resolvable = bdchginfoIsResolvable(&var->ubchginfos[ubchginfopos]);
4635  depth = var->ubchginfos[ubchginfopos].bdchgidx.depth;
4636  oldbound = var->ubchginfos[ubchginfopos].newbound;
4637  newbound = var->ubchginfos[ubchginfopos].oldbound;
4638  }
4639  }
4640  else
4641  {
4642  assert(lbchginfopos >= 0); /* otherwise, undoBdchgsProof() should already have relaxed the local bound */
4643 
4644  /* calculate the difference of current bound to the previous bound the variable was set to */
4645  if( lbchginfopos == var->nlbchginfos )
4646  {
4647  /* current bound is the strong branching or diving bound */
4648  oldbound = SCIPvarGetLbLP(var, set);
4649  newbound = SCIPvarGetLbLocal(var);
4650  depth = currentdepth+1;
4651  resolvable = FALSE;
4652  }
4653  else
4654  {
4655  /* current bound is the result of a local bound change */
4656  resolvable = bdchginfoIsResolvable(&var->lbchginfos[lbchginfopos]);
4657  depth = var->lbchginfos[lbchginfopos].bdchgidx.depth;
4658  oldbound = var->lbchginfos[lbchginfopos].newbound;
4659  newbound = var->lbchginfos[lbchginfopos].oldbound;
4660  }
4661  }
4662 
4663  /* calculate the increase in the proof's activity */
4664  proofactdelta = (newbound - oldbound)*proofcoef;
4665  assert(proofactdelta > 0.0);
4666 
4667  /* calculate score for undoing the bound change */
4668  score = 1.0 - proofactdelta/(prooflhs - proofact);
4669  score = MAX(score, 0.0);
4670  score += set->conf_depthscorefac * (SCIP_Real)(depth+1)/(SCIP_Real)(currentdepth+1);
4671  if( !resolvable )
4672  {
4673  score += 10.0;
4674  if( !SCIPvarIsBinary(var) )
4675  score += 10.0;
4676  }
4677 
4678  /* get enough memory to store new candidate */
4679  SCIP_CALL( ensureCandsSize(set, cands, candscores, newbounds, proofactdeltas, candssize, (*ncands)+1) );
4680  assert(*cands != NULL);
4681  assert(*candscores != NULL);
4682  assert(*newbounds != NULL);
4683  assert(*proofactdeltas != NULL);
4684 
4685  SCIPdebugMessage(" -> local <%s> %s %g, relax <%s> %s %g, proofcoef=%g, dpt=%d, resolve=%u, delta=%g, score=%g\n",
4686  SCIPvarGetName(var), proofcoef > 0.0 ? "<=" : ">=", oldbound,
4687  SCIPvarGetName(var), proofcoef > 0.0 ? "<=" : ">=", newbound,
4688  proofcoef, depth, resolvable, proofactdelta, score);
4689 
4690  /* insert variable in candidate list without touching the already processed candidates */
4691  for( i = *ncands; i > firstcand && score > (*candscores)[i-1]; --i )
4692  {
4693  (*cands)[i] = (*cands)[i-1];
4694  (*candscores)[i] = (*candscores)[i-1];
4695  (*newbounds)[i] = (*newbounds)[i-1];
4696  (*proofactdeltas)[i] = (*proofactdeltas)[i-1];
4697  }
4698  (*cands)[i] = var;
4699  (*candscores)[i] = score;
4700  (*newbounds)[i] = newbound;
4701  (*proofactdeltas)[i] = proofactdelta;
4702  (*ncands)++;
4703 
4704  return SCIP_OKAY;
4705 }
4706 
4707 /** after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
4708  * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
4709  * global bound and we can ignore it by installing a -1 as the corresponding bound change info position
4710  */
4711 static
4713  SCIP_VAR* var, /**< problem variable */
4714  int* lbchginfopos, /**< pointer to lower bound change information position */
4715  int* ubchginfopos /**< pointer to upper bound change information position */
4716  )
4717 {
4718  assert(var != NULL);
4719  assert(lbchginfopos != NULL);
4720  assert(ubchginfopos != NULL);
4721  assert(-1 <= *lbchginfopos && *lbchginfopos <= var->nlbchginfos);
4722  assert(-1 <= *ubchginfopos && *ubchginfopos <= var->nubchginfos);
4723  assert(*lbchginfopos == -1 || *lbchginfopos == var->nlbchginfos
4724  || var->lbchginfos[*lbchginfopos].redundant
4725  == (var->lbchginfos[*lbchginfopos].oldbound == var->lbchginfos[*lbchginfopos].newbound)); /*lint !e777*/
4726  assert(*ubchginfopos == -1 || *ubchginfopos == var->nubchginfos
4727  || var->ubchginfos[*ubchginfopos].redundant
4728  == (var->ubchginfos[*ubchginfopos].oldbound == var->ubchginfos[*ubchginfopos].newbound)); /*lint !e777*/
4729 
4730  if( *lbchginfopos >= 0 && *lbchginfopos < var->nlbchginfos && var->lbchginfos[*lbchginfopos].redundant )
4731  {
4732  assert(SCIPvarGetLbGlobal(var) == var->lbchginfos[*lbchginfopos].oldbound); /*lint !e777*/
4733  *lbchginfopos = -1;
4734  }
4735  if( *ubchginfopos >= 0 && *ubchginfopos < var->nubchginfos && var->ubchginfos[*ubchginfopos].redundant )
4736  {
4737  assert(SCIPvarGetUbGlobal(var) == var->ubchginfos[*ubchginfopos].oldbound); /*lint !e777*/
4738  *ubchginfopos = -1;
4739  }
4740 }
4741 
4742 /** undoes bound changes on variables, still leaving the given infeasibility proof valid */
4743 static
4745  SCIP_SET* set, /**< global SCIP settings */
4746  SCIP_PROB* prob, /**< problem data */
4747  int currentdepth, /**< current depth in the tree */
4748  SCIP_Real* proofcoefs, /**< coefficients in infeasibility proof */
4749  SCIP_Real prooflhs, /**< left hand side of proof */
4750  SCIP_Real proofact, /**< current activity of proof */
4751  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
4752  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
4753  int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
4754  int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
4755  SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
4756  SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
4757  SCIP_Bool* resolve /**< pointer to store whether the changed LP should be resolved again, or NULL */
4758  )
4759 {
4760  SCIP_VAR** vars;
4761  SCIP_VAR** cands;
4762  SCIP_Real* candscores;
4763  SCIP_Real* newbounds;
4764  SCIP_Real* proofactdeltas;
4765  int nvars;
4766  int ncands;
4767  int candssize;
4768  int v;
4769  int i;
4770 
4771  assert(prob != NULL);
4772  assert(proofcoefs != NULL);
4773  assert(SCIPsetIsFeasGT(set, prooflhs, proofact));
4774  assert(curvarlbs != NULL);
4775  assert(curvarubs != NULL);
4776  assert(lbchginfoposs != NULL);
4777  assert(ubchginfoposs != NULL);
4778 
4779  if( resolve != NULL )
4780  *resolve = FALSE;
4781 
4782  vars = prob->vars;
4783  nvars = prob->nvars;
4784  assert(nvars == 0 || vars != NULL);
4785 
4786  /* calculate the order in which the bound changes are tried to be undone, and relax all bounds if this doesn't
4787  * increase the proof's activity
4788  */
4789  SCIP_CALL( SCIPsetAllocBufferArray(set, &cands, nvars) );
4790  SCIP_CALL( SCIPsetAllocBufferArray(set, &candscores, nvars) );
4791  SCIP_CALL( SCIPsetAllocBufferArray(set, &newbounds, nvars) );
4792  SCIP_CALL( SCIPsetAllocBufferArray(set, &proofactdeltas, nvars) );
4793  ncands = 0;
4794  candssize = nvars;
4795  for( v = 0; v < nvars; ++v )
4796  {
4797  SCIP_VAR* var;
4798  SCIP_Bool relaxed;
4799 
4800  var = vars[v];
4801 
4802  /* after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
4803  * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
4804  * global bound and we can ignore it
4805  */
4806  skipRedundantBdchginfos(var, &lbchginfoposs[v], &ubchginfoposs[v]);
4807 
4808  /* ignore variables already relaxed to global bounds */
4809  if( lbchginfoposs[v] == -1 && ubchginfoposs[v] == -1 )
4810  continue;
4811 
4812  /* relax bounds that are not used in the proof to the global bounds */
4813  relaxed = FALSE;
4814  if( !SCIPsetIsNegative(set, proofcoefs[v]) )
4815  {
4816  /* the lower bound is not used */
4817  if( lbchginfoposs[v] >= 0 )
4818  {
4819  SCIPdebugMessage(" -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g\n",
4820  SCIPvarGetName(var), curvarlbs[v], curvarubs[v], SCIPvarGetLbGlobal(var), curvarubs[v],
4821  proofcoefs[v], prooflhs, proofact);
4822  curvarlbs[v] = SCIPvarGetLbGlobal(var);
4823  lbchginfoposs[v] = -1;
4824  relaxed = TRUE;
4825  }
4826  }
4827  if( !SCIPsetIsPositive(set, proofcoefs[v]) )
4828  {
4829  /* the upper bound is not used */
4830  if( ubchginfoposs[v] >= 0 )
4831  {
4832  SCIPdebugMessage(" -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g\n",
4833  SCIPvarGetName(var), curvarlbs[v], curvarubs[v], curvarlbs[v], SCIPvarGetUbGlobal(var),
4834  proofcoefs[v], prooflhs, proofact);
4835  curvarubs[v] = SCIPvarGetUbGlobal(var);
4836  ubchginfoposs[v] = -1;
4837  relaxed = TRUE;
4838  }
4839  }
4840  if( relaxed && oldlpbdchgs != NULL )
4841  {
4842  SCIP_CALL( addBdchg(set, var, curvarlbs[v], curvarubs[v], oldlpbdchgs, relaxedlpbdchgs) );
4843  }
4844 
4845  /* add bound to candidate list */
4846  if( lbchginfoposs[v] >= 0 || ubchginfoposs[v] >= 0 )
4847  {
4848  SCIP_CALL( addCand(set, currentdepth, var, lbchginfoposs[v], ubchginfoposs[v], proofcoefs[v],
4849  prooflhs, proofact, &cands, &candscores, &newbounds, &proofactdeltas, &candssize, &ncands, 0) );
4850  }
4851  }
4852 
4853  /* try to undo remaining local bound changes while still keeping the proof row violated:
4854  * bound changes can be undone, if prooflhs > proofact + proofactdelta;
4855  * afterwards, the current proof activity has to be updated
4856  */
4857  for( i = 0; i < ncands; ++i )
4858  {
4859  assert(proofactdeltas[i] > 0.0);
4860  assert((lbchginfoposs[SCIPvarGetProbindex(cands[i])] >= 0) != (ubchginfoposs[SCIPvarGetProbindex(cands[i])] >= 0));
4861 
4862  /* when relaxing a constraint we still need to stay infeasible; therefore we need to do the comparison in
4863  * feasibility tolerance because if 'prooflhs' is (feas-))equal to 'proofact + proofactdeltas[i]' it would mean
4864  * that there is no violation
4865  */
4866  if( SCIPsetIsFeasGT(set, prooflhs, proofact + proofactdeltas[i]) )
4867  {
4868  v = SCIPvarGetProbindex(cands[i]);
4869  assert(0 <= v && v < nvars);
4870  assert((lbchginfoposs[v] >= 0) != (ubchginfoposs[v] >= 0));
4871 
4872  SCIPdebugMessage(" -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g + %g\n",
4873  SCIPvarGetName(cands[i]), curvarlbs[v], curvarubs[v],
4874  proofcoefs[v] > 0.0 ? curvarlbs[v] : newbounds[i],
4875  proofcoefs[v] > 0.0 ? newbounds[i] : curvarubs[v],
4876  proofcoefs[v], prooflhs, proofact, proofactdeltas[i]);
4877 
4878  assert((SCIPsetIsPositive(set, proofcoefs[v]) && SCIPsetIsGT(set, newbounds[i], curvarubs[v]))
4879  || (SCIPsetIsNegative(set, proofcoefs[v]) && SCIPsetIsLT(set, newbounds[i], curvarlbs[v])));
4880  assert((SCIPsetIsPositive(set, proofcoefs[v])
4881  && SCIPsetIsEQ(set, proofactdeltas[i], (newbounds[i] - curvarubs[v])*proofcoefs[v]))
4882  || (SCIPsetIsNegative(set, proofcoefs[v])
4883  && SCIPsetIsEQ(set, proofactdeltas[i], (newbounds[i] - curvarlbs[v])*proofcoefs[v])));
4884  assert(!SCIPsetIsZero(set, proofcoefs[v]));
4885 
4886  if( proofcoefs[v] > 0.0 )
4887  {
4888  assert(ubchginfoposs[v] >= 0);
4889  assert(lbchginfoposs[v] == -1);
4890  curvarubs[v] = newbounds[i];
4891  ubchginfoposs[v]--;
4892  }
4893  else
4894  {
4895  assert(lbchginfoposs[v] >= 0);
4896  assert(ubchginfoposs[v] == -1);
4897  curvarlbs[v] = newbounds[i];
4898  lbchginfoposs[v]--;
4899  }
4900  if( oldlpbdchgs != NULL )
4901  {
4902  SCIP_CALL( addBdchg(set, cands[i], curvarlbs[v], curvarubs[v], oldlpbdchgs, relaxedlpbdchgs) );
4903  }
4904  proofact += proofactdeltas[i];
4905  if( resolve != NULL && SCIPvarIsInLP(cands[i]) )
4906  *resolve = TRUE;
4907 
4908  /* after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
4909  * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
4910  * global bound and we can ignore it
4911  */
4912  skipRedundantBdchginfos(cands[i], &lbchginfoposs[v], &ubchginfoposs[v]);
4913 
4914  /* insert the new local bound of the variable into the candidate list */
4915  if( lbchginfoposs[v] >= 0 || ubchginfoposs[v] >= 0 )
4916  {
4917  SCIP_CALL( addCand(set, currentdepth, cands[i], lbchginfoposs[v], ubchginfoposs[v], proofcoefs[v],
4918  prooflhs, proofact, &cands, &candscores, &newbounds, &proofactdeltas, &candssize, &ncands, i+1) );
4919  }
4920  }
4921  }
4922 
4923  /* free the buffer for the sorted bound change candidates */
4924  SCIPsetFreeBufferArray(set, &proofactdeltas);
4925  SCIPsetFreeBufferArray(set, &newbounds);
4926  SCIPsetFreeBufferArray(set, &candscores);
4927  SCIPsetFreeBufferArray(set, &cands);
4928 
4929  return SCIP_OKAY;
4930 }
4931 
4932 /* because calculations might cancel out some values, we stop the infeasibility analysis if a value is bigger than
4933  * 2^53 = 9007199254740992
4934  */
4935 #define NUMSTOP 9007199254740992.0
4936 
4937 /** analyzes an infeasible LP and undoes additional bound changes while staying infeasible */
4938 static
4940  SCIP_SET* set, /**< global SCIP settings */
4941  SCIP_PROB* prob, /**< problem data */
4942  SCIP_LP* lp, /**< LP data */
4943  int currentdepth, /**< current depth in the tree */
4944  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
4945  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
4946  int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
4947  int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
4948  SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
4949  SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
4950  SCIP_Bool* valid, /**< pointer to store whether the unfixings are valid */
4951  SCIP_Bool* resolve /**< pointer to store whether the changed LP should be resolved again */
4952  )
4953 {
4954  SCIP_RETCODE retcode;
4955  SCIP_LPI* lpi;
4956  SCIP_ROW** rows;
4957  SCIP_VAR** vars;
4958  SCIP_ROW* row;
4959  SCIP_VAR* var;
4960  SCIP_Real* dualfarkas;
4961  SCIP_Real* farkascoefs;
4962  SCIP_Real farkaslhs;
4963  SCIP_Real farkasact;
4964  int nrows;
4965  int nvars;
4966  int r;
4967  int v;
4968  int i;
4969 
4970  assert(prob != NULL);
4971  assert(lp != NULL);
4972  assert(lp->flushed);
4973  assert(lp->solved);
4974  assert(curvarlbs != NULL);
4975  assert(curvarubs != NULL);
4976  assert(lbchginfoposs != NULL);
4977  assert(ubchginfoposs != NULL);
4978  assert(valid != NULL);
4979  assert(resolve != NULL);
4980 
4981  SCIPdebugMessage("undoing bound changes in infeasible LP: cutoff=%g\n", lp->cutoffbound);
4982 
4983  *valid = FALSE;
4984  *resolve = FALSE;
4985 
4986  /* get LP solver interface */
4987  lpi = SCIPlpGetLPI(lp);
4988 
4989  /* get LP rows and problem variables */
4990  rows = SCIPlpGetRows(lp);
4991  nrows = SCIPlpGetNRows(lp);
4992  vars = prob->vars;
4993  nvars = prob->nvars;
4994  assert(nrows == 0 || rows != NULL);
4995  assert(nrows == lp->nlpirows);
4996 
4997  /* allocate temporary memory */
4998  SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, nrows) );
4999  SCIP_CALL( SCIPsetAllocBufferArray(set, &farkascoefs, nvars) );
5000 
5001  /* if solve for some reason did not produce a dual ray, e.g. because of numerical instabilities, abort conflict analysis */
5002  if( ! SCIPlpiHasDualRay(lpi) )
5003  goto TERMINATE;
5004 
5005  /* get dual Farkas values of rows */
5006  retcode = SCIPlpiGetDualfarkas(lpi, dualfarkas);
5007  if( retcode == SCIP_LPERROR ) /* on an error in the LP solver, just abort the conflict analysis */
5008  goto TERMINATE;
5009  SCIP_CALL( retcode );
5010 
5011  /* calculate the Farkas row */
5012  BMSclearMemoryArray(farkascoefs, nvars);
5013  farkaslhs = 0.0;
5014  for( r = 0; r < nrows; ++r )
5015  {
5016  row = rows[r];
5017  assert(row != NULL);
5018  assert(row->len == 0 || row->cols != NULL);
5019  assert(row->len == 0 || row->vals != NULL);
5020  assert(row == lp->lpirows[r]);
5021 
5022  /* ignore local rows and rows with Farkas value 0.0 */
5023  if( !row->local && !SCIPsetIsZero(set, dualfarkas[r]) )
5024  {
5025 #ifndef NDEBUG
5026  {
5027  SCIP_Real lpilhs;
5028  SCIP_Real lpirhs;
5029 
5030  SCIP_CALL( SCIPlpiGetSides(lpi, r, r, &lpilhs, &lpirhs) );
5031  assert((SCIPsetIsInfinity(set, -lpilhs) && SCIPsetIsInfinity(set, -row->lhs))
5032  || SCIPsetIsRelEQ(set, lpilhs, row->lhs - row->constant));
5033  assert((SCIPsetIsInfinity(set, lpirhs) && SCIPsetIsInfinity(set, row->rhs))
5034  || SCIPsetIsRelEQ(set, lpirhs, row->rhs - row->constant));
5035  }
5036 #endif
5037 
5038  /* add row side to Farkas row lhs: dualfarkas > 0 -> lhs, dualfarkas < 0 -> rhs */
5039  if( dualfarkas[r] > 0.0 )
5040  {
5041  /* check if sign of dual Farkas value is valid */
5042  if( SCIPsetIsInfinity(set, -row->lhs) )
5043  continue;
5044 
5045  /* due to numerical reasons we want to stop */
5046  if( REALABS(dualfarkas[r] * (row->lhs - row->constant)) > NUMSTOP )
5047  goto TERMINATE;
5048 
5049  farkaslhs += dualfarkas[r] * (row->lhs - row->constant);
5050  }
5051  else
5052  {
5053  /* check if sign of dual Farkas value is valid */
5054  if( SCIPsetIsInfinity(set, row->rhs) )
5055  continue;
5056 
5057  /* due to numerical reasons we want to stop */
5058  if( REALABS(dualfarkas[r] * (row->rhs - row->constant)) > NUMSTOP )
5059  goto TERMINATE;
5060 
5061  farkaslhs += dualfarkas[r] * (row->rhs - row->constant);
5062  }
5063  SCIPdebugMessage(" -> farkaslhs: %g<%s>[%g,%g] -> %g\n", dualfarkas[r], SCIProwGetName(row),
5064  row->lhs - row->constant, row->rhs - row->constant, farkaslhs);
5065 
5066  /* due to numerical reasons we want to stop */
5067  if( REALABS(farkaslhs) > NUMSTOP )
5068  goto TERMINATE;
5069 
5070  /* add row coefficients to Farkas row */
5071  for( i = 0; i < row->len; ++i )
5072  {
5073  v = SCIPvarGetProbindex(SCIPcolGetVar(row->cols[i]));
5074  assert(0 <= v && v < nvars);
5075  farkascoefs[v] += dualfarkas[r] * row->vals[i];
5076  }
5077  }
5078 #ifdef SCIP_DEBUG
5079  else if( !SCIPsetIsZero(set, dualfarkas[r]) )
5080  {
5081  SCIPdebugMessage(" -> ignoring %s row <%s> with dual Farkas value %.10f (lhs=%g, rhs=%g)\n",
5082  row->local ? "local" : "global", SCIProwGetName(row), dualfarkas[r],
5083  row->lhs - row->constant, row->rhs - row->constant);
5084  }
5085 #endif
5086  }
5087 
5088  /* calculate the current Farkas activity, always using the best bound w.r.t. the Farkas coefficient */
5089  farkasact = 0.0;
5090  for( v = 0; v < nvars; ++v )
5091  {
5092  var = vars[v];
5093  assert(SCIPvarGetProbindex(var) == v);
5094 
5095  /* ignore coefficients close to 0.0 */
5096  if( SCIPsetIsZero(set, farkascoefs[v]) )
5097  farkascoefs[v] = 0.0;
5098  else if( farkascoefs[v] > 0.0 )
5099  {
5101  || !SCIPsetIsPositive(set, SCIPvarGetUbLP(var, set)));
5102  if( SCIPsetIsInfinity(set, curvarubs[v]) )
5103  goto TERMINATE;
5104  farkasact += farkascoefs[v] * curvarubs[v];
5105  SCIPdebugMessage(" -> farkasact: %g<%s>[%g,%g] -> %g\n", farkascoefs[v], SCIPvarGetName(var),
5106  curvarlbs[v], curvarubs[v], farkasact);
5107  }
5108  else
5109  {
5111  || !SCIPsetIsNegative(set, SCIPvarGetLbLP(var, set)));
5112  if( SCIPsetIsInfinity(set, -curvarlbs[v]) )
5113  goto TERMINATE;
5114  farkasact += farkascoefs[v] * curvarlbs[v];
5115  SCIPdebugMessage(" -> farkasact: %g<%s>[%g,%g] -> %g\n", farkascoefs[v], SCIPvarGetName(var),
5116  curvarlbs[v], curvarubs[v], farkasact);
5117  }
5118  }
5119  SCIPdebugMessage(" -> farkaslhs=%g, farkasact=%g\n", farkaslhs, farkasact);
5120 
5121  /* check, if the Farkas row is still violated (using current bounds and ignoring local rows) */
5122  if( SCIPsetIsFeasGT(set, farkaslhs, farkasact) )
5123  {
5124  /* undo bound changes while keeping the infeasibility proof valid */
5125  SCIP_CALL( undoBdchgsProof(set, prob, currentdepth, farkascoefs, farkaslhs, farkasact,
5126  curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, resolve) );
5127 
5128  *valid = TRUE;
5129 
5130  /* resolving does not make sense: the old dual ray is still valid -> resolving will not change the solution */
5131  *resolve = FALSE;
5132  }
5133 
5134  TERMINATE:
5135 
5136  /* free temporary memory */
5137  SCIPsetFreeBufferArray(set, &farkascoefs);
5138  SCIPsetFreeBufferArray(set, &dualfarkas);
5139 
5140  return SCIP_OKAY;
5141 }
5142 
5143 /** analyzes an LP exceeding the objective limit and undoes additional bound changes while staying beyond the
5144  * objective limit
5145  */
5146 static
5148  SCIP_SET* set, /**< global SCIP settings */
5149  SCIP_PROB* prob, /**< problem data */
5150  SCIP_LP* lp, /**< LP data */
5151  int currentdepth, /**< current depth in the tree */
5152  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
5153  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
5154  int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
5155  int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
5156  SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
5157  SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
5158  SCIP_Bool* valid, /**< pointer to store whether the unfixings are valid */
5159  SCIP_Bool* resolve /**< pointer to store whether the changed LP should be resolved again */
5160  )
5161 {
5162  SCIP_RETCODE retcode;
5163  SCIP_LPI* lpi;
5164  SCIP_ROW** rows;
5165  SCIP_VAR** vars;
5166  SCIP_ROW* row;
5167  SCIP_VAR* var;
5168  SCIP_Real* primsols;
5169  SCIP_Real* dualsols;
5170  SCIP_Real* redcosts;
5171  SCIP_Real* dualcoefs;
5172  SCIP_Real* varredcosts;
5173  SCIP_Real duallhs;
5174  SCIP_Real dualact;
5175  int nrows;
5176  int ncols;
5177  int nvars;
5178  int r;
5179  int v;
5180  int i;
5181 
5182  assert(set != NULL);
5183  assert(prob != NULL);
5184  assert(lp != NULL);
5185  assert(lp->flushed);
5186  assert(lp->solved);
5187  assert(curvarlbs != NULL);
5188  assert(curvarubs != NULL);
5189  assert(lbchginfoposs != NULL);
5190  assert(ubchginfoposs != NULL);
5191  assert(valid != NULL);
5192  assert(resolve != NULL);
5193 
5194  *valid = FALSE;
5195  *resolve = FALSE;
5196 
5197  SCIPdebugMessage("undoing bound changes in LP exceeding cutoff: cutoff=%g\n", lp->cutoffbound);
5198 
5199  /* get LP solver interface */
5200  lpi = SCIPlpGetLPI(lp);
5201 
5202  /* get LP rows and problem variables */
5203  rows = SCIPlpGetRows(lp);
5204  nrows = SCIPlpGetNRows(lp);
5205  ncols = SCIPlpGetNCols(lp);
5206  vars = prob->vars;
5207  nvars = prob->nvars;
5208  assert(nrows == 0 || rows != NULL);
5209  assert(nrows == lp->nlpirows);
5210 
5211  /* get temporary memory */
5212  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsols, ncols) );
5213  SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsols, nrows) );
5214  SCIP_CALL( SCIPsetAllocBufferArray(set, &redcosts, ncols) );
5215  SCIP_CALL( SCIPsetAllocBufferArray(set, &dualcoefs, nvars) );
5216  SCIP_CALL( SCIPsetAllocBufferArray(set, &varredcosts, nvars) );
5217 
5218  /* get solution from LPI */
5219  retcode = SCIPlpiGetSol(lpi, NULL, primsols, dualsols, NULL, redcosts);
5220  if( retcode == SCIP_LPERROR ) /* on an error in the LP solver, just abort the conflict analysis */
5221  goto TERMINATE;
5222  SCIP_CALL( retcode );
5223 #ifdef SCIP_DEBUG
5224  {
5225  SCIP_Real objval;
5226  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
5227  SCIPdebugMessage(" -> LP objval: %g\n", objval);
5228  }
5229 #endif
5230 
5231  /* Let y be the dual solution and r be the reduced cost vector. Let z be defined as
5232  * z_i := y_i if i is a global row,
5233  * z_i := 0 if i is a local row.
5234  * Define the set X := {x | lhs <= Ax <= rhs, lb <= x <= ub, c^Tx <= c*}, with c* being the current primal bound.
5235  * Then the following inequalities are valid for all x \in X:
5236  * - c* <= -c^Tx
5237  * <=> z^TAx - c* <= (z^TA - c^T) x
5238  * <=> z^TAx - c* <= (y^TA - c^T - (y-z)^TA) x
5239  * <=> z^TAx - c* <= (-r^T - (y-z)^TA) x (dual feasibility of (y,r): y^TA + r^T == c^T)
5240  * Because lhs <= Ax <= rhs and lb <= x <= ub, the inequality can be relaxed to give
5241  * min{z^Tq | lhs <= q <= rhs} - c* <= max{(-r^T - (y-z)^TA) x | lb <= x <= ub}, or X = {}.
5242  *
5243  * The resulting dual row is: z^T{lhs,rhs} - c* <= (-r^T - (y-z)^TA){lb,ub},
5244  * where lhs, rhs, lb, and ub are selected in order to maximize the feasibility of the row.
5245  */
5246 
5247  BMSclearMemoryArray(dualcoefs, nvars);
5248 
5249  /* use a slightly tighter cutoff bound, because solutions with equal objective value should also be declared
5250  * infeasible
5251  */
5252  duallhs = -(lp->cutoffbound - SCIPsetSumepsilon(set));
5253  dualact = 0.0;
5254 
5255  /* dual row: z^T{lhs,rhs} - c* <= (-r^T - (y-z)^TA){lb,ub}
5256  * process rows: add z^T{lhs,rhs} to the dual row's left hand side, and -(y-z)^TA to the dual row's coefficients
5257  */
5258  for( r = 0; r < nrows; ++r )
5259  {
5260  row = rows[r];
5261  assert(row != NULL);
5262  assert(row->len == 0 || row->cols != NULL);
5263  assert(row->len == 0 || row->vals != NULL);
5264  assert(row == lp->lpirows[r]);
5265 
5266  /* ignore dual solution values of 0.0 (in this case: y_i == z_i == 0) */
5267  if( SCIPsetIsZero(set, dualsols[r]) )
5268  continue;
5269 
5270  /* check dual feasibility */
5271  if( (SCIPsetIsInfinity(set, -row->lhs) && dualsols[r] > 0.0) || (SCIPsetIsInfinity(set, row->rhs) && dualsols[r] < 0.0) )
5272  {
5273  SCIPdebugMessage(" -> infeasible dual solution %g in row <%s>: lhs=%g, rhs=%g\n",
5274  dualsols[r], SCIProwGetName(row), row->lhs, row->rhs);
5275  goto TERMINATE;
5276  }
5277 
5278  /* local rows add up to the dual row's coefficients (because z_i == 0 => -(y_i - z_i) == -y_i),
5279  * global rows add up to the dual row's left hand side (because z_i == y_i != 0)
5280  */
5281  if( row->local )
5282  {
5283  /* add -y_i A_i to coefficients of dual row */
5284  for( i = 0; i < row->len; ++i )
5285  {
5286  v = SCIPvarGetProbindex(SCIPcolGetVar(row->cols[i]));
5287  assert(0 <= v && v < nvars);
5288  dualcoefs[v] -= dualsols[r] * row->vals[i];
5289  }
5290  SCIPdebugMessage(" -> local row <%s>: dual=%g\n", SCIProwGetName(row), dualsols[r]);
5291  }
5292  else
5293  {
5294  /* add minimal value to dual row's left hand side: z_i == y_i > 0 -> lhs, z_i == y_i < 0 -> rhs */
5295  if( dualsols[r] > 0.0 )
5296  {
5297  assert(!SCIPsetIsInfinity(set, -row->lhs));
5298  duallhs += dualsols[r] * (row->lhs - row->constant);
5299  }
5300  else
5301  {
5302  assert(!SCIPsetIsInfinity(set, row->rhs));
5303  duallhs += dualsols[r] * (row->rhs - row->constant);
5304  }
5305  SCIPdebugMessage(" -> global row <%s>[%g,%g]: dual=%g -> duallhs=%g\n",
5306  SCIProwGetName(row), row->lhs - row->constant, row->rhs - row->constant, dualsols[r], duallhs);
5307  }
5308  }
5309 
5310  /* dual row: z^T{lhs,rhs} - c* <= (-r^T - (y-z)^TA){lb,ub}
5311  * process variables: subtract reduced costs from dual row's coefficients, and calculate current maximal dual
5312  * activity by multiplying the resultant coefficient with lb or ub
5313  */
5314  for( v = 0; v < nvars; ++v )
5315  {
5316  var = vars[v];
5317  assert(SCIPvarGetProbindex(var) == v);
5318 
5320  {
5321  /* reduced costs for loose variables are equal to the objective value */
5322  varredcosts[v] = SCIPvarGetObj(var);
5323  }
5324  else
5325  {
5326  SCIP_COL* col;
5327  int c;
5328 
5329  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
5330  col = SCIPvarGetCol(var);
5331  c = SCIPcolGetLPPos(col);
5332  assert(c == -1 || col == lp->cols[c]);
5333  assert(c == -1 || col == lp->lpicols[c]);
5334 
5335  /* get reduced costs from LPI, or calculate it manually if the column is not in current LP */
5336  varredcosts[v] = (c >= 0 ? redcosts[c] : SCIPcolCalcRedcost(col, dualsols));
5337 
5338  /* check dual feasibility */
5339  if( (SCIPsetIsGT(set, primsols[c], curvarlbs[v]) && SCIPsetIsFeasPositive(set, varredcosts[v]))
5340  || (SCIPsetIsLT(set, primsols[c], curvarubs[v]) && SCIPsetIsFeasNegative(set, varredcosts[v])) )
5341  {
5342  SCIPdebugMessage(" -> infeasible reduced costs %g in var <%s>: lb=%g, ub=%g\n",
5343  varredcosts[v], SCIPvarGetName(var), curvarlbs[v], curvarubs[v]);
5344  goto TERMINATE;
5345  }
5346  }
5347 
5348  /* subtract reduced costs from dual row's coefficients */
5349  dualcoefs[v] -= varredcosts[v];
5350 
5351  /* add maximal value to dual row's activity: dualcoef > 0 -> ub, dualcoef < 0 -> lb */
5352  if( dualcoefs[v] > 0.0 )
5353  {
5354  if( SCIPsetIsInfinity(set, curvarubs[v]) )
5355  goto TERMINATE;
5356  dualact += dualcoefs[v] * curvarubs[v];
5357  }
5358  else
5359  {
5360  if( SCIPsetIsInfinity(set, -curvarlbs[v]) )
5361  goto TERMINATE;
5362  dualact += dualcoefs[v] * curvarlbs[v];
5363  }
5364  }
5365  SCIPdebugMessage(" -> final dual values: lhs=%g, act=%g\n", duallhs, dualact);
5366 
5367  /* check, if the dual row is still violated (using current bounds and ignoring local rows) */
5368  if( SCIPsetIsFeasGT(set, duallhs, dualact) )
5369  {
5370  /* undo bound changes while keeping the infeasibility proof valid */
5371  SCIP_CALL( undoBdchgsProof(set, prob, currentdepth, dualcoefs, duallhs, dualact,
5372  curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, resolve) );
5373 
5374  *valid = TRUE;
5375  }
5376 
5377  TERMINATE:
5378 
5379  /* free temporary memory */
5380  SCIPsetFreeBufferArray(set, &varredcosts);
5381  SCIPsetFreeBufferArray(set, &dualcoefs);
5382  SCIPsetFreeBufferArray(set, &redcosts);
5383  SCIPsetFreeBufferArray(set, &dualsols);
5384  SCIPsetFreeBufferArray(set, &primsols);
5385 
5386  return SCIP_OKAY;
5387 }
5388 
5389 /** applies conflict analysis starting with given bound changes, that could not be undone during previous
5390  * infeasibility analysis
5391  */
5392 static
5394  SCIP_CONFLICT* conflict, /**< conflict analysis data */
5395  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5396  SCIP_SET* set, /**< global SCIP settings */
5397  SCIP_STAT* stat, /**< problem statistics */
5398  SCIP_PROB* prob, /**< problem data */
5399  SCIP_TREE* tree, /**< branch and bound tree */
5400  SCIP_Bool diving, /**< are we in strong branching or diving mode? */
5401  int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
5402  int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
5403  int* nconss, /**< pointer to store the number of generated conflict constraints */
5404  int* nliterals, /**< pointer to store the number of literals in generated conflict constraints */
5405  int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
5406  int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
5407  )
5408 {
5409  SCIP_VAR** vars;
5410  SCIP_VAR* var;
5411  int nvars;
5412  int v;
5413  int nbdchgs;
5414  int maxsize;
5415 
5416  assert(prob != NULL);
5417  assert(lbchginfoposs != NULL);
5418  assert(ubchginfoposs != NULL);
5419  assert(nconss != NULL);
5420  assert(nliterals != NULL);
5421  assert(nreconvconss != NULL);
5422  assert(nreconvliterals != NULL);
5423 
5424  *nconss = 0;
5425  *nliterals = 0;
5426  *nreconvconss = 0;
5427  *nreconvliterals = 0;
5428 
5429  vars = prob->vars;
5430  nvars = prob->nvars;
5431  assert(nvars == 0 || vars != NULL);
5432 
5433  maxsize = 2*conflictCalcMaxsize(set, prob);
5434 
5435  /* initialize conflict data */
5436  SCIP_CALL( SCIPconflictInit(conflict, set, stat, prob) );
5437 
5438  /* add remaining bound changes to conflict queue */
5439  SCIPdebugMessage("initial conflict set after undoing bound changes:\n");
5440  nbdchgs = 0;
5441  for( v = 0; v < nvars && nbdchgs < maxsize; ++v )
5442  {
5443  var = vars[v];
5444  assert(var != NULL);
5445  assert(var->nlbchginfos >= 0);
5446  assert(var->nubchginfos >= 0);
5447  assert(-1 <= lbchginfoposs[v] && lbchginfoposs[v] <= var->nlbchginfos);
5448  assert(-1 <= ubchginfoposs[v] && ubchginfoposs[v] <= var->nubchginfos);
5449 
5450  if( lbchginfoposs[v] == var->nlbchginfos || ubchginfoposs[v] == var->nubchginfos )
5451  {
5452  SCIP_BDCHGINFO* bdchginfo;
5453  SCIP_Real relaxedbd;
5454 
5455  /* the strong branching or diving bound stored in the column is responsible for the conflict:
5456  * it cannot be resolved and therefore has to be directly put into the conflict set
5457  */
5458  assert((lbchginfoposs[v] == var->nlbchginfos) != (ubchginfoposs[v] == var->nubchginfos)); /* only one can be tight in the dual! */
5459  assert(lbchginfoposs[v] < var->nlbchginfos || SCIPvarGetLbLP(var, set) > SCIPvarGetLbLocal(var));
5460  assert(ubchginfoposs[v] < var->nubchginfos || SCIPvarGetUbLP(var, set) < SCIPvarGetUbLocal(var));
5461 
5462  /* create an artificial bound change information for the diving/strong branching bound change;
5463  * they are freed in the SCIPconflictFlushConss() call
5464  */
5465  if( lbchginfoposs[v] == var->nlbchginfos )
5466  {
5467  SCIP_CALL( conflictCreateTmpBdchginfo(conflict, blkmem, set, var, SCIP_BOUNDTYPE_LOWER,
5468  SCIPvarGetLbLocal(var), SCIPvarGetLbLP(var, set), &bdchginfo) );
5469  relaxedbd = SCIPvarGetLbLP(var, set);
5470  }
5471  else
5472  {
5473  SCIP_CALL( conflictCreateTmpBdchginfo(conflict, blkmem, set, var, SCIP_BOUNDTYPE_UPPER,
5474  SCIPvarGetUbLocal(var), SCIPvarGetUbLP(var, set), &bdchginfo) );
5475  relaxedbd = SCIPvarGetUbLP(var, set);
5476  }
5477 
5478  /* put variable into the conflict set */
5479  SCIPdebugMessage(" force: <%s> %s %g [status: %d, type: %d, dive/strong]\n",
5480  SCIPvarGetName(var), lbchginfoposs[v] == var->nlbchginfos ? ">=" : "<=",
5481  lbchginfoposs[v] == var->nlbchginfos ? SCIPvarGetLbLP(var, set) : SCIPvarGetUbLP(var, set),
5482  SCIPvarGetStatus(var), SCIPvarGetType(var));
5483  SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, bdchginfo, relaxedbd) );
5484 
5485  /* each variable which is add to the conflict graph gets an increase in the VSIDS
5486  *
5487  * @note That is different to the VSIDS preseted in the literature
5488  */
5489  SCIP_CALL( incVSIDS(var, blkmem, set, stat, SCIPbdchginfoGetBoundtype(bdchginfo), relaxedbd, set->conf_conflictgraphweight) );
5490  nbdchgs++;
5491  }
5492  else
5493  {
5494  /* put remaining bound changes into conflict candidate queue */
5495  if( lbchginfoposs[v] >= 0 )
5496  {
5497  SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, SCIP_BOUNDTYPE_LOWER, &var->lbchginfos[lbchginfoposs[v]], SCIPbdchginfoGetNewbound(&var->lbchginfos[lbchginfoposs[v]])) );
5498  nbdchgs++;
5499  }
5500  if( ubchginfoposs[v] >= 0 )
5501  {
5502  assert(!SCIPbdchginfoIsRedundant(&var->ubchginfos[ubchginfoposs[v]]));
5503  SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, SCIP_BOUNDTYPE_UPPER, &var->ubchginfos[ubchginfoposs[v]], SCIPbdchginfoGetNewbound(&var->ubchginfos[ubchginfoposs[v]])) );
5504  nbdchgs++;
5505  }
5506  }
5507  }
5508 
5509  if( v == nvars )
5510  {
5511  /* analyze the conflict set, and create conflict constraints on success */
5512  SCIP_CALL( conflictAnalyze(conflict, blkmem, set, stat, prob, tree, diving, 0, FALSE,
5513  nconss, nliterals, nreconvconss, nreconvliterals) );
5514  }
5515 
5516  return SCIP_OKAY;
5517 }
5518 
5519 /** actually performs analysis of infeasible LP */
5520 static
5522  SCIP_CONFLICT* conflict, /**< conflict analysis data */
5523  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5524  SCIP_SET* set, /**< global SCIP settings */
5525  SCIP_STAT* stat, /**< problem statistics */
5526  SCIP_PROB* transprob, /**< transformed problem */
5527  SCIP_PROB* origprob, /**< original problem */
5528  SCIP_TREE* tree, /**< branch and bound tree */
5529  SCIP_LP* lp, /**< LP data */
5530  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5531  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5532  SCIP_Bool diving, /**< are we in strong branching or diving mode? */
5533  int* iterations, /**< pointer to store the total number of LP iterations used */
5534  int* nconss, /**< pointer to store the number of generated conflict constraints */
5535  int* nliterals, /**< pointer to store the number of literals in generated conflict constraints */
5536  int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
5537  int* nreconvliterals, /**< pointer to store the number of literals generated reconvergence constraints */
5538  SCIP_Bool marklpunsolved /**< whether LP should be marked unsolved after analysis (needed for strong branching) */
5539  )
5540 {
5541  SCIP_LPBDCHGS* oldlpbdchgs;
5542  SCIP_LPBDCHGS* relaxedlpbdchgs;
5543  SCIP_LPI* lpi;
5544  SCIP_VAR** vars;
5545  SCIP_Real* curvarlbs;
5546  SCIP_Real* curvarubs;
5547  int* lbchginfoposs;
5548  int* ubchginfoposs;
5549  SCIP_Bool resolve;
5550  SCIP_Bool solvelp;
5551  SCIP_Bool valid;
5552  int ncols;
5553  int nvars;
5554  int v;
5555 
5556  assert(conflict != NULL);
5557  assert(conflict->nconflictsets == 0);
5558  assert(set != NULL);
5559  assert(SCIPprobAllColsInLP(transprob, set, lp)); /* LP conflict analysis is only valid, if all variables are known */
5560  assert(stat != NULL);
5561  assert(transprob != NULL);
5562  assert(lp != NULL);
5563  assert(lp->flushed);
5564  assert(lp->solved);
5565  assert(iterations != NULL);
5566  assert(nconss != NULL);
5567  assert(nliterals != NULL);
5568  assert(nreconvconss != NULL);
5569  assert(nreconvliterals != NULL);
5570 
5571  *iterations = 0;
5572  *nconss = 0;
5573  *nliterals = 0;
5574  *nreconvconss = 0;
5575  *nreconvliterals = 0;
5576 
5577  /* get LP solver interface */
5578  lpi = SCIPlpGetLPI(lp);
5581 
5582  if( !SCIPlpiIsPrimalInfeasible(lpi) )
5583  {
5584  SCIP_Real objval;
5585 
5586  assert(!SCIPlpDivingObjChanged(lp));
5587 
5588  /* make sure, a dual feasible solution exists, that exceeds the objective limit;
5589  * With FASTMIP setting, CPLEX does not apply the final pivot to reach the dual solution exceeding the objective
5590  * limit. Therefore, we have to either turn off FASTMIP and resolve the problem or continue solving it without
5591  * objective limit for at least one iteration. It seems that the strategy to continue with FASTMIP for one
5592  * additional simplex iteration yields better results.
5593  */
5594  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
5595  if( objval < lp->lpiuobjlim )
5596  {
5597  SCIP_RETCODE retcode;
5598 
5599  /* temporarily disable objective limit and install an iteration limit */
5602 
5603  /* start LP timer */
5604  SCIPclockStart(stat->conflictlptime, set);
5605 
5606  /* resolve LP */
5607  retcode = SCIPlpiSolveDual(lpi);
5608 
5609  /* stop LP timer */
5610  SCIPclockStop(stat->conflictlptime, set);
5611 
5612  /* check return code of LP solving call */
5613  valid = (retcode != SCIP_LPERROR);
5614  if( valid )
5615  {
5616  int iter;
5617 
5618  SCIP_CALL( retcode );
5619 
5620  /* count number of LP iterations */
5621  SCIP_CALL( SCIPlpiGetIterations(lpi, &iter) );
5622  (*iterations) += iter;
5623  stat->nconflictlps++;
5624  stat->nconflictlpiterations += iter;
5625  SCIPdebugMessage(" -> resolved objlim exceeding LP in %d iterations (total: %"SCIP_LONGINT_FORMAT") (infeasible:%u, objlim: %u, optimal:%u)\n",
5627  SCIPlpiIsOptimal(lpi));
5629  }
5630 
5631  /* reinstall old objective and iteration limits in LP solver */
5634 
5635  /* abort, if the LP produced an error */
5636  if( !valid )
5637  return SCIP_OKAY;
5638  }
5639  }
5641 
5642  if( !SCIPlpiIsPrimalInfeasible(lpi) )
5643  {
5644  SCIP_Real objval;
5645 
5646  assert(!SCIPlpDivingObjChanged(lp));
5647 
5648  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
5649  if( objval < lp->lpiuobjlim )
5650  {
5651  SCIPdebugMessage(" -> LP does not exceed the cutoff bound: obj=%g, cutoff=%g\n", objval, lp->lpiuobjlim);
5652  return SCIP_OKAY;
5653  }
5654  else
5655  {
5656  SCIPdebugMessage(" -> LP exceeds the cutoff bound: obj=%g, cutoff=%g\n", objval, lp->lpiuobjlim);
5657  }
5658  }
5659 
5660  SCIPdebugMessage("analyzing conflict on infeasible LP (infeasible: %u, objlimexc: %u, optimal:%u) in depth %d (diving: %u)\n",
5662 #ifdef SCIP_DEBUG
5663  {
5664  SCIP_Real uobjlim;
5665 
5666  SCIP_CALL( SCIPlpiGetRealpar(lpi, SCIP_LPPAR_UOBJLIM, &uobjlim) );
5667  SCIPdebugMessage(" -> objective limit in LP solver: %g (in LP: %g)\n", uobjlim, lp->lpiuobjlim);
5668  }
5669 #endif
5670 
5671  /* get active problem variables */
5672  vars = transprob->vars;
5673  nvars = transprob->nvars;
5674 
5675  /* get temporary memory for remembering variables' current bounds and corresponding bound change information
5676  * positions in variable's bound change information arrays
5677  */
5678  SCIP_CALL( SCIPsetAllocBufferArray(set, &curvarlbs, nvars) );
5679  SCIP_CALL( SCIPsetAllocBufferArray(set, &curvarubs, nvars) );
5680  SCIP_CALL( SCIPsetAllocBufferArray(set, &lbchginfoposs, nvars) );
5681  SCIP_CALL( SCIPsetAllocBufferArray(set, &ubchginfoposs, nvars) );
5682 
5683  /* the following algorithm is used to find a subset of changed bounds leading to an infeasible LP:
5684  * 1. call undoBdchgsDualfarkas() or undoBdchgsDualsol()
5685  * -> update lb/ubchginfoposs arrays
5686  * -> store additional changes in bdchg and curvarlbs/ubs arrays
5687  * -> apply additional changes to the LPI
5688  * 2. (optional) if additional bound changes were undone:
5689  * -> resolve LP
5690  * -> goto 1.
5691  * 3. redo all bound changes in the LPI to restore the LPI to its original state
5692  * 4. analyze conflict
5693  * -> put remaining changed bounds (see lb/ubchginfoposs arrays) into starting conflict set
5694  */
5695 
5696  /* get current bounds and current positions in lb/ubchginfos arrays of variables */
5697  valid = TRUE;
5698  for( v = 0; v < nvars && valid; ++v )
5699  {
5700  SCIP_VAR* var;
5701 
5702  var = vars[v];
5703 
5704  curvarlbs[v] = SCIPvarGetLbLP(var, set);
5705  curvarubs[v] = SCIPvarGetUbLP(var, set);
5706  lbchginfoposs[v] = var->nlbchginfos-1;
5707  ubchginfoposs[v] = var->nubchginfos-1;
5708  assert(diving || SCIPsetIsEQ(set, curvarlbs[v], SCIPvarGetLbLocal(var)));
5709  assert(diving || SCIPsetIsEQ(set, curvarubs[v], SCIPvarGetUbLocal(var)));
5710 
5711  /* check, if last bound changes were due to strong branching or diving */
5712  if( diving )
5713  {
5714  SCIP_Real lb;
5715  SCIP_Real ub;
5716 
5717  lb = SCIPvarGetLbLocal(var);
5718  ub = SCIPvarGetUbLocal(var);
5719  if( SCIPsetIsGT(set, curvarlbs[v], lb) )
5720  lbchginfoposs[v] = var->nlbchginfos;
5721  else if( SCIPsetIsLT(set, curvarlbs[v], lb) )
5722  {
5723  /* the bound in the diving LP was relaxed -> the LP is not a subproblem of the current node -> abort! */
5724  /**@todo we could still analyze such a conflict, but we would have to take care with our data structures */
5725  valid = FALSE;
5726  }
5727  if( SCIPsetIsLT(set, curvarubs[v], ub) )
5728  ubchginfoposs[v] = var->nubchginfos;
5729  else if( SCIPsetIsGT(set, curvarubs[v], ub) )
5730  {
5731  /* the bound in the diving LP was relaxed -> the LP is not a subproblem of the current node -> abort! */
5732  /**@todo we could still analyze such a conflict, but we would have to take care with our data structures */
5733  valid = FALSE;
5734  }
5735  }
5736  }
5737 
5738  /* get number of columns in the LP */
5739  ncols = SCIPlpGetNCols(lp);
5740 
5741  /* get temporary memory for remembering bound changes on LPI columns */
5742  SCIP_CALL( lpbdchgsCreate(&oldlpbdchgs, set, ncols) );
5743  SCIP_CALL( lpbdchgsCreate(&relaxedlpbdchgs, set, ncols) );
5744 
5745  /* undo as many bound changes as possible with the current LP solution */
5746  resolve = FALSE;
5747  if( valid )
5748  {
5749  int currentdepth;
5750  currentdepth = SCIPtreeGetCurrentDepth(tree);
5751  if( SCIPlpiIsPrimalInfeasible(lpi) )
5752  {
5753  SCIP_CALL( undoBdchgsDualfarkas(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs,
5754  ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, &valid, &resolve) );
5755  }
5756  else
5757  {
5758  assert(SCIPlpiIsDualFeasible(lpi) || SCIPlpiIsObjlimExc(lpi));
5759  SCIP_CALL( undoBdchgsDualsol(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs,
5760  oldlpbdchgs, relaxedlpbdchgs, &valid, &resolve) );
5761  }
5762  }
5763 
5764  /* check if we want to solve the LP */
5765  assert(SCIPprobAllColsInLP(transprob, set, lp));
5766  solvelp = (set->conf_maxlploops != 0 && set->conf_lpiterations != 0);
5767 
5768  if( valid && resolve && solvelp )
5769  {
5770  SCIP_RETCODE retcode;
5771  SCIP_ROW** rows;
5772  int* sidechginds;
5773  SCIP_Real* sidechgoldlhss;
5774  SCIP_Real* sidechgoldrhss;
5775  SCIP_Real* sidechgnewlhss;
5776  SCIP_Real* sidechgnewrhss;
5777  SCIP_Real lpiinfinity;
5778  int maxlploops;
5779  int lpiterations;
5780  int sidechgssize;
5781  int nsidechgs;
5782  int nrows;
5783  int nloops;
5784  int r;
5785 
5786  /* get infinity value of LP solver */
5787  lpiinfinity = SCIPlpiInfinity(lpi);
5788 
5789  /* temporarily disable objective limit and install an iteration limit */
5790  maxlploops = (set->conf_maxlploops >= 0 ? set->conf_maxlploops : INT_MAX);
5791  lpiterations = (set->conf_lpiterations >= 0 ? set->conf_lpiterations : INT_MAX);
5792  SCIP_CALL( SCIPlpiSetRealpar(lpi, SCIP_LPPAR_UOBJLIM, lpiinfinity) );
5793  SCIP_CALL( SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, lpiterations) );
5794 
5795  /* get LP rows */
5796  rows = SCIPlpGetRows(lp);
5797  nrows = SCIPlpGetNRows(lp);
5798  assert(nrows == 0 || rows != NULL);
5799 
5800  /* get temporary memory for remembering side changes on LPI rows */
5801  SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechginds, nrows) );
5802  SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgoldlhss, nrows) );
5803  SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgoldrhss, nrows) );
5804  SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgnewlhss, nrows) );
5805  SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgnewrhss, nrows) );
5806  sidechgssize = nrows;
5807  nsidechgs = 0;
5808 
5809  /* remove all local rows by setting their sides to infinity;
5810  * finite sides are only changed to near infinity, such that the row's sense in the LP solver
5811  * is not affected (e.g. CPLEX cannot handle free rows)
5812  */
5813  for( r = 0 ; r < nrows; ++r )
5814  {
5815  assert(SCIProwGetLPPos(rows[r]) == r);
5816 
5817  if( SCIProwIsLocal(rows[r]) )
5818  {
5819  SCIPdebugMessage(" -> removing local row <%s> [%g,%g]\n",
5820  SCIProwGetName(rows[r]), SCIProwGetLhs(rows[r]), SCIProwGetRhs(rows[r]));
5821  SCIP_CALL( addSideRemoval(set, rows[r], lpiinfinity, &sidechginds, &sidechgoldlhss, &sidechgoldrhss,
5822  &sidechgnewlhss, &sidechgnewrhss, &sidechgssize, &nsidechgs) );
5823  }
5824  }
5825 
5826  /* apply changes of local rows to the LP solver */
5827  if( nsidechgs > 0 )
5828  {
5829  SCIP_CALL( SCIPlpiChgSides(lpi, nsidechgs, sidechginds, sidechgnewlhss, sidechgnewrhss) );
5830  }
5831 
5832  /* undo as many additional bound changes as possible by resolving the LP */
5833  assert(valid);
5834  assert(resolve);
5835  nloops = 0;
5836  while( valid && resolve && nloops < maxlploops )
5837  {
5838  int iter;
5839 
5840  nloops++;
5841  resolve = FALSE;
5842 
5843  SCIPdebugMessage("infeasible LP conflict analysis loop %d (changed col bounds: %d)\n", nloops, relaxedlpbdchgs->nbdchgs);
5844 
5845  /* apply bound changes to the LP solver */
5846  assert(relaxedlpbdchgs->nbdchgs >= 0);
5847  if( relaxedlpbdchgs->nbdchgs > 0 )
5848  {
5849  SCIPdebugMessage(" -> applying %d bound changes to the LP solver\n", relaxedlpbdchgs->nbdchgs);
5850  SCIP_CALL( SCIPlpiChgBounds(lpi, relaxedlpbdchgs->nbdchgs,
5851  relaxedlpbdchgs->bdchginds, relaxedlpbdchgs->bdchglbs, relaxedlpbdchgs->bdchgubs) );
5852 
5853  /* reset conflict LP bound change data structure */
5854  lpbdchgsReset(relaxedlpbdchgs);
5855  }
5856 
5857  /* start LP timer */
5858  SCIPclockStart(stat->conflictlptime, set);
5859 
5860  /* resolve LP */
5861  retcode = SCIPlpiSolveDual(lpi);
5862 
5863  /* stop LP timer */
5864  SCIPclockStop(stat->conflictlptime, set);
5865 
5866  /* check return code of LP solving call */
5867  if( retcode == SCIP_LPERROR )
5868  {
5869  valid = FALSE;
5870  break;
5871  }
5872  SCIP_CALL( retcode );
5873 
5874  /* count number of LP iterations */
5875  SCIP_CALL( SCIPlpiGetIterations(lpi, &iter) );
5876  (*iterations) += iter;
5877  stat->nconflictlps++;
5878  stat->nconflictlpiterations += iter;
5879  SCIPdebugMessage(" -> resolved LP in %d iterations (total: %"SCIP_LONGINT_FORMAT") (infeasible:%u)\n",
5881 
5882  /* evaluate result */
5883  if( SCIPlpiIsDualFeasible(lpi) || SCIPlpiIsObjlimExc(lpi) )
5884  {
5885  SCIP_Real objval;
5886 
5887  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
5888  valid = (objval >= lp->lpiuobjlim && !SCIPlpDivingObjChanged(lp));
5889  }
5890  else
5891  valid = SCIPlpiIsPrimalInfeasible(lpi);
5892 
5893  if( valid )
5894  {
5895  int currentdepth;
5896  currentdepth = SCIPtreeGetCurrentDepth(tree);
5897  /* undo additional bound changes */
5898  if( SCIPlpiIsPrimalInfeasible(lpi) )
5899  {
5900  SCIP_CALL( undoBdchgsDualfarkas(set, transprob, lp, currentdepth, curvarlbs, curvarubs,
5901  lbchginfoposs, ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, &valid, &resolve) );
5902  }
5903  else
5904  {
5905  assert(SCIPlpiIsDualFeasible(lpi) || SCIPlpiIsObjlimExc(lpi));
5906  SCIP_CALL( undoBdchgsDualsol(set, transprob, lp, currentdepth, curvarlbs, curvarubs,
5907  lbchginfoposs, ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, &valid, &resolve) );
5908  }
5909  }
5910  assert(!resolve || valid);
5911  assert(!resolve || relaxedlpbdchgs->nbdchgs > 0);
5912  SCIPdebugMessage(" -> finished infeasible LP conflict analysis loop %d (iter: %d, nbdchgs: %d)\n",
5913  nloops, iter, relaxedlpbdchgs->nbdchgs);
5914  }
5915 
5916  SCIPdebugMessage("finished undoing bound changes after %d loops (valid=%u, nbdchgs: %d)\n",
5917  nloops, valid, oldlpbdchgs->nbdchgs);
5918 
5919  /* reset variables to local bounds */
5920  if( oldlpbdchgs->nbdchgs > 0 )
5921  {
5922  SCIP_CALL( SCIPlpiChgBounds(lpi, oldlpbdchgs->nbdchgs,
5923  oldlpbdchgs->bdchginds, oldlpbdchgs->bdchglbs, oldlpbdchgs->bdchgubs) );
5924  }
5925 
5926  /* reset changes of local rows */
5927  if( nsidechgs > 0 )
5928  {
5929  SCIP_CALL( SCIPlpiChgSides(lpi, nsidechgs, sidechginds, sidechgoldlhss, sidechgoldrhss) );
5930  }
5931 
5932  /* mark the LP unsolved */
5933  if( oldlpbdchgs->nbdchgs > 0 || nsidechgs > 0 )
5934  {
5935  /* The LPI data are out of sync with LP data. Thus, the LP should be marked
5936  * unsolved. However, for strong branching calls, the LP has to have status 'solved'; in
5937  * this case, marklpunsolved is FALSE and synchronization is performed later. */
5938  if ( marklpunsolved )
5939  {
5940  lp->solved = FALSE;
5941  lp->primalfeasible = FALSE;
5942  lp->dualfeasible = FALSE;
5943  lp->lpobjval = SCIP_INVALID;
5945  }
5946  }
5947 
5948  /* reinstall old objective and iteration limits in LP solver */
5951 
5952  /* free temporary memory */
5953  SCIPsetFreeBufferArray(set, &sidechgnewrhss);
5954  SCIPsetFreeBufferArray(set, &sidechgnewlhss);
5955  SCIPsetFreeBufferArray(set, &sidechgoldrhss);
5956  SCIPsetFreeBufferArray(set, &sidechgoldlhss);
5957  SCIPsetFreeBufferArray(set, &sidechginds);
5958  }
5959 
5960  /* analyze the conflict starting with remaining bound changes */
5961  if( valid )
5962  {
5963  SCIP_CALL( conflictAnalyzeRemainingBdchgs(conflict, blkmem, set, stat, transprob, tree, diving,
5964  lbchginfoposs, ubchginfoposs, nconss, nliterals, nreconvconss, nreconvliterals) );
5965  }
5966 
5967  /* free temporary memory */
5968  lpbdchgsFree(&relaxedlpbdchgs, set);
5969  lpbdchgsFree(&oldlpbdchgs, set);
5970  SCIPsetFreeBufferArray(set, &ubchginfoposs);
5971  SCIPsetFreeBufferArray(set, &lbchginfoposs);
5972  SCIPsetFreeBufferArray(set, &curvarubs);
5973  SCIPsetFreeBufferArray(set, &curvarlbs);
5974 
5975  /* flush conflict set storage */
5976  SCIP_CALL( SCIPconflictFlushConss(conflict, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue) );
5977 
5978  return SCIP_OKAY;
5979 }
5980 
5981 /** analyzes an infeasible LP to find out the bound changes on variables that were responsible for the infeasibility;
5982  * on success, calls standard conflict analysis with the responsible variables as starting conflict set, thus creating
5983  * a conflict constraint out of the resulting conflict set;
5984  * updates statistics for infeasible LP conflict analysis
5985  */
5986 static
5988  SCIP_CONFLICT* conflict, /**< conflict analysis data */
5989  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5990  SCIP_SET* set, /**< global SCIP settings */
5991  SCIP_STAT* stat, /**< problem statistics */
5992  SCIP_PROB* transprob, /**< transformed problem */
5993  SCIP_PROB* origprob, /**< original problem */
5994  SCIP_TREE* tree, /**< branch and bound tree */
5995  SCIP_LP* lp, /**< LP data */
5996  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5997  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5998  SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
5999  )
6000 {
6001  int iterations;
6002  int nconss;
6003  int nliterals;
6004  int nreconvconss;
6005  int nreconvliterals;
6006 
6007  assert(conflict != NULL);
6008  assert(set != NULL);
6009  assert(lp != NULL);
6010  assert(SCIPprobAllColsInLP(transprob, set, lp)); /* LP conflict analysis is only valid, if all variables are known */
6011 
6012  assert(success == NULL || *success == FALSE);
6013 
6014  /* check, if infeasible LP conflict analysis is enabled */
6015  if( !set->conf_enable || !set->conf_useinflp )
6016  return SCIP_OKAY;
6017 
6018  /* check, if there are any conflict handlers to use a conflict set */
6019  if( set->nconflicthdlrs == 0 )
6020  return SCIP_OKAY;
6021 
6022  SCIPdebugMessage("analyzing conflict on infeasible LP in depth %d (solstat: %d, objchanged: %u)\n",
6024 
6025  /* start timing */
6026  SCIPclockStart(conflict->inflpanalyzetime, set);
6027  conflict->ninflpcalls++;
6028 
6029  /* perform conflict analysis */
6030  SCIP_CALL( conflictAnalyzeLP(conflict, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
6031  SCIPlpDiving(lp), &iterations, &nconss, &nliterals, &nreconvconss, &nreconvliterals, TRUE) );
6032  conflict->ninflpsuccess += (nconss > 0 ? 1 : 0);
6033  conflict->ninflpiterations += iterations;
6034  conflict->ninflpconfconss += nconss;
6035  conflict->ninflpconfliterals += nliterals;
6036  conflict->ninflpreconvconss += nreconvconss;
6037  conflict->ninflpreconvliterals += nreconvliterals;
6038  if( success != NULL )
6039  *success = (nconss > 0);
6040 
6041  /* stop timing */
6042  SCIPclockStop(conflict->inflpanalyzetime, set);
6043 
6044  return SCIP_OKAY;
6045 }
6046 
6047 /** analyzes a bound exceeding LP to find out the bound changes on variables that were responsible for exceeding the
6048  * primal bound;
6049  * on success, calls standard conflict analysis with the responsible variables as starting conflict set, thus creating
6050  * a conflict constraint out of the resulting conflict set;
6051  * updates statistics for bound exceeding LP conflict analysis
6052  */
6053 static
6055  SCIP_CONFLICT* conflict, /**< conflict analysis data */
6056  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
6057  SCIP_SET* set, /**< global SCIP settings */
6058  SCIP_STAT* stat, /**< problem statistics */
6059  SCIP_PROB* transprob, /**< transformed problem */
6060  SCIP_PROB* origprob, /**< original problem */
6061  SCIP_TREE* tree, /**< branch and bound tree */
6062  SCIP_LP* lp, /**< LP data */
6063  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6064  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6065  SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
6066  )
6067 {
6068  int iterations;
6069  int nconss;
6070  int nliterals;
6071  int nreconvconss;
6072  int nreconvliterals;
6073 
6074  assert(conflict != NULL);
6075  assert(set != NULL);
6076  assert(lp != NULL);
6077  assert(!SCIPlpDivingObjChanged(lp));
6078  assert(SCIPprobAllColsInLP(transprob, set, lp)); /* LP conflict analysis is only valid, if all variables are known */
6079 
6080  assert(success == NULL || *success == FALSE);
6081 
6082  /* check, if bound exceeding LP conflict analysis is enabled */
6083  if( !set->conf_enable || !set->conf_useboundlp )
6084  return SCIP_OKAY;
6085 
6086  /* check, if there are any conflict handlers to use a conflict set */
6087  if( set->nconflicthdlrs == 0 )
6088  return SCIP_OKAY;
6089 
6090  SCIPdebugMessage("analyzing conflict on bound exceeding LP in depth %d (solstat: %d)\n",
6092 
6093  /* start timing */
6094  SCIPclockStart(conflict->boundlpanalyzetime, set);
6095  conflict->nboundlpcalls++;
6096 
6097  /* perform conflict analysis */
6098  SCIP_CALL( conflictAnalyzeLP(conflict, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
6099  SCIPlpDiving(lp), &iterations, &nconss, &nliterals, &nreconvconss, &nreconvliterals, TRUE) );
6100  conflict->nboundlpsuccess += (nconss > 0 ? 1 : 0);
6101  conflict->nboundlpiterations += iterations;
6102  conflict->nboundlpconfconss += nconss;
6103  conflict->nboundlpconfliterals += nliterals;
6104  conflict->nboundlpreconvconss += nreconvconss;
6105  conflict->nboundlpreconvliterals += nreconvliterals;
6106  if( success != NULL )
6107  *success = (nconss > 0);
6108 
6109  /* stop timing */
6110  SCIPclockStop(conflict->boundlpanalyzetime, set);
6111 
6112  return SCIP_OKAY;
6113 }
6114 
6115 /** analyzes an infeasible or bound exceeding LP to find out the bound changes on variables that were responsible for the
6116  * infeasibility or for exceeding the primal bound;
6117  * on success, calls standard conflict analysis with the responsible variables as starting conflict set, thus creating
6118  * a conflict constraint out of the resulting conflict set;
6119  * updates statistics for infeasible or bound exceeding LP conflict analysis;
6120  * may only be called if SCIPprobAllColsInLP()
6121  */
6123  SCIP_CONFLICT* conflict, /**< conflict analysis data */
6124  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
6125  SCIP_SET* set, /**< global SCIP settings */
6126  SCIP_STAT* stat, /**< problem statistics */
6127  SCIP_PROB* transprob, /**< transformed problem */
6128  SCIP_PROB* origprob, /**< original problem */
6129  SCIP_TREE* tree, /**< branch and bound tree */
6130  SCIP_LP* lp, /**< LP data */
6131  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6132  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6133  SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
6134  )
6135 {
6136  SCIP_LPSOLVALS storedsolvals;
6137  SCIP_COLSOLVALS* storedcolsolvals;
6138  SCIP_ROWSOLVALS* storedrowsolvals;
6139  int c;
6140  int r;
6141 
6142  if( success != NULL )
6143  *success = FALSE;
6144 
6145  /* in rare cases, it might happen that the solution stati of the LP and the LPI are out of sync; in particular this
6146  * happens when a new incumbent which cuts off the current node is found during the LP solving loop; in this case the
6147  * LP has status objlimit, but if diving has been used, the LPI only has the basis information, but is not solved
6148  *
6149  * @todo: alternatively, solve the LPI
6150  */
6151  if( !SCIPlpiWasSolved(SCIPlpGetLPI(lp)) )
6152  return SCIP_OKAY;
6153 
6154  /* LP conflict analysis is only valid, if all variables are known */
6155  assert( SCIPprobAllColsInLP(transprob, set, lp) );
6157  || (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && set->lp_disablecutoff == 1) );
6158 
6159  /* save status */
6160  storedsolvals.lpsolstat = lp->lpsolstat;
6161  storedsolvals.lpobjval = lp->lpobjval;
6162  storedsolvals.primalfeasible = lp->primalfeasible;
6163  storedsolvals.dualfeasible = lp->dualfeasible;
6164  storedsolvals.solisbasic = lp->solisbasic;
6165  storedsolvals.lpissolved = lp->solved;
6166 
6167  /* store solution values */
6168  SCIP_CALL( SCIPsetAllocBufferArray(set, &storedcolsolvals, lp->ncols) );
6169  SCIP_CALL( SCIPsetAllocBufferArray(set, &storedrowsolvals, lp->nrows) );
6170  for (c = 0; c < lp->ncols; ++c)
6171  {
6172  SCIP_COL* col;
6173 
6174  col = lp->cols[c];
6175  assert( col != NULL );
6176 
6177  storedcolsolvals[c].primsol = col->primsol;
6178  storedcolsolvals[c].redcost = col->redcost;
6179  storedcolsolvals[c].basisstatus = col->basisstatus; /*lint !e641 !e732*/
6180  }
6181  for (r = 0; r < lp->nrows; ++r)
6182  {
6183  SCIP_ROW* row;
6184 
6185  row = lp->rows[r];
6186  assert( row != NULL );
6187 
6188  if ( lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
6189  storedrowsolvals[r].dualsol = row->dualfarkas;
6190  else
6191  {
6192  assert( lp->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT ||
6193  (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && set->lp_disablecutoff == 1) );
6194  storedrowsolvals[r].dualsol = row->dualsol;
6195  }
6196  storedrowsolvals[r].activity = row->activity;
6197  storedrowsolvals[r].basisstatus = row->basisstatus; /*lint !e641 !e732*/
6198  }
6199 
6200  /* check, if the LP was infeasible or bound exceeding */
6202  {
6203  SCIP_CALL( conflictAnalyzeInfeasibleLP(conflict, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, success) );
6204  }
6205  else
6206  {
6207  SCIP_CALL( conflictAnalyzeBoundexceedingLP(conflict, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, success) );
6208  }
6209 
6210  /* possibly restore solution values */
6212  {
6213  /* restore status */
6214  lp->lpsolstat = storedsolvals.lpsolstat;
6215  lp->lpobjval = storedsolvals.lpobjval;
6216  lp->primalfeasible = storedsolvals.primalfeasible;
6217  lp->dualfeasible = storedsolvals.dualfeasible;
6218  lp->solisbasic = storedsolvals.solisbasic;
6219  lp->solved = storedsolvals.lpissolved;
6220 
6221  for (c = 0; c < lp->ncols; ++c)
6222  {
6223  SCIP_COL* col;
6224 
6225  col = lp->cols[c];
6226  assert( col != NULL );
6227  col->primsol = storedcolsolvals[c].primsol;
6228  col->redcost = storedcolsolvals[c].redcost;
6229  col->basisstatus = storedcolsolvals[c].basisstatus; /*lint !e641 !e732*/
6230  }
6231  for (r = 0; r < lp->nrows; ++r)
6232  {
6233  SCIP_ROW* row;
6234 
6235  row = lp->rows[r];
6236  assert( row != NULL );
6237 
6238  if ( lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
6239  row->dualfarkas = storedrowsolvals[r].dualsol;
6240  else
6241  {
6242  assert( lp->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT );
6243  row->dualsol = storedrowsolvals[r].dualsol;
6244  }
6245  row->activity = storedrowsolvals[r].activity;
6246  row->basisstatus = storedrowsolvals[r].basisstatus; /*lint !e641 !e732*/
6247  }
6248  }
6249  SCIPsetFreeBufferArray(set, &storedrowsolvals);
6250  SCIPsetFreeBufferArray(set, &storedcolsolvals);
6251 
6252  return SCIP_OKAY;
6253 }
6254 
6255 /** gets time in seconds used for analyzing infeasible LP conflicts */
6257  SCIP_CONFLICT* conflict /**< conflict analysis data */
6258  )
6259 {
6260  assert(conflict != NULL);
6261 
6262  return SCIPclockGetTime(conflict->inflpanalyzetime);
6263 }
6264 
6265 /** gets number of calls to infeasible LP conflict analysis */
6267  SCIP_CONFLICT* conflict /**< conflict analysis data */
6268  )
6269 {
6270  assert(conflict != NULL);
6271 
6272  return conflict->ninflpcalls;
6273 }
6274 
6275 /** gets number of calls to infeasible LP conflict analysis that yield at least one conflict constraint */
6277  SCIP_CONFLICT* conflict /**< conflict analysis data */
6278  )
6279 {
6280  assert(conflict != NULL);
6281 
6282  return conflict->ninflpsuccess;
6283 }
6284 
6285 /** gets number of conflict constraints detected in infeasible LP conflict analysis */
6287  SCIP_CONFLICT* conflict /**< conflict analysis data */
6288  )
6289 {
6290  assert(conflict != NULL);
6291 
6292  return conflict->ninflpconfconss;
6293 }
6294 
6295 /** gets total number of literals in conflict constraints created in infeasible LP conflict analysis */
6297  SCIP_CONFLICT* conflict /**< conflict analysis data */
6298  )
6299 {
6300  assert(conflict != NULL);
6301 
6302  return conflict->ninflpconfliterals;
6303 }
6304 
6305 /** gets number of reconvergence constraints detected in infeasible LP conflict analysis */
6307  SCIP_CONFLICT* conflict /**< conflict analysis data */
6308  )
6309 {
6310  assert(conflict != NULL);
6311 
6312  return conflict->ninflpreconvconss;
6313 }
6314 
6315 /** gets total number of literals in reconvergence constraints created in infeasible LP conflict analysis */
6317  SCIP_CONFLICT* conflict /**< conflict analysis data */
6318  )
6319 {
6320  assert(conflict != NULL);
6321 
6322  return conflict->ninflpreconvliterals;
6323 }
6324 
6325 /** gets number of LP iterations in infeasible LP conflict analysis */
6327  SCIP_CONFLICT* conflict /**< conflict analysis data */
6328  )
6329 {
6330  assert(conflict != NULL);
6331 
6332  return conflict->ninflpiterations;
6333 }
6334 
6335 /** gets time in seconds used for analyzing bound exceeding LP conflicts */
6337  SCIP_CONFLICT* conflict /**< conflict analysis data */
6338  )
6339 {
6340  assert(conflict != NULL);
6341 
6342  return SCIPclockGetTime(conflict->boundlpanalyzetime);
6343 }
6344 
6345 /** gets number of calls to bound exceeding LP conflict analysis */
6347  SCIP_CONFLICT* conflict /**< conflict analysis data */
6348  )
6349 {
6350  assert(conflict != NULL);
6351 
6352  return conflict->nboundlpcalls;
6353 }
6354 
6355 /** gets number of calls to bound exceeding LP conflict analysis that yield at least one conflict constraint */
6357  SCIP_CONFLICT* conflict /**< conflict analysis data */
6358  )
6359 {
6360  assert(conflict != NULL);
6361 
6362  return conflict->nboundlpsuccess;
6363 }
6364 
6365 /** gets number of conflict constraints detected in bound exceeding LP conflict analysis */
6367  SCIP_CONFLICT* conflict /**< conflict analysis data */
6368  )
6369 {
6370  assert(conflict != NULL);
6371 
6372  return conflict->nboundlpconfconss;
6373 }
6374 
6375 /** gets total number of literals in conflict constraints created in bound exceeding LP conflict analysis */
6377  SCIP_CONFLICT* conflict /**< conflict analysis data */
6378  )
6379 {
6380  assert(conflict != NULL);
6381 
6382  return conflict->nboundlpconfliterals;
6383 }
6384 
6385 /** gets number of reconvergence constraints detected in bound exceeding LP conflict analysis */
6387  SCIP_CONFLICT* conflict /**< conflict analysis data */
6388  )
6389 {
6390  assert(conflict != NULL);
6391 
6392  return conflict->nboundlpreconvconss;
6393 }
6394 
6395 /** gets total number of literals in reconvergence constraints created in bound exceeding LP conflict analysis */
6397  SCIP_CONFLICT* conflict /**< conflict analysis data */
6398  )
6399 {
6400  assert(conflict != NULL);
6401 
6402  return conflict->nboundlpreconvliterals;
6403 }
6404 
6405 /** gets number of LP iterations in bound exceeding LP conflict analysis */
6407  SCIP_CONFLICT* conflict /**< conflict analysis data */
6408  )
6409 {
6410  assert(conflict != NULL);
6411 
6412  return conflict->nboundlpiterations;
6413 }
6414 
6415 
6416 
6417 
6418 /*
6419  * infeasible strong branching conflict analysis
6420  */
6421 
6422 /** analyses infeasible strong branching sub problems for conflicts */
6424  SCIP_CONFLICT* conflict, /**< conflict analysis data */
6425  BMS_BLKMEM* blkmem, /**< block memory buffers */
6426  SCIP_SET* set, /**< global SCIP settings */
6427  SCIP_STAT* stat, /**< dynamic problem statistics */
6428  SCIP_PROB* transprob, /**< transformed problem */
6429  SCIP_PROB* origprob, /**< original problem */
6430  SCIP_TREE* tree, /**< branch and bound tree */
6431  SCIP_LP* lp, /**< LP data */
6432  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6433  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6434  SCIP_COL* col, /**< LP column with at least one infeasible strong branching subproblem */
6435  SCIP_Bool* downconflict, /**< pointer to store whether a conflict constraint was created for an
6436  * infeasible downwards branch, or NULL */
6437  SCIP_Bool* upconflict /**< pointer to store whether a conflict constraint was created for an
6438  * infeasible upwards branch, or NULL */
6439  )
6440 {
6441  int* cstat;
6442  int* rstat;
6443  SCIP_RETCODE retcode;
6444  SCIP_Bool resolve;
6445  SCIP_Real oldlb;
6446  SCIP_Real oldub;
6447  SCIP_Real newlb;
6448  SCIP_Real newub;
6449  int iter;
6450  int nconss;
6451  int nliterals;
6452  int nreconvconss;
6453  int nreconvliterals;
6454 
6455  assert(stat != NULL);
6456  assert(lp != NULL);
6457  assert(lp->flushed);
6458  assert(lp->solved);
6459  assert(SCIPprobAllColsInLP(transprob, set, lp)); /* LP conflict analysis is only valid, if all variables are known */
6460  assert(col != NULL);
6461  assert((col->sbdownvalid && SCIPsetIsGE(set, col->sbdown, lp->cutoffbound)
6462  && SCIPsetFeasCeil(set, col->primsol-1.0) >= col->lb - 0.5)
6463  || (col->sbupvalid && SCIPsetIsGE(set, col->sbup, lp->cutoffbound)
6464  && SCIPsetFeasFloor(set, col->primsol+1.0) <= col->ub + 0.5));
6465  assert(SCIPtreeGetCurrentDepth(tree) > 0);
6466 
6467  if( downconflict != NULL )
6468  *downconflict = FALSE;
6469  if( upconflict != NULL )
6470  *upconflict = FALSE;
6471 
6472  /* check, if infeasible LP conflict analysis is enabled */
6473  if( !set->conf_enable || !set->conf_usesb )
6474  return SCIP_OKAY;
6475 
6476  /* check, if there are any conflict handlers to use a conflict set */
6477  if( set->nconflicthdlrs == 0 )
6478  return SCIP_OKAY;
6479 
6480  /* inform the LPI that strong branch is (temporarily) finished */
6482 
6483  /* start timing */
6484  SCIPclockStart(conflict->sbanalyzetime, set);
6485 
6486  /* get temporary memory for storing current LP basis */
6487  SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, lp->nlpicols) );
6488  SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, lp->nlpirows) );
6489 
6490  /* get current LP basis */
6491  SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
6492 
6493  /* remember old bounds */
6494  oldlb = col->lb;
6495  oldub = col->ub;
6496 
6497  resolve = FALSE;
6498 
6499  /* is down branch infeasible? */
6500  if( col->sbdownvalid && SCIPsetIsGE(set, col->sbdown, lp->cutoffbound) )
6501  {
6502  newub = SCIPsetFeasCeil(set, col->primsol-1.0);
6503  if( newub >= col->lb - 0.5 )
6504  {
6505  SCIPdebugMessage("analyzing conflict on infeasible downwards strongbranch for variable <%s>[%g,%g] in depth %d\n",
6507  SCIPtreeGetCurrentDepth(tree));
6508 
6509  conflict->nsbcalls++;
6510 
6511  /* change the upper bound */
6512  col->ub = newub;
6513  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, 1, &col->lpipos, &col->lb, &col->ub) );
6514 
6515  /* start LP timer */
6516  SCIPclockStart(stat->conflictlptime, set);
6517 
6518  /* resolve the LP */
6519  retcode = SCIPlpiSolveDual(lp->lpi);
6520 
6521  /* stop LP timer */
6522  SCIPclockStop(stat->conflictlptime, set);
6523 
6524  /* check return code of LP solving call */
6525  if( retcode != SCIP_LPERROR )
6526  {
6527  SCIP_CALL( retcode );
6528 
6529  /* count number of LP iterations */
6530  SCIP_CALL( SCIPlpiGetIterations(lp->lpi, &iter) );
6531  stat->nconflictlps++;
6532  stat->nconflictlpiterations += iter;
6533  conflict->nsbiterations += iter;
6534  SCIPdebugMessage(" -> resolved downwards strong branching LP in %d iterations\n", iter);
6535 
6536  /* perform conflict analysis on infeasible LP; last parameter guarantees status 'solved' on return */
6537  SCIP_CALL( conflictAnalyzeLP(conflict, blkmem, set, stat, transprob, origprob, tree, lp, branchcand,
6538  eventqueue, TRUE, &iter, &nconss, &nliterals, &nreconvconss, &nreconvliterals, FALSE) );
6539  conflict->nsbsuccess += (nconss > 0 ? 1 : 0);
6540  conflict->nsbiterations += iter;
6541  conflict->nsbconfconss += nconss;
6542  conflict->nsbconfliterals += nliterals;
6543  conflict->nsbreconvconss += nreconvconss;
6544  conflict->nsbreconvliterals += nreconvliterals;
6545  if( downconflict != NULL )
6546  *downconflict = (nconss > 0);
6547  }
6548 
6549  /* reset the upper bound */
6550  col->ub = oldub;
6551  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, 1, &col->lpipos, &col->lb, &col->ub) );
6552 
6553  /* reset LP basis */
6554  SCIP_CALL( SCIPlpiSetBase(lp->lpi, cstat, rstat) );
6555 
6556  /* mark the LP to be resolved at the end */
6557  resolve = TRUE;
6558  }
6559  }
6560 
6561  /* is up branch infeasible? */
6562  if( col->sbupvalid && SCIPsetIsGE(set, col->sbup, lp->cutoffbound) )
6563  {
6564  newlb = SCIPsetFeasFloor(set, col->primsol+1.0);
6565  if( newlb <= col->ub + 0.5 )
6566  {
6567  SCIPdebugMessage("analyzing conflict on infeasible upwards strongbranch for variable <%s>[%g,%g] in depth %d\n",
6569  SCIPtreeGetCurrentDepth(tree));
6570 
6571  conflict->nsbcalls++;
6572 
6573  /* change the lower bound */
6574  col->lb = newlb;
6575  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, 1, &col->lpipos, &col->lb, &col->ub) );
6576 
6577  /* start LP timer */
6578  SCIPclockStart(stat->conflictlptime, set);
6579 
6580  /* resolve the LP */
6581  retcode = SCIPlpiSolveDual(lp->lpi);
6582 
6583  /* stop LP timer */
6584  SCIPclockStop(stat->conflictlptime, set);
6585 
6586  /* check return code of LP solving call */
6587  if( retcode != SCIP_LPERROR )
6588  {
6589  SCIP_CALL( retcode );
6590 
6591  /* count number of LP iterations */
6592  SCIP_CALL( SCIPlpiGetIterations(lp->lpi, &iter) );
6593  stat->nconflictlps++;
6594  stat->nconflictlpiterations += iter;
6595  conflict->nsbiterations += iter;
6596  SCIPdebugMessage(" -> resolved upwards strong branching LP in %d iterations\n", iter);
6597 
6598  /* perform conflict analysis on infeasible LP; last parameter guarantees status 'solved' on return */
6599  SCIP_CALL( conflictAnalyzeLP(conflict, blkmem, set, stat, transprob, origprob, tree, lp, branchcand,
6600  eventqueue, TRUE, &iter, &nconss, &nliterals, &nreconvconss, &nreconvliterals, FALSE) );
6601  conflict->nsbsuccess += (nconss > 0 ? 1 : 0);
6602  conflict->nsbiterations += iter;
6603  conflict->nsbconfconss += nconss;
6604  conflict->nsbconfliterals += nliterals;
6605  conflict->nsbreconvconss += nreconvconss;
6606  conflict->nsbreconvliterals += nreconvliterals;
6607  if( upconflict != NULL )
6608  *upconflict = (nconss > 0);
6609  }
6610 
6611  /* reset the lower bound */
6612  col->lb = oldlb;
6613  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, 1, &col->lpipos, &col->lb, &col->ub) );
6614 
6615  /* reset LP basis */
6616  SCIP_CALL( SCIPlpiSetBase(lp->lpi, cstat, rstat) );
6617 
6618  /* mark the LP to be resolved at the end */
6619  resolve = TRUE;
6620  }
6621  }
6622 
6623  /* free temporary memory for storing current LP basis */
6624  SCIPsetFreeBufferArray(set, &rstat);
6625  SCIPsetFreeBufferArray(set, &cstat);
6626 
6627  assert(lp->flushed);
6628 
6629  /* resolve LP if something has changed in order to synchronize LPI and LP */
6630  if ( resolve )
6631  {
6632  /* start LP timer */
6633  SCIPclockStart(stat->conflictlptime, set);
6634 
6635  /* resolve the LP */
6636  SCIP_CALL( SCIPlpiSolveDual(lp->lpi) );
6637 
6638  /* stop LP timer */
6639  SCIPclockStop(stat->conflictlptime, set);
6640  }
6641 
6642  /* stop timing */
6643  SCIPclockStop(conflict->sbanalyzetime, set);
6644 
6645  /* inform the LPI that strong branch starts (again) */
6647 
6648  return SCIP_OKAY;
6649 }
6650 
6651 /** gets time in seconds used for analyzing infeasible strong branching conflicts */
6653  SCIP_CONFLICT* conflict /**< conflict analysis data */
6654  )
6655 {
6656  assert(conflict != NULL);
6657 
6658  return SCIPclockGetTime(conflict->sbanalyzetime);
6659 }
6660 
6661 /** gets number of calls to infeasible strong branching conflict analysis */
6663  SCIP_CONFLICT* conflict /**< conflict analysis data */
6664  )
6665 {
6666  assert(conflict != NULL);
6667 
6668  return conflict->nsbcalls;
6669 }
6670 
6671 /** gets number of calls to infeasible strong branching conflict analysis that yield at least one conflict constraint */
6673  SCIP_CONFLICT* conflict /**< conflict analysis data */
6674  )
6675 {
6676  assert(conflict != NULL);
6677 
6678  return conflict->nsbsuccess;
6679 }
6680 
6681 /** gets number of conflict constraints detected in infeasible strong branching conflict analysis */
6683  SCIP_CONFLICT* conflict /**< conflict analysis data */
6684  )
6685 {
6686  assert(conflict != NULL);
6687 
6688  return conflict->nsbconfconss;
6689 }
6690 
6691 /** gets total number of literals in conflict constraints created in infeasible strong branching conflict analysis */
6693  SCIP_CONFLICT* conflict /**< conflict analysis data */
6694  )
6695 {
6696  assert(conflict != NULL);
6697 
6698  return conflict->nsbconfliterals;
6699 }
6700 
6701 /** gets number of reconvergence constraints detected in infeasible strong branching conflict analysis */
6703  SCIP_CONFLICT* conflict /**< conflict analysis data */
6704  )
6705 {
6706  assert(conflict != NULL);
6707 
6708  return conflict->nsbreconvconss;
6709 }
6710 
6711 /** gets total number of literals in reconvergence constraints created in infeasible strong branching conflict analysis */
6713  SCIP_CONFLICT* conflict /**< conflict analysis data */
6714  )
6715 {
6716  assert(conflict != NULL);
6717 
6718  return conflict->nsbreconvliterals;
6719 }
6720 
6721 /** gets number of LP iterations in infeasible strong branching conflict analysis */
6723  SCIP_CONFLICT* conflict /**< conflict analysis data */
6724  )
6725 {
6726  assert(conflict != NULL);
6727 
6728  return conflict->nsbiterations;
6729 }
6730 
6731 
6732 
6733 
6734 /*
6735  * pseudo solution conflict analysis
6736  */
6737 
6738 /** analyzes a pseudo solution with objective value exceeding the current cutoff to find out the bound changes on
6739  * variables that were responsible for the objective value degradation;
6740  * on success, calls standard conflict analysis with the responsible variables as starting conflict set, thus creating
6741  * a conflict constraint out of the resulting conflict set;
6742  * updates statistics for pseudo solution conflict analysis
6743  */
6745  SCIP_CONFLICT* conflict, /**< conflict analysis data */
6746  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
6747  SCIP_SET* set, /**< global SCIP settings */
6748  SCIP_STAT* stat, /**< problem statistics */
6749  SCIP_PROB* transprob, /**< transformed problem */
6750  SCIP_PROB* origprob, /**< original problem */
6751  SCIP_TREE* tree, /**< branch and bound tree */
6752  SCIP_LP* lp, /**< LP data */
6753  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6754  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6755  SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
6756  )
6757 {
6758  SCIP_VAR** vars;
6759  SCIP_VAR* var;
6760  SCIP_Real* curvarlbs;
6761  SCIP_Real* curvarubs;
6762  int* lbchginfoposs;
6763  int* ubchginfoposs;
6764  SCIP_Real* pseudocoefs;
6765  SCIP_Real pseudolhs;
6766  SCIP_Real pseudoact;
6767  int nvars;
6768  int v;
6769 
6770  assert(conflict != NULL);
6771  assert(conflict->nconflictsets == 0);
6772  assert(set != NULL);
6773  assert(stat != NULL);
6774  assert(transprob != NULL);
6775  assert(lp != NULL);
6776  assert(!SCIPsetIsInfinity(set, -SCIPlpGetPseudoObjval(lp, set, transprob)));
6777  assert(!SCIPsetIsInfinity(set, lp->cutoffbound));
6778 
6779  if( success != NULL )
6780  *success = FALSE;
6781 
6782  /* check, if pseudo solution conflict analysis is enabled */
6783  if( !set->conf_enable || !set->conf_usepseudo )
6784  return SCIP_OKAY;
6785 
6786  /* check, if there are any conflict handlers to use a conflict set */
6787  if( set->nconflicthdlrs == 0 )
6788  return SCIP_OKAY;
6789 
6790  SCIPdebugMessage("analyzing pseudo solution (obj: %g) that exceeds objective limit (%g)\n",
6791  SCIPlpGetPseudoObjval(lp, set, transprob), lp->cutoffbound);
6792 
6793  /* start timing */
6794  SCIPclockStart(conflict->pseudoanalyzetime, set);
6795  conflict->npseudocalls++;
6796 
6797  vars = transprob->vars;
6798  nvars = transprob->nvars;
6799  assert(nvars == 0 || vars != NULL);
6800 
6801  /* The current primal bound c* gives an upper bound for the current pseudo objective value:
6802  * min{c^T x | lb <= x <= ub} <= c*.
6803  * We have to transform this row into a >= inequality in order to use methods above:
6804  * -c* <= max{-c^T x | lb <= x <= ub}.
6805  * In the local subproblem, this row is violated. We want to undo bound changes while still keeping the
6806  * row violated.
6807  */
6808 
6809  /* get temporary memory for remembering variables' current bounds and corresponding bound change information
6810  * positions in variable's bound change information arrays
6811  */
6812  SCIP_CALL( SCIPsetAllocBufferArray(set, &curvarlbs, nvars) );
6813  SCIP_CALL( SCIPsetAllocBufferArray(set, &curvarubs, nvars) );
6814  SCIP_CALL( SCIPsetAllocBufferArray(set, &lbchginfoposs, nvars) );
6815  SCIP_CALL( SCIPsetAllocBufferArray(set, &ubchginfoposs, nvars) );
6816 
6817  /* get temporary memory for infeasibility proof coefficients */
6818  SCIP_CALL( SCIPsetAllocBufferArray(set, &pseudocoefs, nvars) );
6819 
6820  /* use a slightly tighter cutoff bound, because solutions with equal objective value should also be declared
6821  * infeasible
6822  */
6823  pseudolhs = -(lp->cutoffbound - SCIPsetSumepsilon(set));
6824 
6825  /* store the objective values as infeasibility proof coefficients, and recalculate the pseudo activity */
6826  pseudoact = 0.0;
6827  for( v = 0; v < nvars; ++v )
6828  {
6829  var = vars[v];
6830  pseudocoefs[v] = -SCIPvarGetObj(var);
6831  curvarlbs[v] = SCIPvarGetLbLocal(var);
6832  curvarubs[v] = SCIPvarGetUbLocal(var);
6833  if( pseudocoefs[v] > 0.0 )
6834  pseudoact += pseudocoefs[v] * curvarubs[v];
6835  else
6836  pseudoact += pseudocoefs[v] * curvarlbs[v];
6837  lbchginfoposs[v] = var->nlbchginfos-1;
6838  ubchginfoposs[v] = var->nubchginfos-1;
6839  }
6840  assert(SCIPsetIsFeasEQ(set, pseudoact, -SCIPlpGetPseudoObjval(lp, set, transprob)));
6841  SCIPdebugMessage(" -> recalculated pseudo infeasibility proof: %g <= %g\n", pseudolhs, pseudoact);
6842 
6843  /* check, if the pseudo row is still violated (after recalculation of pseudo activity) */
6844  if( SCIPsetIsFeasGT(set, pseudolhs, pseudoact) )
6845  {
6846  int nconss;
6847  int nliterals;
6848  int nreconvconss;
6849  int nreconvliterals;
6850 
6851  /* undo bound changes without destroying the infeasibility proof */
6852  SCIP_CALL( undoBdchgsProof(set, transprob, SCIPtreeGetCurrentDepth(tree), pseudocoefs, pseudolhs, pseudoact,
6853  curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs, NULL, NULL, NULL) );
6854 
6855  /* analyze conflict on remaining bound changes */
6856  SCIP_CALL( conflictAnalyzeRemainingBdchgs(conflict, blkmem, set, stat, transprob, tree, FALSE,
6857  lbchginfoposs, ubchginfoposs, &nconss, &nliterals, &nreconvconss, &nreconvliterals) );
6858  conflict->npseudosuccess += (nconss > 0 ? 1 : 0);
6859  conflict->npseudoconfconss += nconss;
6860  conflict->npseudoconfliterals += nliterals;
6861  conflict->npseudoreconvconss += nreconvconss;
6862  conflict->npseudoreconvliterals += nreconvliterals;
6863  if( success != NULL )
6864  *success = (nconss > 0);
6865  }
6866 
6867  /* free temporary memory */
6868  SCIPsetFreeBufferArray(set, &pseudocoefs);
6869  SCIPsetFreeBufferArray(set, &curvarubs);
6870  SCIPsetFreeBufferArray(set, &curvarlbs);
6871  SCIPsetFreeBufferArray(set, &ubchginfoposs);
6872  SCIPsetFreeBufferArray(set, &lbchginfoposs);
6873 
6874  /* flush conflict set storage */
6875  SCIP_CALL( SCIPconflictFlushConss(conflict, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue) );
6876 
6877  /* stop timing */
6878  SCIPclockStop(conflict->pseudoanalyzetime, set);
6879 
6880  return SCIP_OKAY;
6881 }
6882 
6883 /** gets time in seconds used for analyzing pseudo solution conflicts */
6885  SCIP_CONFLICT* conflict /**< conflict analysis data */
6886  )
6887 {
6888  assert(conflict != NULL);
6889 
6890  return SCIPclockGetTime(conflict->pseudoanalyzetime);
6891 }
6892 
6893 /** gets number of calls to pseudo solution conflict analysis */
6895  SCIP_CONFLICT* conflict /**< conflict analysis data */
6896  )
6897 {
6898  assert(conflict != NULL);
6899 
6900  return conflict->npseudocalls;
6901 }
6902 
6903 /** gets number of calls to pseudo solution conflict analysis that yield at least one conflict constraint */
6905  SCIP_CONFLICT* conflict /**< conflict analysis data */
6906  )
6907 {
6908  assert(conflict != NULL);
6909 
6910  return conflict->npseudosuccess;
6911 }
6912 
6913 /** gets number of conflict constraints detected in pseudo solution conflict analysis */
6915  SCIP_CONFLICT* conflict /**< conflict analysis data */
6916  )
6917 {
6918  assert(conflict != NULL);
6919 
6920  return conflict->npseudoconfconss;
6921 }
6922 
6923 /** gets total number of literals in conflict constraints created in pseudo solution conflict analysis */
6925  SCIP_CONFLICT* conflict /**< conflict analysis data */
6926  )
6927 {
6928  assert(conflict != NULL);
6929 
6930  return conflict->npseudoconfliterals;
6931 }
6932 
6933 /** gets number of reconvergence constraints detected in pseudo solution conflict analysis */
6935  SCIP_CONFLICT* conflict /**< conflict analysis data */
6936  )
6937 {
6938  assert(conflict != NULL);
6939 
6940  return conflict->npseudoreconvconss;
6941 }
6942 
6943 /** gets total number of literals in reconvergence constraints created in pseudo solution conflict analysis */
6945  SCIP_CONFLICT* conflict /**< conflict analysis data */
6946  )
6947 {
6948  assert(conflict != NULL);
6949 
6950  return conflict->npseudoreconvliterals;
6951 }
6952