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-2018 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  * @author Jakob Witzig
24  *
25  * This file implements a conflict analysis method like the one used in modern
26  * SAT solvers like zchaff. The algorithm works as follows:
27  *
28  * Given is a set of bound changes that are not allowed being applied simultaneously, because they
29  * render the current node infeasible (e.g. because a single constraint is infeasible in the these
30  * bounds, or because the LP relaxation is infeasible). The goal is to deduce a clause on variables
31  * -- a conflict clause -- representing the "reason" for this conflict, i.e., the branching decisions
32  * or the deductions (applied e.g. in domain propagation) that lead to the conflict. This clause can
33  * then be added to the constraint set to help cutting off similar parts of the branch and bound
34  * tree, that would lead to the same conflict. A conflict clause can also be generated, if the
35  * conflict was detected by a locally valid constraint. In this case, the resulting conflict clause
36  * is also locally valid in the same depth as the conflict detecting constraint. If all involved
37  * variables are binary, a linear (set covering) constraint can be generated, otherwise a bound
38  * disjunction constraint is generated. Details are given in
39  *
40  * Tobias Achterberg, Conflict Analysis in Mixed Integer Programming@n
41  * Discrete Optimization, 4, 4-20 (2007)
42  *
43  * See also @ref CONF. Here is an outline of the algorithm:
44  *
45  * -# Put all the given bound changes to a priority queue, which is ordered,
46  * such that the bound change that was applied last due to branching or deduction
47  * is at the top of the queue. The variables in the queue are always active
48  * problem variables. Because binary variables are preferred over general integer
49  * variables, integer variables are put on the priority queue prior to the binary
50  * variables. Create an empty conflict set.
51  * -# Remove the top bound change b from the priority queue.
52  * -# Perform the following case distinction:
53  * -# If the remaining queue is non-empty, and bound change b' (the one that is now
54  * on the top of the queue) was applied at the same depth level as b, and if
55  * b was a deduction with known inference reason, and if the inference constraint's
56  * valid depth is smaller or equal to the conflict detecting constraint's valid
57  * depth:
58  * - Resolve bound change b by asking the constraint that inferred the
59  * bound change to put all the bound changes on the priority queue, that
60  * lead to the deduction of b.
61  * Note that these bound changes have at most the same inference depth
62  * level as b, and were deduced earlier than b.
63  * -# Otherwise, the bound change b was a branching decision or a deduction with
64  * missing inference reason, or the inference constraint's validity is more local
65  * than the one of the conflict detecting constraint.
66  * - If a the bound changed corresponds to a binary variable, add it or its
67  * negation to the conflict set, depending on which of them is currently fixed to
68  * FALSE (i.e., the conflict set consists of literals that cannot be FALSE
69  * altogether at the same time).
70  * - Otherwise put the bound change into the conflict set.
71  * Note that if the bound change was a branching, all deduced bound changes
72  * remaining in the priority queue have smaller inference depth level than b,
73  * since deductions are always applied after the branching decisions. However,
74  * there is the possibility, that b was a deduction, where the inference
75  * reason was not given or the inference constraint was too local.
76  * With this lack of information, we must treat the deduced bound change like
77  * a branching, and there may exist other deduced bound changes of the same
78  * inference depth level in the priority queue.
79  * -# If priority queue is non-empty, goto step 2.
80  * -# The conflict set represents the conflict clause saying that at least one
81  * of the conflict variables must take a different value. The conflict set is then passed
82  * to the conflict handlers, that may create a corresponding constraint (e.g. a logicor
83  * constraint or bound disjunction constraint) out of these conflict variables and
84  * add it to the problem.
85  *
86  * If all deduced bound changes come with (global) inference information, depending on
87  * the conflict analyzing strategy, the resulting conflict set has the following property:
88  * - 1-FirstUIP: In the depth level where the conflict was found, at most one variable
89  * assigned at that level is member of the conflict set. This conflict variable is the
90  * first unique implication point of its depth level (FUIP).
91  * - All-FirstUIP: For each depth level, at most one variable assigned at that level is
92  * member of the conflict set. This conflict variable is the first unique implication
93  * point of its depth level (FUIP).
94  *
95  * The user has to do the following to get the conflict analysis running in its
96  * current implementation:
97  * - A constraint handler or propagator supporting the conflict analysis must implement
98  * the CONSRESPROP/PROPRESPROP call, that processes a bound change inference b and puts all
99  * the reason bounds leading to the application of b with calls to
100  * SCIPaddConflictBound() on the conflict queue (algorithm step 3.(a)).
101  * - If the current bounds lead to a deduction of a bound change (e.g. in domain
102  * propagation), a constraint handler should call SCIPinferVarLbCons() or
103  * SCIPinferVarUbCons(), thus providing the constraint that infered the bound change.
104  * A propagator should call SCIPinferVarLbProp() or SCIPinferVarUbProp() instead,
105  * thus providing a pointer to itself.
106  * - If (in the current bounds) an infeasibility is detected, the constraint handler or
107  * propagator should
108  * 1. call SCIPinitConflictAnalysis() to initialize the conflict queue,
109  * 2. call SCIPaddConflictBound() for each bound that lead to the conflict,
110  * 3. call SCIPanalyzeConflictCons() or SCIPanalyzeConflict() to analyze the conflict
111  * and add an appropriate conflict constraint.
112  */
113 
114 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
115 
116 #include <assert.h>
117 #include <string.h>
118 
119 #include "scip/def.h"
120 #include "scip/set.h"
121 #include "scip/stat.h"
122 #include "scip/clock.h"
123 #include "scip/visual.h"
124 #include "scip/history.h"
125 #include "scip/paramset.h"
126 #include "scip/lp.h"
127 #include "scip/var.h"
128 #include "scip/prob.h"
129 #include "scip/tree.h"
130 #include "scip/sol.h"
131 #include "scip/scip.h"
132 #include "scip/conflict.h"
133 #include "scip/cons.h"
134 #include "scip/prop.h"
135 #include "scip/presolve.h"
136 #include "scip/debug.h"
137 #include "scip/pub_message.h"
138 #include "scip/pub_misc.h"
139 #include "scip/cuts.h"
140 #include "lpi/lpi.h"
141 
142 #include "scip/struct_conflict.h"
143 #include "scip/cons_linear.h"
144 
145 #define BOUNDSWITCH 0.51 /**< threshold for bound switching - see cuts.c */
146 #define POSTPROCESS FALSE /**< apply postprocessing to the cut - see cuts.c */
147 #define USEVBDS FALSE /**< use variable bounds - see cuts.c */
148 #define ALLOWLOCAL FALSE /**< allow to generate local cuts - see cuts. */
149 #define MINFRAC 0.05 /**< minimal fractionality of floor(rhs) - see cuts.c */
150 #define MAXFRAC 0.999 /**< maximal fractionality of floor(rhs) - see cuts.c */
151 
152 /*#define SCIP_CONFGRAPH*/
153 
154 
155 #ifdef SCIP_CONFGRAPH
156 /*
157  * Output of Conflict Graph
158  */
159 
160 #include <stdio.h>
161 
162 static FILE* confgraphfile = NULL; /**< output file for current conflict graph */
163 static SCIP_BDCHGINFO* confgraphcurrentbdchginfo = NULL; /**< currently resolved bound change */
164 static int confgraphnconflictsets = 0; /**< number of conflict sets marked in the graph */
165 
166 /** writes a node section to the conflict graph file */
167 static
168 void confgraphWriteNode(
169  void* idptr, /**< id of the node */
170  const char* label, /**< label of the node */
171  const char* nodetype, /**< type of the node */
172  const char* fillcolor, /**< color of the node's interior */
173  const char* bordercolor /**< color of the node's border */
174  )
175 {
176  assert(confgraphfile != NULL);
177 
178  SCIPgmlWriteNode(confgraphfile, (unsigned int)(size_t)idptr, label, nodetype, fillcolor, bordercolor);
179 }
180 
181 /** writes an edge section to the conflict graph file */
182 static
183 void confgraphWriteEdge(
184  void* source, /**< source node of the edge */
185  void* target, /**< target node of the edge */
186  const char* color /**< color of the edge */
187  )
188 {
189  assert(confgraphfile != NULL);
190 
191 #ifndef SCIP_CONFGRAPH_EDGE
192  SCIPgmlWriteArc(confgraphfile, (unsigned int)(size_t)source, (unsigned int)(size_t)target, NULL, color);
193 #else
194  SCIPgmlWriteEdge(confgraphfile, (unsigned int)(size_t)source, (unsigned int)(size_t)target, NULL, color);
195 #endif
196 }
197 
198 /** creates a file to output the current conflict graph into; adds the conflict vertex to the graph */
199 static
200 SCIP_RETCODE confgraphCreate(
201  SCIP_SET* set, /**< global SCIP settings */
202  SCIP_CONFLICT* conflict /**< conflict analysis data */
203  )
204 {
205  char fname[SCIP_MAXSTRLEN];
206 
207  assert(conflict != NULL);
208  assert(confgraphfile == NULL);
209 
210  (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "conf%p%d.gml", conflict, conflict->count);
211  SCIPinfoMessage(set->scip, NULL, "storing conflict graph in file <%s>\n", fname);
212 
213  confgraphfile = fopen(fname, "w");
214 
215  if( confgraphfile == NULL )
216  {
217  SCIPerrorMessage("cannot open graph file <%s>\n", fname);
218  SCIPABORT(); /*lint !e527*/
219  return SCIP_WRITEERROR;
220  }
221 
222  SCIPgmlWriteOpening(confgraphfile, TRUE);
223 
224  confgraphWriteNode(NULL, "conflict", "ellipse", "#ff0000", "#000000");
225 
226  confgraphcurrentbdchginfo = NULL;
227 
228  return SCIP_OKAY;
229 }
230 
231 /** closes conflict graph file */
232 static
233 void confgraphFree(
234  void
235  )
236 {
237  if( confgraphfile != NULL )
238  {
239  SCIPgmlWriteClosing(confgraphfile);
240 
241  fclose(confgraphfile);
242 
243  confgraphfile = NULL;
244  confgraphnconflictsets = 0;
245  }
246 }
247 
248 /** adds a bound change node to the conflict graph and links it to the currently resolved bound change */
249 static
250 void confgraphAddBdchg(
251  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict graph */
252  )
253 {
254  const char* colors[] = {
255  "#8888ff", /* blue for constraint resolving */
256  "#ffff00", /* yellow for propagator resolving */
257  "#55ff55" /* green branching decision */
258  };
259  char label[SCIP_MAXSTRLEN];
260  char depth[SCIP_MAXSTRLEN];
261  int col;
262 
263 
264  switch( SCIPbdchginfoGetChgtype(bdchginfo) )
265  {
267  col = 2;
268  break;
270  col = 0;
271  break;
273  col = (SCIPbdchginfoGetInferProp(bdchginfo) == NULL ? 1 : 0);
274  break;
275  default:
276  SCIPerrorMessage("invalid bound change type\n");
277  col = 0;
278  SCIPABORT();
279  break;
280  }
281 
282  if( SCIPbdchginfoGetDepth(bdchginfo) == INT_MAX )
283  (void) SCIPsnprintf(depth, SCIP_MAXSTRLEN, "dive");
284  else
285  (void) SCIPsnprintf(depth, SCIP_MAXSTRLEN, "%d", SCIPbdchginfoGetDepth(bdchginfo));
286  (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "%s %s %g\n[%s:%d]", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
287  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
288  SCIPbdchginfoGetNewbound(bdchginfo), depth, SCIPbdchginfoGetPos(bdchginfo));
289  confgraphWriteNode(bdchginfo, label, "ellipse", colors[col], "#000000");
290  confgraphWriteEdge(bdchginfo, confgraphcurrentbdchginfo, "#000000");
291 }
292 
293 /** links the already existing bound change node to the currently resolved bound change */
294 static
295 void confgraphLinkBdchg(
296  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict graph */
297  )
298 {
299  confgraphWriteEdge(bdchginfo, confgraphcurrentbdchginfo, "#000000");
300 }
301 
302 /** marks the given bound change to be the currently resolved bound change */
303 static
304 void confgraphSetCurrentBdchg(
305  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict graph */
306  )
307 {
308  confgraphcurrentbdchginfo = bdchginfo;
309 }
310 
311 /** marks given conflict set in the conflict graph */
312 static
313 void confgraphMarkConflictset(
314  SCIP_CONFLICTSET* conflictset /**< conflict set */
315  )
316 {
317  char label[SCIP_MAXSTRLEN];
318  int i;
319 
320  assert(conflictset != NULL);
321 
322  confgraphnconflictsets++;
323  (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "conf %d (%d)", confgraphnconflictsets, conflictset->validdepth);
324  confgraphWriteNode((void*)(size_t)confgraphnconflictsets, label, "rectangle", "#ff00ff", "#000000");
325  for( i = 0; i < conflictset->nbdchginfos; ++i )
326  confgraphWriteEdge((void*)(size_t)confgraphnconflictsets, conflictset->bdchginfos[i], "#ff00ff");
327 }
328 
329 #endif
330 
331 /*
332  * Conflict Handler
333  */
334 
335 /** compares two conflict handlers w. r. to their priority */
336 SCIP_DECL_SORTPTRCOMP(SCIPconflicthdlrComp)
337 { /*lint --e{715}*/
338  return ((SCIP_CONFLICTHDLR*)elem2)->priority - ((SCIP_CONFLICTHDLR*)elem1)->priority;
339 }
340 
341 /** comparison method for sorting conflict handler w.r.t. to their name */
342 SCIP_DECL_SORTPTRCOMP(SCIPconflicthdlrCompName)
343 {
345 }
346 
347 /** method to call, when the priority of a conflict handler was changed */
348 static
349 SCIP_DECL_PARAMCHGD(paramChgdConflicthdlrPriority)
350 { /*lint --e{715}*/
351  SCIP_PARAMDATA* paramdata;
352 
353  paramdata = SCIPparamGetData(param);
354  assert(paramdata != NULL);
355 
356  /* use SCIPsetConflicthdlrPriority() to mark the conflicthdlrs unsorted */
357  SCIP_CALL( SCIPsetConflicthdlrPriority(scip, (SCIP_CONFLICTHDLR*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
358 
359  return SCIP_OKAY;
360 }
361 
362 /** copies the given conflict handler to a new scip */
364  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
365  SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
366  )
367 {
368  assert(conflicthdlr != NULL);
369  assert(set != NULL);
370  assert(set->scip != NULL);
371 
372  if( conflicthdlr->conflictcopy != NULL )
373  {
374  SCIPsetDebugMsg(set, "including conflict handler %s in subscip %p\n", SCIPconflicthdlrGetName(conflicthdlr), (void*)set->scip);
375  SCIP_CALL( conflicthdlr->conflictcopy(set->scip, conflicthdlr) );
376  }
377 
378  return SCIP_OKAY;
379 }
380 
381 /** creates a conflict handler */
383  SCIP_CONFLICTHDLR** conflicthdlr, /**< pointer to conflict handler data structure */
384  SCIP_SET* set, /**< global SCIP settings */
385  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
386  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
387  const char* name, /**< name of conflict handler */
388  const char* desc, /**< description of conflict handler */
389  int priority, /**< priority of the conflict handler */
390  SCIP_DECL_CONFLICTCOPY((*conflictcopy)), /**< copy method of conflict handler or NULL if you don't want to copy your plugin into sub-SCIPs */
391  SCIP_DECL_CONFLICTFREE((*conflictfree)), /**< destructor of conflict handler */
392  SCIP_DECL_CONFLICTINIT((*conflictinit)), /**< initialize conflict handler */
393  SCIP_DECL_CONFLICTEXIT((*conflictexit)), /**< deinitialize conflict handler */
394  SCIP_DECL_CONFLICTINITSOL((*conflictinitsol)),/**< solving process initialization method of conflict handler */
395  SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol)),/**< solving process deinitialization method of conflict handler */
396  SCIP_DECL_CONFLICTEXEC((*conflictexec)), /**< conflict processing method of conflict handler */
397  SCIP_CONFLICTHDLRDATA* conflicthdlrdata /**< conflict handler data */
398  )
399 {
400  char paramname[SCIP_MAXSTRLEN];
401  char paramdesc[SCIP_MAXSTRLEN];
402 
403  assert(conflicthdlr != NULL);
404  assert(name != NULL);
405  assert(desc != NULL);
406 
407  SCIP_ALLOC( BMSallocMemory(conflicthdlr) );
408  SCIP_ALLOC( BMSduplicateMemoryArray(&(*conflicthdlr)->name, name, strlen(name)+1) );
409  SCIP_ALLOC( BMSduplicateMemoryArray(&(*conflicthdlr)->desc, desc, strlen(desc)+1) );
410  (*conflicthdlr)->priority = priority;
411  (*conflicthdlr)->conflictcopy = conflictcopy;
412  (*conflicthdlr)->conflictfree = conflictfree;
413  (*conflicthdlr)->conflictinit = conflictinit;
414  (*conflicthdlr)->conflictexit = conflictexit;
415  (*conflicthdlr)->conflictinitsol = conflictinitsol;
416  (*conflicthdlr)->conflictexitsol = conflictexitsol;
417  (*conflicthdlr)->conflictexec = conflictexec;
418  (*conflicthdlr)->conflicthdlrdata = conflicthdlrdata;
419  (*conflicthdlr)->initialized = FALSE;
420 
421  SCIP_CALL( SCIPclockCreate(&(*conflicthdlr)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
422  SCIP_CALL( SCIPclockCreate(&(*conflicthdlr)->conflicttime, SCIP_CLOCKTYPE_DEFAULT) );
423 
424  /* add parameters */
425  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "conflict/%s/priority", name);
426  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of conflict handler <%s>", name);
427  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc, &(*conflicthdlr)->priority, TRUE, \
428  priority, INT_MIN, INT_MAX, paramChgdConflicthdlrPriority, (SCIP_PARAMDATA*)(*conflicthdlr)) ); /*lint !e740*/
429 
430  return SCIP_OKAY;
431 }
432 
433 /** calls destructor and frees memory of conflict handler */
435  SCIP_CONFLICTHDLR** conflicthdlr, /**< pointer to conflict handler data structure */
436  SCIP_SET* set /**< global SCIP settings */
437  )
438 {
439  assert(conflicthdlr != NULL);
440  assert(*conflicthdlr != NULL);
441  assert(!(*conflicthdlr)->initialized);
442  assert(set != NULL);
443 
444  /* call destructor of conflict handler */
445  if( (*conflicthdlr)->conflictfree != NULL )
446  {
447  SCIP_CALL( (*conflicthdlr)->conflictfree(set->scip, *conflicthdlr) );
448  }
449 
450  SCIPclockFree(&(*conflicthdlr)->conflicttime);
451  SCIPclockFree(&(*conflicthdlr)->setuptime);
452 
453  BMSfreeMemoryArray(&(*conflicthdlr)->name);
454  BMSfreeMemoryArray(&(*conflicthdlr)->desc);
455  BMSfreeMemory(conflicthdlr);
456 
457  return SCIP_OKAY;
458 }
459 
460 /** calls initialization method of conflict handler */
462  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
463  SCIP_SET* set /**< global SCIP settings */
464  )
465 {
466  assert(conflicthdlr != NULL);
467  assert(set != NULL);
468 
469  if( conflicthdlr->initialized )
470  {
471  SCIPerrorMessage("conflict handler <%s> already initialized\n", conflicthdlr->name);
472  return SCIP_INVALIDCALL;
473  }
474 
475  if( set->misc_resetstat )
476  {
477  SCIPclockReset(conflicthdlr->setuptime);
478  SCIPclockReset(conflicthdlr->conflicttime);
479  }
480 
481  /* call initialization method of conflict handler */
482  if( conflicthdlr->conflictinit != NULL )
483  {
484  /* start timing */
485  SCIPclockStart(conflicthdlr->setuptime, set);
486 
487  SCIP_CALL( conflicthdlr->conflictinit(set->scip, conflicthdlr) );
488 
489  /* stop timing */
490  SCIPclockStop(conflicthdlr->setuptime, set);
491  }
492  conflicthdlr->initialized = TRUE;
493 
494  return SCIP_OKAY;
495 }
496 
497 /** calls exit method of conflict handler */
499  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
500  SCIP_SET* set /**< global SCIP settings */
501  )
502 {
503  assert(conflicthdlr != NULL);
504  assert(set != NULL);
505 
506  if( !conflicthdlr->initialized )
507  {
508  SCIPerrorMessage("conflict handler <%s> not initialized\n", conflicthdlr->name);
509  return SCIP_INVALIDCALL;
510  }
511 
512  /* call deinitialization method of conflict handler */
513  if( conflicthdlr->conflictexit != NULL )
514  {
515  /* start timing */
516  SCIPclockStart(conflicthdlr->setuptime, set);
517 
518  SCIP_CALL( conflicthdlr->conflictexit(set->scip, conflicthdlr) );
519 
520  /* stop timing */
521  SCIPclockStop(conflicthdlr->setuptime, set);
522  }
523  conflicthdlr->initialized = FALSE;
524 
525  return SCIP_OKAY;
526 }
527 
528 /** informs conflict handler that the branch and bound process is being started */
530  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
531  SCIP_SET* set /**< global SCIP settings */
532  )
533 {
534  assert(conflicthdlr != NULL);
535  assert(set != NULL);
536 
537  /* call solving process initialization method of conflict handler */
538  if( conflicthdlr->conflictinitsol != NULL )
539  {
540  /* start timing */
541  SCIPclockStart(conflicthdlr->setuptime, set);
542 
543  SCIP_CALL( conflicthdlr->conflictinitsol(set->scip, conflicthdlr) );
544 
545  /* stop timing */
546  SCIPclockStop(conflicthdlr->setuptime, set);
547  }
548 
549  return SCIP_OKAY;
550 }
551 
552 /** informs conflict handler that the branch and bound process data is being freed */
554  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
555  SCIP_SET* set /**< global SCIP settings */
556  )
557 {
558  assert(conflicthdlr != NULL);
559  assert(set != NULL);
560 
561  /* call solving process deinitialization method of conflict handler */
562  if( conflicthdlr->conflictexitsol != NULL )
563  {
564  /* start timing */
565  SCIPclockStart(conflicthdlr->setuptime, set);
566 
567  SCIP_CALL( conflicthdlr->conflictexitsol(set->scip, conflicthdlr) );
568 
569  /* stop timing */
570  SCIPclockStop(conflicthdlr->setuptime, set);
571  }
572 
573  return SCIP_OKAY;
574 }
575 
576 /** calls execution method of conflict handler */
578  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
579  SCIP_SET* set, /**< global SCIP settings */
580  SCIP_NODE* node, /**< node to add conflict constraint to */
581  SCIP_NODE* validnode, /**< node at which the constraint is valid */
582  SCIP_BDCHGINFO** bdchginfos, /**< bound change resembling the conflict set */
583  SCIP_Real* relaxedbds, /**< array with relaxed bounds which are efficient to create a valid conflict */
584  int nbdchginfos, /**< number of bound changes in the conflict set */
585  SCIP_CONFTYPE conftype, /**< type of the conflict */
586  SCIP_Bool usescutoffbound, /**< depends the conflict on the cutoff bound? */
587  SCIP_Bool resolved, /**< was the conflict set already used to create a constraint? */
588  SCIP_RESULT* result /**< pointer to store the result of the callback method */
589  )
590 {
591 
592  assert(conflicthdlr != NULL);
593  assert(set != NULL);
594  assert(bdchginfos != NULL || nbdchginfos == 0);
595  assert(result != NULL);
596 
597  /* call solution start method of conflict handler */
598  *result = SCIP_DIDNOTRUN;
599  if( conflicthdlr->conflictexec != NULL )
600  {
601  /* start timing */
602  SCIPclockStart(conflicthdlr->conflicttime, set);
603 
604  SCIP_CALL( conflicthdlr->conflictexec(set->scip, conflicthdlr, node, validnode, bdchginfos, relaxedbds, nbdchginfos,
605  conftype, usescutoffbound, set->conf_separate, (SCIPnodeGetDepth(validnode) > 0), set->conf_dynamic,
606  set->conf_removable, resolved, result) );
607 
608  /* stop timing */
609  SCIPclockStop(conflicthdlr->conflicttime, set);
610 
611  if( *result != SCIP_CONSADDED
612  && *result != SCIP_DIDNOTFIND
613  && *result != SCIP_DIDNOTRUN )
614  {
615  SCIPerrorMessage("execution method of conflict handler <%s> returned invalid result <%d>\n",
616  conflicthdlr->name, *result);
617  return SCIP_INVALIDRESULT;
618  }
619  }
620 
621  return SCIP_OKAY;
622 }
623 
624 /** gets user data of conflict handler */
626  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
627  )
628 {
629  assert(conflicthdlr != NULL);
630 
631  return conflicthdlr->conflicthdlrdata;
632 }
633 
634 /** sets user data of conflict handler; user has to free old data in advance! */
636  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
637  SCIP_CONFLICTHDLRDATA* conflicthdlrdata /**< new conflict handler user data */
638  )
639 {
640  assert(conflicthdlr != NULL);
641 
642  conflicthdlr->conflicthdlrdata = conflicthdlrdata;
643 }
644 
645 /** set copy method of conflict handler */
647  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
648  SCIP_DECL_CONFLICTCOPY((*conflictcopy)) /**< copy method of the conflict handler */
649  )
650 {
651  assert(conflicthdlr != NULL);
652 
653  conflicthdlr->conflictcopy = conflictcopy;
654 }
655 
656 /** set destructor of conflict handler */
658  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
659  SCIP_DECL_CONFLICTFREE((*conflictfree)) /**< destructor of conflict handler */
660  )
661 {
662  assert(conflicthdlr != NULL);
663 
664  conflicthdlr->conflictfree = conflictfree;
665 }
666 
667 /** set initialization method of conflict handler */
669  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
670  SCIP_DECL_CONFLICTINIT((*conflictinit)) /**< initialization method conflict handler */
671  )
672 {
673  assert(conflicthdlr != NULL);
674 
675  conflicthdlr->conflictinit = conflictinit;
676 }
677 
678 /** set deinitialization method of conflict handler */
680  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
681  SCIP_DECL_CONFLICTEXIT((*conflictexit)) /**< deinitialization method conflict handler */
682  )
683 {
684  assert(conflicthdlr != NULL);
685 
686  conflicthdlr->conflictexit = conflictexit;
687 }
688 
689 /** set solving process initialization method of conflict handler */
691  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
692  SCIP_DECL_CONFLICTINITSOL((*conflictinitsol))/**< solving process initialization method of conflict handler */
693  )
694 {
695  assert(conflicthdlr != NULL);
696 
697  conflicthdlr->conflictinitsol = conflictinitsol;
698 }
699 
700 /** set solving process deinitialization method of conflict handler */
702  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
703  SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol))/**< solving process deinitialization method of conflict handler */
704  )
705 {
706  assert(conflicthdlr != NULL);
707 
708  conflicthdlr->conflictexitsol = conflictexitsol;
709 }
710 
711 /** gets name of conflict handler */
713  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
714  )
715 {
716  assert(conflicthdlr != NULL);
717 
718  return conflicthdlr->name;
719 }
720 
721 /** gets description of conflict handler */
723  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
724  )
725 {
726  assert(conflicthdlr != NULL);
727 
728  return conflicthdlr->desc;
729 }
730 
731 /** gets priority of conflict handler */
733  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
734  )
735 {
736  assert(conflicthdlr != NULL);
737 
738  return conflicthdlr->priority;
739 }
740 
741 /** sets priority of conflict handler */
743  SCIP_CONFLICTHDLR* conflicthdlr, /**< conflict handler */
744  SCIP_SET* set, /**< global SCIP settings */
745  int priority /**< new priority of the conflict handler */
746  )
747 {
748  assert(conflicthdlr != NULL);
749  assert(set != NULL);
750 
751  conflicthdlr->priority = priority;
752  set->conflicthdlrssorted = FALSE;
753 }
754 
755 /** is conflict handler initialized? */
757  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
758  )
759 {
760  assert(conflicthdlr != NULL);
761 
762  return conflicthdlr->initialized;
763 }
764 
765 /** enables or disables all clocks of \p conflicthdlr, depending on the value of the flag */
767  SCIP_CONFLICTHDLR* conflicthdlr, /**< the conflict handler for which all clocks should be enabled or disabled */
768  SCIP_Bool enable /**< should the clocks of the conflict handler be enabled? */
769  )
770 {
771  assert(conflicthdlr != NULL);
772 
773  SCIPclockEnableOrDisable(conflicthdlr->setuptime, enable);
774  SCIPclockEnableOrDisable(conflicthdlr->conflicttime, enable);
775 }
776 
777 /** gets time in seconds used in this conflict handler for setting up for next stages */
779  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
780  )
781 {
782  assert(conflicthdlr != NULL);
783 
784  return SCIPclockGetTime(conflicthdlr->setuptime);
785 }
786 
787 /** gets time in seconds used in this conflict handler */
789  SCIP_CONFLICTHDLR* conflicthdlr /**< conflict handler */
790  )
791 {
792  assert(conflicthdlr != NULL);
793 
794  return SCIPclockGetTime(conflicthdlr->conflicttime);
795 }
796 
797 /*
798  * Conflict LP Bound Changes
799  */
800 
801 
802 /** create conflict LP bound change data structure */
803 static
805  SCIP_LPBDCHGS** lpbdchgs, /**< pointer to store the conflict LP bound change data structure */
806  SCIP_SET* set, /**< global SCIP settings */
807  int ncols /**< number of columns */
808  )
809 {
810  SCIP_CALL( SCIPsetAllocBuffer(set, lpbdchgs) );
811 
812  SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchginds, ncols) );
813  SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchglbs, ncols) );
814  SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchgubs, ncols) );
815  SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->bdchgcolinds, ncols) );
816  SCIP_CALL( SCIPsetAllocBufferArray(set, &(*lpbdchgs)->usedcols, ncols) );
817  BMSclearMemoryArray((*lpbdchgs)->usedcols, ncols);
818 
819  (*lpbdchgs)->nbdchgs = 0;
820 
821  return SCIP_OKAY;
822 }
823 
824 /** reset conflict LP bound change data structure */
825 static
827  SCIP_LPBDCHGS* lpbdchgs, /**< conflict LP bound change data structure */
828  int ncols /**< number of columns */
829  )
830 {
831  assert(lpbdchgs != NULL);
832 
833  BMSclearMemoryArray(lpbdchgs->usedcols, ncols);
834  lpbdchgs->nbdchgs = 0;
835 }
836 
837 /** free conflict LP bound change data structure */
838 static
840  SCIP_LPBDCHGS** lpbdchgs, /**< pointer to store the conflict LP bound change data structure */
841  SCIP_SET* set /**< global SCIP settings */
842  )
843 {
844  SCIPsetFreeBufferArray(set, &(*lpbdchgs)->usedcols);
845  SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchgcolinds);
846  SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchgubs);
847  SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchglbs);
848  SCIPsetFreeBufferArray(set, &(*lpbdchgs)->bdchginds);
849 
850  SCIPsetFreeBuffer(set, lpbdchgs);
851 }
852 
853 /*
854  * Proof Sets
855  */
856 
857 /** resets the data structure of a proofset */
858 static
860  SCIP_PROOFSET* proofset /**< proof set */
861  )
862 {
863  assert(proofset != NULL);
864 
865  proofset->nnz = 0;
866  proofset->rhs = 0.0;
868 }
869 
870 /** creates a proofset */
871 static
873  SCIP_PROOFSET** proofset, /**< proof set */
874  BMS_BLKMEM* blkmem /**< block memory of transformed problem */
875  )
876 {
877  assert(proofset != NULL);
878 
879  SCIP_ALLOC( BMSallocBlockMemory(blkmem, proofset) );
880  (*proofset)->vals = NULL;
881  (*proofset)->inds = NULL;
882  (*proofset)->rhs = 0.0;
883  (*proofset)->nnz = 0;
884  (*proofset)->size = 0;
885  (*proofset)->conflicttype = SCIP_CONFTYPE_UNKNOWN;
886 
887  return SCIP_OKAY;
888 }
889 
890 /** creates and clears the proofset */
891 static
893  SCIP_CONFLICT* conflict, /**< conflict analysis data */
894  BMS_BLKMEM* blkmem /**< block memory of transformed problem */
895  )
896 {
897  assert(conflict != NULL);
898  assert(blkmem != NULL);
899 
900  SCIP_CALL( proofsetCreate(&conflict->proofset, blkmem) );
901 
902  return SCIP_OKAY;
903 }
904 
905 /** frees a proofset */
906 static
908  SCIP_PROOFSET** proofset, /**< proof set */
909  BMS_BLKMEM* blkmem /**< block memory */
910  )
911 {
912  assert(proofset != NULL);
913  assert(*proofset != NULL);
914  assert(blkmem != NULL);
915 
916  BMSfreeBlockMemoryArrayNull(blkmem, &(*proofset)->vals, (*proofset)->size);
917  BMSfreeBlockMemoryArrayNull(blkmem, &(*proofset)->inds, (*proofset)->size);
918  BMSfreeBlockMemory(blkmem, proofset);
919  (*proofset) = NULL;
920 }
921 
922 #ifdef SCIP_DEBUG
923 static
924 void proofsetPrint(
925  SCIP_PROOFSET* proofset,
926  SCIP_SET* set,
927  SCIP_PROB* transprob
928  )
929 {
930  SCIP_VAR** vars;
931  int i;
932 
933  assert(proofset != NULL);
934 
935  vars = SCIPprobGetVars(transprob);
936  assert(vars != NULL);
937 
938  printf("proofset: ");
939  for( i = 0; i < proofset->nnz; i++ )
940  printf("%+.15g <%s> ", proofset->vals[i], SCIPvarGetName(vars[proofset->inds[i]]));
941  printf(" <= %.15g\n", proofset->rhs);
942 }
943 #endif
944 
945 /** return the indices of variables in the proofset */
946 static
948  SCIP_PROOFSET* proofset /**< proof set */
949  )
950 {
951  assert(proofset != NULL);
952 
953  return proofset->inds;
954 }
955 
956 /** return coefficient of variable in the proofset with given probindex */
957 static
959  SCIP_PROOFSET* proofset /**< proof set */
960  )
961 {
962  assert(proofset != NULL);
963 
964  return proofset->vals;
965 }
966 
967 /** return the right-hand side if a proofset */
968 static
970  SCIP_PROOFSET* proofset /**< proof set */
971  )
972 {
973  assert(proofset != NULL);
974 
975  return proofset->rhs;
976 }
977 
978 /** returns the number of variables in the proofset */
979 static
981  SCIP_PROOFSET* proofset /**< proof set */
982  )
983 {
984  assert(proofset != NULL);
985 
986  return proofset->nnz;
987 }
988 
989 /** returns the number of variables in the proofset */
990 static
992  SCIP_PROOFSET* proofset /**< proof set */
993  )
994 {
995  assert(proofset != NULL);
996 
997  return proofset->conflicttype;
998 }
999 
1000 /** adds given data as aggregation row to the proofset */
1001 static
1003  SCIP_PROOFSET* proofset, /**< proof set */
1004  BMS_BLKMEM* blkmem, /**< block memory */
1005  SCIP_Real* vals, /**< variable coefficients */
1006  int* inds, /**< variable array */
1007  int nnz, /**< size of variable and coefficient array */
1008  SCIP_Real rhs /**< right-hand side of the aggregation row */
1009  )
1010 {
1011  assert(proofset != NULL);
1012  assert(blkmem != NULL);
1013 
1014  if( proofset->size == 0 )
1015  {
1016  assert(proofset->vals == NULL);
1017  assert(proofset->inds == NULL);
1018 
1019  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &proofset->vals, vals, nnz) );
1020  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &proofset->inds, inds, nnz) );
1021 
1022  proofset->size = nnz;
1023  }
1024  else
1025  {
1026  int i;
1027 
1028  assert(proofset->vals != NULL);
1029  assert(proofset->inds != NULL);
1030 
1031  if( proofset->size < nnz )
1032  {
1033  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &proofset->vals, proofset->size, nnz) );
1034  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &proofset->inds, proofset->size, nnz) );
1035  proofset->size = nnz;
1036  }
1037 
1038  for( i = 0; i < nnz; i++ )
1039  {
1040  proofset->vals[i] = vals[i];
1041  proofset->inds[i] = inds[i];
1042  }
1043  }
1044 
1045  proofset->rhs = rhs;
1046  proofset->nnz = nnz;
1047 
1048  return SCIP_OKAY;
1049 }
1050 
1051 /** adds an aggregation row to the proofset */
1052 static
1054  SCIP_PROOFSET* proofset, /**< proof set */
1055  SCIP_SET* set, /**< global SCIP settings */
1056  BMS_BLKMEM* blkmem, /**< block memory */
1057  SCIP_AGGRROW* aggrrow /**< aggregation row to add */
1058  )
1059 {
1060  SCIP_Real* vals;
1061  int* inds;
1062  int nnz;
1063  int i;
1064 
1065  assert(proofset != NULL);
1066  assert(set != NULL);
1067 
1068  inds = SCIPaggrRowGetInds(aggrrow);
1069  assert(inds != NULL);
1070 
1071  nnz = SCIPaggrRowGetNNz(aggrrow);
1072  assert(nnz > 0);
1073 
1074  SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, nnz) );
1075 
1076  for( i = 0; i < nnz; i++ )
1077  {
1078  vals[i] = SCIPaggrRowGetProbvarValue(aggrrow, inds[i]);
1079  }
1080 
1081  SCIP_CALL( proofsetAddSparseData(proofset, blkmem, vals, inds, nnz, SCIPaggrRowGetRhs(aggrrow)) );
1082 
1083  SCIPsetFreeBufferArray(set, &vals);
1084 
1085  return SCIP_OKAY;
1086 }
1087 
1088 /** Removes a given variable @p var from position @p pos from the proofset and updates the right-hand side according
1089  * to sign of the coefficient, i.e., rhs -= coef * bound, where bound = lb if coef >= 0 and bound = ub, otherwise.
1090  *
1091  * @note: The list of non-zero indices and coefficients will be updated by swapping the last non-zero index to @p pos.
1092  */
1093 static
1095  SCIP_PROOFSET* proofset,
1096  SCIP_SET* set,
1097  SCIP_VAR* var,
1098  int pos,
1099  SCIP_Bool* valid
1100  )
1101 {
1102  assert(proofset != NULL);
1103  assert(var != NULL);
1104  assert(pos >= 0 && pos < proofset->nnz);
1105  assert(valid != NULL);
1106 
1107  *valid = TRUE;
1108 
1109  /* cancel with lower bound */
1110  if( proofset->vals[pos] > 0.0 )
1111  {
1112  proofset->rhs -= proofset->vals[pos] * SCIPvarGetLbGlobal(var);
1113  }
1114  /* cancel with upper bound */
1115  else
1116  {
1117  assert(proofset->vals[pos] < 0.0);
1118  proofset->rhs -= proofset->vals[pos] * SCIPvarGetUbGlobal(var);
1119  }
1120 
1121  --proofset->nnz;
1122 
1123  proofset->vals[pos] = proofset->vals[proofset->nnz];
1124  proofset->inds[pos] = proofset->inds[proofset->nnz];
1125  proofset->vals[proofset->nnz] = 0.0;
1126  proofset->inds[proofset->nnz] = 0;
1127 
1128  if( SCIPsetIsInfinity(set, proofset->rhs) )
1129  *valid = FALSE;
1130 }
1131 
1132 /*
1133  * Conflict Sets
1134  */
1135 
1136 /** resizes the array of the temporary bound change informations to be able to store at least num bound change entries */
1137 static
1139  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1140  SCIP_SET* set, /**< global SCIP settings */
1141  int num /**< minimal number of slots in arrays */
1142  )
1143 {
1144  assert(conflict != NULL);
1145  assert(set != NULL);
1146 
1147  if( num > conflict->tmpbdchginfossize )
1148  {
1149  int newsize;
1150 
1151  newsize = SCIPsetCalcMemGrowSize(set, num);
1152  SCIP_ALLOC( BMSreallocMemoryArray(&conflict->tmpbdchginfos, newsize) );
1153  conflict->tmpbdchginfossize = newsize;
1154  }
1155  assert(num <= conflict->tmpbdchginfossize);
1156 
1157  return SCIP_OKAY;
1158 }
1159 
1160 /** creates a temporary bound change information object that is destroyed after the conflict sets are flushed */
1161 static
1163  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1164  BMS_BLKMEM* blkmem, /**< block memory */
1165  SCIP_SET* set, /**< global SCIP settings */
1166  SCIP_VAR* var, /**< active variable that changed the bounds */
1167  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1168  SCIP_Real oldbound, /**< old value for bound */
1169  SCIP_Real newbound, /**< new value for bound */
1170  SCIP_BDCHGINFO** bdchginfo /**< pointer to store bound change information */
1171  )
1172 {
1173  assert(conflict != NULL);
1174 
1175  SCIP_CALL( conflictEnsureTmpbdchginfosMem(conflict, set, conflict->ntmpbdchginfos+1) );
1176  SCIP_CALL( SCIPbdchginfoCreate(&conflict->tmpbdchginfos[conflict->ntmpbdchginfos], blkmem,
1177  var, boundtype, oldbound, newbound) );
1178  *bdchginfo = conflict->tmpbdchginfos[conflict->ntmpbdchginfos];
1179  conflict->ntmpbdchginfos++;
1180 
1181  return SCIP_OKAY;
1182 }
1183 
1184 /** frees all temporarily created bound change information data */
1185 static
1187  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1188  BMS_BLKMEM* blkmem /**< block memory */
1189  )
1190 {
1191  int i;
1192 
1193  assert(conflict != NULL);
1194 
1195  for( i = 0; i < conflict->ntmpbdchginfos; ++i )
1196  SCIPbdchginfoFree(&conflict->tmpbdchginfos[i], blkmem);
1197  conflict->ntmpbdchginfos = 0;
1198 }
1199 
1200 /** clears the given conflict set */
1201 static
1203  SCIP_CONFLICTSET* conflictset /**< conflict set */
1204  )
1205 {
1206  assert(conflictset != NULL);
1207 
1208  conflictset->nbdchginfos = 0;
1209  conflictset->validdepth = 0;
1210  conflictset->insertdepth = 0;
1211  conflictset->conflictdepth = 0;
1212  conflictset->repropdepth = 0;
1213  conflictset->repropagate = TRUE;
1214  conflictset->usescutoffbound = FALSE;
1215  conflictset->conflicttype = SCIP_CONFTYPE_UNKNOWN;
1216 }
1217 
1218 /** creates an empty conflict set */
1219 static
1221  SCIP_CONFLICTSET** conflictset, /**< pointer to store the conflict set */
1222  BMS_BLKMEM* blkmem /**< block memory of transformed problem */
1223  )
1224 {
1225  assert(conflictset != NULL);
1226 
1227  SCIP_ALLOC( BMSallocBlockMemory(blkmem, conflictset) );
1228  (*conflictset)->bdchginfos = NULL;
1229  (*conflictset)->relaxedbds = NULL;
1230  (*conflictset)->sortvals = NULL;
1231  (*conflictset)->bdchginfossize = 0;
1232 
1233  conflictsetClear(*conflictset);
1234 
1235  return SCIP_OKAY;
1236 }
1237 
1238 /** creates a copy of the given conflict set, allocating an additional amount of memory */
1239 static
1241  SCIP_CONFLICTSET** targetconflictset, /**< pointer to store the conflict set */
1242  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
1243  SCIP_CONFLICTSET* sourceconflictset, /**< source conflict set */
1244  int nadditionalelems /**< number of additional elements to allocate memory for */
1245  )
1246 {
1247  int targetsize;
1248 
1249  assert(targetconflictset != NULL);
1250  assert(sourceconflictset != NULL);
1251 
1252  targetsize = sourceconflictset->nbdchginfos + nadditionalelems;
1253  SCIP_ALLOC( BMSallocBlockMemory(blkmem, targetconflictset) );
1254  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetconflictset)->bdchginfos, targetsize) );
1255  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetconflictset)->relaxedbds, targetsize) );
1256  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetconflictset)->sortvals, targetsize) );
1257  (*targetconflictset)->bdchginfossize = targetsize;
1258 
1259  BMScopyMemoryArray((*targetconflictset)->bdchginfos, sourceconflictset->bdchginfos, sourceconflictset->nbdchginfos);
1260  BMScopyMemoryArray((*targetconflictset)->relaxedbds, sourceconflictset->relaxedbds, sourceconflictset->nbdchginfos);
1261  BMScopyMemoryArray((*targetconflictset)->sortvals, sourceconflictset->sortvals, sourceconflictset->nbdchginfos);
1262 
1263  (*targetconflictset)->nbdchginfos = sourceconflictset->nbdchginfos;
1264  (*targetconflictset)->validdepth = sourceconflictset->validdepth;
1265  (*targetconflictset)->insertdepth = sourceconflictset->insertdepth;
1266  (*targetconflictset)->conflictdepth = sourceconflictset->conflictdepth;
1267  (*targetconflictset)->repropdepth = sourceconflictset->repropdepth;
1268  (*targetconflictset)->usescutoffbound = sourceconflictset->usescutoffbound;
1269  (*targetconflictset)->conflicttype = sourceconflictset->conflicttype;
1270 
1271  return SCIP_OKAY;
1272 }
1273 
1274 /** frees a conflict set */
1275 static
1277  SCIP_CONFLICTSET** conflictset, /**< pointer to the conflict set */
1278  BMS_BLKMEM* blkmem /**< block memory of transformed problem */
1279  )
1280 {
1281  assert(conflictset != NULL);
1282  assert(*conflictset != NULL);
1283 
1284  BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->bdchginfos, (*conflictset)->bdchginfossize);
1285  BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->relaxedbds, (*conflictset)->bdchginfossize);
1286  BMSfreeBlockMemoryArrayNull(blkmem, &(*conflictset)->sortvals, (*conflictset)->bdchginfossize);
1287  BMSfreeBlockMemory(blkmem, conflictset);
1288 }
1289 
1290 /** resizes the arrays of the conflict set to be able to store at least num bound change entries */
1291 static
1293  SCIP_CONFLICTSET* conflictset, /**< conflict set */
1294  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
1295  SCIP_SET* set, /**< global SCIP settings */
1296  int num /**< minimal number of slots in arrays */
1297  )
1298 {
1299  assert(conflictset != NULL);
1300  assert(set != NULL);
1301 
1302  if( num > conflictset->bdchginfossize )
1303  {
1304  int newsize;
1305 
1306  newsize = SCIPsetCalcMemGrowSize(set, num);
1307  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->bdchginfos, conflictset->bdchginfossize, newsize) );
1308  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->relaxedbds, conflictset->bdchginfossize, newsize) );
1309  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conflictset->sortvals, conflictset->bdchginfossize, newsize) );
1310  conflictset->bdchginfossize = newsize;
1311  }
1312  assert(num <= conflictset->bdchginfossize);
1313 
1314  return SCIP_OKAY;
1315 }
1316 
1317 /** calculates the score of the conflict set
1318  *
1319  * the score is weighted sum of number of bound changes, repropagation depth, and valid depth
1320  */
1321 static
1323  SCIP_CONFLICTSET* conflictset, /**< conflict set */
1324  SCIP_SET* set /**< global SCIP settings */
1325  )
1326 {
1327  assert(conflictset != NULL);
1328 
1329  return -(set->conf_weightsize * conflictset->nbdchginfos
1330  + set->conf_weightrepropdepth * conflictset->repropdepth
1331  + set->conf_weightvaliddepth * conflictset->validdepth);
1332 }
1333 
1334 /** calculates the score of a bound change within a conflict */
1335 static
1337  SCIP_Real prooflhs, /**< lhs of proof constraint */
1338  SCIP_Real proofact, /**< activity of the proof constraint */
1339  SCIP_Real proofactdelta, /**< activity change */
1340  SCIP_Real proofcoef, /**< coefficient in proof constraint */
1341  int depth, /**< bound change depth */
1342  int currentdepth, /**< current depth */
1343  SCIP_VAR* var, /**< variable corresponding to bound change */
1344  SCIP_SET* set /**< global SCIP settings */
1345  )
1346 {
1347  SCIP_COL* col;
1348  SCIP_Real score;
1349 
1350  score = set->conf_proofscorefac * (1.0 - proofactdelta/(prooflhs - proofact));
1351  score = MAX(score, 0.0);
1352  score += set->conf_depthscorefac * (SCIP_Real)(depth+1)/(SCIP_Real)(currentdepth+1);
1353 
1355  col = SCIPvarGetCol(var);
1356  else
1357  col = NULL;
1358 
1359  if( proofcoef > 0.0 )
1360  {
1361  if( col != NULL && SCIPcolGetNNonz(col) > 0 )
1362  score += set->conf_uplockscorefac * (SCIP_Real)(SCIPvarGetNLocksUp(var))/(SCIP_Real)(SCIPcolGetNNonz(col));
1363  else
1364  score += set->conf_uplockscorefac * SCIPvarGetNLocksUp(var);
1365  }
1366  else
1367  {
1368  if( col != NULL && SCIPcolGetNNonz(col) > 0 )
1369  score += set->conf_downlockscorefac * (SCIP_Real)(SCIPvarGetNLocksDown(var))/(SCIP_Real)(SCIPcolGetNNonz(col));
1370  else
1371  score += set->conf_downlockscorefac * SCIPvarGetNLocksDown(var);
1372  }
1373 
1374  return score;
1375 }
1376 
1377 /** check if the bound change info (which is the potential next candidate which is queued) is valid for the current
1378  * conflict analysis; a bound change info can get invalid if after this one was added to the queue, a weaker bound
1379  * change was added to the queue (due the bound widening idea) which immediately makes this bound change redundant; due
1380  * to the priority we did not removed that bound change info since that cost O(log(n)); hence we have to skip/ignore it
1381  * now
1382  *
1383  * The following situations can occur before for example the bound change info (x >= 3) is potentially popped from the
1384  * queue.
1385  *
1386  * Postcondition: the reason why (x >= 3) was queued is that at this time point no lower bound of x was involved yet in
1387  * the current conflict or the lower bound which was involved until then was stronger, e.g., (x >= 2).
1388  *
1389  * 1) during the time until (x >= 3) gets potentially popped no weaker lower bound was added to the queue, in that case
1390  * the conflictlbcount is valid and conflictlb is 3; that is (var->conflictlbcount == conflict->count &&
1391  * var->conflictlb == 3)
1392  *
1393  * 2) a weaker bound change info gets queued (e.g., x >= 4); this bound change is popped before (x >= 3) since it has
1394  * higher priority (which is the time stamp of the bound change info and (x >= 4) has to be done after (x >= 3)
1395  * during propagation or branching)
1396  *
1397  * a) if (x >= 4) is popped and added to the conflict set the conflictlbcount is still valid and conflictlb is at
1398  * most 4; that is (var->conflictlbcount == conflict->count && var->conflictlb >= 4); it follows that any bound
1399  * change info which is stronger than (x >= 4) gets ignored (for example x >= 2)
1400  *
1401  * b) if (x >= 4) is popped and resolved without introducing a new lower bound on x until (x >= 3) is a potentially
1402  * candidate the conflictlbcount indicates that bound change is currently not present; that is
1403  * (var->conflictlbcount != conflict->count)
1404  *
1405  * 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
1406  * pooped, the conflictlbcount indicates that bound change is currently present; that is (var->conflictlbcount ==
1407  * conflict->count); however the (x >= 3) only has be explained if conflictlb matches that one; that is
1408  * (var->conflictlb == bdchginfo->newbound); otherwise it redundant/invalid.
1409  */
1410 static
1412  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1413  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
1414  )
1415 {
1416  SCIP_VAR* var;
1417 
1418  assert(bdchginfo != NULL);
1419 
1420  var = SCIPbdchginfoGetVar(bdchginfo);
1421  assert(var != NULL);
1422 
1423  /* the bound change info of a binary (domained) variable can never be invalid since the concepts of relaxed bounds
1424  * and bound widening do not make sense for these type of variables
1425  */
1426  if( SCIPvarIsBinary(var) )
1427  return FALSE;
1428 
1429  /* check if the bdchginfo is invaild since a tight/weaker bound change was already explained */
1431  {
1432  if( var->conflictlbcount != conflict->count || var->conflictlb != SCIPbdchginfoGetNewbound(bdchginfo) ) /*lint !e777*/
1433  {
1434  assert(!SCIPvarIsBinary(var));
1435  return TRUE;
1436  }
1437  }
1438  else
1439  {
1440  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER);
1441 
1442  if( var->conflictubcount != conflict->count || var->conflictub != SCIPbdchginfoGetNewbound(bdchginfo) ) /*lint !e777*/
1443  {
1444  assert(!SCIPvarIsBinary(var));
1445  return TRUE;
1446  }
1447  }
1448 
1449  return FALSE;
1450 }
1451 
1452 /** adds a bound change to a conflict set */
1453 static
1455  SCIP_CONFLICTSET* conflictset, /**< conflict set */
1456  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
1457  SCIP_SET* set, /**< global SCIP settings */
1458  SCIP_BDCHGINFO* bdchginfo, /**< bound change to add to the conflict set */
1459  SCIP_Real relaxedbd /**< relaxed bound */
1460  )
1461 {
1462  SCIP_BDCHGINFO** bdchginfos;
1463  SCIP_Real* relaxedbds;
1464  int* sortvals;
1465  SCIP_VAR* var;
1466  SCIP_BOUNDTYPE boundtype;
1467  int idx;
1468  int sortval;
1469  int pos;
1470 
1471  assert(conflictset != NULL);
1472  assert(bdchginfo != NULL);
1473 
1474  /* allocate memory for additional element */
1475  SCIP_CALL( conflictsetEnsureBdchginfosMem(conflictset, blkmem, set, conflictset->nbdchginfos+1) );
1476 
1477  /* insert the new bound change in the arrays sorted by increasing variable index and by bound type */
1478  bdchginfos = conflictset->bdchginfos;
1479  relaxedbds = conflictset->relaxedbds;
1480  sortvals = conflictset->sortvals;
1481  var = SCIPbdchginfoGetVar(bdchginfo);
1482  boundtype = SCIPbdchginfoGetBoundtype(bdchginfo);
1483  idx = SCIPvarGetIndex(var);
1484  assert(idx < INT_MAX/2);
1485  assert((int)boundtype == 0 || (int)boundtype == 1);
1486  sortval = 2*idx + (int)boundtype; /* first sorting criteria: variable index, second criteria: boundtype */
1487 
1488  /* insert new element into the sorted arrays; if an element exits with the same value insert the new element afterwards
1489  *
1490  * @todo check if it better (faster) to first search for the position O(log n) and compare the sort values and if
1491  * they are equal just replace the element and if not run the insert method O(n)
1492  */
1493 
1494  SCIPsortedvecInsertIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, sortval, (void*)bdchginfo, relaxedbd, &conflictset->nbdchginfos, &pos);
1495  assert(pos == conflictset->nbdchginfos - 1 || sortval < sortvals[pos+1]);
1496 
1497  /* merge multiple bound changes */
1498  if( pos > 0 && sortval == sortvals[pos-1] )
1499  {
1500  /* this is a multiple bound change */
1501  if( SCIPbdchginfoIsTighter(bdchginfo, bdchginfos[pos-1]) )
1502  {
1503  /* remove the "old" bound change since the "new" one in tighter */
1504  SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos-1, &conflictset->nbdchginfos);
1505  }
1506  else if( SCIPbdchginfoIsTighter(bdchginfos[pos-1], bdchginfo) )
1507  {
1508  /* remove the "new" bound change since the "old" one is tighter */
1509  SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos, &conflictset->nbdchginfos);
1510  }
1511  else
1512  {
1513  /* both bound change are equivalent; hence, keep the worse relaxed bound and remove one of them */
1514  relaxedbds[pos-1] = boundtype == SCIP_BOUNDTYPE_LOWER ? MAX(relaxedbds[pos-1], relaxedbd) : MIN(relaxedbds[pos-1], relaxedbd);
1515  SCIPsortedvecDelPosIntPtrReal(sortvals, (void**)bdchginfos, relaxedbds, pos, &conflictset->nbdchginfos);
1516  }
1517  }
1518 
1519  return SCIP_OKAY;
1520 }
1521 
1522 /** adds given bound changes to a conflict set */
1523 static
1525  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1526  SCIP_CONFLICTSET* conflictset, /**< conflict set */
1527  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
1528  SCIP_SET* set, /**< global SCIP settings */
1529  SCIP_BDCHGINFO** bdchginfos, /**< bound changes to add to the conflict set */
1530  int nbdchginfos /**< number of bound changes to add */
1531  )
1532 {
1533  SCIP_BDCHGINFO** confbdchginfos;
1534  SCIP_BDCHGINFO* bdchginfo;
1535  SCIP_Real* confrelaxedbds;
1536  int* confsortvals;
1537  int confnbdchginfos;
1538  int idx;
1539  int sortval;
1540  int i;
1541  SCIP_BOUNDTYPE boundtype;
1542 
1543  assert(conflict != NULL);
1544  assert(conflictset != NULL);
1545  assert(blkmem != NULL);
1546  assert(set != NULL);
1547  assert(bdchginfos != NULL || nbdchginfos == 0);
1548 
1549  /* nothing to add */
1550  if( nbdchginfos == 0 )
1551  return SCIP_OKAY;
1552 
1553  assert(bdchginfos != NULL);
1554 
1555  /* only one element to add, use the single insertion method */
1556  if( nbdchginfos == 1 )
1557  {
1558  bdchginfo = bdchginfos[0];
1559  assert(bdchginfo != NULL);
1560 
1561  if( !bdchginfoIsInvalid(conflict, bdchginfo) )
1562  {
1563  SCIP_CALL( conflictsetAddBound(conflictset, blkmem, set, bdchginfo, SCIPbdchginfoGetRelaxedBound(bdchginfo)) );
1564  }
1565  else
1566  {
1567  SCIPsetDebugMsg(set, "-> bound change info [%d:<%s> %s %g] is invaild -> ignore it\n", SCIPbdchginfoGetDepth(bdchginfo),
1568  SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
1569  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
1570  SCIPbdchginfoGetNewbound(bdchginfo));
1571  }
1572 
1573  return SCIP_OKAY;
1574  }
1575 
1576  confnbdchginfos = conflictset->nbdchginfos;
1577 
1578  /* allocate memory for additional element */
1579  SCIP_CALL( conflictsetEnsureBdchginfosMem(conflictset, blkmem, set, confnbdchginfos + nbdchginfos) );
1580 
1581  confbdchginfos = conflictset->bdchginfos;
1582  confrelaxedbds = conflictset->relaxedbds;
1583  confsortvals = conflictset->sortvals;
1584 
1585  assert(SCIP_BOUNDTYPE_LOWER == FALSE);/*lint !e641*/
1586  assert(SCIP_BOUNDTYPE_UPPER == TRUE);/*lint !e641*/
1587 
1588  for( i = 0; i < nbdchginfos; ++i )
1589  {
1590  bdchginfo = bdchginfos[i];
1591  assert(bdchginfo != NULL);
1592 
1593  /* add only valid bound change infos */
1594  if( !bdchginfoIsInvalid(conflict, bdchginfo) )
1595  {
1596  /* calculate sorting value */
1597  boundtype = SCIPbdchginfoGetBoundtype(bdchginfo);
1598  assert(SCIPbdchginfoGetVar(bdchginfo) != NULL);
1599 
1600  idx = SCIPvarGetIndex(SCIPbdchginfoGetVar(bdchginfo));
1601  assert(idx < INT_MAX/2);
1602 
1603  assert((int)boundtype == 0 || (int)boundtype == 1);
1604  sortval = 2*idx + (int)boundtype; /* first sorting criteria: variable index, second criteria: boundtype */
1605 
1606  /* add new element */
1607  confbdchginfos[confnbdchginfos] = bdchginfo;
1608  confrelaxedbds[confnbdchginfos] = SCIPbdchginfoGetRelaxedBound(bdchginfo);
1609  confsortvals[confnbdchginfos] = sortval;
1610  ++confnbdchginfos;
1611  }
1612  else
1613  {
1614  SCIPsetDebugMsg(set, "-> bound change info [%d:<%s> %s %g] is invaild -> ignore it\n", SCIPbdchginfoGetDepth(bdchginfo),
1615  SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
1616  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
1617  SCIPbdchginfoGetNewbound(bdchginfo));
1618  }
1619  }
1620  assert(confnbdchginfos <= conflictset->nbdchginfos + nbdchginfos);
1621 
1622  /* sort and merge the new conflict set */
1623  if( confnbdchginfos > conflictset->nbdchginfos )
1624  {
1625  int k = 0;
1626 
1627  /* sort array */
1628  SCIPsortIntPtrReal(confsortvals, (void**)confbdchginfos, confrelaxedbds, confnbdchginfos);
1629 
1630  i = 1;
1631  /* merge multiple bound changes */
1632  while( i < confnbdchginfos )
1633  {
1634  assert(i > k);
1635 
1636  /* is this a multiple bound change */
1637  if( confsortvals[k] == confsortvals[i] )
1638  {
1639  if( SCIPbdchginfoIsTighter(confbdchginfos[k], confbdchginfos[i]) )
1640  ++i;
1641  else if( SCIPbdchginfoIsTighter(confbdchginfos[i], confbdchginfos[k]) )
1642  {
1643  /* replace worse bound change info by tighter bound change info */
1644  confbdchginfos[k] = confbdchginfos[i];
1645  confrelaxedbds[k] = confrelaxedbds[i];
1646  confsortvals[k] = confsortvals[i];
1647  ++i;
1648  }
1649  else
1650  {
1651  assert(confsortvals[k] == confsortvals[i]);
1652 
1653  /* both bound change are equivalent; hence, keep the worse relaxed bound and remove one of them */
1654  confrelaxedbds[k] = (confsortvals[k] % 2 == 0) ? MAX(confrelaxedbds[k], confrelaxedbds[i]) : MIN(confrelaxedbds[k], confrelaxedbds[i]);
1655  ++i;
1656  }
1657  }
1658  else
1659  {
1660  /* all bound change infos must be valid */
1661  assert(!bdchginfoIsInvalid(conflict, confbdchginfos[k]));
1662 
1663  ++k;
1664  /* move next comparison element to the correct position */
1665  if( k != i )
1666  {
1667  confbdchginfos[k] = confbdchginfos[i];
1668  confrelaxedbds[k] = confrelaxedbds[i];
1669  confsortvals[k] = confsortvals[i];
1670  }
1671  ++i;
1672  }
1673  }
1674  /* last bound change infos must also be valid */
1675  assert(!bdchginfoIsInvalid(conflict, confbdchginfos[k]));
1676  /* the number of bound change infos cannot be decreased, it would mean that the conflict set was not merged
1677  * before
1678  */
1679  assert(conflictset->nbdchginfos <= k + 1 );
1680  assert(k + 1 <= confnbdchginfos);
1681 
1682  conflictset->nbdchginfos = k + 1;
1683  }
1684 
1685  return SCIP_OKAY;
1686 }
1687 
1688 /** calculates the conflict and the repropagation depths of the conflict set */
1689 static
1691  SCIP_CONFLICTSET* conflictset /**< conflict set */
1692  )
1693 {
1694  int maxdepth[2];
1695  int i;
1696 
1697  assert(conflictset != NULL);
1698  assert(conflictset->validdepth <= conflictset->insertdepth);
1699 
1700  /* get the depth of the last and last but one bound change */
1701  maxdepth[0] = conflictset->validdepth;
1702  maxdepth[1] = conflictset->validdepth;
1703  for( i = 0; i < conflictset->nbdchginfos; ++i )
1704  {
1705  int depth;
1706 
1707  depth = SCIPbdchginfoGetDepth(conflictset->bdchginfos[i]);
1708  assert(depth >= 0);
1709  if( depth > maxdepth[0] )
1710  {
1711  maxdepth[1] = maxdepth[0];
1712  maxdepth[0] = depth;
1713  }
1714  else if( depth > maxdepth[1] )
1715  maxdepth[1] = depth;
1716  }
1717  assert(maxdepth[0] >= maxdepth[1]);
1718 
1719  conflictset->conflictdepth = maxdepth[0];
1720  conflictset->repropdepth = maxdepth[1];
1721 }
1722 
1723 /** identifies the depth, at which the conflict set should be added:
1724  * - if the branching rule operates on variables only, and if all branching variables up to a certain
1725  * depth level are member of the conflict, the conflict constraint can only be violated in the subtree
1726  * of the node at that depth, because in all other nodes, at least one of these branching variables
1727  * violates its conflicting bound, such that the conflict constraint is feasible
1728  * - if there is at least one branching variable in a node, we assume, that this branching was performed
1729  * on variables, and that the siblings of this node are disjunct w.r.t. the branching variables' fixings
1730  * - we have to add the conflict set at least in the valid depth of the initial conflict set,
1731  * so we start searching at the first branching after this depth level, i.e. validdepth+1
1732  */
1733 static
1735  SCIP_CONFLICTSET* conflictset, /**< conflict set */
1736  SCIP_SET* set, /**< global SCIP settings */
1737  SCIP_TREE* tree /**< branch and bound tree */
1738  )
1739 {
1740  SCIP_Bool* branchingincluded;
1741  int currentdepth;
1742  int i;
1743 
1744  assert(conflictset != NULL);
1745  assert(set != NULL);
1746  assert(tree != NULL);
1747 
1748  /* the conflict set must not be inserted prior to its valid depth */
1749  conflictset->insertdepth = conflictset->validdepth;
1750  assert(conflictset->insertdepth >= 0);
1751 
1752  currentdepth = SCIPtreeGetCurrentDepth(tree);
1753  assert(currentdepth == tree->pathlen-1);
1754 
1755  /* mark the levels for which a branching variable is included in the conflict set */
1756  SCIP_CALL( SCIPsetAllocBufferArray(set, &branchingincluded, currentdepth+2) );
1757  BMSclearMemoryArray(branchingincluded, currentdepth+2);
1758  for( i = 0; i < conflictset->nbdchginfos; ++i )
1759  {
1760  int depth;
1761 
1762  depth = SCIPbdchginfoGetDepth(conflictset->bdchginfos[i]);
1763  depth = MIN(depth, currentdepth+1); /* put diving/probing/strong branching changes in this depth level */
1764  branchingincluded[depth] = TRUE;
1765  }
1766 
1767  /* skip additional depth levels where branching on the conflict variables was applied */
1768  while( conflictset->insertdepth < currentdepth && branchingincluded[conflictset->insertdepth+1] )
1769  conflictset->insertdepth++;
1770 
1771  /* free temporary memory */
1772  SCIPsetFreeBufferArray(set, &branchingincluded);
1773 
1774  assert(conflictset->validdepth <= conflictset->insertdepth && conflictset->insertdepth <= currentdepth);
1775 
1776  return SCIP_OKAY;
1777 }
1778 
1779 /** checks whether the first conflict set is redundant to the second one */
1780 static
1782  SCIP_CONFLICTSET* conflictset1, /**< first conflict conflict set */
1783  SCIP_CONFLICTSET* conflictset2 /**< second conflict conflict set */
1784  )
1785 {
1786  int i1;
1787  int i2;
1788 
1789  assert(conflictset1 != NULL);
1790  assert(conflictset2 != NULL);
1791 
1792  /* if conflictset1 has smaller validdepth, it is definitely not redundant to conflictset2 */
1793  if( conflictset1->validdepth < conflictset2->validdepth )
1794  return FALSE;
1795 
1796  /* check, if all bound changes in conflictset2 are also present at least as tight in conflictset1;
1797  * we can stop immediately, if more bound changes are remaining in conflictset2 than in conflictset1
1798  */
1799  for( i1 = 0, i2 = 0; i2 < conflictset2->nbdchginfos && conflictset1->nbdchginfos - i1 >= conflictset2->nbdchginfos - i2;
1800  ++i1, ++i2 )
1801  {
1802  int sortval;
1803 
1804  assert(i2 == 0 || conflictset2->sortvals[i2-1] < conflictset2->sortvals[i2]);
1805 
1806  sortval = conflictset2->sortvals[i2];
1807  for( ; i1 < conflictset1->nbdchginfos && conflictset1->sortvals[i1] < sortval; ++i1 )
1808  {
1809  /* while scanning conflictset1, check consistency */
1810  assert(i1 == 0 || conflictset1->sortvals[i1-1] < conflictset1->sortvals[i1]);
1811  }
1812  if( i1 >= conflictset1->nbdchginfos || conflictset1->sortvals[i1] > sortval
1813  || SCIPbdchginfoIsTighter(conflictset2->bdchginfos[i2], conflictset1->bdchginfos[i1]) )
1814  return FALSE;
1815  }
1816 
1817  return (i2 == conflictset2->nbdchginfos);
1818 }
1819 
1820 #ifdef SCIP_DEBUG
1821 /** prints a conflict set to the screen */
1822 static
1823 void conflictsetPrint(
1824  SCIP_CONFLICTSET* conflictset /**< conflict set */
1825  )
1826 {
1827  int i;
1828 
1829  assert(conflictset != NULL);
1830  for( i = 0; i < conflictset->nbdchginfos; ++i )
1831  {
1832  SCIPdebugPrintf(" [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(conflictset->bdchginfos[i]),
1833  SCIPvarGetName(SCIPbdchginfoGetVar(conflictset->bdchginfos[i])),
1834  SCIPbdchginfoGetBoundtype(conflictset->bdchginfos[i]) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
1835  SCIPbdchginfoGetNewbound(conflictset->bdchginfos[i]), conflictset->relaxedbds[i]);
1836  }
1837  SCIPdebugPrintf("\n");
1838 }
1839 #endif
1840 
1841 /** resizes proofsets array to be able to store at least num entries */
1842 static
1844  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1845  SCIP_SET* set, /**< global SCIP settings */
1846  int num /**< minimal number of slots in array */
1847  )
1848 {
1849  assert(conflict != NULL);
1850  assert(set != NULL);
1851 
1852  if( num > conflict->proofsetssize )
1853  {
1854  int newsize;
1855 
1856  newsize = SCIPsetCalcMemGrowSize(set, num);
1857  SCIP_ALLOC( BMSreallocMemoryArray(&conflict->proofsets, newsize) );
1858  conflict->proofsetssize = newsize;
1859  }
1860  assert(num <= conflict->proofsetssize);
1861 
1862  return SCIP_OKAY;
1863 }
1864 
1865 /** resizes conflictsets array to be able to store at least num entries */
1866 static
1868  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1869  SCIP_SET* set, /**< global SCIP settings */
1870  int num /**< minimal number of slots in array */
1871  )
1872 {
1873  assert(conflict != NULL);
1874  assert(set != NULL);
1875 
1876  if( num > conflict->conflictsetssize )
1877  {
1878  int newsize;
1879 
1880  newsize = SCIPsetCalcMemGrowSize(set, num);
1881  SCIP_ALLOC( BMSreallocMemoryArray(&conflict->conflictsets, newsize) );
1882  SCIP_ALLOC( BMSreallocMemoryArray(&conflict->conflictsetscores, newsize) );
1883  conflict->conflictsetssize = newsize;
1884  }
1885  assert(num <= conflict->conflictsetssize);
1886 
1887  return SCIP_OKAY;
1888 }
1889 
1890 /** add a proofset to the list of all proofsets */
1891 static
1893  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1894  SCIP_SET* set, /**< global SCIP settings */
1895  SCIP_PROOFSET* proofset /**< proof set to add */
1896  )
1897 {
1898  assert(conflict != NULL);
1899  assert(proofset != NULL);
1900 
1901  /* insert proofset into the sorted proofsets array */
1902  SCIP_CALL( conflictEnsureProofsetsMem(conflict, set, conflict->nproofsets + 1) );
1903 
1904  conflict->proofsets[conflict->nproofsets] = proofset;
1905  ++conflict->nproofsets;
1906 
1907  return SCIP_OKAY;
1908 }
1909 
1910 /** inserts conflict set into sorted conflictsets array and deletes the conflict set pointer */
1911 static
1913  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1914  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
1915  SCIP_SET* set, /**< global SCIP settings */
1916  SCIP_CONFLICTSET** conflictset /**< pointer to conflict set to insert */
1917  )
1918 {
1919  SCIP_Real score;
1920  int pos;
1921  int i;
1922  int j;
1923 
1924  assert(conflict != NULL);
1925  assert(set != NULL);
1926  assert(conflictset != NULL);
1927  assert(*conflictset != NULL);
1928  assert((*conflictset)->validdepth <= (*conflictset)->insertdepth);
1929  assert(set->conf_allowlocal || (*conflictset)->validdepth == 0);
1930 
1931  /* calculate conflict and repropagation depth */
1932  conflictsetCalcConflictDepth(*conflictset);
1933 
1934  /* if we apply repropagations, the conflict set should be inserted at most at its repropdepth */
1935  if( set->conf_repropagate )
1936  (*conflictset)->insertdepth = MIN((*conflictset)->insertdepth, (*conflictset)->repropdepth);
1937  else
1938  (*conflictset)->repropdepth = INT_MAX;
1939  assert((*conflictset)->insertdepth <= (*conflictset)->repropdepth);
1940 
1941  SCIPsetDebugMsg(set, "inserting conflict set (valid: %d, insert: %d, conf: %d, reprop: %d):\n",
1942  (*conflictset)->validdepth, (*conflictset)->insertdepth, (*conflictset)->conflictdepth, (*conflictset)->repropdepth);
1943  SCIPdebug(conflictsetPrint(*conflictset));
1944 
1945  /* get the score of the conflict set */
1946  score = conflictsetCalcScore(*conflictset, set);
1947 
1948  /* check, if conflict set is redundant to a better conflict set */
1949  for( pos = 0; pos < conflict->nconflictsets && score < conflict->conflictsetscores[pos]; ++pos )
1950  {
1951  /* check if conflict set is redundant with respect to conflictsets[pos] */
1952  if( conflictsetIsRedundant(*conflictset, conflict->conflictsets[pos]) )
1953  {
1954  SCIPsetDebugMsg(set, " -> conflict set is redundant to: ");
1955  SCIPdebug(conflictsetPrint(conflict->conflictsets[pos]));
1956  conflictsetFree(conflictset, blkmem);
1957  return SCIP_OKAY;
1958  }
1959 
1960  /**@todo like in sepastore.c: calculate overlap between conflictsets -> large overlap reduces score */
1961 
1962  }
1963 
1964  /* insert conflictset into the sorted conflictsets array */
1965  SCIP_CALL( conflictEnsureConflictsetsMem(conflict, set, conflict->nconflictsets + 1) );
1966  for( i = conflict->nconflictsets; i > pos; --i )
1967  {
1968  assert(score >= conflict->conflictsetscores[i-1]);
1969  conflict->conflictsets[i] = conflict->conflictsets[i-1];
1970  conflict->conflictsetscores[i] = conflict->conflictsetscores[i-1];
1971  }
1972  conflict->conflictsets[pos] = *conflictset;
1973  conflict->conflictsetscores[pos] = score;
1974  conflict->nconflictsets++;
1975 
1976  /* remove worse conflictsets that are redundant to the new conflictset */
1977  for( i = pos+1, j = pos+1; i < conflict->nconflictsets; ++i )
1978  {
1979  if( conflictsetIsRedundant(conflict->conflictsets[i], *conflictset) )
1980  {
1981  SCIPsetDebugMsg(set, " -> conflict set dominates: ");
1982  SCIPdebug(conflictsetPrint(conflict->conflictsets[i]));
1983  conflictsetFree(&conflict->conflictsets[i], blkmem);
1984  }
1985  else
1986  {
1987  assert(j <= i);
1988  conflict->conflictsets[j] = conflict->conflictsets[i];
1989  conflict->conflictsetscores[j] = conflict->conflictsetscores[i];
1990  j++;
1991  }
1992  }
1993  assert(j <= conflict->nconflictsets);
1994  conflict->nconflictsets = j;
1995 
1996 #ifdef SCIP_CONFGRAPH
1997  confgraphMarkConflictset(*conflictset);
1998 #endif
1999 
2000  *conflictset = NULL; /* ownership of pointer is now in the conflictsets array */
2001 
2002  return SCIP_OKAY;
2003 }
2004 
2005 /** calculates the maximal size of conflict sets to be used */
2006 static
2008  SCIP_SET* set, /**< global SCIP settings */
2009  SCIP_PROB* prob /**< problem data */
2010  )
2011 {
2012  int maxsize;
2013 
2014  assert(set != NULL);
2015  assert(prob != NULL);
2016 
2017  maxsize = (int)(set->conf_maxvarsfac * (prob->nvars - prob->ncontvars));
2018  maxsize = MAX(maxsize, set->conf_minmaxvars);
2019 
2020  return maxsize;
2021 }
2022 
2023 /** increases the conflict score of the variable in the given direction */
2024 static
2026  SCIP_VAR* var, /**< problem variable */
2027  BMS_BLKMEM* blkmem, /**< block memory */
2028  SCIP_SET* set, /**< global SCIP settings */
2029  SCIP_STAT* stat, /**< dynamic problem statistics */
2030  SCIP_BOUNDTYPE boundtype, /**< type of bound for which the score should be increased */
2031  SCIP_Real value, /**< value of the bound */
2032  SCIP_Real weight /**< weight of this VSIDS updates */
2033  )
2034 {
2035  SCIP_BRANCHDIR branchdir;
2036 
2037  assert(var != NULL);
2038  assert(stat != NULL);
2039 
2040  /* weight the VSIDS by the given weight */
2041  weight *= stat->vsidsweight;
2042 
2043  if( SCIPsetIsZero(set, weight) )
2044  return SCIP_OKAY;
2045 
2046  branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
2047  SCIP_CALL( SCIPvarIncVSIDS(var, blkmem, set, stat, branchdir, value, weight) );
2048  SCIPhistoryIncVSIDS(stat->glbhistory, branchdir, weight);
2049  SCIPhistoryIncVSIDS(stat->glbhistorycrun, branchdir, weight);
2050 
2051  return SCIP_OKAY;
2052 }
2053 
2054 /** update conflict statistics */
2055 static
2057  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2058  BMS_BLKMEM* blkmem, /**< block memory */
2059  SCIP_SET* set, /**< global SCIP settings */
2060  SCIP_STAT* stat, /**< dynamic problem statistics */
2061  SCIP_CONFLICTSET* conflictset, /**< conflict set to add to the tree */
2062  int insertdepth /**< depth level at which the conflict set should be added */
2063  )
2064 {
2065  if( insertdepth > 0 )
2066  {
2067  conflict->nappliedlocconss++;
2068  conflict->nappliedlocliterals += conflictset->nbdchginfos;
2069  }
2070  else
2071  {
2072  int i;
2073  int conflictlength;
2074  conflictlength = conflictset->nbdchginfos;
2075 
2076  for( i = 0; i < conflictlength; i++ )
2077  {
2078  SCIP_VAR* var;
2079  SCIP_BRANCHDIR branchdir;
2080  SCIP_BOUNDTYPE boundtype;
2081  SCIP_Real bound;
2082 
2083  assert(stat != NULL);
2084 
2085  var = conflictset->bdchginfos[i]->var;
2086  boundtype = SCIPbdchginfoGetBoundtype(conflictset->bdchginfos[i]);
2087  bound = conflictset->relaxedbds[i];
2088 
2089  branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
2090 
2091  SCIP_CALL( SCIPvarIncNActiveConflicts(var, blkmem, set, stat, branchdir, bound, (SCIP_Real)conflictlength) );
2092  SCIPhistoryIncNActiveConflicts(stat->glbhistory, branchdir, (SCIP_Real)conflictlength);
2093  SCIPhistoryIncNActiveConflicts(stat->glbhistorycrun, branchdir, (SCIP_Real)conflictlength);
2094 
2095  /* each variable which is part of the conflict gets an increase in the VSIDS */
2096  SCIP_CALL( incVSIDS(var, blkmem, set, stat, boundtype, bound, set->conf_conflictweight) );
2097  }
2098  conflict->nappliedglbconss++;
2099  conflict->nappliedglbliterals += conflictset->nbdchginfos;
2100  }
2101 
2102  return SCIP_OKAY;
2103 }
2104 
2105 
2106 /** check conflict set for redundancy, other conflicts in the same conflict analysis could have led to global reductions
2107  * an made this conflict set redundant
2108  */
2109 static
2111  SCIP_SET* set, /**< global SCIP settings */
2112  SCIP_CONFLICTSET* conflictset /**< conflict set */
2113  )
2114 {
2115  SCIP_BDCHGINFO** bdchginfos;
2116  SCIP_VAR* var;
2117  SCIP_Real* relaxedbds;
2118  SCIP_Real bound;
2119  int v;
2120 
2121  assert(set != NULL);
2122  assert(conflictset != NULL);
2123 
2124  bdchginfos = conflictset->bdchginfos;
2125  relaxedbds = conflictset->relaxedbds;
2126  assert(bdchginfos != NULL);
2127  assert(relaxedbds != NULL);
2128 
2129  /* check all boundtypes and bounds for redundancy */
2130  for( v = conflictset->nbdchginfos - 1; v >= 0; --v )
2131  {
2132  var = SCIPbdchginfoGetVar(bdchginfos[v]);
2133  assert(var != NULL);
2134  assert(SCIPvarGetProbindex(var) >= 0);
2135 
2136  /* check if the relaxed bound is really a relaxed bound */
2137  assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
2138  assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
2139 
2140  bound = relaxedbds[v];
2141 
2142  if( SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_UPPER )
2143  {
2145  {
2146  assert(SCIPsetIsIntegral(set, bound));
2147  bound += 1.0;
2148  }
2149 
2150  /* check if the bound is already fulfilled globally */
2151  if( SCIPsetIsFeasGE(set, SCIPvarGetLbGlobal(var), bound) )
2152  return TRUE;
2153  }
2154  else
2155  {
2156  assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_LOWER);
2157 
2159  {
2160  assert(SCIPsetIsIntegral(set, bound));
2161  bound -= 1.0;
2162  }
2163 
2164  /* check if the bound is already fulfilled globally */
2165  if( SCIPsetIsFeasLE(set, SCIPvarGetUbGlobal(var), bound) )
2166  return TRUE;
2167  }
2168  }
2169 
2170  return FALSE;
2171 }
2172 
2173 /** find global fixings which can be derived from the new conflict set */
2174 static
2176  SCIP_SET* set, /**< global SCIP settings */
2177  SCIP_PROB* prob, /**< transformed problem after presolve */
2178  SCIP_CONFLICTSET* conflictset, /**< conflict set to add to the tree */
2179  int* nbdchgs, /**< number of global deducted bound changes due to the conflict set */
2180  int* nredvars, /**< number of redundant and removed variables from conflict set */
2181  SCIP_Bool* redundant /**< did we found a global reduction on a conflict set variable, which makes this conflict redundant */
2182  )
2183 {
2184  SCIP_BDCHGINFO** bdchginfos;
2185  SCIP_Real* relaxedbds;
2186  SCIP_VAR* var;
2187  SCIP_Bool* boundtypes;
2188  SCIP_Real* bounds;
2189  SCIP_Longint* nbinimpls;
2190  int* sortvals;
2191  SCIP_Real bound;
2192  SCIP_Bool isupper;
2193  int ntrivialredvars;
2194  int nbdchginfos;
2195  int nzeroimpls;
2196  int v;
2197 
2198  assert(set != NULL);
2199  assert(prob != NULL);
2200  assert(SCIPprobIsTransformed(prob));
2201  assert(conflictset != NULL);
2202  assert(nbdchgs != NULL);
2203  assert(nredvars != NULL);
2204  /* only check conflict sets with more than one variable */
2205  assert(conflictset->nbdchginfos > 1);
2206 
2207  *nbdchgs = 0;
2208  *nredvars = 0;
2209 
2210  /* due to other conflict in the same conflict analysis, this conflict set might have become redundant */
2211  *redundant = checkRedundancy(set, conflictset);
2212 
2213  if( *redundant )
2214  return SCIP_OKAY;
2215 
2216  bdchginfos = conflictset->bdchginfos;
2217  relaxedbds = conflictset->relaxedbds;
2218  nbdchginfos = conflictset->nbdchginfos;
2219  sortvals = conflictset->sortvals;
2220 
2221  assert(bdchginfos != NULL);
2222  assert(relaxedbds != NULL);
2223  assert(sortvals != NULL);
2224 
2225  /* check if the boolean representation of boundtypes matches the 'standard' definition */
2226  assert(SCIP_BOUNDTYPE_LOWER == FALSE); /*lint !e641*/
2227  assert(SCIP_BOUNDTYPE_UPPER == TRUE); /*lint !e641*/
2228 
2229  ntrivialredvars = 0;
2230 
2231  /* due to multiple conflict sets for one conflict, it can happen, that we already have redundant information in the
2232  * conflict set
2233  */
2234  for( v = nbdchginfos - 1; v >= 0; --v )
2235  {
2236  var = SCIPbdchginfoGetVar(bdchginfos[v]);
2237  bound = relaxedbds[v];
2238  isupper = (SCIP_Bool) SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(bdchginfos[v]));
2239 
2240  /* for integral variable we can increase/decrease the conflicting bound */
2241  if( SCIPvarIsIntegral(var) )
2242  bound += (isupper ? -1.0 : +1.0);
2243 
2244  /* if conflict variable cannot fulfill the conflict we can remove it */
2245  if( (isupper && SCIPsetIsFeasLT(set, bound, SCIPvarGetLbGlobal(var))) ||
2246  (!isupper && SCIPsetIsFeasGT(set, bound, SCIPvarGetUbGlobal(var))) )
2247  {
2248  SCIPsetDebugMsg(set, "remove redundant variable <%s> from conflict set\n", SCIPvarGetName(var));
2249 
2250  bdchginfos[v] = bdchginfos[nbdchginfos - 1];
2251  relaxedbds[v] = relaxedbds[nbdchginfos - 1];
2252  sortvals[v] = sortvals[nbdchginfos - 1];
2253 
2254  --nbdchginfos;
2255  ++ntrivialredvars;
2256  }
2257  }
2258  assert(ntrivialredvars + nbdchginfos == conflictset->nbdchginfos);
2259 
2260  SCIPsetDebugMsg(set, "trivially removed %d redundant of %d variables from conflictset (%p)\n", ntrivialredvars, conflictset->nbdchginfos, (void*)conflictset);
2261  conflictset->nbdchginfos = nbdchginfos;
2262 
2263  /* all variables where removed, the conflict cannot be fulfilled, i.e., we have an infeasibility proof */
2264  if( conflictset->nbdchginfos == 0 )
2265  return SCIP_OKAY;
2266 
2267  /* do not check to big or trivial conflicts */
2268  if( conflictset->nbdchginfos > set->conf_maxvarsdetectimpliedbounds || conflictset->nbdchginfos == 1 )
2269  {
2270  *nredvars = ntrivialredvars;
2271  return SCIP_OKAY;
2272  }
2273 
2274  /* create array of boundtypes, and bound values in conflict set */
2275  SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtypes, nbdchginfos) );
2276  SCIP_CALL( SCIPsetAllocBufferArray(set, &bounds, nbdchginfos) );
2277  /* memory for the estimates for binary implications used for sorting */
2278  SCIP_CALL( SCIPsetAllocBufferArray(set, &nbinimpls, nbdchginfos) );
2279 
2280  nzeroimpls = 0;
2281 
2282  /* collect estimates and initialize variables, boundtypes, and bounds array */
2283  for( v = 0; v < nbdchginfos; ++v )
2284  {
2285  var = SCIPbdchginfoGetVar(bdchginfos[v]);
2286  boundtypes[v] = (SCIP_Bool) SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(bdchginfos[v]));
2287  bounds[v] = relaxedbds[v];
2288 
2289  assert(SCIPvarGetProbindex(var) >= 0);
2290 
2291  /* check if the relaxed bound is really a relaxed bound */
2292  assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
2293  assert(SCIPbdchginfoGetBoundtype(bdchginfos[v]) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbds[v], SCIPbdchginfoGetNewbound(bdchginfos[v])));
2294 
2295  /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
2296  if( SCIPvarIsBinary(var) )
2297  {
2298  if( !boundtypes[v] )
2299  {
2300  assert(SCIPsetIsZero(set, bounds[v]));
2301  bounds[v] = 1.0;
2302  nbinimpls[v] = (SCIP_Longint)SCIPvarGetNCliques(var, TRUE) * 2;
2303  }
2304  else
2305  {
2306  assert(SCIPsetIsEQ(set, bounds[v], 1.0));
2307  bounds[v] = 0.0;
2308  nbinimpls[v] = (SCIP_Longint)SCIPvarGetNCliques(var, FALSE) * 2;
2309  }
2310  }
2311  else if( SCIPvarIsIntegral(var) )
2312  {
2313  assert(SCIPsetIsIntegral(set, bounds[v]));
2314 
2315  bounds[v] += ((!boundtypes[v]) ? +1.0 : -1.0);
2316  nbinimpls[v] = (boundtypes[v] ? SCIPvarGetNVlbs(var) : SCIPvarGetNVubs(var));
2317  }
2318  else if( ((!boundtypes[v]) && SCIPsetIsFeasEQ(set, SCIPvarGetLbGlobal(var), bounds[v]))
2319  || ((boundtypes[v]) && SCIPsetIsFeasEQ(set, SCIPvarGetUbGlobal(var), bounds[v])) )
2320  {
2321  /* the literal is satisfied in global bounds (may happen due to weak "negation" of continuous variables)
2322  * -> discard the conflict constraint
2323  */
2324  break;
2325  }
2326  else
2327  {
2328  nbinimpls[v] = (boundtypes[v] ? SCIPvarGetNVlbs(var) : SCIPvarGetNVubs(var));
2329  }
2330 
2331  if( nbinimpls[v] == 0 )
2332  ++nzeroimpls;
2333  }
2334 
2335  /* starting to derive global bound changes */
2336  if( v == nbdchginfos && ((!set->conf_fullshortenconflict && nzeroimpls < 2) || (set->conf_fullshortenconflict && nzeroimpls < nbdchginfos)) )
2337  {
2338  SCIP_VAR** vars;
2339  SCIP_Bool* redundants;
2340  SCIP_Bool glbinfeas;
2341 
2342  /* sort variables in increasing order of binary implications to gain speed later on */
2343  SCIPsortLongPtrRealRealBool(nbinimpls, (void**)bdchginfos, relaxedbds, bounds, boundtypes, v);
2344 
2345  SCIPsetDebugMsg(set, "checking for global reductions and redundant conflict variables(in %s) on conflict:\n", SCIPprobGetName(prob));
2346  SCIPsetDebugMsg(set, "[");
2347  for( v = 0; v < nbdchginfos; ++v )
2348  {
2349  SCIPsetDebugMsgPrint(set, "%s %s %g", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfos[v])), (!boundtypes[v]) ? ">=" : "<=", bounds[v]);
2350  if( v < nbdchginfos - 1 )
2351  SCIPsetDebugMsgPrint(set, ", ");
2352  }
2353  SCIPsetDebugMsgPrint(set, "]\n");
2354 
2355  SCIP_CALL( SCIPsetAllocBufferArray(set, &vars, v) );
2356  SCIP_CALL( SCIPsetAllocCleanBufferArray(set, &redundants, v) );
2357 
2358  /* initialize conflict variable data */
2359  for( v = 0; v < nbdchginfos; ++v )
2360  vars[v] = SCIPbdchginfoGetVar(bdchginfos[v]);
2361 
2362  SCIP_CALL( SCIPshrinkDisjunctiveVarSet(set->scip, vars, bounds, boundtypes, redundants, nbdchginfos, nredvars, \
2363  nbdchgs, redundant, &glbinfeas, set->conf_fullshortenconflict) );
2364 
2365  if( glbinfeas )
2366  {
2367  SCIPsetDebugMsg(set, "conflict set (%p) led to global infeasibility\n", (void*) conflictset);
2368  goto TERMINATE;
2369  }
2370 
2371 #ifdef SCIP_DEBUG
2372  if( *nbdchgs > 0 )
2373  {
2374  SCIPsetDebugMsg(set, "conflict set (%p) led to %d global bound reductions\n", (void*) conflictset, *nbdchgs);
2375  }
2376 #endif
2377 
2378  /* remove as redundant marked variables */
2379  if( *redundant )
2380  {
2381  SCIPsetDebugMsg(set, "conflict set (%p) is redundant because at least one global reduction, fulfills the conflict constraint\n", (void*)conflictset);
2382 
2383  BMSclearMemoryArray(redundants, nbdchginfos);
2384  }
2385  else if( *nredvars > 0 )
2386  {
2387  assert(bdchginfos == conflictset->bdchginfos);
2388  assert(relaxedbds == conflictset->relaxedbds);
2389  assert(sortvals == conflictset->sortvals);
2390 
2391  for( v = nbdchginfos - 1; v >= 0; --v )
2392  {
2393  /* if conflict variable was marked to be redundant remove it */
2394  if( redundants[v] )
2395  {
2396  SCIPsetDebugMsg(set, "remove redundant variable <%s> from conflict set\n", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfos[v])));
2397 
2398  bdchginfos[v] = bdchginfos[nbdchginfos - 1];
2399  relaxedbds[v] = relaxedbds[nbdchginfos - 1];
2400  sortvals[v] = sortvals[nbdchginfos - 1];
2401 
2402  /* reset redundants[v] to 0 */
2403  redundants[v] = 0;
2404 
2405  --nbdchginfos;
2406  }
2407  }
2408  assert((*nredvars) + nbdchginfos == conflictset->nbdchginfos);
2409 
2410  SCIPsetDebugMsg(set, "removed %d redundant of %d variables from conflictset (%p)\n", (*nredvars), conflictset->nbdchginfos, (void*)conflictset);
2411  conflictset->nbdchginfos = nbdchginfos;
2412  }
2413 
2414  TERMINATE:
2415  SCIPsetFreeCleanBufferArray(set, &redundants);
2416  SCIPsetFreeBufferArray(set, &vars);
2417  }
2418 
2419  /* free temporary memory */
2420  SCIPsetFreeBufferArray(set, &nbinimpls);
2421  SCIPsetFreeBufferArray(set, &bounds);
2422  SCIPsetFreeBufferArray(set, &boundtypes);
2423 
2424  *nredvars += ntrivialredvars;
2425 
2426  return SCIP_OKAY;
2427 }
2428 
2429 /** tighten the bound of a singleton variable in a constraint
2430  *
2431  * if the bound is contradicting with a global bound we cannot tighten the bound directly.
2432  * in this case we need to create and add a constraint of size one such that propagating this constraint will
2433  * enforce the infeasibility.
2434  */
2435 static
2437  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2438  SCIP_SET* set, /**< global SCIP settings */
2439  SCIP_STAT* stat, /**< dynamic SCIP statistics */
2440  SCIP_TREE* tree, /**< tree data */
2441  BMS_BLKMEM* blkmem, /**< block memory */
2442  SCIP_PROB* origprob, /**< original problem */
2443  SCIP_PROB* transprob, /**< transformed problem */
2444  SCIP_REOPT* reopt, /**< reoptimization data */
2445  SCIP_LP* lp, /**< LP data */
2446  SCIP_BRANCHCAND* branchcand, /**< branching candidates */
2447  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2448  SCIP_CLIQUETABLE* cliquetable, /**< clique table */
2449  SCIP_VAR* var, /**< problem variable */
2450  SCIP_Real val, /**< coefficient of the variable */
2451  SCIP_Real rhs, /**< rhs of the constraint */
2452  SCIP_CONFTYPE prooftype /**< type of the proof */
2453  )
2454 {
2455  SCIP_Real newbound;
2456  SCIP_BOUNDTYPE boundtype;
2457 
2458  assert(tree != NULL);
2459 
2460  /* if variable and coefficient are integral the rhs can be rounded down */
2461  if( SCIPvarIsIntegral(var) && SCIPsetIsIntegral(set, val) )
2462  {
2463  newbound = SCIPsetFeasFloor(set, rhs)/val;
2464  boundtype = (val > 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
2465  SCIPvarAdjustBd(var, set, boundtype, &newbound);
2466  }
2467  else
2468  {
2469  newbound = rhs/val;
2470  boundtype = (val > 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
2471  SCIPvarAdjustBd(var, set, boundtype, &newbound);
2472  }
2473 
2474  /* skip numerical unstable bound changes */
2475  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsLE(set, newbound, SCIPvarGetLbGlobal(var)))
2476  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsGE(set, newbound, SCIPvarGetUbGlobal(var))) )
2477  {
2478  return SCIP_OKAY;
2479  }
2480 
2481  /* the new bound contradicts a global bound, we can cutoff the root node immediately */
2482  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, SCIPvarGetUbGlobal(var)))
2483  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, SCIPvarGetLbGlobal(var))) )
2484  {
2485  SCIPsetDebugMsg(set, "detect global infeasibility at var <%s>: locdom=[%g,%g] glbdom=[%g,%g] new %s bound=%g\n",
2487  SCIPvarGetUbGlobal(var), (boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper"), newbound);
2488 
2489  SCIP_CALL( SCIPnodeCutoff(tree->path[0], set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
2490  }
2491  else
2492  {
2493  SCIPsetDebugMsg(set, "change %s bound of <%s>: %g -> %g\n", (boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper"),
2494  SCIPvarGetName(var), (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIPvarGetLbGlobal(var) : SCIPvarGetUbGlobal(var)),
2495  newbound);
2496 
2497  if( lp->strongbranching )
2498  {
2499  SCIP_CONS* cons;
2500  SCIP_Real conslhs;
2501  SCIP_Real consrhs;
2502  char name[SCIP_MAXSTRLEN];
2503 
2504  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "pc_fix_%s", SCIPvarGetName(var));
2505 
2506  if( boundtype == SCIP_BOUNDTYPE_UPPER )
2507  {
2508  conslhs = -SCIPsetInfinity(set);
2509  consrhs = newbound;
2510  }
2511  else
2512  {
2513  conslhs = newbound;
2514  consrhs = SCIPsetInfinity(set);
2515  }
2516 
2517  SCIP_CALL( SCIPcreateConsLinear(set->scip, &cons, name, 0, NULL, NULL, conslhs, consrhs,
2519 
2520  SCIP_CALL( SCIPaddCoefLinear(set->scip, cons, var, 1.0) );
2521 
2522  SCIP_CALL( SCIPprobAddCons(transprob, set, stat, cons) );
2523  SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
2524  }
2525  else
2526  {
2527  SCIP_CALL( SCIPnodeAddBoundchg(tree->root, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, \
2528  eventqueue, cliquetable, var, newbound, boundtype, FALSE) );
2529 
2530  /* mark the node in the repropdepth to be propagated again */
2531  SCIPnodePropagateAgain(tree->path[0], set, stat, tree);
2532  }
2533  }
2534 
2535  ++conflict->nglbchgbds;
2536 
2537  if( prooftype == SCIP_CONFTYPE_INFEASLP || prooftype == SCIP_CONFTYPE_ALTINFPROOF )
2538  {
2539  ++conflict->dualrayinfnnonzeros; /* we count a global bound reduction as size 1 */
2540  ++conflict->ndualrayinfsuccess;
2541  ++conflict->ndualrayinfglobal;
2542  ++conflict->ninflpsuccess;
2543  }
2544  else
2545  {
2546  ++conflict->dualraybndnnonzeros; /* we count a global bound reduction as size 1 */
2547  ++conflict->ndualraybndsuccess;
2548  ++conflict->ndualraybndglobal;
2549  ++conflict->nboundlpsuccess;
2550  }
2551 
2552  return SCIP_OKAY;
2553 }
2554 
2555 /** calculates the minimal activity of a given aggregation row */
2556 static
2558  SCIP_PROB* transprob, /**< transformed problem data */
2559  SCIP_AGGRROW* aggrrow, /**< aggregation row */
2560  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables (or NULL for global bounds) */
2561  SCIP_Real* curvarubs /**< current upper bounds of active problem variables (or NULL for global bounds) */
2562  )
2563 {
2564  SCIP_VAR** vars;
2565  SCIP_Real minact = 0.0;
2566  int* inds;
2567  int nnz;
2568  int i;
2569 
2570  vars = SCIPprobGetVars(transprob);
2571  assert(vars != NULL);
2572 
2573  nnz = SCIPaggrRowGetNNz(aggrrow);
2574  inds = SCIPaggrRowGetInds(aggrrow);
2575 
2576  for( i = 0; i < nnz; i++ )
2577  {
2578  SCIP_Real val;
2579  int v = inds[i];
2580 
2581  assert(SCIPvarGetProbindex(vars[v]) == v);
2582 
2583  val = SCIPaggrRowGetProbvarValue(aggrrow, v);
2584 
2585  /* calculate the minimal activity */
2586  if( val > 0.0 )
2587  minact += val * (curvarlbs == NULL ? SCIPvarGetLbGlobal(vars[v]) : curvarlbs[v]);
2588  else
2589  minact += val * (curvarubs == NULL ? SCIPvarGetUbGlobal(vars[v]) : curvarubs[v]);
2590  }
2591 
2592  return minact;
2593 }
2594 
2595 /** calculates the minimal activity of a given set of bounds and coefficients */
2596 static
2598  SCIP_PROB* transprob, /**< transformed problem data */
2599  SCIP_Real* coefs, /**< coefficients in sparse representation */
2600  int* inds, /**< non-zero indices */
2601  int nnz, /**< number of non-zero indices */
2602  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables (or NULL for global bounds) */
2603  SCIP_Real* curvarubs /**< current upper bounds of active problem variables (or NULL for global bounds) */
2604  )
2605 {
2606  SCIP_VAR** vars;
2607  SCIP_Real minact = 0.0;
2608  int i;
2609 
2610  assert(coefs != NULL);
2611  assert(inds != NULL);
2612 
2613  vars = SCIPprobGetVars(transprob);
2614  assert(vars != NULL);
2615 
2616  for( i = 0; i < nnz; i++ )
2617  {
2618  SCIP_Real val;
2619  int v = inds[i];
2620 
2621  assert(SCIPvarGetProbindex(vars[v]) == v);
2622 
2623  val = coefs[i];
2624 
2625  /* calculate the minimal activity */
2626  if( val > 0.0 )
2627  minact += val * (curvarlbs == NULL ? SCIPvarGetLbGlobal(vars[v]) : curvarlbs[v]);
2628  else
2629  minact += val * (curvarubs == NULL ? SCIPvarGetUbGlobal(vars[v]) : curvarubs[v]);
2630  }
2631 
2632  return minact;
2633 }
2634 
2635 /** calculates the minimal activity of a given set of bounds and coefficients */
2636 static
2638  SCIP_PROB* transprob, /**< transformed problem data */
2639  SCIP_Real* coefs, /**< coefficients in sparse representation */
2640  int* inds, /**< non-zero indices */
2641  int nnz, /**< number of non-zero indices */
2642  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables (or NULL for global bounds) */
2643  SCIP_Real* curvarubs /**< current upper bounds of active problem variables (or NULL for global bounds) */
2644  )
2645 {
2646  SCIP_VAR** vars;
2647  SCIP_Real maxact = 0.0;
2648  int i;
2649 
2650  assert(coefs != NULL);
2651  assert(inds != NULL);
2652 
2653  vars = SCIPprobGetVars(transprob);
2654  assert(vars != NULL);
2655 
2656  for( i = 0; i < nnz; i++ )
2657  {
2658  SCIP_Real val;
2659  int v = inds[i];
2660 
2661  assert(SCIPvarGetProbindex(vars[v]) == v);
2662 
2663  val = coefs[i];
2664 
2665  /* calculate the minimal activity */
2666  if( val < 0.0 )
2667  maxact += val * (curvarlbs == NULL ? SCIPvarGetLbGlobal(vars[v]) : curvarlbs[v]);
2668  else
2669  maxact += val * (curvarubs == NULL ? SCIPvarGetUbGlobal(vars[v]) : curvarubs[v]);
2670  }
2671 
2672  return maxact;
2673 }
2674 
2675 static
2677  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2678  SCIP_SET* set, /**< global SCIP settings */
2679  SCIP_STAT* stat, /**< dynamic SCIP statistics */
2680  SCIP_REOPT* reopt, /**< reoptimization data */
2681  SCIP_TREE* tree, /**< tree data */
2682  BMS_BLKMEM* blkmem, /**< block memory */
2683  SCIP_PROB* origprob, /**< original problem */
2684  SCIP_PROB* transprob, /**< transformed problem */
2685  SCIP_LP* lp, /**< LP data */
2686  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2687  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2688  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2689  SCIP_Real* coefs, /**< coefficients in sparse representation */
2690  int* inds, /**< non-zero indices */
2691  int nnz, /**< number of non-zero indices */
2692  SCIP_Real rhs, /**< right-hand side */
2693  SCIP_CONFTYPE conflicttype /**< type of the conflict */
2694  )
2695 {
2696  SCIP_VAR** vars;
2697  SCIP_Real minact;
2698  int i;
2699 
2700  assert(coefs != NULL);
2701  assert(inds != NULL);
2702  assert(nnz >= 0);
2703 
2704  vars = SCIPprobGetVars(transprob);
2705  minact = getMinActivity(transprob, coefs, inds, nnz, NULL, NULL);
2706 
2707  for( i = 0; i < nnz; i++ )
2708  {
2709  SCIP_VAR* var;
2710  SCIP_Real val;
2711  SCIP_Real resminact;
2712  SCIP_Real lb;
2713  SCIP_Real ub;
2714  int pos;
2715 
2716  pos = inds[i];
2717  val = coefs[i];
2718  var = vars[pos];
2719  lb = SCIPvarGetLbGlobal(var);
2720  ub = SCIPvarGetUbGlobal(var);
2721 
2722  assert(!SCIPsetIsZero(set, val));
2723 
2724  resminact = minact;
2725 
2726  /* we got a potential new upper bound */
2727  if( val > 0.0 )
2728  {
2729  SCIP_Real newub;
2730 
2731  resminact -= (val * lb);
2732  newub = (rhs - resminact)/val;
2733 
2734  if( SCIPsetIsInfinity(set, newub) )
2735  continue;
2736 
2737  /* we cannot tighten the upper bound */
2738  if( SCIPsetIsGE(set, newub, ub) )
2739  continue;
2740 
2741  SCIP_CALL( tightenSingleVar(conflict, set, stat, tree, blkmem, origprob, transprob, reopt, lp, branchcand, \
2742  eventqueue, cliquetable, var, val, rhs-resminact, conflicttype) );
2743  }
2744  /* we got a potential new lower bound */
2745  else
2746  {
2747  SCIP_Real newlb;
2748 
2749  resminact -= (val * ub);
2750  newlb = (rhs - resminact)/val;
2751 
2752  if( SCIPsetIsInfinity(set, -newlb) )
2753  continue;
2754 
2755  /* we cannot tighten the lower bound */
2756  if( SCIPsetIsLE(set, newlb, lb) )
2757  continue;
2758 
2759  SCIP_CALL( tightenSingleVar(conflict, set, stat, tree, blkmem, origprob, transprob, reopt, lp, branchcand, \
2760  eventqueue, cliquetable, var, val, rhs-resminact, conflicttype) );
2761  }
2762 
2763  /* the minimal activity should stay unchanged because we tightened the bound that doesn't contribute to the
2764  * minimal activity
2765  */
2766  assert(SCIPsetIsEQ(set, minact, getMinActivity(transprob, coefs, inds, nnz, NULL, NULL)));
2767  }
2768 
2769  return SCIP_OKAY;
2770 }
2771 
2772 
2773 /** creates a proof constraint and tries to add it to the storage */
2774 static
2776  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2777  SCIP_CONFLICTSTORE* conflictstore, /**< conflict pool data */
2778  SCIP_PROOFSET* proofset, /**< proof set */
2779  SCIP_SET* set, /**< global SCIP settings */
2780  SCIP_STAT* stat, /**< dynamic SCIP statistics */
2781  SCIP_PROB* origprob, /**< original problem */
2782  SCIP_PROB* transprob, /**< transformed problem */
2783  SCIP_TREE* tree, /**< tree data */
2784  SCIP_REOPT* reopt, /**< reoptimization data */
2785  SCIP_LP* lp, /**< LP data */
2786  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2787  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2788  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2789  BMS_BLKMEM* blkmem /**< block memory */
2790  )
2791 {
2792  SCIP_CONS* cons;
2793  SCIP_CONS* upgdcons;
2794  SCIP_VAR** vars;
2795  SCIP_Real* coefs;
2796  int* inds;
2797  SCIP_Real rhs;
2798  SCIP_Real fillin;
2799  SCIP_Real globalminactivity;
2800  SCIP_Bool toolong;
2801  SCIP_CONFTYPE conflicttype;
2802  char name[SCIP_MAXSTRLEN];
2803  int nnz;
2804  int i;
2805 
2806  assert(conflict != NULL);
2807  assert(conflictstore != NULL);
2808  assert(proofset != NULL);
2809 
2810  nnz = proofsetGetNVars(proofset);
2811 
2812  if( nnz == 0 )
2813  return SCIP_OKAY;
2814 
2815  vars = SCIPprobGetVars(transprob);
2816 
2817  rhs = proofsetGetRhs(proofset);
2818  assert(!SCIPsetIsInfinity(set, rhs));
2819 
2820  coefs = proofsetGetVals(proofset);
2821  assert(coefs != NULL);
2822 
2823  inds = proofsetGetInds(proofset);
2824  assert(inds != NULL);
2825 
2826  conflicttype = proofsetGetConftype(proofset);
2827 
2828  if( conflicttype == SCIP_CONFTYPE_ALTINFPROOF || conflicttype == SCIP_CONFTYPE_ALTBNDPROOF )
2829  {
2830  SCIP_Real globalmaxactivity = getMaxActivity(transprob, coefs, inds, nnz, NULL, NULL);
2831 
2832  /* check whether the alternative proof is redundant */
2833  if( SCIPsetIsLE(set, globalmaxactivity, rhs) )
2834  return SCIP_OKAY;
2835  }
2836 
2837  /* check whether the constraint proves global infeasibility */
2838  globalminactivity = getMinActivity(transprob, coefs, inds, nnz, NULL, NULL);
2839  if( SCIPsetIsGT(set, globalminactivity, rhs) )
2840  {
2841  SCIPsetDebugMsg(set, "detect global infeasibility: minactivity=%g, rhs=%g\n", globalminactivity, rhs);
2842 
2843  SCIP_CALL( SCIPnodeCutoff(tree->path[0], set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
2844 
2845  goto UPDATESTATISTICS;
2846  }
2847 
2848  if( set->conf_minmaxvars >= nnz )
2849  toolong = FALSE;
2850  else
2851  {
2852  SCIP_Real maxnnz;
2853 
2854  if( transprob->startnconss < 100 )
2855  maxnnz = 0.85 * transprob->nvars;
2856  else
2857  maxnnz = (SCIP_Real)transprob->nvars;
2858 
2859  fillin = nnz;
2860  if( conflicttype == SCIP_CONFTYPE_INFEASLP || conflicttype == SCIP_CONFTYPE_ALTINFPROOF )
2861  {
2862  fillin += SCIPconflictstoreGetNDualInfProofs(conflictstore) * SCIPconflictstoreGetAvgNnzDualInfProofs(conflictstore);
2863  fillin /= (SCIPconflictstoreGetNDualInfProofs(conflictstore) + 1.0);
2864  toolong = (fillin > MIN(2.0 * stat->avgnnz, maxnnz));
2865  }
2866  else
2867  {
2868  assert(conflicttype == SCIP_CONFTYPE_BNDEXCEEDING || conflicttype == SCIP_CONFTYPE_ALTBNDPROOF);
2869 
2870  fillin += SCIPconflictstoreGetNDualBndProofs(conflictstore) * SCIPconflictstoreGetAvgNnzDualBndProofs(conflictstore);
2871  fillin /= (SCIPconflictstoreGetNDualBndProofs(conflictstore) + 1.0);
2872  toolong = (fillin > MIN(1.5 * stat->avgnnz, maxnnz));
2873  }
2874 
2875  toolong = (toolong && (nnz > set->conf_maxvarsfac * transprob->nvars));
2876  }
2877 
2878  /* don't store global dual proofs that are to long / have to much non-zeros */
2879  if( toolong )
2880  {
2881  SCIP_CALL( propagateLongProof(conflict, set, stat, reopt, tree, blkmem, origprob, transprob, lp, branchcand,
2882  eventqueue, cliquetable, coefs, inds, nnz, rhs, conflicttype) );
2883  return SCIP_OKAY;
2884  }
2885 
2886  if( conflicttype == SCIP_CONFTYPE_INFEASLP || conflicttype == SCIP_CONFTYPE_ALTINFPROOF )
2887  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "dualproof_inf_%d", conflict->ndualrayinfsuccess);
2888  else if( conflicttype == SCIP_CONFTYPE_BNDEXCEEDING || conflicttype == SCIP_CONFTYPE_ALTBNDPROOF )
2889  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "dualproof_bnd_%d", conflict->ndualraybndsuccess);
2890  else
2891  return SCIP_INVALIDCALL;
2892 
2893  SCIP_CALL( SCIPcreateConsLinear(set->scip, &cons, name, 0, NULL, NULL, -SCIPsetInfinity(set), rhs,
2895 
2896  for( i = 0; i < nnz; i++ )
2897  {
2898  int v = inds[i];
2899  SCIP_CALL( SCIPaddCoefLinear(set->scip, cons, vars[v], coefs[i]) );
2900  }
2901 
2902  /* do not upgrade linear constraints of size 1 */
2903  if( nnz > 1 )
2904  {
2905  upgdcons = NULL;
2906  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
2907  SCIP_CALL( SCIPupgradeConsLinear(set->scip, cons, &upgdcons) );
2908  if( upgdcons != NULL )
2909  {
2910  SCIP_CALL( SCIPreleaseCons(set->scip, &cons) );
2911  cons = upgdcons;
2912 
2913  if( conflicttype == SCIP_CONFTYPE_INFEASLP )
2914  conflicttype = SCIP_CONFTYPE_ALTINFPROOF;
2915  else if( conflicttype == SCIP_CONFTYPE_BNDEXCEEDING )
2916  conflicttype = SCIP_CONFTYPE_ALTBNDPROOF;
2917  }
2918  }
2919 
2920  /* mark constraint to be a conflict */
2921  SCIPconsMarkConflict(cons);
2922 
2923  /* add constraint to storage */
2924  if( conflicttype == SCIP_CONFTYPE_INFEASLP || conflicttype == SCIP_CONFTYPE_ALTINFPROOF )
2925  {
2926  /* add constraint based on dual ray to storage */
2927  SCIP_CALL( SCIPconflictstoreAddDualraycons(conflictstore, cons, blkmem, set, stat, transprob, reopt) );
2928  }
2929  else
2930  {
2931  SCIP_Real scale = 1.0;
2932  SCIP_Bool updateside = FALSE;
2933 
2934  /* In some cases the constraint could not be updated to a more special type. However, it is possible that
2935  * constraint got scaled. Therefore, we need to be very careful when updating the lhs/rhs after the incumbent
2936  * solution has improved.
2937  */
2938  if( conflicttype == SCIP_CONFTYPE_BNDEXCEEDING )
2939  {
2940  SCIP_Real side;
2941 
2942 #ifndef NDEBUG
2943  SCIP_CONSHDLR* conshdlr = SCIPconsGetHdlr(cons);
2944 
2945  assert(conshdlr != NULL);
2946  assert(strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0);
2947 #endif
2948  side = SCIPgetLhsLinear(set->scip, cons);
2949 
2950  if( !SCIPsetIsInfinity(set, -side) )
2951  {
2952  if( SCIPsetIsZero(set, side) )
2953  {
2954  scale = 1.0;
2955  }
2956  else
2957  {
2958  scale = proofsetGetRhs(proofset) / side;
2959  assert(SCIPsetIsNegative(set, scale));
2960  }
2961  }
2962  else
2963  {
2964  side = SCIPgetRhsLinear(set->scip, cons);
2965  assert(!SCIPsetIsInfinity(set, side));
2966 
2967  if( SCIPsetIsZero(set, side) )
2968  {
2969  scale = 1.0;
2970  }
2971  else
2972  {
2973  scale = proofsetGetRhs(proofset) / side;
2974  assert(SCIPsetIsPositive(set, scale));
2975  }
2976  }
2977  updateside = TRUE;
2978  }
2979 
2980  /* add constraint based on dual solution to storage */
2981  SCIP_CALL( SCIPconflictstoreAddDualsolcons(conflictstore, cons, blkmem, set, stat, transprob, reopt, scale, updateside) );
2982  }
2983 
2984  /* add the constraint to the global problem */
2985  SCIP_CALL( SCIPprobAddCons(transprob, set, stat, cons) );
2986 
2987  SCIPsetDebugMsg(set, "added proof-constraint to node %p in depth 0 (nproofconss %d)\n", (void*)tree->path[0],
2988  SCIPconflictstoreGetNDualInfProofs(conflictstore));
2989 
2990  /* release the constraint */
2991  SCIP_CALL( SCIPreleaseCons(set->scip, &cons) );
2992 
2993  UPDATESTATISTICS:
2994  /* update statistics */
2995  if( conflicttype == SCIP_CONFTYPE_INFEASLP || conflicttype == SCIP_CONFTYPE_ALTINFPROOF )
2996  {
2997  conflict->dualrayinfnnonzeros += nnz;
2998  ++conflict->ndualrayinfglobal;
2999  ++conflict->ndualrayinfsuccess;
3000  }
3001  else
3002  {
3003  assert(conflicttype == SCIP_CONFTYPE_BNDEXCEEDING || conflicttype == SCIP_CONFTYPE_ALTBNDPROOF);
3004  conflict->dualraybndnnonzeros += nnz;
3005  ++conflict->ndualraybndglobal;
3006  ++conflict->ndualraybndsuccess;
3007  }
3008  return SCIP_OKAY;
3009 }
3010 
3011 /* create proof constraints out of proof sets */
3012 static
3014  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3015  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
3016  BMS_BLKMEM* blkmem, /**< block memory */
3017  SCIP_SET* set, /**< global SCIP settings */
3018  SCIP_STAT* stat, /**< dynamic problem statistics */
3019  SCIP_PROB* transprob, /**< transformed problem after presolve */
3020  SCIP_PROB* origprob, /**< original problem */
3021  SCIP_TREE* tree, /**< branch and bound tree */
3022  SCIP_REOPT* reopt, /**< reoptimization data structure */
3023  SCIP_LP* lp, /**< current LP data */
3024  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3025  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3026  SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
3027  )
3028 {
3029  assert(conflict != NULL);
3030 
3032  {
3033  /* only one variable has a coefficient different to zero, we add this bound change instead of a constraint */
3034  if( proofsetGetNVars(conflict->proofset) == 1 )
3035  {
3036  SCIP_VAR** vars;
3037  SCIP_Real* coefs;
3038  int* inds;
3039  SCIP_Real rhs;
3040 
3041  vars = SCIPprobGetVars(transprob);
3042 
3043  coefs = proofsetGetVals(conflict->proofset);
3044  inds = proofsetGetInds(conflict->proofset);
3045  rhs = proofsetGetRhs(conflict->proofset);
3046 
3047  SCIP_CALL( tightenSingleVar(conflict, set, stat, tree, blkmem, origprob, transprob, reopt, lp, \
3048  branchcand, eventqueue, cliquetable, vars[inds[0]], coefs[0], rhs, conflict->proofset->conflicttype) );
3049  }
3050  else
3051  {
3052  SCIP_Bool skipinitialproof = FALSE;
3053 
3054  /* prefer an infeasibility proof
3055  *
3056  * todo: check whether this is really what we want
3057  */
3058  if( set->conf_prefinfproof && proofsetGetConftype(conflict->proofset) == SCIP_CONFTYPE_BNDEXCEEDING )
3059  {
3060  int i;
3061 
3062  for( i = 0; i < conflict->nproofsets; i++ )
3063  {
3065  {
3066  skipinitialproof = TRUE;
3067  break;
3068  }
3069  }
3070  }
3071 
3072  if( !skipinitialproof )
3073  {
3074  /* create and add the original proof */
3075  SCIP_CALL( createAndAddProofcons(conflict, conflictstore, conflict->proofset, set, stat, origprob, transprob, \
3076  tree, reopt, lp, branchcand, eventqueue, cliquetable, blkmem) );
3077  }
3078  }
3079 
3080  /* clear the proof set anyway */
3081  proofsetClear(conflict->proofset);
3082  }
3083 
3084  if( conflict->nproofsets > 0 )
3085  {
3086  int i;
3087 
3088  for( i = 0; i < conflict->nproofsets; i++ )
3089  {
3090  assert(conflict->proofsets[i] != NULL);
3091  assert(proofsetGetConftype(conflict->proofsets[i]) != SCIP_CONFTYPE_UNKNOWN);
3092 
3093  /* only one variable has a coefficient different to zero, we add this bound change instead of a constraint */
3094  if( proofsetGetNVars(conflict->proofsets[i]) == 1 )
3095  {
3096  SCIP_VAR** vars;
3097  SCIP_Real* coefs;
3098  int* inds;
3099  SCIP_Real rhs;
3100 
3101  vars = SCIPprobGetVars(transprob);
3102 
3103  coefs = proofsetGetVals(conflict->proofsets[i]);
3104  inds = proofsetGetInds(conflict->proofsets[i]);
3105  rhs = proofsetGetRhs(conflict->proofsets[i]);
3106 
3107  SCIP_CALL( tightenSingleVar(conflict, set, stat, tree, blkmem, origprob, transprob, reopt, lp,
3108  branchcand, eventqueue, cliquetable, vars[inds[0]], coefs[0], rhs,
3109  conflict->proofsets[i]->conflicttype) );
3110  }
3111  else
3112  {
3113  /* create and add proof constraint */
3114  SCIP_CALL( createAndAddProofcons(conflict, conflictstore, conflict->proofsets[i], set, stat, origprob, \
3115  transprob, tree, reopt, lp, branchcand, eventqueue, cliquetable, blkmem) );
3116  }
3117  }
3118 
3119  /* free all proofsets */
3120  for( i = 0; i < conflict->nproofsets; i++ )
3121  proofsetFree(&conflict->proofsets[i], blkmem);
3122 
3123  conflict->nproofsets = 0;
3124  }
3125 
3126  return SCIP_OKAY;
3127 }
3128 
3129 /** adds the given conflict set as conflict constraint to the problem */
3130 static
3132  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3133  BMS_BLKMEM* blkmem, /**< block memory */
3134  SCIP_SET* set, /**< global SCIP settings */
3135  SCIP_STAT* stat, /**< dynamic problem statistics */
3136  SCIP_PROB* transprob, /**< transformed problem after presolve */
3137  SCIP_PROB* origprob, /**< original problem */
3138  SCIP_TREE* tree, /**< branch and bound tree */
3139  SCIP_REOPT* reopt, /**< reoptimization data structure */
3140  SCIP_LP* lp, /**< current LP data */
3141  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3142  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3143  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3144  SCIP_CONFLICTSET* conflictset, /**< conflict set to add to the tree */
3145  int insertdepth, /**< depth level at which the conflict set should be added */
3146  SCIP_Bool* success /**< pointer to store whether the addition was successful */
3147  )
3148 {
3149  SCIP_Bool redundant;
3150  int h;
3151 
3152  assert(conflict != NULL);
3153  assert(tree != NULL);
3154  assert(tree->path != NULL);
3155  assert(conflictset != NULL);
3156  assert(conflictset->validdepth <= insertdepth);
3157  assert(success != NULL);
3158 
3159  *success = FALSE;
3160  redundant = FALSE;
3161 
3162  /* try to derive global bound changes and shorten the conflictset by using implication and clique and variable bound
3163  * information
3164  */
3165  if( conflictset->nbdchginfos > 1 && insertdepth == 0 && !lp->strongbranching )
3166  {
3167  int nbdchgs;
3168  int nredvars;
3169 #ifdef SCIP_DEBUG
3170  int oldnbdchginfos = conflictset->nbdchginfos;
3171 #endif
3172  assert(conflictset->validdepth == 0);
3173 
3174  SCIPclockStart(conflict->dIBclock, set);
3175 
3176  /* find global bound changes which can be derived from the new conflict set */
3177  SCIP_CALL( detectImpliedBounds(set, transprob, conflictset, &nbdchgs, &nredvars, &redundant) );
3178 
3179  /* all variables where removed, we have an infeasibility proof */
3180  if( conflictset->nbdchginfos == 0 )
3181  return SCIP_OKAY;
3182 
3183  /* debug check for reduced conflict set */
3184  if( nredvars > 0 )
3185  {
3186  /* check conflict set on debugging solution */
3187  SCIP_CALL( SCIPdebugCheckConflict(blkmem, set, tree->root, conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos) ); /*lint !e506 !e774*/
3188  }
3189 
3190 #ifdef SCIP_DEBUG
3191  SCIPsetDebugMsg(set, " -> conflict set removed %d redundant variables (old nvars %d, new nvars = %d)\n", nredvars, oldnbdchginfos, conflictset->nbdchginfos);
3192  SCIPsetDebugMsg(set, " -> conflict set led to %d global bound changes %s(cdpt:%d, fdpt:%d, confdpt:%d, len:%d):\n",
3193  nbdchgs, redundant ? "(conflict became redundant) " : "", SCIPtreeGetCurrentDepth(tree), SCIPtreeGetFocusDepth(tree),
3194  conflictset->conflictdepth, conflictset->nbdchginfos);
3195  conflictsetPrint(conflictset);
3196 #endif
3197 
3198  SCIPclockStop(conflict->dIBclock, set);
3199 
3200  if( redundant )
3201  {
3202  if( nbdchgs > 0 )
3203  *success = TRUE;
3204 
3205  return SCIP_OKAY;
3206  }
3207  }
3208 
3209  /* in case the conflict set contains only one bound change which is globally valid we apply that bound change
3210  * directly (except if we are in strong branching or diving - in this case a bound change would yield an unflushed LP
3211  * and is not handled when restoring the information)
3212  *
3213  * @note A bound change can only be applied if it is are related to the active node or if is a global bound
3214  * change. Bound changes which are related to any other node cannot be handled at point due to the internal
3215  * data structure
3216  */
3217  if( conflictset->nbdchginfos == 1 && insertdepth == 0 && !lp->strongbranching && !lp->diving )
3218  {
3219  SCIP_VAR* var;
3220  SCIP_Real bound;
3221  SCIP_BOUNDTYPE boundtype;
3222 
3223  var = conflictset->bdchginfos[0]->var;
3224  assert(var != NULL);
3225 
3226  boundtype = SCIPboundtypeOpposite((SCIP_BOUNDTYPE) conflictset->bdchginfos[0]->boundtype);
3227  bound = conflictset->relaxedbds[0];
3228 
3229  /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
3230  if( SCIPvarIsIntegral(var) )
3231  {
3232  assert(SCIPsetIsIntegral(set, bound));
3233  bound += (boundtype == SCIP_BOUNDTYPE_LOWER ? +1.0 : -1.0);
3234  }
3235 
3236  SCIPsetDebugMsg(set, " -> apply global bound change: <%s> %s %g\n",
3237  SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", bound);
3238 
3239  SCIP_CALL( SCIPnodeAddBoundchg(tree->path[conflictset->validdepth], blkmem, set, stat, transprob, origprob, tree,
3240  reopt, lp, branchcand, eventqueue, cliquetable, var, bound, boundtype, FALSE) );
3241 
3242  *success = TRUE;
3243  SCIP_CALL( updateStatistics(conflict, blkmem, set, stat, conflictset, insertdepth) );
3244  }
3245  else
3246  {
3247  /* sort conflict handlers by priority */
3249 
3250  /* call conflict handlers to create a conflict constraint */
3251  for( h = 0; h < set->nconflicthdlrs; ++h )
3252  {
3253  SCIP_RESULT result;
3254 
3255  assert(conflictset->conflicttype != SCIP_CONFTYPE_UNKNOWN);
3256 
3257  SCIP_CALL( SCIPconflicthdlrExec(set->conflicthdlrs[h], set, tree->path[insertdepth],
3258  tree->path[conflictset->validdepth], conflictset->bdchginfos, conflictset->relaxedbds,
3259  conflictset->nbdchginfos, conflictset->conflicttype, conflictset->usescutoffbound, *success, &result) );
3260  if( result == SCIP_CONSADDED )
3261  {
3262  *success = TRUE;
3263  SCIP_CALL( updateStatistics(conflict, blkmem, set, stat, conflictset, insertdepth) );
3264  }
3265 
3266  SCIPsetDebugMsg(set, " -> call conflict handler <%s> (prio=%d) to create conflict set with %d bounds returned result %d\n",
3267  SCIPconflicthdlrGetName(set->conflicthdlrs[h]), SCIPconflicthdlrGetPriority(set->conflicthdlrs[h]),
3268  conflictset->nbdchginfos, result);
3269  }
3270  }
3271 
3272  return SCIP_OKAY;
3273 }
3274 
3275 /** adds the collected conflict constraints to the corresponding nodes; the best set->conf_maxconss conflict constraints
3276  * are added to the node of their validdepth; additionally (if not yet added, and if repropagation is activated), the
3277  * conflict constraint that triggers the earliest repropagation is added to the node of its validdepth
3278  */
3280  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3281  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3282  SCIP_SET* set, /**< global SCIP settings */
3283  SCIP_STAT* stat, /**< dynamic problem statistics */
3284  SCIP_PROB* transprob, /**< transformed problem */
3285  SCIP_PROB* origprob, /**< original problem */
3286  SCIP_TREE* tree, /**< branch and bound tree */
3287  SCIP_REOPT* reopt, /**< reoptimization data structure */
3288  SCIP_LP* lp, /**< current LP data */
3289  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3290  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3291  SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
3292  )
3293 {
3294  assert(conflict != NULL);
3295  assert(set != NULL);
3296  assert(stat != NULL);
3297  assert(transprob != NULL);
3298  assert(tree != NULL);
3299 
3300  /* is there anything to do? */
3301  if( conflict->nconflictsets > 0 )
3302  {
3303  SCIP_CONFLICTSET* repropconflictset;
3304  int nconflictsetsused;
3305  int focusdepth;
3306 #ifndef NDEBUG
3307  int currentdepth;
3308 #endif
3309  int cutoffdepth;
3310  int repropdepth;
3311  int maxconflictsets;
3312  int maxsize;
3313  int i;
3314 
3315  /* calculate the maximal number of conflict sets to accept, and the maximal size of each accepted conflict set */
3316  maxconflictsets = (set->conf_maxconss == -1 ? INT_MAX : set->conf_maxconss);
3317  maxsize = conflictCalcMaxsize(set, transprob);
3318 
3319  focusdepth = SCIPtreeGetFocusDepth(tree);
3320 #ifndef NDEBUG
3321  currentdepth = SCIPtreeGetCurrentDepth(tree);
3322  assert(focusdepth <= currentdepth);
3323  assert(currentdepth == tree->pathlen-1);
3324 #endif
3325 
3326  SCIPsetDebugMsg(set, "flushing %d conflict sets at focus depth %d (maxconflictsets: %d, maxsize: %d)\n",
3327  conflict->nconflictsets, focusdepth, maxconflictsets, maxsize);
3328 
3329  /* mark the focus node to have produced conflict sets in the visualization output */
3330  SCIPvisualFoundConflict(stat->visual, stat, tree->path[focusdepth]);
3331 
3332  /* insert the conflict sets at the corresponding nodes */
3333  nconflictsetsused = 0;
3334  cutoffdepth = INT_MAX;
3335  repropdepth = INT_MAX;
3336  repropconflictset = NULL;
3337  for( i = 0; i < conflict->nconflictsets && nconflictsetsused < maxconflictsets; ++i )
3338  {
3339  SCIP_CONFLICTSET* conflictset;
3340 
3341  conflictset = conflict->conflictsets[i];
3342  assert(conflictset != NULL);
3343  assert(0 <= conflictset->validdepth);
3344  assert(conflictset->validdepth <= conflictset->insertdepth);
3345  assert(conflictset->insertdepth <= focusdepth);
3346  assert(conflictset->insertdepth <= conflictset->repropdepth);
3347  assert(conflictset->repropdepth <= currentdepth || conflictset->repropdepth == INT_MAX); /* INT_MAX for dive/probing/strong */
3348  assert(conflictset->conflictdepth <= currentdepth || conflictset->conflictdepth == INT_MAX); /* INT_MAX for dive/probing/strong */
3349 
3350  /* ignore conflict sets that are only valid at a node that was already cut off */
3351  if( conflictset->insertdepth >= cutoffdepth )
3352  {
3353  SCIPsetDebugMsg(set, " -> ignoring conflict set with insertdepth %d >= cutoffdepth %d\n",
3354  conflictset->validdepth, cutoffdepth);
3355  continue;
3356  }
3357 
3358  /* if no conflict bounds exist, the node and its sub tree in the conflict set's valid depth can be
3359  * cut off completely
3360  */
3361  if( conflictset->nbdchginfos == 0 )
3362  {
3363  SCIPsetDebugMsg(set, " -> empty conflict set in depth %d cuts off sub tree at depth %d\n",
3364  focusdepth, conflictset->validdepth);
3365 
3366  SCIP_CALL( SCIPnodeCutoff(tree->path[conflictset->validdepth], set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
3367  cutoffdepth = conflictset->validdepth;
3368  continue;
3369  }
3370 
3371  /* if the conflict set is too long, use the conflict set only if it decreases the repropagation depth */
3372  if( conflictset->nbdchginfos > maxsize )
3373  {
3374  SCIPsetDebugMsg(set, " -> conflict set is too long: %d > %d literals\n", conflictset->nbdchginfos, maxsize);
3375  if( set->conf_keepreprop && conflictset->repropagate && conflictset->repropdepth < repropdepth )
3376  {
3377  repropdepth = conflictset->repropdepth;
3378  repropconflictset = conflictset;
3379  }
3380  }
3381  else
3382  {
3383  SCIP_Bool success;
3384 
3385  /* call conflict handlers to create a conflict constraint */
3386  SCIP_CALL( conflictAddConflictCons(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, \
3387  branchcand, eventqueue, cliquetable, conflictset, conflictset->insertdepth, &success) );
3388 
3389  /* if no conflict bounds exist, the node and its sub tree in the conflict set's valid depth can be
3390  * cut off completely
3391  */
3392  if( conflictset->nbdchginfos == 0 )
3393  {
3394  assert(!success);
3395 
3396  SCIPsetDebugMsg(set, " -> empty conflict set in depth %d cuts off sub tree at depth %d\n",
3397  focusdepth, conflictset->validdepth);
3398 
3399  SCIP_CALL( SCIPnodeCutoff(tree->path[conflictset->validdepth], set, stat, tree, transprob, origprob, \
3400  reopt, lp, blkmem) );
3401  cutoffdepth = conflictset->validdepth;
3402  continue;
3403  }
3404 
3405  if( success )
3406  {
3407  SCIPsetDebugMsg(set, " -> conflict set %d/%d added (cdpt:%d, fdpt:%d, insert:%d, valid:%d, conf:%d, reprop:%d, len:%d):\n",
3408  nconflictsetsused+1, maxconflictsets, SCIPtreeGetCurrentDepth(tree), SCIPtreeGetFocusDepth(tree),
3409  conflictset->insertdepth, conflictset->validdepth, conflictset->conflictdepth, conflictset->repropdepth,
3410  conflictset->nbdchginfos);
3411  SCIPdebug(conflictsetPrint(conflictset));
3412 
3413  if( conflictset->repropagate && conflictset->repropdepth <= repropdepth )
3414  {
3415  repropdepth = conflictset->repropdepth;
3416  repropconflictset = NULL;
3417  }
3418  nconflictsetsused++;
3419  }
3420  }
3421  }
3422 
3423  /* reactivate propagation on the first node where one of the new conflict sets trigger a deduction */
3424  if( set->conf_repropagate && repropdepth < cutoffdepth && repropdepth < tree->pathlen )
3425  {
3426  assert(0 <= repropdepth && repropdepth < tree->pathlen);
3427  assert((int) tree->path[repropdepth]->depth == repropdepth);
3428 
3429  /* if the conflict constraint of smallest repropagation depth was not yet added, insert it now */
3430  if( repropconflictset != NULL )
3431  {
3432  SCIP_Bool success;
3433 
3434  assert(repropconflictset->repropagate);
3435  assert(repropconflictset->repropdepth == repropdepth);
3436 
3437  SCIP_CALL( conflictAddConflictCons(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, \
3438  branchcand, eventqueue, cliquetable, repropconflictset, repropdepth, &success) );
3439 
3440  /* if no conflict bounds exist, the node and its sub tree in the conflict set's valid depth can be
3441  * cut off completely
3442  */
3443  if( repropconflictset->nbdchginfos == 0 )
3444  {
3445  assert(!success);
3446 
3447  SCIPsetDebugMsg(set, " -> empty reprop conflict set in depth %d cuts off sub tree at depth %d\n",
3448  focusdepth, repropconflictset->validdepth);
3449 
3450  SCIP_CALL( SCIPnodeCutoff(tree->path[repropconflictset->validdepth], set, stat, tree, transprob, \
3451  origprob, reopt, lp, blkmem) );
3452  }
3453 
3454 #ifdef SCIP_DEBUG
3455  if( success )
3456  {
3457  SCIPsetDebugMsg(set, " -> additional reprop conflict set added (cdpt:%d, fdpt:%d, insert:%d, valid:%d, conf:%d, reprop:%d, len:%d):\n",
3459  repropconflictset->insertdepth, repropconflictset->validdepth, repropconflictset->conflictdepth,
3460  repropconflictset->repropdepth, repropconflictset->nbdchginfos);
3461  SCIPdebug(conflictsetPrint(repropconflictset));
3462  }
3463 #endif
3464  }
3465 
3466  /* mark the node in the repropdepth to be propagated again */
3467  SCIPnodePropagateAgain(tree->path[repropdepth], set, stat, tree);
3468 
3469  SCIPsetDebugMsg(set, "marked node %p in depth %d to be repropagated due to conflicts found in depth %d\n",
3470  (void*)tree->path[repropdepth], repropdepth, focusdepth);
3471  }
3472 
3473  /* free the conflict store */
3474  for( i = 0; i < conflict->nconflictsets; ++i )
3475  {
3476  conflictsetFree(&conflict->conflictsets[i], blkmem);
3477  }
3478  conflict->nconflictsets = 0;
3479  }
3480 
3481  /* free all temporarily created bound change information data */
3482  conflictFreeTmpBdchginfos(conflict, blkmem);
3483 
3484  return SCIP_OKAY;
3485 }
3486 
3487 /** returns the current number of conflict sets in the conflict set storage */
3489  SCIP_CONFLICT* conflict /**< conflict analysis data */
3490  )
3491 {
3492  assert(conflict != NULL);
3493 
3494  return conflict->nconflictsets;
3495 }
3496 
3497 /** returns the total number of conflict constraints that were added to the problem */
3499  SCIP_CONFLICT* conflict /**< conflict analysis data */
3500  )
3501 {
3502  assert(conflict != NULL);
3503 
3504  return conflict->nappliedglbconss + conflict->nappliedlocconss;
3505 }
3506 
3507 /** returns the total number of literals in conflict constraints that were added to the problem */
3509  SCIP_CONFLICT* conflict /**< conflict analysis data */
3510  )
3511 {
3512  assert(conflict != NULL);
3513 
3514  return conflict->nappliedglbliterals + conflict->nappliedlocliterals;
3515 }
3516 
3517 /** returns the total number of global bound changes applied by the conflict analysis */
3519  SCIP_CONFLICT* conflict /**< conflict analysis data */
3520  )
3521 {
3522  assert(conflict != NULL);
3523 
3524  return conflict->nglbchgbds;
3525 }
3526 
3527 /** returns the total number of conflict constraints that were added globally to the problem */
3529  SCIP_CONFLICT* conflict /**< conflict analysis data */
3530  )
3531 {
3532  assert(conflict != NULL);
3533 
3534  return conflict->nappliedglbconss;
3535 }
3536 
3537 /** returns the total number of literals in conflict constraints that were added globally to the problem */
3539  SCIP_CONFLICT* conflict /**< conflict analysis data */
3540  )
3541 {
3542  assert(conflict != NULL);
3543 
3544  return conflict->nappliedglbliterals;
3545 }
3546 
3547 /** returns the total number of local bound changes applied by the conflict analysis */
3549  SCIP_CONFLICT* conflict /**< conflict analysis data */
3550  )
3551 {
3552  assert(conflict != NULL);
3553 
3554  return conflict->nlocchgbds;
3555 }
3556 
3557 /** returns the total number of conflict constraints that were added locally to the problem */
3559  SCIP_CONFLICT* conflict /**< conflict analysis data */
3560  )
3561 {
3562  assert(conflict != NULL);
3563 
3564  return conflict->nappliedlocconss;
3565 }
3566 
3567 /** returns the total number of literals in conflict constraints that were added locally to the problem */
3569  SCIP_CONFLICT* conflict /**< conflict analysis data */
3570  )
3571 {
3572  assert(conflict != NULL);
3573 
3574  return conflict->nappliedlocliterals;
3575 }
3576 
3577 
3578 
3579 
3580 /*
3581  * Propagation Conflict Analysis
3582  */
3583 
3584 /** returns whether bound change has a valid reason that can be resolved in conflict analysis */
3585 static
3587  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
3588  )
3589 {
3590  assert(bdchginfo != NULL);
3591  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3592 
3595  && SCIPbdchginfoGetInferProp(bdchginfo) != NULL));
3596 }
3597 
3598 /** compares two conflict set entries, such that bound changes infered later are
3599  * ordered prior to ones that were infered earlier
3600  */
3601 static
3602 SCIP_DECL_SORTPTRCOMP(conflictBdchginfoComp)
3603 { /*lint --e{715}*/
3604  SCIP_BDCHGINFO* bdchginfo1;
3605  SCIP_BDCHGINFO* bdchginfo2;
3606 
3607  bdchginfo1 = (SCIP_BDCHGINFO*)elem1;
3608  bdchginfo2 = (SCIP_BDCHGINFO*)elem2;
3609  assert(bdchginfo1 != NULL);
3610  assert(bdchginfo2 != NULL);
3611  assert(!SCIPbdchginfoIsRedundant(bdchginfo1));
3612  assert(!SCIPbdchginfoIsRedundant(bdchginfo2));
3613 
3615  return -1;
3616  else
3617  return +1;
3618 }
3619 
3620 /** return TRUE if conflict analysis is applicable; In case the function return FALSE there is no need to initialize the
3621  * conflict analysis since it will not be applied
3622  */
3624  SCIP_SET* set /**< global SCIP settings */
3625  )
3626 {
3627  /* check, if propagation conflict analysis is enabled */
3628  if( !set->conf_enable || !set->conf_useprop )
3629  return FALSE;
3630 
3631  /* check, if there are any conflict handlers to use a conflict set */
3632  if( set->nconflicthdlrs == 0 )
3633  return FALSE;
3634 
3635  return TRUE;
3636 }
3637 
3638 /** creates conflict analysis data for propagation conflicts */
3640  SCIP_CONFLICT** conflict, /**< pointer to conflict analysis data */
3641  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3642  SCIP_SET* set /**< global SCIP settings */
3643  )
3644 {
3645  assert(conflict != NULL);
3646 
3647  SCIP_ALLOC( BMSallocMemory(conflict) );
3648 
3649  SCIP_CALL( SCIPclockCreate(&(*conflict)->dIBclock, SCIP_CLOCKTYPE_DEFAULT) );
3650  SCIP_CALL( SCIPclockCreate(&(*conflict)->propanalyzetime, SCIP_CLOCKTYPE_DEFAULT) );
3651  SCIP_CALL( SCIPclockCreate(&(*conflict)->inflpanalyzetime, SCIP_CLOCKTYPE_DEFAULT) );
3652  SCIP_CALL( SCIPclockCreate(&(*conflict)->boundlpanalyzetime, SCIP_CLOCKTYPE_DEFAULT) );
3653  SCIP_CALL( SCIPclockCreate(&(*conflict)->sbanalyzetime, SCIP_CLOCKTYPE_DEFAULT) );
3654  SCIP_CALL( SCIPclockCreate(&(*conflict)->pseudoanalyzetime, SCIP_CLOCKTYPE_DEFAULT) );
3655 
3656  /* enable or disable timing depending on the parameter statistic timing */
3657  SCIPconflictEnableOrDisableClocks((*conflict), set->time_statistictiming);
3658 
3659  SCIP_CALL( SCIPpqueueCreate(&(*conflict)->bdchgqueue, set->mem_arraygrowinit, set->mem_arraygrowfac,
3660  conflictBdchginfoComp) );
3661  SCIP_CALL( SCIPpqueueCreate(&(*conflict)->forcedbdchgqueue, set->mem_arraygrowinit, set->mem_arraygrowfac,
3662  conflictBdchginfoComp) );
3663  SCIP_CALL( conflictsetCreate(&(*conflict)->conflictset, blkmem) );
3664  (*conflict)->conflictsets = NULL;
3665  (*conflict)->conflictsetscores = NULL;
3666  (*conflict)->tmpbdchginfos = NULL;
3667  (*conflict)->conflictsetssize = 0;
3668  (*conflict)->nconflictsets = 0;
3669  (*conflict)->proofsets = NULL;
3670  (*conflict)->proofsetssize = 0;
3671  (*conflict)->nproofsets = 0;
3672  (*conflict)->tmpbdchginfossize = 0;
3673  (*conflict)->ntmpbdchginfos = 0;
3674  (*conflict)->count = 0;
3675  (*conflict)->nglbchgbds = 0;
3676  (*conflict)->nappliedglbconss = 0;
3677  (*conflict)->nappliedglbliterals = 0;
3678  (*conflict)->nlocchgbds = 0;
3679  (*conflict)->nappliedlocconss = 0;
3680  (*conflict)->nappliedlocliterals = 0;
3681  (*conflict)->npropcalls = 0;
3682  (*conflict)->npropsuccess = 0;
3683  (*conflict)->npropconfconss = 0;
3684  (*conflict)->npropconfliterals = 0;
3685  (*conflict)->npropreconvconss = 0;
3686  (*conflict)->npropreconvliterals = 0;
3687  (*conflict)->ninflpcalls = 0;
3688  (*conflict)->ninflpsuccess = 0;
3689  (*conflict)->ninflpconfconss = 0;
3690  (*conflict)->ninflpconfliterals = 0;
3691  (*conflict)->ninflpreconvconss = 0;
3692  (*conflict)->ninflpreconvliterals = 0;
3693  (*conflict)->ninflpiterations = 0;
3694  (*conflict)->nboundlpcalls = 0;
3695  (*conflict)->nboundlpsuccess = 0;
3696  (*conflict)->nboundlpconfconss = 0;
3697  (*conflict)->nboundlpconfliterals = 0;
3698  (*conflict)->nboundlpreconvconss = 0;
3699  (*conflict)->nboundlpreconvliterals = 0;
3700  (*conflict)->nboundlpiterations = 0;
3701  (*conflict)->nsbcalls = 0;
3702  (*conflict)->nsbsuccess = 0;
3703  (*conflict)->nsbconfconss = 0;
3704  (*conflict)->nsbconfliterals = 0;
3705  (*conflict)->nsbreconvconss = 0;
3706  (*conflict)->nsbreconvliterals = 0;
3707  (*conflict)->nsbiterations = 0;
3708  (*conflict)->npseudocalls = 0;
3709  (*conflict)->npseudosuccess = 0;
3710  (*conflict)->npseudoconfconss = 0;
3711  (*conflict)->npseudoconfliterals = 0;
3712  (*conflict)->npseudoreconvconss = 0;
3713  (*conflict)->npseudoreconvliterals = 0;
3714  (*conflict)->ndualrayinfglobal = 0;
3715  (*conflict)->ndualrayinfsuccess = 0;
3716  (*conflict)->dualrayinfnnonzeros = 0;
3717  (*conflict)->ndualraybndglobal = 0;
3718  (*conflict)->ndualraybndsuccess = 0;
3719  (*conflict)->dualraybndnnonzeros = 0;
3720 
3721  SCIP_CALL( conflictInitProofset((*conflict), blkmem) );
3722 
3723  return SCIP_OKAY;
3724 }
3725 
3726 /** frees conflict analysis data for propagation conflicts */
3728  SCIP_CONFLICT** conflict, /**< pointer to conflict analysis data */
3729  BMS_BLKMEM* blkmem /**< block memory of transformed problem */
3730  )
3731 {
3732  assert(conflict != NULL);
3733  assert(*conflict != NULL);
3734  assert((*conflict)->nconflictsets == 0);
3735  assert((*conflict)->ntmpbdchginfos == 0);
3736 
3737 #ifdef SCIP_CONFGRAPH
3738  confgraphFree();
3739 #endif
3740 
3741  SCIPclockFree(&(*conflict)->dIBclock);
3742  SCIPclockFree(&(*conflict)->propanalyzetime);
3743  SCIPclockFree(&(*conflict)->inflpanalyzetime);
3744  SCIPclockFree(&(*conflict)->boundlpanalyzetime);
3745  SCIPclockFree(&(*conflict)->sbanalyzetime);
3746  SCIPclockFree(&(*conflict)->pseudoanalyzetime);
3747  SCIPpqueueFree(&(*conflict)->bdchgqueue);
3748  SCIPpqueueFree(&(*conflict)->forcedbdchgqueue);
3749  conflictsetFree(&(*conflict)->conflictset, blkmem);
3750  proofsetFree(&(*conflict)->proofset, blkmem);
3751 
3752  BMSfreeMemoryArrayNull(&(*conflict)->conflictsets);
3753  BMSfreeMemoryArrayNull(&(*conflict)->conflictsetscores);
3754  BMSfreeMemoryArrayNull(&(*conflict)->proofsets);
3755  BMSfreeMemoryArrayNull(&(*conflict)->tmpbdchginfos);
3756  BMSfreeMemory(conflict);
3757 
3758  return SCIP_OKAY;
3759 }
3760 
3761 /** clears the conflict queue and the current conflict set */
3762 static
3764  SCIP_CONFLICT* conflict /**< conflict analysis data */
3765  )
3766 {
3767  assert(conflict != NULL);
3768 
3769  SCIPpqueueClear(conflict->bdchgqueue);
3770  SCIPpqueueClear(conflict->forcedbdchgqueue);
3771  conflictsetClear(conflict->conflictset);
3772 }
3773 
3774 /** initializes the propagation conflict analysis by clearing the conflict candidate queue */
3776  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3777  SCIP_SET* set, /**< global SCIP settings */
3778  SCIP_STAT* stat, /**< problem statistics */
3779  SCIP_PROB* prob, /**< problem data */
3780  SCIP_CONFTYPE conftype, /**< type of the conflict */
3781  SCIP_Bool usescutoffbound /**< depends the conflict on a cutoff bound? */
3782  )
3783 {
3784  assert(conflict != NULL);
3785  assert(set != NULL);
3786  assert(stat != NULL);
3787  assert(prob != NULL);
3788 
3789  SCIPsetDebugMsg(set, "initializing conflict analysis\n");
3790 
3791  /* clear the conflict candidate queue and the conflict set */
3792  conflictClear(conflict);
3793 
3794  /* set conflict type */
3795  assert(conftype == SCIP_CONFTYPE_BNDEXCEEDING || conftype == SCIP_CONFTYPE_INFEASLP
3796  || conftype == SCIP_CONFTYPE_PROPAGATION);
3797  conflict->conflictset->conflicttype = conftype;
3798 
3799  /* set whether a cutoff bound is involved */
3800  conflict->conflictset->usescutoffbound = usescutoffbound;
3801 
3802  /* increase the conflict counter, such that binary variables of new conflict set and new conflict queue are labeled
3803  * with this new counter
3804  */
3805  conflict->count++;
3806  if( conflict->count == 0 ) /* make sure, 0 is not a valid conflict counter (may happen due to integer overflow) */
3807  conflict->count = 1;
3808 
3809  /* increase the conflict score weight for history updates of future conflict reasons */
3810  if( stat->nnodes > stat->lastconflictnode )
3811  {
3812  assert(0.0 < set->conf_scorefac && set->conf_scorefac <= 1.0);
3813  stat->vsidsweight /= set->conf_scorefac;
3814  assert(stat->vsidsweight > 0.0);
3815 
3816  /* if the conflict score for the next conflict exceeds 1000.0, rescale all history conflict scores */
3817  if( stat->vsidsweight >= 1000.0 )
3818  {
3819  int v;
3820 
3821  for( v = 0; v < prob->nvars; ++v )
3822  {
3823  SCIP_CALL( SCIPvarScaleVSIDS(prob->vars[v], 1.0/stat->vsidsweight) );
3824  }
3825  SCIPhistoryScaleVSIDS(stat->glbhistory, 1.0/stat->vsidsweight);
3827  stat->vsidsweight = 1.0;
3828  }
3829  stat->lastconflictnode = stat->nnodes;
3830  }
3831 
3832 #ifdef SCIP_CONFGRAPH
3833  confgraphFree();
3834  SCIP_CALL( confgraphCreate(set, conflict) );
3835 #endif
3836 
3837  return SCIP_OKAY;
3838 }
3839 
3840 /** marks bound to be present in the current conflict and returns whether a bound which is at least as tight was already
3841  * member of the current conflict (i.e., the given bound change does not need to be added)
3842  */
3843 static
3845  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3846  SCIP_SET* set, /**< global SCIP settings */
3847  SCIP_BDCHGINFO* bdchginfo, /**< bound change to add to the conflict set */
3848  SCIP_Real relaxedbd /**< relaxed bound */
3849  )
3850 {
3851  SCIP_VAR* var;
3852  SCIP_Real newbound;
3853 
3854  assert(conflict != NULL);
3855 
3856  var = SCIPbdchginfoGetVar(bdchginfo);
3857  newbound = SCIPbdchginfoGetNewbound(bdchginfo);
3858  assert(var != NULL);
3859 
3860  switch( SCIPbdchginfoGetBoundtype(bdchginfo) )
3861  {
3862  case SCIP_BOUNDTYPE_LOWER:
3863  /* check if the variables lower bound is already member of the conflict */
3864  if( var->conflictlbcount == conflict->count )
3865  {
3866  /* the variable is already member of the conflict; hence check if the new bound is redundant */
3867  if( var->conflictlb > newbound )
3868  {
3869  SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> >= %g since a stronger lower bound exist <%s> >= %g\n",
3870  SCIPvarGetName(var), newbound, SCIPvarGetName(var), var->conflictlb);
3871  return TRUE;
3872  }
3873  else if( var->conflictlb == newbound ) /*lint !e777*/
3874  {
3875  SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> >= %g since this lower bound is already present\n", SCIPvarGetName(var), newbound);
3876  SCIPsetDebugMsg(set, "adjust relaxed lower bound <%g> -> <%g>\n", var->conflictlb, relaxedbd);
3877  var->conflictrelaxedlb = MAX(var->conflictrelaxedlb, relaxedbd);
3878  return TRUE;
3879  }
3880  }
3881 
3882  /* add the variable lower bound to the current conflict */
3883  var->conflictlbcount = conflict->count;
3884 
3885  /* remember the lower bound and relaxed bound to allow only better/tighter lower bounds for that variables
3886  * w.r.t. this conflict
3887  */
3888  var->conflictlb = newbound;
3889  var->conflictrelaxedlb = relaxedbd;
3890 
3891  return FALSE;
3892 
3893  case SCIP_BOUNDTYPE_UPPER:
3894  /* check if the variables upper bound is already member of the conflict */
3895  if( var->conflictubcount == conflict->count )
3896  {
3897  /* the variable is already member of the conflict; hence check if the new bound is redundant */
3898  if( var->conflictub < newbound )
3899  {
3900  SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> <= %g since a stronger upper bound exist <%s> <= %g\n",
3901  SCIPvarGetName(var), newbound, SCIPvarGetName(var), var->conflictub);
3902  return TRUE;
3903  }
3904  else if( var->conflictub == newbound ) /*lint !e777*/
3905  {
3906  SCIPsetDebugMsg(set, "ignoring redundant bound change <%s> <= %g since this upper bound is already present\n", SCIPvarGetName(var), newbound);
3907  SCIPsetDebugMsg(set, "adjust relaxed upper bound <%g> -> <%g>\n", var->conflictub, relaxedbd);
3908  var->conflictrelaxedub = MIN(var->conflictrelaxedub, relaxedbd);
3909  return TRUE;
3910  }
3911  }
3912 
3913  /* add the variable upper bound to the current conflict */
3914  var->conflictubcount = conflict->count;
3915 
3916  /* remember the upper bound and relaxed bound to allow only better/tighter upper bounds for that variables
3917  * w.r.t. this conflict
3918  */
3919  var->conflictub = newbound;
3920  var->conflictrelaxedub = relaxedbd;
3921 
3922  return FALSE;
3923 
3924  default:
3925  SCIPerrorMessage("invalid bound type %d\n", SCIPbdchginfoGetBoundtype(bdchginfo));
3926  SCIPABORT();
3927  return FALSE; /*lint !e527*/
3928  }
3929 }
3930 
3931 /** puts bound change into the current conflict set */
3932 static
3934  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3935  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3936  SCIP_SET* set, /**< global SCIP settings */
3937  SCIP_BDCHGINFO* bdchginfo, /**< bound change to add to the conflict set */
3938  SCIP_Real relaxedbd /**< relaxed bound */
3939  )
3940 {
3941  assert(conflict != NULL);
3942  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
3943 
3944  /* check if the relaxed bound is really a relaxed bound */
3945  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
3946  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
3947 
3948  SCIPsetDebugMsg(set, "putting bound change <%s> %s %g(%g) at depth %d to current conflict set\n",
3949  SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
3950  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", SCIPbdchginfoGetNewbound(bdchginfo),
3951  relaxedbd, SCIPbdchginfoGetDepth(bdchginfo));
3952 
3953  /* mark the bound to be member of the conflict and check if a bound which is at least as tight is already member of
3954  * the conflict
3955  */
3956  if( !conflictMarkBoundCheckPresence(conflict, set, bdchginfo, relaxedbd) )
3957  {
3958  /* add the bound change to the current conflict set */
3959  SCIP_CALL( conflictsetAddBound(conflict->conflictset, blkmem, set, bdchginfo, relaxedbd) );
3960 
3961 #ifdef SCIP_CONFGRAPH
3962  if( bdchginfo != confgraphcurrentbdchginfo )
3963  confgraphAddBdchg(bdchginfo);
3964 #endif
3965  }
3966 #ifdef SCIP_CONFGRAPH
3967  else
3968  confgraphLinkBdchg(bdchginfo);
3969 #endif
3970 
3971  return SCIP_OKAY;
3972 }
3973 
3974 /** returns whether the negation of the given bound change would lead to a globally valid literal */
3975 static
3977  SCIP_SET* set, /**< global SCIP settings */
3978  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
3979  )
3980 {
3981  SCIP_VAR* var;
3982  SCIP_BOUNDTYPE boundtype;
3983  SCIP_Real bound;
3984 
3985  var = SCIPbdchginfoGetVar(bdchginfo);
3986  boundtype = SCIPbdchginfoGetBoundtype(bdchginfo);
3987  bound = SCIPbdchginfoGetNewbound(bdchginfo);
3988 
3989  return (SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS
3990  && ((boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGE(set, bound, SCIPvarGetUbGlobal(var)))
3991  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLE(set, bound, SCIPvarGetLbGlobal(var)))));
3992 }
3993 
3994 /** adds given bound change information to the conflict candidate queue */
3995 static
3997  SCIP_CONFLICT* conflict, /**< conflict analysis data */
3998  SCIP_SET* set, /**< global SCIP settings */
3999  SCIP_BDCHGINFO* bdchginfo, /**< bound change information */
4000  SCIP_Real relaxedbd /**< relaxed bound */
4001  )
4002 {
4003  assert(conflict != NULL);
4004  assert(set != NULL);
4005  assert(bdchginfo != NULL);
4006  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
4007 
4008  /* check if the relaxed bound is really a relaxed bound */
4009  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER || SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4010  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER || SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4011 
4012  /* mark the bound to be member of the conflict and check if a bound which is at least as tight is already member of
4013  * the conflict
4014  */
4015  if( !conflictMarkBoundCheckPresence(conflict, set, bdchginfo, relaxedbd) )
4016  {
4017  /* insert the bound change into the conflict queue */
4018  if( (!set->conf_preferbinary || SCIPvarIsBinary(SCIPbdchginfoGetVar(bdchginfo)))
4019  && !isBoundchgUseless(set, bdchginfo) )
4020  {
4021  SCIP_CALL( SCIPpqueueInsert(conflict->bdchgqueue, (void*)bdchginfo) );
4022  }
4023  else
4024  {
4025  SCIP_CALL( SCIPpqueueInsert(conflict->forcedbdchgqueue, (void*)bdchginfo) );
4026  }
4027 
4028 #ifdef SCIP_CONFGRAPH
4029  confgraphAddBdchg(bdchginfo);
4030 #endif
4031  }
4032 #ifdef SCIP_CONFGRAPH
4033  else
4034  confgraphLinkBdchg(bdchginfo);
4035 #endif
4036 
4037  return SCIP_OKAY;
4038 }
4039 
4040 /** convert variable and bound change to active variable */
4041 static
4043  SCIP_VAR** var, /**< pointer to variable */
4044  SCIP_SET* set, /**< global SCIP settings */
4045  SCIP_BOUNDTYPE* boundtype, /**< pointer to type of bound that was changed: lower or upper bound */
4046  SCIP_Real* bound /**< pointer to bound to convert, or NULL */
4047  )
4048 {
4049  SCIP_Real scalar;
4050  SCIP_Real constant;
4051 
4052  scalar = 1.0;
4053  constant = 0.0;
4054 
4055  /* transform given varibale to active varibale */
4056  SCIP_CALL( SCIPvarGetProbvarSum(var, set, &scalar, &constant) );
4057  assert(SCIPvarGetStatus(*var) == SCIP_VARSTATUS_FIXED || scalar != 0.0); /*lint !e777*/
4058 
4059  if( SCIPvarGetStatus(*var) == SCIP_VARSTATUS_FIXED )
4060  return SCIP_OKAY;
4061 
4062  /* if the scalar of the aggregation is negative, we have to switch the bound type */
4063  if( scalar < 0.0 )
4064  (*boundtype) = SCIPboundtypeOpposite(*boundtype);
4065 
4066  if( bound != NULL )
4067  {
4068  (*bound) -= constant;
4069  (*bound) /= scalar;
4070  }
4071 
4072  return SCIP_OKAY;
4073 }
4074 
4075 /** adds variable's bound to conflict candidate queue */
4076 static
4078  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4079  BMS_BLKMEM* blkmem, /**< block memory */
4080  SCIP_SET* set, /**< global SCIP settings */
4081  SCIP_STAT* stat, /**< dynamic problem statistics */
4082  SCIP_VAR* var, /**< problem variable */
4083  SCIP_BOUNDTYPE boundtype, /**< type of bound that was changed: lower or upper bound */
4084  SCIP_BDCHGINFO* bdchginfo, /**< bound change info, or NULL */
4085  SCIP_Real relaxedbd /**< relaxed bound */
4086  )
4087 {
4088  assert(SCIPvarIsActive(var));
4089  assert(bdchginfo != NULL);
4090  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
4091 
4092  SCIPsetDebugMsg(set, " -> adding bound <%s> %s %.15g(%.15g) [status:%d, type:%d, depth:%d, pos:%d, reason:<%s>, info:%d] to candidates\n",
4093  SCIPvarGetName(var),
4094  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4095  SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd,
4096  SCIPvarGetStatus(var), SCIPvarGetType(var),
4097  SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
4098  SCIPbdchginfoGetChgtype(bdchginfo) == SCIP_BOUNDCHGTYPE_BRANCHING ? "branch"
4101  : (SCIPbdchginfoGetInferProp(bdchginfo) != NULL ? SCIPpropGetName(SCIPbdchginfoGetInferProp(bdchginfo))
4102  : "none")),
4104 
4105  /* the local bound change may be resolved and has to be put on the candidate queue;
4106  * we even put bound changes without inference information on the queue in order to automatically
4107  * eliminate multiple insertions of the same bound change
4108  */
4109  assert(SCIPbdchginfoGetVar(bdchginfo) == var);
4110  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == boundtype);
4111  assert(SCIPbdchginfoGetDepth(bdchginfo) >= 0);
4112  assert(SCIPbdchginfoGetPos(bdchginfo) >= 0);
4113 
4114  /* the relaxed bound should be a relaxation */
4115  assert(boundtype == SCIP_BOUNDTYPE_LOWER ? SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)) : SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4116 
4117  /* the relaxed bound should be worse then the old bound of the bound change info */
4118  assert(boundtype == SCIP_BOUNDTYPE_LOWER ? SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) : SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
4119 
4120  /* put bound change information into priority queue */
4121  SCIP_CALL( conflictQueueBound(conflict, set, bdchginfo, relaxedbd) );
4122 
4123  /* each variable which is add to the conflict graph gets an increase in the VSIDS
4124  *
4125  * @note That is different to the VSIDS preseted in the literature
4126  */
4127  SCIP_CALL( incVSIDS(var, blkmem, set, stat, boundtype, relaxedbd, set->conf_conflictgraphweight) );
4128 
4129  return SCIP_OKAY;
4130 }
4131 
4132 /** adds variable's bound to conflict candidate queue */
4134  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4135  BMS_BLKMEM* blkmem, /**< block memory */
4136  SCIP_SET* set, /**< global SCIP settings */
4137  SCIP_STAT* stat, /**< dynamic problem statistics */
4138  SCIP_VAR* var, /**< problem variable */
4139  SCIP_BOUNDTYPE boundtype, /**< type of bound that was changed: lower or upper bound */
4140  SCIP_BDCHGIDX* bdchgidx /**< bound change index (time stamp of bound change), or NULL for current time */
4141  )
4142 {
4143  SCIP_BDCHGINFO* bdchginfo;
4144 
4145  assert(conflict != NULL);
4146  assert(stat != NULL);
4147  assert(var != NULL);
4148 
4149  /* convert bound to active problem variable */
4150  SCIP_CALL( convertToActiveVar(&var, set, &boundtype, NULL) );
4151 
4152  /* we can ignore fixed variables */
4154  return SCIP_OKAY;
4155 
4156  /* if the variable is multi-aggregated, add the bounds of all aggregation variables */
4158  {
4159  SCIP_VAR** vars;
4160  SCIP_Real* scalars;
4161  int nvars;
4162  int i;
4163 
4164  vars = SCIPvarGetMultaggrVars(var);
4165  scalars = SCIPvarGetMultaggrScalars(var);
4166  nvars = SCIPvarGetMultaggrNVars(var);
4167  for( i = 0; i < nvars; ++i )
4168  {
4169  SCIP_CALL( SCIPconflictAddBound(conflict, blkmem, set, stat, vars[i],
4170  (scalars[i] < 0.0 ? SCIPboundtypeOpposite(boundtype) : boundtype), bdchgidx) );
4171  }
4172 
4173  return SCIP_OKAY;
4174  }
4175  assert(SCIPvarIsActive(var));
4176 
4177  /* get bound change information */
4178  bdchginfo = SCIPvarGetBdchgInfo(var, boundtype, bdchgidx, FALSE);
4179 
4180  /* if bound of variable was not changed (this means it is still the global bound), we can ignore the conflicting
4181  * bound
4182  */
4183  if( bdchginfo == NULL )
4184  return SCIP_OKAY;
4185 
4186  assert(SCIPbdchgidxIsEarlier(SCIPbdchginfoGetIdx(bdchginfo), bdchgidx));
4187 
4188  SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchginfo, SCIPbdchginfoGetNewbound(bdchginfo)) );
4189 
4190  return SCIP_OKAY;
4191 }
4192 
4193 /** adds variable's bound to conflict candidate queue */
4195  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4196  BMS_BLKMEM* blkmem, /**< block memory */
4197  SCIP_SET* set, /**< global SCIP settings */
4198  SCIP_STAT* stat, /**< dynamic problem statistics */
4199  SCIP_VAR* var, /**< problem variable */
4200  SCIP_BOUNDTYPE boundtype, /**< type of bound that was changed: lower or upper bound */
4201  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4202  SCIP_Real relaxedbd /**< the relaxed bound */
4203  )
4204 {
4205  SCIP_BDCHGINFO* bdchginfo;
4206  int nbdchgs;
4207 
4208  assert(conflict != NULL);
4209  assert(stat != NULL);
4210  assert(var != NULL);
4211 
4212  if( !SCIPvarIsActive(var) )
4213  {
4214  /* convert bound to active problem variable */
4215  SCIP_CALL( convertToActiveVar(&var, set, &boundtype, &relaxedbd) );
4216 
4217  /* we can ignore fixed variables */
4219  return SCIP_OKAY;
4220 
4221  /* if the variable is multi-aggregated, add the bounds of all aggregation variables */
4223  {
4224  SCIPsetDebugMsg(set, "ignoring relaxed bound information since variable <%s> is multi-aggregated active\n", SCIPvarGetName(var));
4225 
4226  SCIP_CALL( SCIPconflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchgidx) );
4227 
4228  return SCIP_OKAY;
4229  }
4230  }
4231  assert(SCIPvarIsActive(var));
4232 
4233  /* get bound change information */
4234  bdchginfo = SCIPvarGetBdchgInfo(var, boundtype, bdchgidx, FALSE);
4235 
4236  /* if bound of variable was not changed (this means it is still the global bound), we can ignore the conflicting
4237  * bound
4238  */
4239  if( bdchginfo == NULL )
4240  return SCIP_OKAY;
4241 
4242  /* check that the bound change info is not a temporary one */
4243  assert(SCIPbdchgidxGetPos(&bdchginfo->bdchgidx) >= 0);
4244 
4245  /* get the position of the bound change information within the bound change array of the variable */
4246  nbdchgs = (int) bdchginfo->pos;
4247  assert(nbdchgs >= 0);
4248 
4249  /* if the relaxed bound should be ignored, set the relaxed bound to the bound given by the bdchgidx; that ensures
4250  * that the loop(s) below will be skipped
4251  */
4252  if( set->conf_ignorerelaxedbd )
4253  relaxedbd = SCIPbdchginfoGetNewbound(bdchginfo);
4254 
4255  /* search for the bound change information which includes the relaxed bound */
4256  if( boundtype == SCIP_BOUNDTYPE_LOWER )
4257  {
4258  SCIP_Real newbound;
4259 
4260  /* adjust relaxed lower bound w.r.t. variable type */
4261  SCIPvarAdjustLb(var, set, &relaxedbd);
4262 
4263  /* due to numericis we compare the relaxed lower bound to the one present at the particular time point and take
4264  * the better one
4265  */
4266  newbound = SCIPbdchginfoGetNewbound(bdchginfo);
4267  relaxedbd = MIN(relaxedbd, newbound);
4268 
4269  /* check if relaxed lower bound is smaller or equal to global lower bound; if so we can ignore the conflicting
4270  * bound
4271  */
4272  if( SCIPsetIsLE(set, relaxedbd, SCIPvarGetLbGlobal(var)) )
4273  return SCIP_OKAY;
4274 
4275  while( nbdchgs > 0 )
4276  {
4277  assert(SCIPsetIsLE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4278 
4279  /* check if the old lower bound is greater than or equal to relaxed lower bound; if not we found the bound
4280  * change info which we need to report
4281  */
4282  if( SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) )
4283  break;
4284 
4285  bdchginfo = SCIPvarGetBdchgInfoLb(var, nbdchgs-1);
4286 
4287  SCIPsetDebugMsg(set, "lower bound change %d oldbd=%.15g, newbd=%.15g, depth=%d, pos=%d, redundant=%u\n",
4288  nbdchgs, SCIPbdchginfoGetOldbound(bdchginfo), SCIPbdchginfoGetNewbound(bdchginfo),
4289  SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
4290  SCIPbdchginfoIsRedundant(bdchginfo));
4291 
4292  /* if bound change is redundant (this means it now a global bound), we can ignore the conflicting bound */
4293  if( SCIPbdchginfoIsRedundant(bdchginfo) )
4294  return SCIP_OKAY;
4295 
4296  nbdchgs--;
4297  }
4298  assert(SCIPsetIsGT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
4299  }
4300  else
4301  {
4302  SCIP_Real newbound;
4303 
4304  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
4305 
4306  /* adjust relaxed upper bound w.r.t. variable type */
4307  SCIPvarAdjustUb(var, set, &relaxedbd);
4308 
4309  /* due to numericis we compare the relaxed upper bound to the one present at the particular time point and take
4310  * the better one
4311  */
4312  newbound = SCIPbdchginfoGetNewbound(bdchginfo);
4313  relaxedbd = MAX(relaxedbd, newbound);
4314 
4315  /* check if relaxed upper bound is greater or equal to global upper bound; if so we can ignore the conflicting
4316  * bound
4317  */
4318  if( SCIPsetIsGE(set, relaxedbd, SCIPvarGetUbGlobal(var)) )
4319  return SCIP_OKAY;
4320 
4321  while( nbdchgs > 0 )
4322  {
4323  assert(SCIPsetIsGE(set, relaxedbd, SCIPbdchginfoGetNewbound(bdchginfo)));
4324 
4325  /* check if the old upper bound is smaller than or equal to the relaxed upper bound; if not we found the
4326  * bound change info which we need to report
4327  */
4328  if( SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)) )
4329  break;
4330 
4331  bdchginfo = SCIPvarGetBdchgInfoUb(var, nbdchgs-1);
4332 
4333  SCIPsetDebugMsg(set, "upper bound change %d oldbd=%.15g, newbd=%.15g, depth=%d, pos=%d, redundant=%u\n",
4334  nbdchgs, SCIPbdchginfoGetOldbound(bdchginfo), SCIPbdchginfoGetNewbound(bdchginfo),
4335  SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
4336  SCIPbdchginfoIsRedundant(bdchginfo));
4337 
4338  /* if bound change is redundant (this means it now a global bound), we can ignore the conflicting bound */
4339  if( SCIPbdchginfoIsRedundant(bdchginfo) )
4340  return SCIP_OKAY;
4341 
4342  nbdchgs--;
4343  }
4344  assert(SCIPsetIsLT(set, relaxedbd, SCIPbdchginfoGetOldbound(bdchginfo)));
4345  }
4346 
4347  assert(SCIPbdchgidxIsEarlier(SCIPbdchginfoGetIdx(bdchginfo), bdchgidx));
4348 
4349  /* put bound change information into priority queue */
4350  SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, boundtype, bdchginfo, relaxedbd) );
4351 
4352  return SCIP_OKAY;
4353 }
4354 
4355 /** checks if the given variable is already part of the current conflict set or queued for resolving with the same or
4356  * even stronger bound
4357  */
4359  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4360  SCIP_VAR* var, /**< problem variable */
4361  SCIP_SET* set, /**< global SCIP settings */
4362  SCIP_BOUNDTYPE boundtype, /**< type of bound for which the score should be increased */
4363  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4364  SCIP_Bool* used /**< pointer to store if the variable is already used */
4365  )
4366 {
4367  SCIP_Real newbound;
4368 
4369  /* convert bound to active problem variable */
4370  SCIP_CALL( convertToActiveVar(&var, set, &boundtype, NULL) );
4371 
4373  *used = FALSE;
4374  else
4375  {
4376  assert(SCIPvarIsActive(var));
4377  assert(var != NULL);
4378 
4379  switch( boundtype )
4380  {
4381  case SCIP_BOUNDTYPE_LOWER:
4382 
4383  newbound = SCIPgetVarLbAtIndex(set->scip, var, bdchgidx, FALSE);
4384 
4385  if( var->conflictlbcount == conflict->count && var->conflictlb >= newbound )
4386  {
4387  SCIPsetDebugMsg(set, "already queued bound change <%s> >= %g\n", SCIPvarGetName(var), newbound);
4388  *used = TRUE;
4389  }
4390  else
4391  *used = FALSE;
4392  break;
4393  case SCIP_BOUNDTYPE_UPPER:
4394 
4395  newbound = SCIPgetVarUbAtIndex(set->scip, var, bdchgidx, FALSE);
4396 
4397  if( var->conflictubcount == conflict->count && var->conflictub <= newbound )
4398  {
4399  SCIPsetDebugMsg(set, "already queued bound change <%s> <= %g\n", SCIPvarGetName(var), newbound);
4400  *used = TRUE;
4401  }
4402  else
4403  *used = FALSE;
4404  break;
4405  default:
4406  SCIPerrorMessage("invalid bound type %d\n", boundtype);
4407  SCIPABORT();
4408  *used = FALSE; /*lint !e527*/
4409  }
4410  }
4411 
4412  return SCIP_OKAY;
4413 }
4414 
4415 /** returns the conflict lower bound if the variable is present in the current conflict set; otherwise the global lower
4416  * bound
4417  */
4419  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4420  SCIP_VAR* var /**< problem variable */
4421  )
4422 {
4423  if( var->conflictlbcount == conflict->count )
4424  {
4425  assert(EPSGE(var->conflictlb, var->conflictrelaxedlb, 1e-09));
4426  return var->conflictrelaxedlb;
4427  }
4428 
4429  return SCIPvarGetLbGlobal(var);
4430 }
4431 
4432 /** returns the conflict upper bound if the variable is present in the current conflict set; otherwise the global upper
4433  * bound
4434  */
4436  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4437  SCIP_VAR* var /**< problem variable */
4438  )
4439 {
4440  if( var->conflictubcount == conflict->count )
4441  {
4442  assert(EPSLE(var->conflictub, var->conflictrelaxedub, 1e-09));
4443  return var->conflictrelaxedub;
4444  }
4445 
4446  return SCIPvarGetUbGlobal(var);
4447 }
4448 
4449 /** removes and returns next conflict analysis candidate from the candidate queue */
4450 static
4452  SCIP_CONFLICT* conflict /**< conflict analysis data */
4453  )
4454 {
4455  SCIP_BDCHGINFO* bdchginfo;
4456  SCIP_VAR* var;
4457 
4458  assert(conflict != NULL);
4459 
4460  if( SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0 )
4461  bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->forcedbdchgqueue));
4462  else
4463  bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->bdchgqueue));
4464 
4465  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
4466 
4467  /* if we have a candidate this one should be valid for the current conflict analysis */
4468  assert(!bdchginfoIsInvalid(conflict, bdchginfo));
4469 
4470  /* mark the bound change to be no longer in the conflict (it will be either added again to the conflict set or
4471  * replaced by resolving, which might add a weaker change on the same bound to the queue)
4472  */
4473  var = SCIPbdchginfoGetVar(bdchginfo);
4475  {
4476  var->conflictlbcount = 0;
4478  }
4479  else
4480  {
4481  assert(SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER);
4482  var->conflictubcount = 0;
4484  }
4485 
4486 #ifdef SCIP_CONFGRAPH
4487  confgraphSetCurrentBdchg(bdchginfo);
4488 #endif
4489 
4490  return bdchginfo;
4491 }
4492 
4493 /** returns next conflict analysis candidate from the candidate queue without removing it */
4494 static
4496  SCIP_CONFLICT* conflict /**< conflict analysis data */
4497  )
4498 {
4499  SCIP_BDCHGINFO* bdchginfo;
4500 
4501  assert(conflict != NULL);
4502 
4503  if( SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0 )
4504  {
4505  /* get next potetioal candidate */
4506  bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueFirst(conflict->forcedbdchgqueue));
4507 
4508  /* check if this candidate is valid */
4509  if( bdchginfoIsInvalid(conflict, bdchginfo) )
4510  {
4511  SCIPdebugMessage("bound change info [%d:<%s> %s %g] is invaild -> pop it from the force queue\n", SCIPbdchginfoGetDepth(bdchginfo),
4512  SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
4513  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4514  SCIPbdchginfoGetNewbound(bdchginfo));
4515 
4516  /* pop the invalid bound change info from the queue */
4517  (void)(SCIPpqueueRemove(conflict->forcedbdchgqueue));
4518 
4519  /* call method recursively to get next conflict analysis candidate */
4520  bdchginfo = conflictFirstCand(conflict);
4521  }
4522  }
4523  else
4524  {
4525  bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueFirst(conflict->bdchgqueue));
4526 
4527  /* check if this candidate is valid */
4528  if( bdchginfo != NULL && bdchginfoIsInvalid(conflict, bdchginfo) )
4529  {
4530  SCIPdebugMessage("bound change info [%d:<%s> %s %g] is invaild -> pop it from the queue\n", SCIPbdchginfoGetDepth(bdchginfo),
4531  SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)),
4532  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4533  SCIPbdchginfoGetNewbound(bdchginfo));
4534 
4535  /* pop the invalid bound change info from the queue */
4536  (void)(SCIPpqueueRemove(conflict->bdchgqueue));
4537 
4538  /* call method recursively to get next conflict analysis candidate */
4539  bdchginfo = conflictFirstCand(conflict);
4540  }
4541  }
4542  assert(bdchginfo == NULL || !SCIPbdchginfoIsRedundant(bdchginfo));
4543 
4544  return bdchginfo;
4545 }
4546 
4547 /** adds the current conflict set (extended by all remaining bound changes in the queue) to the pool of conflict sets */
4548 static
4550  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4551  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
4552  SCIP_SET* set, /**< global SCIP settings */
4553  SCIP_STAT* stat, /**< dynamic problem statistics */
4554  SCIP_TREE* tree, /**< branch and bound tree */
4555  int validdepth, /**< minimal depth level at which the conflict set is valid */
4556  SCIP_Bool diving, /**< are we in strong branching or diving mode? */
4557  SCIP_Bool repropagate, /**< should the constraint trigger a repropagation? */
4558  SCIP_Bool* success, /**< pointer to store whether the conflict set is valid */
4559  int* nliterals /**< pointer to store the number of literals in the generated conflictset */
4560  )
4561 {
4562  SCIP_CONFLICTSET* conflictset;
4563  SCIP_BDCHGINFO** bdchginfos;
4564  int nbdchginfos;
4565  int currentdepth;
4566  int focusdepth;
4567 
4568  assert(conflict != NULL);
4569  assert(conflict->conflictset != NULL);
4570  assert(set != NULL);
4571  assert(stat != NULL);
4572  assert(tree != NULL);
4573  assert(success != NULL);
4574  assert(nliterals != NULL);
4575  assert(SCIPpqueueNElems(conflict->forcedbdchgqueue) == 0);
4576 
4577  *success = FALSE;
4578  *nliterals = 0;
4579 
4580  /* check, whether local conflicts are allowed */
4581  validdepth = MAX(validdepth, conflict->conflictset->validdepth);
4582  if( !set->conf_allowlocal && validdepth > 0 )
4583  return SCIP_OKAY;
4584 
4585  focusdepth = SCIPtreeGetFocusDepth(tree);
4586  currentdepth = SCIPtreeGetCurrentDepth(tree);
4587  assert(currentdepth == tree->pathlen-1);
4588  assert(focusdepth <= currentdepth);
4589  assert(0 <= conflict->conflictset->validdepth && conflict->conflictset->validdepth <= currentdepth);
4590  assert(0 <= validdepth && validdepth <= currentdepth);
4591 
4592  /* get the elements of the bound change queue */
4593  bdchginfos = (SCIP_BDCHGINFO**)SCIPpqueueElems(conflict->bdchgqueue);
4594  nbdchginfos = SCIPpqueueNElems(conflict->bdchgqueue);
4595 
4596  /* create a copy of the current conflict set, allocating memory for the additional elements of the queue */
4597  SCIP_CALL( conflictsetCopy(&conflictset, blkmem, conflict->conflictset, nbdchginfos) );
4598  conflictset->validdepth = validdepth;
4599  conflictset->repropagate = repropagate;
4600 
4601  /* add the valid queue elements to the conflict set */
4602  SCIPsetDebugMsg(set, "adding %d variables from the queue as temporary conflict variables\n", nbdchginfos);
4603  SCIP_CALL( conflictsetAddBounds(conflict, conflictset, blkmem, set, bdchginfos, nbdchginfos) );
4604 
4605  /* calculate the depth, at which the conflictset should be inserted */
4606  SCIP_CALL( conflictsetCalcInsertDepth(conflictset, set, tree) );
4607  assert(conflictset->validdepth <= conflictset->insertdepth && conflictset->insertdepth <= currentdepth);
4608  SCIPsetDebugMsg(set, " -> conflict with %d literals found at depth %d is active in depth %d and valid in depth %d\n",
4609  conflictset->nbdchginfos, currentdepth, conflictset->insertdepth, conflictset->validdepth);
4610 
4611  /* if all branching variables are in the conflict set, the conflict set is of no use;
4612  * don't use conflict sets that are only valid in the probing path but not in the problem tree
4613  */
4614  if( (diving || conflictset->insertdepth < currentdepth) && conflictset->insertdepth <= focusdepth )
4615  {
4616  /* if the conflict should not be located only in the subtree where it is useful, put it to its valid depth level */
4617  if( !set->conf_settlelocal )
4618  conflictset->insertdepth = conflictset->validdepth;
4619 
4620  *nliterals = conflictset->nbdchginfos;
4621  SCIPsetDebugMsg(set, " -> final conflict set has %d literals\n", *nliterals);
4622 
4623  /* check conflict set on debugging solution */
4624  SCIP_CALL( SCIPdebugCheckConflict(blkmem, set, tree->path[validdepth], \
4625  conflictset->bdchginfos, conflictset->relaxedbds, conflictset->nbdchginfos) ); /*lint !e506 !e774*/
4626 
4627  /* move conflictset to the conflictset storage */
4628  SCIP_CALL( conflictInsertConflictset(conflict, blkmem, set, &conflictset) );
4629  *success = TRUE;
4630  }
4631  else
4632  {
4633  /* free the temporary conflict set */
4634  conflictsetFree(&conflictset, blkmem);
4635  }
4636 
4637  return SCIP_OKAY;
4638 }
4639 
4640 /** tries to resolve given bound change
4641  * - resolutions on local constraints are only applied, if the constraint is valid at the
4642  * current minimal valid depth level, because this depth level is the topmost level to add the conflict
4643  * constraint to anyways
4644  *
4645  * @note it is sufficient to explain the relaxed bound change
4646  */
4647 static
4649  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4650  SCIP_SET* set, /**< global SCIP settings */
4651  SCIP_BDCHGINFO* bdchginfo, /**< bound change to resolve */
4652  SCIP_Real relaxedbd, /**< the relaxed bound */
4653  int validdepth, /**< minimal depth level at which the conflict is valid */
4654  SCIP_Bool* resolved /**< pointer to store whether the bound change was resolved */
4655  )
4656 {
4657  SCIP_VAR* actvar;
4658  SCIP_CONS* infercons;
4659  SCIP_PROP* inferprop;
4660  SCIP_RESULT result;
4661 
4662 #ifndef NDEBUG
4663  int nforcedbdchgqueue;
4664  int nbdchgqueue;
4665 
4666  /* store the current size of the conflict queues */
4667  assert(conflict != NULL);
4668  nforcedbdchgqueue = SCIPpqueueNElems(conflict->forcedbdchgqueue);
4669  nbdchgqueue = SCIPpqueueNElems(conflict->bdchgqueue);
4670 #else
4671  assert(conflict != NULL);
4672 #endif
4673 
4674  assert(resolved != NULL);
4675  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
4676 
4677  *resolved = FALSE;
4678 
4679  actvar = SCIPbdchginfoGetVar(bdchginfo);
4680  assert(actvar != NULL);
4681  assert(SCIPvarIsActive(actvar));
4682 
4683 #ifdef SCIP_DEBUG
4684  {
4685  int i;
4686  SCIPsetDebugMsg(set, "processing next conflicting bound (depth: %d, valid depth: %d, bdchgtype: %s [%s], vartype: %d): [<%s> %s %g(%g)]\n",
4687  SCIPbdchginfoGetDepth(bdchginfo), validdepth,
4688  SCIPbdchginfoGetChgtype(bdchginfo) == SCIP_BOUNDCHGTYPE_BRANCHING ? "branch"
4689  : SCIPbdchginfoGetChgtype(bdchginfo) == SCIP_BOUNDCHGTYPE_CONSINFER ? "cons" : "prop",
4693  : SCIPbdchginfoGetInferProp(bdchginfo) == NULL ? "-"
4695  SCIPvarGetType(actvar), SCIPvarGetName(actvar),
4696  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4697  SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd);
4698  SCIPsetDebugMsg(set, " - conflict set :");
4699 
4700  for( i = 0; i < conflict->conflictset->nbdchginfos; ++i )
4701  {
4702  SCIPsetDebugMsgPrint(set, " [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(conflict->conflictset->bdchginfos[i]),
4704  SCIPbdchginfoGetBoundtype(conflict->conflictset->bdchginfos[i]) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4705  SCIPbdchginfoGetNewbound(conflict->conflictset->bdchginfos[i]), conflict->conflictset->relaxedbds[i]);
4706  }
4707  SCIPsetDebugMsgPrint(set, "\n");
4708  SCIPsetDebugMsg(set, " - forced candidates :");
4709 
4710  for( i = 0; i < SCIPpqueueNElems(conflict->forcedbdchgqueue); ++i )
4711  {
4713  SCIPsetDebugMsgPrint(set, " [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(info), SCIPvarGetName(SCIPbdchginfoGetVar(info)),
4714  bdchginfoIsInvalid(conflict, info) ? "<!>" : SCIPbdchginfoGetBoundtype(info) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4716  }
4717  SCIPsetDebugMsgPrint(set, "\n");
4718  SCIPsetDebugMsg(set, " - optional candidates:");
4719 
4720  for( i = 0; i < SCIPpqueueNElems(conflict->bdchgqueue); ++i )
4721  {
4722  SCIP_BDCHGINFO* info = (SCIP_BDCHGINFO*)(SCIPpqueueElems(conflict->bdchgqueue)[i]);
4723  SCIPsetDebugMsgPrint(set, " [%d:<%s> %s %g(%g)]", SCIPbdchginfoGetDepth(info), SCIPvarGetName(SCIPbdchginfoGetVar(info)),
4724  bdchginfoIsInvalid(conflict, info) ? "<!>" : SCIPbdchginfoGetBoundtype(info) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4726  }
4727  SCIPsetDebugMsgPrint(set, "\n");
4728  }
4729 #endif
4730 
4731  /* check, if the bound change can and should be resolved:
4732  * - resolutions on local constraints should only be applied, if the constraint is valid at the
4733  * current minimal valid depth level (which is initialized with the valid depth level of the initial
4734  * conflict set), because this depth level is the topmost level to add the conflict constraint to anyways
4735  */
4736  switch( SCIPbdchginfoGetChgtype(bdchginfo) )
4737  {
4739  infercons = SCIPbdchginfoGetInferCons(bdchginfo);
4740  assert(infercons != NULL);
4741 
4742  if( SCIPconsIsGlobal(infercons) || SCIPconsGetValidDepth(infercons) <= validdepth )
4743  {
4744  SCIP_VAR* infervar;
4745  int inferinfo;
4746  SCIP_BOUNDTYPE inferboundtype;
4747  SCIP_BDCHGIDX* bdchgidx;
4748 
4749  /* resolve bound change by asking the constraint that infered the bound to put all bounds that were
4750  * the reasons for the conflicting bound change on the priority queue
4751  */
4752  infervar = SCIPbdchginfoGetInferVar(bdchginfo);
4753  inferinfo = SCIPbdchginfoGetInferInfo(bdchginfo);
4754  inferboundtype = SCIPbdchginfoGetInferBoundtype(bdchginfo);
4755  bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
4756  assert(infervar != NULL);
4757 
4758  SCIPsetDebugMsg(set, "resolving bound <%s> %s %g(%g) [status:%d, type:%d, depth:%d, pos:%d]: <%s> %s %g [cons:<%s>(%s), info:%d]\n",
4759  SCIPvarGetName(actvar),
4760  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4761  SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd,
4762  SCIPvarGetStatus(actvar), SCIPvarGetType(actvar),
4763  SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
4764  SCIPvarGetName(infervar),
4765  inferboundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4766  SCIPgetVarBdAtIndex(set->scip, infervar, inferboundtype, bdchgidx, TRUE),
4767  SCIPconsGetName(infercons),
4768  SCIPconsIsGlobal(infercons) ? "global" : "local",
4769  inferinfo);
4770 
4771  /* in case the inference variables is not an active variables, we need to transform the relaxed bound */
4772  if( actvar != infervar )
4773  {
4774  SCIP_VAR* var;
4775  SCIP_Real scalar;
4776  SCIP_Real constant;
4777 
4778  assert(SCIPvarGetStatus(infervar) == SCIP_VARSTATUS_AGGREGATED
4780  || (SCIPvarGetStatus(infervar) == SCIP_VARSTATUS_MULTAGGR && SCIPvarGetMultaggrNVars(infervar) == 1));
4781 
4782  scalar = 1.0;
4783  constant = 0.0;
4784 
4785  var = infervar;
4786 
4787  /* transform given varibale to active varibale */
4788  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
4789  assert(var == actvar);
4790 
4791  relaxedbd *= scalar;
4792  relaxedbd += constant;
4793  }
4794 
4795  SCIP_CALL( SCIPconsResolvePropagation(infercons, set, infervar, inferinfo, inferboundtype, bdchgidx, relaxedbd, &result) );
4796  *resolved = (result == SCIP_SUCCESS);
4797  }
4798  break;
4799 
4801  inferprop = SCIPbdchginfoGetInferProp(bdchginfo);
4802  if( inferprop != NULL )
4803  {
4804  SCIP_VAR* infervar;
4805  int inferinfo;
4806  SCIP_BOUNDTYPE inferboundtype;
4807  SCIP_BDCHGIDX* bdchgidx;
4808 
4809  /* resolve bound change by asking the propagator that infered the bound to put all bounds that were
4810  * the reasons for the conflicting bound change on the priority queue
4811  */
4812  infervar = SCIPbdchginfoGetInferVar(bdchginfo);
4813  inferinfo = SCIPbdchginfoGetInferInfo(bdchginfo);
4814  inferboundtype = SCIPbdchginfoGetInferBoundtype(bdchginfo);
4815  bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
4816  assert(infervar != NULL);
4817 
4818  SCIPsetDebugMsg(set, "resolving bound <%s> %s %g(%g) [status:%d, depth:%d, pos:%d]: <%s> %s %g [prop:<%s>, info:%d]\n",
4819  SCIPvarGetName(actvar),
4820  SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4821  SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd,
4822  SCIPvarGetStatus(actvar), SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
4823  SCIPvarGetName(infervar),
4824  inferboundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
4825  SCIPgetVarBdAtIndex(set->scip, infervar, inferboundtype, bdchgidx, TRUE),
4826  SCIPpropGetName(inferprop), inferinfo);
4827 
4828  SCIP_CALL( SCIPpropResolvePropagation(inferprop, set, infervar, inferinfo, inferboundtype, bdchgidx, relaxedbd, &result) );
4829  *resolved = (result == SCIP_SUCCESS);
4830  }
4831  break;
4832 
4834  assert(!(*resolved));
4835  break;
4836 
4837  default:
4838  SCIPerrorMessage("invalid bound change type <%d>\n", SCIPbdchginfoGetChgtype(bdchginfo));
4839  return SCIP_INVALIDDATA;
4840  }
4841 
4842  SCIPsetDebugMsg(set, "resolving status: %u\n", *resolved);
4843 
4844 #ifndef NDEBUG
4845  /* subtract the size of the conflicq queues */
4846  nforcedbdchgqueue -= SCIPpqueueNElems(conflict->forcedbdchgqueue);
4847  nbdchgqueue -= SCIPpqueueNElems(conflict->bdchgqueue);
4848 
4849  /* in case the bound change was not resolved, the conflict queues should have the same size (contents) */
4850  assert((*resolved) || (nforcedbdchgqueue == 0 && nbdchgqueue == 0));
4851 #endif
4852 
4853  return SCIP_OKAY;
4854 }
4855 
4856 /** if only one conflicting bound change of the last depth level was used, and if this can be resolved,
4857  * creates GRASP-like reconvergence conflict constraints in the conflict graph up to the branching variable of this
4858  * depth level
4859  */
4860 static
4862  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4863  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
4864  SCIP_SET* set, /**< global SCIP settings */
4865  SCIP_STAT* stat, /**< problem statistics */
4866  SCIP_PROB* prob, /**< problem data */
4867  SCIP_TREE* tree, /**< branch and bound tree */
4868  SCIP_Bool diving, /**< are we in strong branching or diving mode? */
4869  int validdepth, /**< minimal depth level at which the initial conflict set is valid */
4870  SCIP_BDCHGINFO* firstuip, /**< first UIP of conflict graph */
4871  int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
4872  int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
4873  )
4874 {
4875  SCIP_BDCHGINFO* uip;
4876  SCIP_CONFTYPE conftype;
4877  SCIP_Bool usescutoffbound;
4878  int firstuipdepth;
4879  int focusdepth;
4880  int currentdepth;
4881  int maxvaliddepth;
4882 
4883  assert(conflict != NULL);
4884  assert(firstuip != NULL);
4885  assert(nreconvconss != NULL);
4886  assert(nreconvliterals != NULL);
4887  assert(!SCIPbdchginfoIsRedundant(firstuip));
4888 
4889  focusdepth = SCIPtreeGetFocusDepth(tree);
4890  currentdepth = SCIPtreeGetCurrentDepth(tree);
4891  assert(currentdepth == tree->pathlen-1);
4892  assert(focusdepth <= currentdepth);
4893 
4894  /* check, whether local constraints are allowed; however, don't generate reconvergence constraints that are only valid
4895  * in the probing path and not in the problem tree (i.e. that exceed the focusdepth)
4896  */
4897  maxvaliddepth = (set->conf_allowlocal ? MIN(currentdepth-1, focusdepth) : 0);
4898  if( validdepth > maxvaliddepth )
4899  return SCIP_OKAY;
4900 
4901  firstuipdepth = SCIPbdchginfoGetDepth(firstuip);
4902 
4903  conftype = conflict->conflictset->conflicttype;
4904  usescutoffbound = conflict->conflictset->usescutoffbound;
4905 
4906  /* for each succeeding UIP pair of the last depth level, create one reconvergence constraint */
4907  uip = firstuip;
4908  while( uip != NULL && SCIPbdchginfoGetDepth(uip) == SCIPbdchginfoGetDepth(firstuip) && bdchginfoIsResolvable(uip) )
4909  {
4910  SCIP_BDCHGINFO* oppositeuip;
4911  SCIP_BDCHGINFO* bdchginfo;
4912  SCIP_BDCHGINFO* nextuip;
4913  SCIP_VAR* uipvar;
4914  SCIP_Real oppositeuipbound;
4915  SCIP_BOUNDTYPE oppositeuipboundtype;
4916  int nresolutions;
4917 
4918  assert(!SCIPbdchginfoIsRedundant(uip));
4919 
4920  SCIPsetDebugMsg(set, "creating reconvergence constraint for UIP <%s> %s %g in depth %d pos %d\n",
4923 
4924  /* initialize conflict data */
4925  SCIP_CALL( SCIPconflictInit(conflict, set, stat, prob, conftype, usescutoffbound) );
4926 
4927  conflict->conflictset->conflicttype = conftype;
4928  conflict->conflictset->usescutoffbound = usescutoffbound;
4929 
4930  /* create a temporary bound change information for the negation of the UIP's bound change;
4931  * this bound change information is freed in the SCIPconflictFlushConss() call;
4932  * for reconvergence constraints for continuous variables we can only use the "negation" !(x <= u) == (x >= u);
4933  * during conflict analysis, we treat a continuous bound "x >= u" in the conflict set as "x > u", and in the
4934  * generated constraint this is negated again to "x <= u" which is correct.
4935  */
4936  uipvar = SCIPbdchginfoGetVar(uip);
4937  oppositeuipboundtype = SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(uip));
4938  oppositeuipbound = SCIPbdchginfoGetNewbound(uip);
4939  if( SCIPvarIsIntegral(uipvar) )
4940  {
4941  assert(SCIPsetIsIntegral(set, oppositeuipbound));
4942  oppositeuipbound += (oppositeuipboundtype == SCIP_BOUNDTYPE_LOWER ? +1.0 : -1.0);
4943  }
4944  SCIP_CALL( conflictCreateTmpBdchginfo(conflict, blkmem, set, uipvar, oppositeuipboundtype, \
4945  oppositeuipboundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_REAL_MIN : SCIP_REAL_MAX, oppositeuipbound, &oppositeuip) );
4946 
4947  /* put the negated UIP into the conflict set */
4948  SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, oppositeuip, oppositeuipbound) );
4949 
4950  /* put positive UIP into priority queue */
4951  SCIP_CALL( conflictQueueBound(conflict, set, uip, SCIPbdchginfoGetNewbound(uip) ) );
4952 
4953  /* resolve the queue until the next UIP is reached */
4954  bdchginfo = conflictFirstCand(conflict);
4955  nextuip = NULL;
4956  nresolutions = 0;
4957  while( bdchginfo != NULL && validdepth <= maxvaliddepth )
4958  {
4959  SCIP_BDCHGINFO* nextbdchginfo;
4960  SCIP_Real relaxedbd;
4961  SCIP_Bool forceresolve;
4962  int bdchgdepth;
4963 
4964  /* check if the next bound change must be resolved in every case */
4965  forceresolve = (SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0);
4966 
4967  /* remove currently processed candidate and get next conflicting bound from the conflict candidate queue before
4968  * we remove the candidate we have to collect the relaxed bound since removing the candidate from the queue
4969  * invalidates the relaxed bound
4970  */
4971  assert(bdchginfo == conflictFirstCand(conflict));
4972  relaxedbd = SCIPbdchginfoGetRelaxedBound(bdchginfo);
4973  bdchginfo = conflictRemoveCand(conflict);
4974  nextbdchginfo = conflictFirstCand(conflict);
4975  bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
4976  assert(bdchginfo != NULL);
4977  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
4978  assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(bdchginfo) >= SCIPbdchginfoGetDepth(nextbdchginfo)
4979  || forceresolve);
4980  assert(bdchgdepth <= firstuipdepth);
4981 
4982  /* bound changes that are higher in the tree than the valid depth of the conflict can be ignored;
4983  * multiple insertions of the same bound change can be ignored
4984  */
4985  if( bdchgdepth > validdepth && bdchginfo != nextbdchginfo )
4986  {
4987  SCIP_VAR* actvar;
4988  SCIP_Bool resolved;
4989 
4990  actvar = SCIPbdchginfoGetVar(bdchginfo);
4991  assert(actvar != NULL);
4992  assert(SCIPvarIsActive(actvar));
4993 
4994  /* check if we have to resolve the bound change in this depth level
4995  * - the starting uip has to be resolved
4996  * - a bound change should be resolved, if it is in the fuip's depth level and not the
4997  * next uip (i.e., if it is not the last bound change in the fuip's depth level)
4998  * - a forced bound change must be resolved in any case
4999  */
5000  resolved = FALSE;
5001  if( bdchginfo == uip
5002  || (bdchgdepth == firstuipdepth
5003  && nextbdchginfo != NULL
5004  && SCIPbdchginfoGetDepth(nextbdchginfo) == bdchgdepth)
5005  || forceresolve )
5006  {
5007  SCIP_CALL( conflictResolveBound(conflict, set, bdchginfo, relaxedbd, validdepth, &resolved) );
5008  }
5009 
5010  if( resolved )
5011  nresolutions++;
5012  else if( forceresolve )
5013  {
5014  /* variable cannot enter the conflict clause: we have to make the conflict clause local, s.t.
5015  * the unresolved bound change is active in the whole sub tree of the conflict clause
5016  */
5017  assert(bdchgdepth >= validdepth);
5018  validdepth = bdchgdepth;
5019 
5020  SCIPsetDebugMsg(set, "couldn't resolve forced bound change on <%s> -> new valid depth: %d\n",
5021  SCIPvarGetName(actvar), validdepth);
5022  }
5023  else if( bdchginfo != uip )
5024  {
5025  assert(conflict->conflictset != NULL);
5026  assert(conflict->conflictset->nbdchginfos >= 1); /* starting UIP is already member of the conflict set */
5027 
5028  /* if this is the first variable of the conflict set besides the current starting UIP, it is the next
5029  * UIP (or the first unresolvable bound change)
5030  */
5031  if( bdchgdepth == firstuipdepth && conflict->conflictset->nbdchginfos == 1 )
5032  {
5033  assert(nextuip == NULL);
5034  nextuip = bdchginfo;
5035  }
5036 
5037  /* put bound change into the conflict set */
5038  SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, bdchginfo, relaxedbd) );
5039  assert(conflict->conflictset->nbdchginfos >= 2);
5040  }
5041  else
5042  assert(conflictFirstCand(conflict) == NULL); /* the starting UIP was not resolved */
5043  }
5044 
5045  /* get next conflicting bound from the conflict candidate queue (this does not need to be nextbdchginfo, because
5046  * due to resolving the bound changes, a variable could be added to the queue which must be
5047  * resolved before nextbdchginfo)
5048  */
5049  bdchginfo = conflictFirstCand(conflict);
5050  }
5051  assert(nextuip != uip);
5052 
5053  /* if only one propagation was resolved, the reconvergence constraint is already member of the constraint set
5054  * (it is exactly the constraint that produced the propagation)
5055  */
5056  if( nextuip != NULL && nresolutions >= 2 && bdchginfo == NULL && validdepth <= maxvaliddepth )
5057  {
5058  int nlits;
5059  SCIP_Bool success;
5060 
5061  assert(SCIPbdchginfoGetDepth(nextuip) == SCIPbdchginfoGetDepth(uip));
5062 
5063  /* check conflict graph frontier on debugging solution */
5064  SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth], \
5065  bdchginfo, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, \
5066  conflict->conflictset->nbdchginfos, conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
5067 
5068  SCIPsetDebugMsg(set, "creating reconvergence constraint from UIP <%s> to UIP <%s> in depth %d with %d literals after %d resolutions\n",
5070  SCIPbdchginfoGetDepth(uip), conflict->conflictset->nbdchginfos, nresolutions);
5071 
5072  /* call the conflict handlers to create a conflict set */
5073  SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, FALSE, &success, &nlits) );
5074  if( success )
5075  {
5076  (*nreconvconss)++;
5077  (*nreconvliterals) += nlits;
5078  }
5079  }
5080 
5081  /* clear the conflict candidate queue and the conflict set (to make sure, oppositeuip is not referenced anymore) */
5082  conflictClear(conflict);
5083 
5084  uip = nextuip;
5085  }
5086 
5087  conflict->conflictset->conflicttype = conftype;
5088  conflict->conflictset->usescutoffbound = usescutoffbound;
5089 
5090 
5091  return SCIP_OKAY;
5092 }
5093 
5094 /** analyzes conflicting bound changes that were added with calls to SCIPconflictAddBound() and
5095  * SCIPconflictAddRelaxedBound(), and on success, calls the conflict handlers to create a conflict constraint out of
5096  * the resulting conflict set; afterwards the conflict queue and the conflict set is cleared
5097  */
5098 static
5100  SCIP_CONFLICT* conflict, /**< conflict analysis data */
5101  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5102  SCIP_SET* set, /**< global SCIP settings */
5103  SCIP_STAT* stat, /**< problem statistics */
5104  SCIP_PROB* prob, /**< problem data */
5105  SCIP_TREE* tree, /**< branch and bound tree */
5106  SCIP_Bool diving, /**< are we in strong branching or diving mode? */
5107  int validdepth, /**< minimal depth level at which the initial conflict set is valid */
5108  SCIP_Bool mustresolve, /**< should the conflict set only be used, if a resolution was applied? */
5109  int* nconss, /**< pointer to store the number of generated conflict constraints */
5110  int* nliterals, /**< pointer to store the number of literals in generated conflict constraints */
5111  int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
5112  int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
5113  )
5114 {
5115  SCIP_BDCHGINFO* bdchginfo;
5116  SCIP_BDCHGINFO** firstuips;
5117  int nfirstuips;
5118  int focusdepth;
5119  int currentdepth;
5120  int maxvaliddepth;
5121  int resolvedepth;
5122  int nresolutions;
5123  int lastconsnresolutions;
5124  int lastconsresoldepth;
5125 
5126  assert(conflict != NULL);
5127  assert(conflict->conflictset != NULL);
5128  assert(conflict->conflictset->nbdchginfos >= 0);
5129  assert(set != NULL);
5130  assert(stat != NULL);
5131  assert(0 <= validdepth && validdepth <= SCIPtreeGetCurrentDepth(tree));
5132  assert(nconss != NULL);
5133  assert(nliterals != NULL);
5134  assert(nreconvconss != NULL);
5135  assert(nreconvliterals != NULL);
5136 
5137  focusdepth = SCIPtreeGetFocusDepth(tree);
5138  currentdepth = SCIPtreeGetCurrentDepth(tree);
5139  assert(currentdepth == tree->pathlen-1);
5140  assert(focusdepth <= currentdepth);
5141 
5142  resolvedepth = ((set->conf_fuiplevels >= 0 && set->conf_fuiplevels <= currentdepth)
5143  ? currentdepth - set->conf_fuiplevels + 1 : 0);
5144  assert(0 <= resolvedepth && resolvedepth <= currentdepth + 1);
5145 
5146  /* if we must resolve at least one bound change, find the first UIP at least in the last depth level */
5147  if( mustresolve )
5148  resolvedepth = MIN(resolvedepth, currentdepth);
5149 
5150  SCIPsetDebugMsg(set, "analyzing conflict with %d+%d conflict candidates and starting conflict set of size %d in depth %d (resolvedepth=%d)\n",
5152  conflict->conflictset->nbdchginfos, currentdepth, resolvedepth);
5153 
5154  *nconss = 0;
5155  *nliterals = 0;
5156  *nreconvconss = 0;
5157  *nreconvliterals = 0;
5158 
5159  /* check, whether local conflicts are allowed; however, don't generate conflict constraints that are only valid in the
5160  * probing path and not in the problem tree (i.e. that exceed the focusdepth)
5161  */
5162  maxvaliddepth = (set->conf_allowlocal ? MIN(currentdepth-1, focusdepth) : 0);
5163  if( validdepth > maxvaliddepth )
5164  return SCIP_OKAY;
5165 
5166  /* allocate temporary memory for storing first UIPs (in each depth level, at most two bound changes can be flagged
5167  * as UIP, namely a binary and a non-binary bound change)
5168  */
5169  SCIP_CALL( SCIPsetAllocBufferArray(set, &firstuips, 2*(currentdepth+1)) ); /*lint !e647*/
5170 
5171  /* process all bound changes in the conflict candidate queue */
5172  nresolutions = 0;
5173  lastconsnresolutions = (mustresolve ? 0 : -1);
5174  lastconsresoldepth = (mustresolve ? currentdepth : INT_MAX);
5175  bdchginfo = conflictFirstCand(conflict);
5176  nfirstuips = 0;
5177 
5178  /* check if the initial reason on debugging solution */
5179  SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth], \
5180  NULL, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, conflict->conflictset->nbdchginfos, \
5181  conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
5182 
5183  while( bdchginfo != NULL && validdepth <= maxvaliddepth )
5184  {
5185  SCIP_BDCHGINFO* nextbdchginfo;
5186  SCIP_Real relaxedbd;
5187  SCIP_Bool forceresolve;
5188  int bdchgdepth;
5189 
5190  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
5191 
5192  /* check if the next bound change must be resolved in every case */
5193  forceresolve = (SCIPpqueueNElems(conflict->forcedbdchgqueue) > 0);
5194 
5195  /* resolve next bound change in queue */
5196  bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
5197  assert(0 <= bdchgdepth && bdchgdepth <= currentdepth);
5198  assert(SCIPvarIsActive(SCIPbdchginfoGetVar(bdchginfo)));
5199  assert(bdchgdepth < tree->pathlen);
5200  assert(tree->path[bdchgdepth] != NULL);
5201  assert(tree->path[bdchgdepth]->domchg != NULL);
5202  assert(SCIPbdchginfoGetPos(bdchginfo) < (int)tree->path[bdchgdepth]->domchg->domchgbound.nboundchgs);
5203  assert(tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].var
5204  == SCIPbdchginfoGetVar(bdchginfo));
5205  assert(tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].newbound
5206  == SCIPbdchginfoGetNewbound(bdchginfo)
5209  == SCIPbdchginfoGetNewbound(bdchginfo)); /*lint !e777*/
5210  assert((SCIP_BOUNDTYPE)tree->path[bdchgdepth]->domchg->domchgbound.boundchgs[SCIPbdchginfoGetPos(bdchginfo)].boundtype
5211  == SCIPbdchginfoGetBoundtype(bdchginfo));
5212 
5213  /* create intermediate conflict constraint */
5214  assert(nresolutions >= lastconsnresolutions);
5215  if( !forceresolve )
5216  {
5217  if( nresolutions == lastconsnresolutions )
5218  lastconsresoldepth = bdchgdepth; /* all intermediate depth levels consisted of only unresolved bound changes */
5219  else if( bdchgdepth < lastconsresoldepth && (set->conf_interconss == -1 || *nconss < set->conf_interconss) )
5220  {
5221  int nlits;
5222  SCIP_Bool success;
5223 
5224  /* call the conflict handlers to create a conflict set */
5225  SCIPsetDebugMsg(set, "creating intermediate conflictset after %d resolutions up to depth %d (valid at depth %d): %d conflict bounds, %d bounds in queue\n",
5226  nresolutions, bdchgdepth, validdepth, conflict->conflictset->nbdchginfos,
5227  SCIPpqueueNElems(conflict->bdchgqueue));
5228 
5229  SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, TRUE, &success, &nlits) );
5230  lastconsnresolutions = nresolutions;
5231  lastconsresoldepth = bdchgdepth;
5232  if( success )
5233  {
5234  (*nconss)++;
5235  (*nliterals) += nlits;
5236  }
5237  }
5238  }
5239 
5240  /* remove currently processed candidate and get next conflicting bound from the conflict candidate queue before
5241  * we remove the candidate we have to collect the relaxed bound since removing the candidate from the queue
5242  * invalidates the relaxed bound
5243  */
5244  assert(bdchginfo == conflictFirstCand(conflict));
5245  relaxedbd = SCIPbdchginfoGetRelaxedBound(bdchginfo);
5246  bdchginfo = conflictRemoveCand(conflict);
5247  nextbdchginfo = conflictFirstCand(conflict);
5248  assert(bdchginfo != NULL);
5249  assert(!SCIPbdchginfoIsRedundant(bdchginfo));
5250  assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(bdchginfo) >= SCIPbdchginfoGetDepth(nextbdchginfo)
5251  || forceresolve);
5252 
5253  /* we don't need to resolve bound changes that are already active in the valid depth of the current conflict set,
5254  * because the conflict set can only be added locally at the valid depth, and all bound changes applied in this
5255  * depth or earlier can be removed from the conflict constraint, since they are already applied in the constraint's
5256  * subtree;
5257  * if the next bound change on the remaining queue is equal to the current bound change,
5258  * this is a multiple insertion in the conflict candidate queue and we can ignore the current
5259  * bound change
5260  */
5261  if( bdchgdepth > validdepth && bdchginfo != nextbdchginfo )
5262  {
5263  SCIP_VAR* actvar;
5264  SCIP_Bool resolved;
5265 
5266  actvar = SCIPbdchginfoGetVar(bdchginfo);
5267  assert(actvar != NULL);
5268  assert(SCIPvarIsActive(actvar));
5269 
5270  /* check if we want to resolve the bound change in this depth level
5271  * - bound changes should be resolved, if
5272  * (i) we must apply at least one resolution and didn't resolve a bound change yet, or
5273  * (ii) their depth level is at least equal to the minimal resolving depth, and
5274  * they are not the last remaining conflicting bound change in their depth level
5275  * (iii) the bound change resolving is forced (i.e., the forced queue was non-empty)
5276  */
5277  resolved = FALSE;
5278  if( (mustresolve && nresolutions == 0)
5279  || (bdchgdepth >= resolvedepth
5280  && nextbdchginfo != NULL
5281  && SCIPbdchginfoGetDepth(nextbdchginfo) == bdchgdepth)
5282  || forceresolve )
5283  {
5284  SCIP_CALL( conflictResolveBound(conflict, set, bdchginfo, relaxedbd, validdepth, &resolved) );
5285  }
5286 
5287  if( resolved )
5288  nresolutions++;
5289  else if( forceresolve )
5290  {
5291  /* variable cannot enter the conflict clause: we have to make the conflict clause local, s.t.
5292  * the unresolved bound change is active in the whole sub tree of the conflict clause
5293  */
5294  assert(bdchgdepth >= validdepth);
5295  validdepth = bdchgdepth;
5296 
5297  SCIPsetDebugMsg(set, "couldn't resolve forced bound change on <%s> -> new valid depth: %d\n",
5298  SCIPvarGetName(actvar), validdepth);
5299  }
5300  else
5301  {
5302  /* if this is a UIP (the last bound change in its depth level), it can be used to generate a
5303  * UIP reconvergence constraint
5304  */
5305  if( nextbdchginfo == NULL || SCIPbdchginfoGetDepth(nextbdchginfo) != bdchgdepth )
5306  {
5307  assert(nfirstuips < 2*(currentdepth+1));
5308  firstuips[nfirstuips] = bdchginfo;
5309  nfirstuips++;
5310  }
5311 
5312  /* put variable into the conflict set, using the literal that is currently fixed to FALSE */
5313  SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, bdchginfo, relaxedbd) );
5314  }
5315  }
5316 
5317  /* check conflict graph frontier on debugging solution */
5318  SCIP_CALL( SCIPdebugCheckConflictFrontier(blkmem, set, tree->path[validdepth], \
5319  bdchginfo, conflict->conflictset->bdchginfos, conflict->conflictset->relaxedbds, conflict->conflictset->nbdchginfos, \
5320  conflict->bdchgqueue, conflict->forcedbdchgqueue) ); /*lint !e506 !e774*/
5321 
5322  /* get next conflicting bound from the conflict candidate queue (this needs not to be nextbdchginfo, because
5323  * due to resolving the bound changes, a bound change could be added to the queue which must be
5324  * resolved before nextbdchginfo)
5325  */
5326  bdchginfo = conflictFirstCand(conflict);
5327  }
5328 
5329  /* check, if a valid conflict set was found */
5330  if( bdchginfo == NULL
5331  && nresolutions > lastconsnresolutions
5332  && validdepth <= maxvaliddepth
5333  && (!mustresolve || nresolutions > 0 || conflict->conflictset->nbdchginfos == 0)
5334  && SCIPpqueueNElems(conflict->forcedbdchgqueue) == 0 )
5335  {
5336  int nlits;
5337  SCIP_Bool success;
5338 
5339  /* call the conflict handlers to create a conflict set */
5340  SCIP_CALL( conflictAddConflictset(conflict, blkmem, set, stat, tree, validdepth, diving, TRUE, &success, &nlits) );
5341  if( success )
5342  {
5343  (*nconss)++;
5344  (*nliterals) += nlits;
5345  }
5346  }
5347 
5348  /* produce reconvergence constraints defined by succeeding UIP's of the last depth level */
5349  if( set->conf_reconvlevels != 0 && validdepth <= maxvaliddepth )
5350  {
5351  int reconvlevels;
5352  int i;
5353 
5354  reconvlevels = (set->conf_reconvlevels == -1 ? INT_MAX : set->conf_reconvlevels);
5355  for( i = 0; i < nfirstuips; ++i )
5356  {
5357  if( SCIPbdchginfoHasInferenceReason(firstuips[i])
5358  && currentdepth - SCIPbdchginfoGetDepth(firstuips[i]) < reconvlevels )
5359  {
5360  SCIP_CALL( conflictCreateReconvergenceConss(conflict, blkmem, set, stat, prob, tree, diving, \
5361  validdepth, firstuips[i], nreconvconss, nreconvliterals) );
5362  }
5363  }
5364  }
5365 
5366  /* free the temporary memory */
5367  SCIPsetFreeBufferArray(set, &firstuips);
5368 
5369  /* clear the conflict candidate queue and the conflict set */
5370  conflictClear(conflict);
5371 
5372  return SCIP_OKAY;
5373 }
5374 
5375 /** analyzes conflicting bound changes that were added with calls to SCIPconflictAddBound(), and on success, calls the
5376  * conflict handlers to create a conflict constraint out of the resulting conflict set;
5377  * updates statistics for propagation conflict analysis
5378  */
5380  SCIP_CONFLICT* conflict, /**< conflict analysis data */
5381  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5382  SCIP_SET* set, /**< global SCIP settings */
5383  SCIP_STAT* stat, /**< problem statistics */
5384  SCIP_PROB* prob, /**< problem data */
5385  SCIP_TREE* tree, /**< branch and bound tree */
5386  int validdepth, /**< minimal depth level at which the initial conflict set is valid */
5387  SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
5388  )
5389 {
5390  int nconss;
5391  int nliterals;
5392  int nreconvconss;
5393  int nreconvliterals;
5394 
5395  assert(conflict != NULL);
5396  assert(conflict->conflictset != NULL);
5397  assert(set != NULL);
5398  assert(prob != NULL);
5399 
5400  if( success != NULL )
5401  *success = FALSE;
5402 
5403  /* check if the conflict analysis is applicable */
5404  if( !SCIPconflictApplicable(set) )
5405  return SCIP_OKAY;
5406 
5407  /* check, if the conflict set will get too large with high probability */
5408  if( conflict->conflictset->nbdchginfos + SCIPpqueueNElems(conflict->bdchgqueue)
5409  + SCIPpqueueNElems(conflict->forcedbdchgqueue) >= 2*conflictCalcMaxsize(set, prob) )
5410  return SCIP_OKAY;
5411 
5412  SCIPsetDebugMsg(set, "analyzing conflict after infeasible propagation in depth %d\n", SCIPtreeGetCurrentDepth(tree));
5413 
5414  /* start timing */
5415  SCIPclockStart(conflict->propanalyzetime, set);
5416 
5417  conflict->npropcalls++;
5418 
5419  /* analyze the conflict set, and create a conflict constraint on success */
5420  SCIP_CALL( conflictAnalyze(conflict, blkmem, set, stat, prob, tree, FALSE, validdepth, TRUE, &nconss, &nliterals, \
5421  &nreconvconss, &nreconvliterals) );
5422  conflict->npropsuccess += (nconss > 0 ? 1 : 0);
5423  conflict->npropconfconss += nconss;
5424  conflict->npropconfliterals += nliterals;
5425  conflict->npropreconvconss += nreconvconss;
5426  conflict->npropreconvliterals += nreconvliterals;
5427  if( success != NULL )
5428  *success = (nconss > 0);
5429 
5430  /* stop timing */
5431  SCIPclockStop(conflict->propanalyzetime, set);
5432 
5433  return SCIP_OKAY;
5434 }
5435 
5436 /** gets time in seconds used for preprocessing global conflict constraint before appliance */
5438  SCIP_CONFLICT* conflict /**< conflict analysis data */
5439  )
5440 {
5441  assert(conflict != NULL);
5442 
5443  return SCIPclockGetTime(conflict->dIBclock);
5444 }
5445 
5446 /** gets time in seconds used for analyzing propagation conflicts */
5448  SCIP_CONFLICT* conflict /**< conflict analysis data */
5449  )
5450 {
5451  assert(conflict != NULL);
5452 
5453  return SCIPclockGetTime(conflict->propanalyzetime);
5454 }
5455 
5456 /** gets number of calls to propagation conflict analysis */
5458  SCIP_CONFLICT* conflict /**< conflict analysis data */
5459  )
5460 {
5461  assert(conflict != NULL);
5462 
5463  return conflict->npropcalls;
5464 }
5465 
5466 /** gets number of calls to propagation conflict analysis that yield at least one conflict constraint */
5468  SCIP_CONFLICT* conflict /**< conflict analysis data */
5469  )
5470 {
5471  assert(conflict != NULL);
5472 
5473  return conflict->npropsuccess;
5474 }
5475 
5476 /** gets number of conflict constraints detected in propagation conflict analysis */
5478  SCIP_CONFLICT* conflict /**< conflict analysis data */
5479  )
5480 {
5481  assert(conflict != NULL);
5482 
5483  return conflict->npropconfconss;
5484 }
5485 
5486 /** gets total number of literals in conflict constraints created in propagation conflict analysis */
5488  SCIP_CONFLICT* conflict /**< conflict analysis data */
5489  )
5490 {
5491  assert(conflict != NULL);
5492 
5493  return conflict->npropconfliterals;
5494 }
5495 
5496 /** gets number of reconvergence constraints detected in propagation conflict analysis */
5498  SCIP_CONFLICT* conflict /**< conflict analysis data */
5499  )
5500 {
5501  assert(conflict != NULL);
5502 
5503  return conflict->npropreconvconss;
5504 }
5505 
5506 /** gets total number of literals in reconvergence constraints created in propagation conflict analysis */
5508  SCIP_CONFLICT* conflict /**< conflict analysis data */
5509  )
5510 {
5511  assert(conflict != NULL);
5512 
5513  return conflict->npropreconvliterals;
5514 }
5515 
5516 
5517 
5518 
5519 /*
5520  * Infeasible LP Conflict Analysis
5521  */
5522 
5523 /** ensures, that side change arrays can store at least num entries */
5524 static
5526  SCIP_SET* set, /**< global SCIP settings */
5527  int** sidechginds, /**< pointer to side change index array */
5528  SCIP_Real** sidechgoldlhss, /**< pointer to side change old left hand sides array */
5529  SCIP_Real** sidechgoldrhss, /**< pointer to side change old right hand sides array */
5530  SCIP_Real** sidechgnewlhss, /**< pointer to side change new left hand sides array */
5531  SCIP_Real** sidechgnewrhss, /**< pointer to side change new right hand sides array */
5532  int* sidechgssize, /**< pointer to size of side change arrays */
5533  int num /**< minimal number of entries to be able to store in side change arrays */
5534  )
5535 {
5536  assert(sidechginds != NULL);
5537  assert(sidechgoldlhss != NULL);
5538  assert(sidechgoldrhss != NULL);
5539  assert(sidechgnewlhss != NULL);
5540  assert(sidechgnewrhss != NULL);
5541  assert(sidechgssize != NULL);
5542 
5543  if( num > *sidechgssize )
5544  {
5545  int newsize;
5546 
5547  newsize = SCIPsetCalcMemGrowSize(set, num);
5548  SCIP_CALL( SCIPsetReallocBufferArray(set, sidechginds, newsize) );
5549  SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgoldlhss, newsize) );
5550  SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgoldrhss, newsize) );
5551  SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgnewlhss, newsize) );
5552  SCIP_CALL( SCIPsetReallocBufferArray(set, sidechgnewrhss, newsize) );
5553  *sidechgssize = newsize;
5554  }
5555  assert(num <= *sidechgssize);
5556 
5557  return SCIP_OKAY;
5558 }
5559 
5560 /** adds removal of row's side to side change arrays; finite sides are only replaced by near infinite sides, such
5561  * that the row's sense in the LP solver is not changed
5562  */
5563 static
5565  SCIP_SET* set, /**< global SCIP settings */
5566  SCIP_ROW* row, /**< LP row to change the sides for */
5567  SCIP_Real lpiinfinity, /**< value treated as infinity in LP solver */
5568  int** sidechginds, /**< pointer to side change index array */
5569  SCIP_Real** sidechgoldlhss, /**< pointer to side change old left hand sides array */
5570  SCIP_Real** sidechgoldrhss, /**< pointer to side change old right hand sides array */
5571  SCIP_Real** sidechgnewlhss, /**< pointer to side change new left hand sides array */
5572  SCIP_Real** sidechgnewrhss, /**< pointer to side change new right hand sides array */
5573  int* sidechgssize, /**< pointer to size of side change arrays */
5574  int* nsidechgs /**< pointer to number of used slots in side change arrays */
5575  )
5576 {
5577  SCIP_Real lhs;
5578  SCIP_Real rhs;
5579  SCIP_Real constant;
5580 
5581  assert(sidechginds != NULL);
5582  assert(sidechgoldlhss != NULL);
5583  assert(sidechgoldrhss != NULL);
5584  assert(sidechgnewlhss != NULL);
5585  assert(sidechgnewrhss != NULL);
5586  assert(sidechgssize != NULL);
5587  assert(nsidechgs != NULL);
5588 
5589  lhs = SCIProwGetLhs(row);
5590  rhs = SCIProwGetRhs(row);
5591  constant = SCIProwGetConstant(row);
5592  assert(!SCIPsetIsInfinity(set, -lhs) || !SCIPsetIsInfinity(set, rhs));
5593 
5594  /* get memory to store additional side change */
5595  SCIP_CALL( ensureSidechgsSize(set, sidechginds, sidechgoldlhss, sidechgoldrhss, sidechgnewlhss, sidechgnewrhss, \
5596  sidechgssize, (*nsidechgs)+1) );
5597  assert(*nsidechgs < *sidechgssize);
5598  assert(*sidechginds != NULL);
5599  assert(*sidechgoldlhss != NULL);
5600  assert(*sidechgoldrhss != NULL);
5601  assert(*sidechgnewlhss != NULL);
5602  assert(*sidechgnewrhss != NULL);
5603 
5604  /* store side change */
5605  (*sidechginds)[*nsidechgs] = SCIProwGetLPPos(row);
5606  if( SCIPsetIsInfinity(set, -lhs) )
5607  {
5608  (*sidechgoldlhss)[*nsidechgs] = -lpiinfinity;
5609  (*sidechgnewlhss)[*nsidechgs] = -lpiinfinity;
5610  }
5611  else
5612  {
5613  (*sidechgoldlhss)[*nsidechgs] = lhs - constant;
5614  (*sidechgnewlhss)[*nsidechgs] = -lpiinfinity;
5615  }
5616  if( SCIPsetIsInfinity(set, rhs) )
5617  {
5618  (*sidechgoldrhss)[*nsidechgs] = lpiinfinity;
5619  (*sidechgnewrhss)[*nsidechgs] = lpiinfinity;
5620  }
5621  else
5622  {
5623  (*sidechgoldrhss)[*nsidechgs] = rhs - constant;
5624  (*sidechgnewrhss)[*nsidechgs] = lpiinfinity;
5625  }
5626  (*nsidechgs)++;
5627 
5628  return SCIP_OKAY;
5629 }
5630 
5631 /** inserts variable's new bounds into bound change arrays */
5632 static
5634  SCIP_SET* set, /**< global SCIP settings */
5635  SCIP_VAR* var, /**< variable to change the LP bounds for */
5636  SCIP_Real newlb, /**< new lower bound */
5637  SCIP_Real newub, /**< new upper bound */
5638  SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change */
5639  SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change */
5640  SCIP_LPI* lpi /**< pointer to LPi to access infinity of LP solver; necessary to set correct value */
5641  )
5642 {
5643  assert(newlb <= newub);
5644  assert(oldlpbdchgs != NULL);
5645  assert(relaxedlpbdchgs != NULL);
5646 
5648  {
5649  SCIP_COL* col;
5650  int idx;
5651  int c;
5652 
5653  col = SCIPvarGetCol(var);
5654  c = SCIPcolGetLPPos(col);
5655 
5656  if( c >= 0 )
5657  {
5658  /* store old bound change for resetting the LP later */
5659  if( !oldlpbdchgs->usedcols[c] )
5660  {
5661  idx = oldlpbdchgs->nbdchgs;
5662  oldlpbdchgs->usedcols[c] = TRUE;
5663  oldlpbdchgs->bdchgcolinds[c] = idx;
5664  oldlpbdchgs->nbdchgs++;
5665 
5666  oldlpbdchgs->bdchginds[idx] = c;
5667  oldlpbdchgs->bdchglbs[idx] = SCIPvarGetLbLP(var, set);
5668  oldlpbdchgs->bdchgubs[idx] = SCIPvarGetUbLP(var, set);
5669  }
5670  assert(oldlpbdchgs->bdchginds[oldlpbdchgs->bdchgcolinds[c]] == c);
5671  assert((SCIPlpiIsInfinity(lpi, -oldlpbdchgs->bdchglbs[oldlpbdchgs->bdchgcolinds[c]]) && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var, set))) ||
5672  SCIPsetIsEQ(set, oldlpbdchgs->bdchglbs[oldlpbdchgs->bdchgcolinds[c]], SCIPvarGetLbLP(var, set)));
5673  assert((SCIPlpiIsInfinity(lpi, oldlpbdchgs->bdchgubs[oldlpbdchgs->bdchgcolinds[c]]) && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var, set))) ||
5674  SCIPsetIsEQ(set, oldlpbdchgs->bdchgubs[oldlpbdchgs->bdchgcolinds[c]], SCIPvarGetUbLP(var, set)));
5675 
5676  /* store bound change for conflict analysis */
5677  if( !relaxedlpbdchgs->usedcols[c] )
5678  {
5679  idx = relaxedlpbdchgs->nbdchgs;
5680  relaxedlpbdchgs->usedcols[c] = TRUE;
5681  relaxedlpbdchgs->bdchgcolinds[c] = idx;
5682  relaxedlpbdchgs->nbdchgs++;
5683 
5684  /* remember the positive for later further bound widenings */
5685  relaxedlpbdchgs->bdchginds[idx] = c;
5686  }
5687  else
5688  {
5689  idx = relaxedlpbdchgs->bdchgcolinds[c];
5690  assert(relaxedlpbdchgs->bdchginds[idx] == c);
5691 
5692  /* the new bound should be the same or more relaxed */
5693  assert(relaxedlpbdchgs->bdchglbs[idx] >= newlb ||
5694  (SCIPlpiIsInfinity(lpi, -relaxedlpbdchgs->bdchglbs[idx]) && SCIPsetIsInfinity(set, -newlb)));
5695  assert(relaxedlpbdchgs->bdchgubs[idx] <= newub ||
5696  (SCIPlpiIsInfinity(lpi, relaxedlpbdchgs->bdchgubs[idx]) && SCIPsetIsInfinity(set, newub)));
5697  }
5698 
5699  /* set the new bounds for the LP with the correct infinity value */
5700  relaxedlpbdchgs->bdchglbs[idx] = SCIPsetIsInfinity(set, -newlb) ? -SCIPlpiInfinity(lpi) : newlb;
5701  relaxedlpbdchgs->bdchgubs[idx] = SCIPsetIsInfinity(set, newub) ? SCIPlpiInfinity(lpi) : newub;
5702  if( SCIPsetIsInfinity(set, -oldlpbdchgs->bdchglbs[idx]) )
5703  oldlpbdchgs->bdchglbs[idx] = -SCIPlpiInfinity(lpi);
5704  if( SCIPsetIsInfinity(set, oldlpbdchgs->bdchgubs[idx]) )
5705  oldlpbdchgs->bdchgubs[idx] = SCIPlpiInfinity(lpi);
5706  }
5707  }
5708 
5709  return SCIP_OKAY;
5710 }
5711 
5712 /** ensures, that candidate array can store at least num entries */
5713 static
5715  SCIP_SET* set, /**< global SCIP settings */
5716  SCIP_VAR*** cands, /**< pointer to candidate array */
5717  SCIP_Real** candscores, /**< pointer to candidate score array */
5718  SCIP_Real** newbounds, /**< pointer to candidate new bounds array */
5719  SCIP_Real** proofactdeltas, /**< pointer to candidate proof delta array */
5720  int* candssize, /**< pointer to size of array */
5721  int num /**< minimal number of candidates to store in array */
5722  )
5723 {
5724  assert(cands != NULL);
5725  assert(candssize != NULL);
5726 
5727  if( num > *candssize )
5728  {
5729  int newsize;
5730 
5731  newsize = SCIPsetCalcMemGrowSize(set, num);
5732  SCIP_CALL( SCIPsetReallocBufferArray(set, cands, newsize) );
5733  SCIP_CALL( SCIPsetReallocBufferArray(set, candscores, newsize) );
5734  SCIP_CALL( SCIPsetReallocBufferArray(set, newbounds, newsize) );
5735  SCIP_CALL( SCIPsetReallocBufferArray(set, proofactdeltas, newsize) );
5736  *candssize = newsize;
5737  }
5738  assert(num <= *candssize);
5739 
5740  return SCIP_OKAY;
5741 }
5742 
5743 /** adds variable to candidate list, if the current best bound corresponding to the proof coefficient is local;
5744  * returns the array position in the candidate list, where the new candidate was inserted, or -1 if the
5745  * variable can relaxed to global bounds immediately without increasing the proof's activity;
5746  * the candidates are sorted with respect to the following two criteria:
5747  * - prefer bound changes that have been applied deeper in the tree, to get a more global conflict
5748  * - prefer variables with small Farkas coefficient to get rid of as many bound changes as possible
5749  */
5750 static
5752  SCIP_SET* set, /**< global SCIP settings */
5753  int currentdepth, /**< current depth in the tree */
5754  SCIP_VAR* var, /**< variable to add to candidate array */
5755  int lbchginfopos, /**< positions of currently active lower bound change information in variable's array */
5756  int ubchginfopos, /**< positions of currently active upper bound change information in variable's array */
5757  SCIP_Real proofcoef, /**< coefficient of variable in infeasibility/bound proof */
5758  SCIP_Real prooflhs, /**< left hand side of infeasibility/bound proof */
5759  SCIP_Real proofact, /**< activity of infeasibility/bound proof row */
5760  SCIP_VAR*** cands, /**< pointer to candidate array for undoing bound changes */
5761  SCIP_Real** candscores, /**< pointer to candidate score array for undoing bound changes */
5762  SCIP_Real** newbounds, /**< pointer to candidate new bounds array for undoing bound changes */
5763  SCIP_Real** proofactdeltas, /**< pointer to proof activity increase array for undoing bound changes */
5764  int* candssize, /**< pointer to size of cands arrays */
5765  int* ncands, /**< pointer to count number of candidates in bound change list */
5766  int firstcand /**< position of first unprocessed bound change candidate */
5767  )
5768 {
5769  SCIP_Real oldbound;
5770  SCIP_Real newbound;
5771  SCIP_Real proofactdelta;
5772  SCIP_Real score;
5773  int depth;
5774  int i;
5775  SCIP_Bool resolvable;
5776 
5777  assert(set != NULL);
5778  assert(var != NULL);
5779  assert(-1 <= lbchginfopos && lbchginfopos <= var->nlbchginfos);
5780  assert(-1 <= ubchginfopos && ubchginfopos <= var->nubchginfos);
5781  assert(!SCIPsetIsZero(set, proofcoef));
5782  assert(SCIPsetIsGT(set, prooflhs, proofact));
5783  assert(cands != NULL);
5784  assert(candscores != NULL);
5785  assert(newbounds != NULL);
5786  assert(proofactdeltas != NULL);
5787  assert(candssize != NULL);
5788  assert(ncands != NULL);
5789  assert(*ncands <= *candssize);
5790  assert(0 <= firstcand && firstcand <= *ncands);
5791 
5792  /* in the infeasibility or dual bound proof, the variable's bound is chosen to maximize the proof's activity */
5793  if( proofcoef > 0.0 )
5794  {
5795  assert(ubchginfopos >= 0); /* otherwise, undoBdchgsProof() should already have relaxed the local bound */
5796 
5797  /* calculate the difference of current bound to the previous bound the variable was set to */
5798  if( ubchginfopos == var->nubchginfos )
5799  {
5800  /* current bound is the strong branching or diving bound */
5801  oldbound = SCIPvarGetUbLP(var, set);
5802  newbound = SCIPvarGetUbLocal(var);
5803  depth = currentdepth+1;
5804  resolvable = FALSE;
5805  }
5806  else
5807  {
5808  /* current bound is the result of a local bound change */
5809  resolvable = bdchginfoIsResolvable(&var->ubchginfos[ubchginfopos]);
5810  depth = var->ubchginfos[ubchginfopos].bdchgidx.depth;
5811  oldbound = var->ubchginfos[ubchginfopos].newbound;
5812  newbound = var->ubchginfos[ubchginfopos].oldbound;
5813  }
5814  }
5815  else
5816  {
5817  assert(lbchginfopos >= 0); /* otherwise, undoBdchgsProof() should already have relaxed the local bound */
5818 
5819  /* calculate the difference of current bound to the previous bound the variable was set to */
5820  if( lbchginfopos == var->nlbchginfos )
5821  {
5822  /* current bound is the strong branching or diving bound */
5823  oldbound = SCIPvarGetLbLP(var, set);
5824  newbound = SCIPvarGetLbLocal(var);
5825  depth = currentdepth+1;
5826  resolvable = FALSE;
5827  }
5828  else
5829  {
5830  /* current bound is the result of a local bound change */
5831  resolvable = bdchginfoIsResolvable(&var->lbchginfos[lbchginfopos]);
5832  depth = var->lbchginfos[lbchginfopos].bdchgidx.depth;
5833  oldbound = var->lbchginfos[lbchginfopos].newbound;
5834  newbound = var->lbchginfos[lbchginfopos].oldbound;
5835  }
5836  }
5837 
5838  /* calculate the increase in the proof's activity */
5839  proofactdelta = (newbound - oldbound)*proofcoef;
5840  assert(proofactdelta > 0.0);
5841 
5842 
5843  /* calculate score for undoing the bound change */
5844  score = calcBdchgScore(prooflhs, proofact, proofactdelta, proofcoef, depth, currentdepth, var, set);
5845 
5846  if( !resolvable )
5847  {
5848  score += 10.0;
5849  if( !SCIPvarIsBinary(var) )
5850  score += 10.0;
5851  }
5852 
5853  /* get enough memory to store new candidate */
5854  SCIP_CALL( ensureCandsSize(set, cands, candscores, newbounds, proofactdeltas, candssize, (*ncands)+1) );
5855  assert(*cands != NULL);
5856  assert(*candscores != NULL);
5857  assert(*newbounds != NULL);
5858  assert(*proofactdeltas != NULL);
5859 
5860  SCIPsetDebugMsg(set, " -> local <%s> %s %g, relax <%s> %s %g, proofcoef=%g, dpt=%d, resolve=%u, delta=%g, score=%g\n",
5861  SCIPvarGetName(var), proofcoef > 0.0 ? "<=" : ">=", oldbound,
5862  SCIPvarGetName(var), proofcoef > 0.0 ? "<=" : ">=", newbound,
5863  proofcoef, depth, resolvable, proofactdelta, score);
5864 
5865  /* insert variable in candidate list without touching the already processed candidates */
5866  for( i = *ncands; i > firstcand && score > (*candscores)[i-1]; --i )
5867  {
5868  (*cands)[i] = (*cands)[i-1];
5869  (*candscores)[i] = (*candscores)[i-1];
5870  (*newbounds)[i] = (*newbounds)[i-1];
5871  (*proofactdeltas)[i] = (*proofactdeltas)[i-1];
5872  }
5873  (*cands)[i] = var;
5874  (*candscores)[i] = score;
5875  (*newbounds)[i] = newbound;
5876  (*proofactdeltas)[i] = proofactdelta;
5877  (*ncands)++;
5878 
5879  return SCIP_OKAY;
5880 }
5881 
5882 /** after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
5883  * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
5884  * global bound and we can ignore it by installing a -1 as the corresponding bound change info position
5885  */
5886 static
5888  SCIP_VAR* var, /**< problem variable */
5889  int* lbchginfopos, /**< pointer to lower bound change information position */
5890  int* ubchginfopos /**< pointer to upper bound change information position */
5891  )
5892 {
5893  assert(var != NULL);
5894  assert(lbchginfopos != NULL);
5895  assert(ubchginfopos != NULL);
5896  assert(-1 <= *lbchginfopos && *lbchginfopos <= var->nlbchginfos);
5897  assert(-1 <= *ubchginfopos && *ubchginfopos <= var->nubchginfos);
5898  assert(*lbchginfopos == -1 || *lbchginfopos == var->nlbchginfos
5899  || var->lbchginfos[*lbchginfopos].redundant
5900  == (var->lbchginfos[*lbchginfopos].oldbound == var->lbchginfos[*lbchginfopos].newbound)); /*lint !e777*/
5901  assert(*ubchginfopos == -1 || *ubchginfopos == var->nubchginfos
5902  || var->ubchginfos[*ubchginfopos].redundant
5903  == (var->ubchginfos[*ubchginfopos].oldbound == var->ubchginfos[*ubchginfopos].newbound)); /*lint !e777*/
5904 
5905  if( *lbchginfopos >= 0 && *lbchginfopos < var->nlbchginfos && var->lbchginfos[*lbchginfopos].redundant )
5906  {
5907  assert(SCIPvarGetLbGlobal(var) == var->lbchginfos[*lbchginfopos].oldbound); /*lint !e777*/
5908  *lbchginfopos = -1;
5909  }
5910  if( *ubchginfopos >= 0 && *ubchginfopos < var->nubchginfos && var->ubchginfos[*ubchginfopos].redundant )
5911  {
5912  assert(SCIPvarGetUbGlobal(var) == var->ubchginfos[*ubchginfopos].oldbound); /*lint !e777*/
5913  *ubchginfopos = -1;
5914  }
5915 }
5916 
5917 /** undoes bound changes on variables, still leaving the given infeasibility proof valid */
5918 static
5920  SCIP_SET* set, /**< global SCIP settings */
5921  SCIP_PROB* prob, /**< problem data */
5922  int currentdepth, /**< current depth in the tree */
5923  SCIP_Real* proofcoefs, /**< coefficients in infeasibility proof */
5924  SCIP_Real prooflhs, /**< left hand side of proof */
5925  SCIP_Real* proofact, /**< current activity of proof */
5926  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
5927  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
5928  int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
5929  int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
5930  SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
5931  SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
5932  SCIP_Bool* resolve, /**< pointer to store whether the changed LP should be resolved again, or NULL */
5933  SCIP_LPI* lpi /**< pointer to LPi to access infinity of LP solver; necessary to set correct values */
5934  )
5935 {
5936  SCIP_VAR** vars;
5937  SCIP_VAR** cands;
5938  SCIP_Real* candscores;
5939  SCIP_Real* newbounds;
5940  SCIP_Real* proofactdeltas;
5941  int nvars;
5942  int ncands;
5943  int candssize;
5944  int v;
5945  int i;
5946 
5947  assert(prob != NULL);
5948  assert(proofcoefs != NULL);
5949  assert(SCIPsetIsFeasGT(set, prooflhs, (*proofact)));
5950  assert(curvarlbs != NULL);
5951  assert(curvarubs != NULL);
5952  assert(lbchginfoposs != NULL);
5953  assert(ubchginfoposs != NULL);
5954 
5955  if( resolve != NULL )
5956  *resolve = FALSE;
5957 
5958  vars = prob->vars;
5959  nvars = prob->nvars;
5960  assert(nvars == 0 || vars != NULL);
5961 
5962  /* calculate the order in which the bound changes are tried to be undone, and relax all bounds if this doesn't
5963  * increase the proof's activity
5964  */
5965  SCIP_CALL( SCIPsetAllocBufferArray(set, &cands, nvars) );
5966  SCIP_CALL( SCIPsetAllocBufferArray(set, &candscores, nvars) );
5967  SCIP_CALL( SCIPsetAllocBufferArray(set, &newbounds, nvars) );
5968  SCIP_CALL( SCIPsetAllocBufferArray(set, &proofactdeltas, nvars) );
5969  ncands = 0;
5970  candssize = nvars;
5971  for( v = 0; v < nvars; ++v )
5972  {
5973  SCIP_VAR* var;
5974  SCIP_Bool relaxed;
5975 
5976  var = vars[v];
5977 
5978  /* after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
5979  * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
5980  * global bound and we can ignore it
5981  */
5982  skipRedundantBdchginfos(var, &lbchginfoposs[v], &ubchginfoposs[v]);
5983 
5984  /* ignore variables already relaxed to global bounds */
5985  if( (lbchginfoposs[v] == -1 && ubchginfoposs[v] == -1) )
5986  {
5987  proofcoefs[v] = 0.0;
5988  continue;
5989  }
5990 
5991  /* relax bounds that are not used in the proof to the global bounds */
5992  relaxed = FALSE;
5993  if( !SCIPsetIsNegative(set, proofcoefs[v]) )
5994  {
5995  /* the lower bound is not used */
5996  if( lbchginfoposs[v] >= 0 )
5997  {
5998  SCIPsetDebugMsg(set, " -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g\n",
5999  SCIPvarGetName(var), curvarlbs[v], curvarubs[v], SCIPvarGetLbGlobal(var), curvarubs[v],
6000  proofcoefs[v], prooflhs, (*proofact));
6001  curvarlbs[v] = SCIPvarGetLbGlobal(var);
6002  lbchginfoposs[v] = -1;
6003  relaxed = TRUE;
6004  }
6005  }
6006  if( !SCIPsetIsPositive(set, proofcoefs[v]) )
6007  {
6008  /* the upper bound is not used */
6009  if( ubchginfoposs[v] >= 0 )
6010  {
6011  SCIPsetDebugMsg(set, " -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g\n",
6012  SCIPvarGetName(var), curvarlbs[v], curvarubs[v], curvarlbs[v], SCIPvarGetUbGlobal(var),
6013  proofcoefs[v], prooflhs, (*proofact));
6014  curvarubs[v] = SCIPvarGetUbGlobal(var);
6015  ubchginfoposs[v] = -1;
6016  relaxed = TRUE;
6017  }
6018  }
6019  if( relaxed && oldlpbdchgs != NULL )
6020  {
6021  SCIP_CALL( addBdchg(set, var, curvarlbs[v], curvarubs[v], oldlpbdchgs, relaxedlpbdchgs, lpi) );
6022  }
6023 
6024  /* add bound to candidate list */
6025  if( lbchginfoposs[v] >= 0 || ubchginfoposs[v] >= 0 )
6026  {
6027  SCIP_CALL( addCand(set, currentdepth, var, lbchginfoposs[v], ubchginfoposs[v], proofcoefs[v],
6028  prooflhs, (*proofact), &cands, &candscores, &newbounds, &proofactdeltas, &candssize, &ncands, 0) );
6029  }
6030  /* we can set the proof coefficient to zero, because the variable is not needed */
6031  else
6032  proofcoefs[v] = 0.0;
6033  }
6034 
6035  /* try to undo remaining local bound changes while still keeping the proof row violated:
6036  * bound changes can be undone, if prooflhs > proofact + proofactdelta;
6037  * afterwards, the current proof activity has to be updated
6038  */
6039  for( i = 0; i < ncands; ++i )
6040  {
6041  assert(proofactdeltas[i] > 0.0);
6042  assert((lbchginfoposs[SCIPvarGetProbindex(cands[i])] >= 0) != (ubchginfoposs[SCIPvarGetProbindex(cands[i])] >= 0));
6043 
6044  /* when relaxing a constraint we still need to stay infeasible; therefore we need to do the comparison in
6045  * feasibility tolerance because if 'prooflhs' is (feas-))equal to 'proofact + proofactdeltas[i]' it would mean
6046  * that there is no violation
6047  */
6048  if( SCIPsetIsFeasGT(set, prooflhs, (*proofact) + proofactdeltas[i]) )
6049  {
6050  v = SCIPvarGetProbindex(cands[i]);
6051  assert(0 <= v && v < nvars);
6052  assert((lbchginfoposs[v] >= 0) != (ubchginfoposs[v] >= 0));
6053 
6054  SCIPsetDebugMsg(set, " -> relaxing variable <%s>[%g,%g] to [%g,%g]: proofcoef=%g, %g <= %g + %g\n",
6055  SCIPvarGetName(cands[i]), curvarlbs[v], curvarubs[v],
6056  proofcoefs[v] > 0.0 ? curvarlbs[v] : newbounds[i],
6057  proofcoefs[v] > 0.0 ? newbounds[i] : curvarubs[v],
6058  proofcoefs[v], prooflhs, (*proofact), proofactdeltas[i]);
6059 
6060  assert((SCIPsetIsPositive(set, proofcoefs[v]) && SCIPsetIsGT(set, newbounds[i], curvarubs[v]))
6061  || (SCIPsetIsNegative(set, proofcoefs[v]) && SCIPsetIsLT(set, newbounds[i], curvarlbs[v])));
6062  assert((SCIPsetIsPositive(set, proofcoefs[v])
6063  && SCIPsetIsEQ(set, proofactdeltas[i], (newbounds[i] - curvarubs[v])*proofcoefs[v]))
6064  || (SCIPsetIsNegative(set, proofcoefs[v])
6065  && SCIPsetIsEQ(set, proofactdeltas[i], (newbounds[i] - curvarlbs[v])*proofcoefs[v])));
6066  assert(!SCIPsetIsZero(set, proofcoefs[v]));
6067 
6068  if( proofcoefs[v] > 0.0 )
6069  {
6070  assert(ubchginfoposs[v] >= 0);
6071  assert(lbchginfoposs[v] == -1);
6072  curvarubs[v] = newbounds[i];
6073  ubchginfoposs[v]--;
6074  }
6075  else
6076  {
6077  assert(lbchginfoposs[v] >= 0);
6078  assert(ubchginfoposs[v] == -1);
6079  curvarlbs[v] = newbounds[i];
6080  lbchginfoposs[v]--;
6081  }
6082  if( oldlpbdchgs != NULL )
6083  {
6084  SCIP_CALL( addBdchg(set, cands[i], curvarlbs[v], curvarubs[v], oldlpbdchgs, relaxedlpbdchgs, lpi) );
6085  }
6086  (*proofact) += proofactdeltas[i];
6087  if( resolve != NULL && SCIPvarIsInLP(cands[i]) )
6088  *resolve = TRUE;
6089 
6090  /* after changing the global bound of a variable, the bdchginfos that are now redundant are replaced with
6091  * oldbound = newbound = global bound; if the current bdchginfo is of such kind, the bound is equal to the
6092  * global bound and we can ignore it
6093  */
6094  skipRedundantBdchginfos(cands[i], &lbchginfoposs[v], &ubchginfoposs[v]);
6095 
6096  /* insert the new local bound of the variable into the candidate list */
6097  if( lbchginfoposs[v] >= 0 || ubchginfoposs[v] >= 0 )
6098  {
6099  SCIP_CALL( addCand(set, currentdepth, cands[i], lbchginfoposs[v], ubchginfoposs[v], proofcoefs[v],
6100  prooflhs, (*proofact), &cands, &candscores, &newbounds, &proofactdeltas, &candssize, &ncands, i+1) );
6101  }
6102  else
6103  proofcoefs[v] = 0.0;
6104  }
6105  }
6106 
6107  /* free the buffer for the sorted bound change candidates */
6108  SCIPsetFreeBufferArray(set, &proofactdeltas);
6109  SCIPsetFreeBufferArray(set, &newbounds);
6110  SCIPsetFreeBufferArray(set, &candscores);
6111  SCIPsetFreeBufferArray(set, &cands);
6112 
6113  return SCIP_OKAY;
6114 }
6115 
6116 /* because calculations might cancel out some values, we stop the infeasibility analysis if a value is bigger than
6117  * 2^53 = 9007199254740992
6118  */
6119 #define NUMSTOP 9007199254740992.0
6120 
6121 /** analyzes an infeasible LP and undoes additional bound changes while staying infeasible */
6122 static
6124  SCIP_SET* set, /**< global SCIP settings */
6125  SCIP_PROB* prob, /**< problem data */
6126  SCIP_LP* lp, /**< LP data */
6127  int currentdepth, /**< current depth in the tree */
6128  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
6129  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
6130  int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
6131  int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
6132  SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
6133  SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
6134  SCIP_Bool* valid, /**< pointer to store whether the unfixings are valid */
6135  SCIP_Bool* resolve, /**< pointer to store whether the changed LP should be resolved again */
6136  SCIP_Real* farkascoefs, /**< coefficients in the proof constraint */
6137  SCIP_Real farkaslhs, /**< lhs of the proof constraint */
6138  SCIP_Real* farkasactivity /**< maximal activity of the proof constraint */
6139  )
6140 {
6141  SCIP_LPI* lpi;
6142 
6143  assert(prob != NULL);
6144  assert(lp != NULL);
6145  assert(lp->flushed);
6146  assert(lp->solved);
6147  assert(curvarlbs != NULL);
6148  assert(curvarubs != NULL);
6149  assert(lbchginfoposs != NULL);
6150  assert(ubchginfoposs != NULL);
6151  assert(valid != NULL);
6152  assert(resolve != NULL);
6153 
6154  SCIPsetDebugMsg(set, "undoing bound changes in infeasible LP: cutoff=%g\n", lp->cutoffbound);
6155 
6156  *valid = FALSE;
6157  *resolve = FALSE;
6158 
6159  lpi = SCIPlpGetLPI(lp);
6160 
6161  /* check, if the Farkas row is still violated (using current bounds and ignoring local rows) */
6162  if( SCIPsetIsFeasGT(set, farkaslhs, *farkasactivity) )
6163  {
6164  /* undo bound changes while keeping the infeasibility proof valid */
6165  SCIP_CALL( undoBdchgsProof(set, prob, currentdepth, farkascoefs, farkaslhs, farkasactivity, \
6166  curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, resolve, lpi) );
6167 
6168  *valid = TRUE;
6169 
6170  /* resolving does not make sense: the old dual ray is still valid -> resolving will not change the solution */
6171  *resolve = FALSE;
6172  }
6173 
6174  return SCIP_OKAY;
6175 }
6176 
6177 /** analyzes an LP exceeding the objective limit and undoes additional bound changes while staying beyond the
6178  * objective limit
6179  */
6180 static
6182  SCIP_SET* set, /**< global SCIP settings */
6183  SCIP_PROB* prob, /**< problem data */
6184  SCIP_LP* lp, /**< LP data */
6185  int currentdepth, /**< current depth in the tree */
6186  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
6187  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
6188  int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
6189  int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
6190  SCIP_LPBDCHGS* oldlpbdchgs, /**< old LP bound changes used for reset the LP bound change, or NULL */
6191  SCIP_LPBDCHGS* relaxedlpbdchgs, /**< relaxed LP bound changes used for reset the LP bound change, or NULL */
6192  SCIP_Bool* valid, /**< pointer to store whether the unfixings are valid */
6193  SCIP_Bool* resolve, /**< pointer to store whether the changed LP should be resolved again */
6194  SCIP_Real* dualcoefs, /**< coefficients in the proof constraint */
6195  SCIP_Real duallhs, /**< lhs of the proof constraint */
6196  SCIP_Real* dualactivity /**< maximal activity of the proof constraint */
6197  )
6198 {
6199  SCIP_LPI* lpi;
6200 
6201  assert(set != NULL);
6202  assert(prob != NULL);
6203  assert(lp != NULL);
6204  assert(lp->flushed);
6205  assert(lp->solved);
6206  assert(curvarlbs != NULL);
6207  assert(curvarubs != NULL);
6208  assert(lbchginfoposs != NULL);
6209  assert(ubchginfoposs != NULL);
6210  assert(valid != NULL);
6211  assert(resolve != NULL);
6212 
6213  *valid = FALSE;
6214  *resolve = FALSE;
6215 
6216  SCIPsetDebugMsg(set, "undoing bound changes in LP exceeding cutoff: cutoff=%g\n", lp->cutoffbound);
6217 
6218  /* get LP solver interface */
6219  lpi = SCIPlpGetLPI(lp);
6220 
6221  /* check, if the dual row is still violated (using current bounds and ignoring local rows) */
6222  if( SCIPsetIsFeasGT(set, duallhs, *dualactivity) )
6223  {
6224  /* undo bound changes while keeping the infeasibility proof valid */
6225  SCIP_CALL( undoBdchgsProof(set, prob, currentdepth, dualcoefs, duallhs, dualactivity, curvarlbs, curvarubs, \
6226  lbchginfoposs, ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, resolve, lpi) );
6227 
6228  *valid = TRUE;
6229  }
6230 
6231  return SCIP_OKAY;
6232 }
6233 
6234 /** applies conflict analysis starting with given bound changes, that could not be undone during previous
6235  * infeasibility analysis
6236  */
6237 static
6239  SCIP_CONFLICT* conflict, /**< conflict analysis data */
6240  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
6241  SCIP_SET* set, /**< global SCIP settings */
6242  SCIP_STAT* stat, /**< problem statistics */
6243  SCIP_PROB* prob, /**< problem data */
6244  SCIP_TREE* tree, /**< branch and bound tree */
6245  SCIP_Bool diving, /**< are we in strong branching or diving mode? */
6246  int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
6247  int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
6248  int* nconss, /**< pointer to store the number of generated conflict constraints */
6249  int* nliterals, /**< pointer to store the number of literals in generated conflict constraints */
6250  int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
6251  int* nreconvliterals /**< pointer to store the number of literals generated reconvergence constraints */
6252  )
6253 {
6254  SCIP_VAR** vars;
6255  SCIP_VAR* var;
6256  SCIP_CONFTYPE conftype;
6257  SCIP_Bool usescutoffbound;
6258  int nvars;
6259  int v;
6260  int nbdchgs;
6261  int maxsize;
6262 
6263  assert(prob != NULL);
6264  assert(lbchginfoposs != NULL);
6265  assert(ubchginfoposs != NULL);
6266  assert(nconss != NULL);
6267  assert(nliterals != NULL);
6268  assert(nreconvconss != NULL);
6269  assert(nreconvliterals != NULL);
6270 
6271  *nconss = 0;
6272  *nliterals = 0;
6273  *nreconvconss = 0;
6274  *nreconvliterals = 0;
6275 
6276  vars = prob->vars;
6277  nvars = prob->nvars;
6278  assert(nvars == 0 || vars != NULL);
6279 
6280  maxsize = 2*conflictCalcMaxsize(set, prob);
6281 
6282  /* initialize conflict data */
6283  conftype = conflict->conflictset->conflicttype;
6284  usescutoffbound = conflict->conflictset->usescutoffbound;
6285 
6286  SCIP_CALL( SCIPconflictInit(conflict, set, stat, prob, conftype, usescutoffbound) );
6287 
6288  conflict->conflictset->conflicttype = conftype;
6289  conflict->conflictset->usescutoffbound = usescutoffbound;
6290 
6291  /* add remaining bound changes to conflict queue */
6292  SCIPsetDebugMsg(set, "initial conflict set after undoing bound changes:\n");
6293 
6294  nbdchgs = 0;
6295  for( v = 0; v < nvars && nbdchgs < maxsize; ++v )
6296  {
6297  var = vars[v];
6298  assert(var != NULL);
6299  assert(var->nlbchginfos >= 0);
6300  assert(var->nubchginfos >= 0);
6301  assert(-1 <= lbchginfoposs[v] && lbchginfoposs[v] <= var->nlbchginfos);
6302  assert(-1 <= ubchginfoposs[v] && ubchginfoposs[v] <= var->nubchginfos);
6303 
6304  if( lbchginfoposs[v] == var->nlbchginfos || ubchginfoposs[v] == var->nubchginfos )
6305  {
6306  SCIP_BDCHGINFO* bdchginfo;
6307  SCIP_Real relaxedbd;
6308 
6309  /* the strong branching or diving bound stored in the column is responsible for the conflict:
6310  * it cannot be resolved and therefore has to be directly put into the conflict set
6311  */
6312  assert((lbchginfoposs[v] == var->nlbchginfos) != (ubchginfoposs[v] == var->nubchginfos)); /* only one can be tight in the dual! */
6313  assert(lbchginfoposs[v] < var->nlbchginfos || SCIPvarGetLbLP(var, set) > SCIPvarGetLbLocal(var));
6314  assert(ubchginfoposs[v] < var->nubchginfos || SCIPvarGetUbLP(var, set) < SCIPvarGetUbLocal(var));
6315 
6316  /* create an artificial bound change information for the diving/strong branching bound change;
6317  * they are freed in the SCIPconflictFlushConss() call
6318  */
6319  if( lbchginfoposs[v] == var->nlbchginfos )
6320  {
6321  SCIP_CALL( conflictCreateTmpBdchginfo(conflict, blkmem, set, var, SCIP_BOUNDTYPE_LOWER,
6322  SCIPvarGetLbLocal(var), SCIPvarGetLbLP(var, set), &bdchginfo) );
6323  relaxedbd = SCIPvarGetLbLP(var, set);
6324  }
6325  else
6326  {
6327  SCIP_CALL( conflictCreateTmpBdchginfo(conflict, blkmem, set, var, SCIP_BOUNDTYPE_UPPER,
6328  SCIPvarGetUbLocal(var), SCIPvarGetUbLP(var, set), &bdchginfo) );
6329  relaxedbd = SCIPvarGetUbLP(var, set);
6330  }
6331 
6332  /* put variable into the conflict set */
6333  SCIPsetDebugMsg(set, " force: <%s> %s %g [status: %d, type: %d, dive/strong]\n",
6334  SCIPvarGetName(var), lbchginfoposs[v] == var->nlbchginfos ? ">=" : "<=",
6335  lbchginfoposs[v] == var->nlbchginfos ? SCIPvarGetLbLP(var, set) : SCIPvarGetUbLP(var, set),
6336  SCIPvarGetStatus(var), SCIPvarGetType(var));
6337  SCIP_CALL( conflictAddConflictBound(conflict, blkmem, set, bdchginfo, relaxedbd) );
6338 
6339  /* each variable which is add to the conflict graph gets an increase in the VSIDS
6340  *
6341  * @note That is different to the VSIDS preseted in the literature
6342  */
6343  SCIP_CALL( incVSIDS(var, blkmem, set, stat, SCIPbdchginfoGetBoundtype(bdchginfo), relaxedbd, set->conf_conflictgraphweight) );
6344  nbdchgs++;
6345  }
6346  else
6347  {
6348  /* put remaining bound changes into conflict candidate queue */
6349  if( lbchginfoposs[v] >= 0 )
6350  {
6351  SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, SCIP_BOUNDTYPE_LOWER, \
6352  &var->lbchginfos[lbchginfoposs[v]], SCIPbdchginfoGetNewbound(&var->lbchginfos[lbchginfoposs[v]])) );
6353  nbdchgs++;
6354  }
6355  if( ubchginfoposs[v] >= 0 )
6356  {
6357  assert(!SCIPbdchginfoIsRedundant(&var->ubchginfos[ubchginfoposs[v]]));
6358  SCIP_CALL( conflictAddBound(conflict, blkmem, set, stat, var, SCIP_BOUNDTYPE_UPPER, \
6359  &var->ubchginfos[ubchginfoposs[v]], SCIPbdchginfoGetNewbound(&var->ubchginfos[ubchginfoposs[v]])) );
6360  nbdchgs++;
6361  }
6362  }
6363  }
6364 
6365  if( v == nvars )
6366  {
6367  /* analyze the conflict set, and create conflict constraints on success */
6368  SCIP_CALL( conflictAnalyze(conflict, blkmem, set, stat, prob, tree, diving, 0, FALSE, nconss, nliterals, \
6369  nreconvconss, nreconvliterals) );
6370  }
6371 
6372  return SCIP_OKAY;
6373 }
6374 
6375 /** calculates a Farkas proof from the current dual LP solution */
6376 static
6378  SCIP_SET* set, /**< global SCIP settings */
6379  SCIP_PROB* prob, /**< transformed problem */
6380  SCIP_LP* lp, /**< LP data */
6381  SCIP_LPI* lpi, /**< LPI data */
6382  SCIP_AGGRROW* farkasrow, /**< aggregated row representing the proof */
6383  SCIP_Real* farkasact, /**< maximal activity of the proof constraint */
6384  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
6385  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
6386  SCIP_Bool* valid /**< pointer store whether the proof constraint is valid */
6387  )
6388 {
6389  SCIP_ROW** rows;
6390  SCIP_Real* dualfarkas;
6391  SCIP_ROW* row;
6392  int nrows;
6393  int r;
6394 
6397 
6398  /* get LP rows and problem variables */
6399  rows = SCIPlpGetRows(lp);
6400  nrows = SCIPlpGetNRows(lp);
6401  assert(nrows == 0 || rows != NULL);
6402  assert(nrows == lp->nlpirows);
6403 
6404  /* it can happen that infeasibility is detetected within LP presolve. in that case, the LP solver may not be able to
6405  * to return the dual ray.
6406  */
6407  if( !SCIPlpiHasDualRay(lpi) )
6408  {
6409  *valid = FALSE;
6410  return SCIP_OKAY;
6411  }
6412 
6413  assert(farkasrow != NULL);
6414 
6415  /* allocate temporary memory */
6416  SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, nrows) );
6417  BMSclearMemoryArray(dualfarkas, nrows);
6418 
6419  /* get dual Farkas values of rows */
6420  SCIP_CALL( SCIPlpiGetDualfarkas(lpi, dualfarkas) );
6421 
6422  /* calculate the Farkas row */
6423  (*valid) = TRUE;
6424  for( r = 0; r < nrows; ++r )
6425  {
6426  row = rows[r];
6427  assert(row != NULL);
6428  assert(row->len == 0 || row->cols != NULL);
6429  assert(row->len == 0 || row->vals != NULL);
6430  assert(row == lp->lpirows[r]);
6431 
6432  /* ignore local rows and rows with Farkas value 0.0 */
6433  if( !row->local && !SCIPsetIsDualfeasZero(set, dualfarkas[r]) )
6434  {
6435 #ifndef NDEBUG
6436  {
6437  SCIP_Real lpilhs;
6438  SCIP_Real lpirhs;
6439 
6440  SCIP_CALL( SCIPlpiGetSides(lpi, r, r, &lpilhs, &lpirhs) );
6441  assert((SCIPsetIsInfinity(set, -lpilhs) && SCIPsetIsInfinity(set, -row->lhs))
6442  || SCIPsetIsRelEQ(set, lpilhs, row->lhs - row->constant));
6443  assert((SCIPsetIsInfinity(set, lpirhs) && SCIPsetIsInfinity(set, row->rhs))
6444  || SCIPsetIsRelEQ(set, lpirhs, row->rhs - row->constant));
6445  }
6446 #endif
6447 
6448  /* add row side to Farkas row lhs: dualfarkas > 0 -> lhs, dualfarkas < 0 -> rhs */
6449  if( dualfarkas[r] > 0.0 )
6450  {
6451  /* check if sign of dual Farkas value is valid */
6452  if( SCIPsetIsInfinity(set, -row->lhs) )
6453  continue;
6454 
6455  /* due to numerical reasons we want to stop */
6456  if( REALABS(dualfarkas[r] * (row->lhs - row->constant)) > NUMSTOP )
6457  {
6458  (*valid) = FALSE;
6459  goto TERMINATE;
6460  }
6461 
6462  SCIP_CALL( SCIPaggrRowAddRow(set->scip, farkasrow, row, -dualfarkas[r], -1) );
6463  }
6464  else
6465  {
6466  /* check if sign of dual Farkas value is valid */
6467  if( SCIPsetIsInfinity(set, row->rhs) )
6468  continue;
6469 
6470  /* due to numerical reasons we want to stop */
6471  if( REALABS(dualfarkas[r] * (row->rhs - row->constant)) > NUMSTOP )
6472  {
6473  (*valid) = FALSE;
6474  goto TERMINATE;
6475  }
6476 
6477  SCIP_CALL( SCIPaggrRowAddRow(set->scip, farkasrow, row, -dualfarkas[r], +1) );
6478  }
6479  SCIPsetDebugMsg(set, " -> farkasrhs: %g<%s>[%g,%g] -> %g\n", dualfarkas[r], SCIProwGetName(row),
6480  row->lhs - row->constant, row->rhs - row->constant, SCIPaggrRowGetRhs(farkasrow));
6481 
6482  /* due to numerical reasons we want to stop */
6483  if( REALABS(SCIPaggrRowGetRhs(farkasrow)) > NUMSTOP )
6484  {
6485  (*valid) = FALSE;
6486  goto TERMINATE;
6487  }
6488  }
6489 #ifdef SCIP_DEBUG
6490  else if( !SCIPsetIsZero(set, dualfarkas[r]) )
6491  {
6492  SCIPsetDebugMsg(set, " -> ignoring %s row <%s> with dual Farkas value %.10f (lhs=%g, rhs=%g)\n",
6493  row->local ? "local" : "global", SCIProwGetName(row), dualfarkas[r],
6494  row->lhs - row->constant, row->rhs - row->constant);
6495  }
6496 #endif
6497  }
6498 
6499  /* remove all coefficients that are too close to zero */
6500  SCIPaggrRowRemoveZeros(set->scip, farkasrow, valid);
6501 
6502  if( !(*valid) )
6503  goto TERMINATE;
6504 
6505  /* calculate the current Farkas activity, always using the best bound w.r.t. the Farkas coefficient */
6506  *farkasact = aggrRowGetMinActivity(prob, farkasrow, curvarlbs, curvarubs);
6507 
6508  SCIPsetDebugMsg(set, " -> farkasact=%g farkasrhs=%g, \n", (*farkasact), SCIPaggrRowGetRhs(farkasrow));
6509 
6510  /* the constructed proof is not valid, this can happen due to numerical reasons,
6511  * e.g., we only consider rows r with !SCIPsetIsZero(set, dualfarkas[r])
6512  */
6513  if( SCIPsetIsFeasLE(set, *farkasact, SCIPaggrRowGetRhs(farkasrow)) )
6514  {
6515  (*valid) = FALSE;
6516  SCIPsetDebugMsg(set, " -> proof is not valid: %g <= %g\n", *farkasact, SCIPaggrRowGetRhs(farkasrow));
6517  }
6518 
6519 TERMINATE:
6520  SCIPsetFreeBufferArray(set, &dualfarkas);
6521 
6522  return SCIP_OKAY;
6523 }
6524 
6525 /** calculates a Farkas proof from the current dual LP solution */
6526 static
6528  SCIP_SET* set, /**< global SCIP settings */
6529  SCIP_PROB* prob, /**< transformed problem */
6530  SCIP_LP* lp, /**< LP data */
6531  SCIP_LPI* lpi, /**< LPI data */
6532  SCIP_AGGRROW* farkasrow, /**< aggregated row representing the proof */
6533  SCIP_Real* farkasact, /**< maximal activity of the proof constraint */
6534  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
6535  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
6536  SCIP_Bool* valid /**< pointer store whether the proof constraint is valid */
6537  )
6538 {
6539  SCIP_RETCODE retcode;
6540  SCIP_ROW** rows;
6541  SCIP_ROW* row;
6542  SCIP_Real* primsols;
6543  SCIP_Real* dualsols;
6544  SCIP_Real* redcosts;
6545  SCIP_Real maxabsdualsol;
6546  int nrows;
6547  int ncols;
6548  int r;
6549 
6550  assert(set != NULL);
6551  assert(prob != NULL);
6552  assert(lp != NULL);
6553  assert(lp->flushed);
6554  assert(lp->solved);
6555  assert(curvarlbs != NULL);
6556  assert(curvarubs != NULL);
6557  assert(valid != NULL);
6558 
6559  *valid = TRUE;
6560 
6561  /* get LP rows and problem variables */
6562  rows = SCIPlpGetRows(lp);
6563  nrows = SCIPlpGetNRows(lp);
6564  ncols = SCIPlpGetNCols(lp);
6565  assert(nrows == 0 || rows != NULL);
6566  assert(nrows == lp->nlpirows);
6567 
6568  /* get temporary memory */
6569  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsols, ncols) );
6570  SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsols, nrows) );
6571  SCIP_CALL( SCIPsetAllocBufferArray(set, &redcosts, ncols) );
6572 
6573  /* get solution from LPI */
6574  retcode = SCIPlpiGetSol(lpi, NULL, primsols, dualsols, NULL, redcosts);
6575  if( retcode == SCIP_LPERROR ) /* on an error in the LP solver, just abort the conflict analysis */
6576  {
6577  (*valid) = FALSE;
6578  goto TERMINATE;
6579  }
6580  SCIP_CALL( retcode );
6581 #ifdef SCIP_DEBUG
6582  {
6583  SCIP_Real objval;
6584  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
6585  SCIPsetDebugMsg(set, " -> LP objval: %g\n", objval);
6586  }
6587 #endif
6588 
6589  /* check whether the dual solution is numerically stable */
6590  maxabsdualsol = 0;
6591  for( r = 0; r < nrows; r++ )
6592  {
6593  SCIP_Real absdualsol = REALABS(dualsols[r]);
6594 
6595  if( absdualsol > maxabsdualsol )
6596  maxabsdualsol = absdualsol;
6597  }
6598 
6599  /* don't consider dual solution with maxabsdualsol > 1e+07, this would almost cancel out the objective constraint */
6600  if( maxabsdualsol > 1e+07 )
6601  {
6602  (*valid) = FALSE;
6603  goto TERMINATE;
6604  }
6605 
6606  /* clear the proof */
6607  SCIPaggrRowClear(farkasrow);
6608 
6609  /* Let y be the dual solution and r be the reduced cost vector. Let z be defined as
6610  * z_i := y_i if i is a global row,
6611  * z_i := 0 if i is a local row.
6612  * Define the set X := {x | lhs <= Ax <= rhs, lb <= x <= ub, c^Tx <= c*}, with c* being the current primal bound.
6613  * Then the following inequalities are valid for all x \in X:
6614  * - c* <= -c^Tx
6615  * <=> z^TAx - c* <= (z^TA - c^T) x
6616  * <=> z^TAx - c* <= (y^TA - c^T - (y-z)^TA) x
6617  * <=> z^TAx - c* <= (-r^T - (y-z)^TA) x (dual feasibility of (y,r): y^TA + r^T == c^T)
6618  * Because lhs <= Ax <= rhs and lb <= x <= ub, the inequality can be relaxed to give
6619  * min{z^Tq | lhs <= q <= rhs} - c* <= max{(-r^T - (y-z)^TA) x | lb <= x <= ub}, or X = {}.
6620  *
6621  * The resulting dual row is: z^T{lhs,rhs} - c* <= (-r^T - (y-z)^TA){lb,ub},
6622  * where lhs, rhs, lb, and ub are selected in order to maximize the feasibility of the row.
6623  */
6624 
6625  /* add the objective function to the aggregation row with current cutoff bound as right-hand side
6626  *
6627  * use a slightly tighter cutoff bound, because solutions with equal objective value should also be declared
6628  * infeasible
6629  */
6630  SCIP_CALL( SCIPaggrRowAddObjectiveFunction(set->scip, farkasrow, lp->cutoffbound - SCIPsetSumepsilon(set), 1.0) );
6631 
6632  /* dual row: z^T{lhs,rhs} - c* <= (-r^T - (y-z)^TA){lb,ub}
6633  * 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
6634  */
6635  for( r = 0; r < nrows; ++r )
6636  {
6637  row = rows[r];
6638  assert(row != NULL);
6639  assert(row->len == 0 || row->cols != NULL);
6640  assert(row->len == 0 || row->vals != NULL);
6641  assert(row == lp->lpirows[r]);
6642 
6643  /* ignore dual solution values of 0.0 (in this case: y_i == z_i == 0) */
6644  if( SCIPsetIsDualfeasZero(set, dualsols[r]) )
6645  continue;
6646 
6647  /* check dual feasibility */
6648  if( (SCIPsetIsInfinity(set, -row->lhs) && dualsols[r] > 0.0) || (SCIPsetIsInfinity(set, row->rhs) && dualsols[r] < 0.0) )
6649  {
6650  SCIPsetDebugMsg(set, " -> infeasible dual solution %g in row <%s>: lhs=%g, rhs=%g\n",
6651  dualsols[r], SCIProwGetName(row), row->lhs, row->rhs);
6652  (*valid) = FALSE;
6653  goto TERMINATE;
6654  }
6655 
6656  /* local rows add up to the dual row's coefficients (because z_i == 0 => -(y_i - z_i) == -y_i),
6657  * global rows add up to the dual row's left hand side (because z_i == y_i != 0)
6658  */
6659  if( row->local )
6660  {
6661 #if 0
6662  /* add -y_i A_i to coefficients of dual row */
6663  for( i = 0; i < row->len; ++i )
6664  {
6665  v = SCIPvarGetProbindex(SCIPcolGetVar(row->cols[i]));
6666  assert(0 <= v && v < prob->nvars);
6667  dualcoefs[v] -= dualsols[r] * row->vals[i]; // TODO use row
6668  }
6669 #endif
6670  SCIPsetDebugMsg(set, " -> local row <%s>: dual=%g\n", SCIProwGetName(row), dualsols[r]);
6671  }
6672  else
6673  {
6674  /* add minimal value to dual row's left hand side: z_i == y_i > 0 -> lhs, z_i == y_i < 0 -> rhs */
6675  if( dualsols[r] > 0.0 )
6676  {
6677  assert(!SCIPsetIsInfinity(set, -row->lhs));
6678  SCIP_CALL( SCIPaggrRowAddRow(set->scip, farkasrow, row, -dualsols[r], -1) );
6679  }
6680  else
6681  {
6682  assert(!SCIPsetIsInfinity(set, row->rhs));
6683  SCIP_CALL( SCIPaggrRowAddRow(set->scip, farkasrow, row, -dualsols[r], +1) );
6684  }
6685  SCIPsetDebugMsg(set, " -> global row <%s>[%g,%g]: dual=%g -> dualrhs=%g\n",
6686  SCIProwGetName(row), row->lhs - row->constant, row->rhs - row->constant, -dualsols[r], SCIPaggrRowGetRhs(farkasrow));
6687  }
6688  }
6689 
6690  /* remove all nearly zero coefficients */
6691  SCIPaggrRowRemoveZeros(set->scip, farkasrow, valid);
6692 
6693  if( !(*valid) )
6694  goto TERMINATE;
6695 
6696  /* check validity of the proof */
6697  *farkasact = aggrRowGetMinActivity(prob, farkasrow, curvarlbs, curvarubs);
6698 
6699  if( SCIPsetIsLE(set, *farkasact, SCIPaggrRowGetRhs(farkasrow)) )
6700  {
6701  *valid = FALSE;
6702  SCIPsetDebugMsg(set, " -> proof is not valid: %g <= %g\n", *farkasact, SCIPaggrRowGetRhs(farkasrow));
6703  }
6704 
6705  TERMINATE:
6706  SCIPsetFreeBufferArray(set, &redcosts);
6707  SCIPsetFreeBufferArray(set, &dualsols);
6708  SCIPsetFreeBufferArray(set, &primsols);
6709 
6710  return SCIP_OKAY;
6711 }
6712 
6713 #ifdef SCIP_DEBUG
6714 static
6716  SCIP_SET* set, /**< global SCIP settings */
6717  SCIP_Real minact, /**< min activity */
6718  SCIP_Real rhs, /**< right hand side */
6719  const char* infostr /**< additional info for this debug message, or NULL */
6720  )
6721 {
6722  SCIPsetDebugMsg(set, "-> %sminact=%.15g rhs=%.15g violation=%.15g\n",infostr != NULL ? infostr : "" , minact, rhs, minact - rhs);
6723 }
6724 #else
6725 #define debugPrintViolationInfo(...) /**/
6726 #endif
6727 
6728 /** apply coefficient tightening */
6729 static
6731  SCIP_SET* set, /**< global SCIP settings */
6732  SCIP_PROOFSET* proofset, /**< proof set */
6733  int* nchgcoefs, /**< pointer to store number of changed coefficients */
6734  SCIP_Bool* redundant /**< pointer to store whether the proof set is redundant */
6735  )
6736 {
6737 #ifdef SCIP_DEBUG
6738  SCIP_Real absmax = 0.0;
6739  SCIP_Real absmin = SCIPsetInfinity(set);
6740  int i;
6741 
6742  for( i = 0; i < proofset->nnz; i++ )
6743  {
6744  absmax = MAX(absmax, REALABS(proofset->vals[i]));
6745  absmin = MIN(absmin, REALABS(proofset->vals[i]));
6746  }
6747 #endif
6748 
6749  (*redundant) = SCIPcutsTightenCoefficients(set->scip, FALSE, proofset->vals, &proofset->rhs, proofset->inds, &proofset->nnz, nchgcoefs);
6750 
6751 #ifdef SCIP_DEBUG
6752  {
6753  SCIP_Real newabsmax = 0.0;
6754  SCIP_Real newabsmin = SCIPsetInfinity(set);
6755 
6756  for( i = 0; i < proofset->nnz; i++ )
6757  {
6758  newabsmax = MAX(newabsmax, REALABS(proofset->vals[i]));
6759  newabsmin = MIN(newabsmin, REALABS(proofset->vals[i]));
6760  }
6761 
6762  SCIPsetDebugMsg(set, "coefficient tightening: [%.15g,%.15g] -> [%.15g,%.15g] (nnz: %d, nchg: %d rhs: %.15g)\n",
6763  absmin, absmax, newabsmin, newabsmax, proofsetGetNVars(proofset), *nchgcoefs, proofsetGetRhs(proofset));
6764  printf("coefficient tightening: [%.15g,%.15g] -> [%.15g,%.15g] (nnz: %d, nchg: %d rhs: %.15g)\n",
6765  absmin, absmax, newabsmin, newabsmax, proofsetGetNVars(proofset), *nchgcoefs, proofsetGetRhs(proofset));
6766  }
6767 #endif
6768 }
6769 
6770 /** try to generate alternative proofs by applying subadditive functions */
6771 static
6773  SCIP_CONFLICT* conflict, /**< conflict analysis data */
6774  SCIP_SET* set, /**< global SCIP settings */
6775  SCIP_STAT* stat, /**< dynamic SCIP statistics */
6776  SCIP_PROB* transprob, /**< transformed problem */
6777  SCIP_TREE* tree, /**< tree data */
6778  BMS_BLKMEM* blkmem, /**< block memory */
6779  SCIP_AGGRROW* proofrow, /**< proof rows data */
6780  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
6781  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
6782  SCIP_CONFTYPE conflicttype /**< type of the conflict */
6783  )
6784 {
6785  SCIP_VAR** vars;
6786  SCIP_SOL* refsol;
6787  SCIP_Real* cutcoefs;
6788  SCIP_Real cutefficacy;
6789  SCIP_Real cutrhs;
6790  SCIP_Real proofefficiacy;
6791  SCIP_Real efficiacynorm;
6792  SCIP_Bool islocal;
6793  SCIP_Bool cutsuccess;
6794  SCIP_Bool success;
6795  int* cutinds;
6796  int* inds;
6797  int cutnnz;
6798  int nnz;
6799  int nvars;
6800  int i;
6801 
6802  vars = SCIPprobGetVars(transprob);
6803  nvars = SCIPprobGetNVars(transprob);
6804 
6805  inds = SCIPaggrRowGetInds(proofrow);
6806  nnz = SCIPaggrRowGetNNz(proofrow);
6807 
6808  proofefficiacy = aggrRowGetMinActivity(transprob, proofrow, curvarlbs, curvarubs) - SCIPaggrRowGetRhs(proofrow);
6809 
6810  efficiacynorm = SCIPaggrRowCalcEfficacyNorm(set->scip, proofrow);
6811  proofefficiacy /= MAX(1e-6, efficiacynorm);
6812 
6813  /* create reference solution */
6814  SCIP_CALL( SCIPcreateSol(set->scip, &refsol, NULL) );
6815 
6816  /* initialize with average solution */
6817  for( i = 0; i < nvars; i++ )
6818  {
6819  SCIP_CALL( SCIPsolSetVal(refsol, set, stat, tree, vars[i], SCIPvarGetAvgSol(vars[i])) );
6820  }
6821 
6822  /* set all variables that are part of the proof to its active local bound */
6823  for( i = 0; i < nnz; i++ )
6824  {
6825  SCIP_Real val = SCIPaggrRowGetProbvarValue(proofrow, inds[i]);
6826 
6827  if( val > 0.0 )
6828  {
6829  SCIP_CALL( SCIPsolSetVal(refsol, set, stat, tree, vars[inds[i]], curvarubs[inds[i]]) );
6830  }
6831  else
6832  {
6833  SCIP_CALL( SCIPsolSetVal(refsol, set, stat, tree, vars[inds[i]], curvarlbs[inds[i]]) );
6834  }
6835  }
6836 
6837  SCIP_CALL( SCIPsetAllocBufferArray(set, &cutcoefs, nvars) );
6838  SCIP_CALL( SCIPsetAllocBufferArray(set, &cutinds, nvars) );
6839 
6840  cutnnz = 0;
6841  cutefficacy = -SCIPsetInfinity(set);
6842 
6843  /* apply flow cover */
6844  SCIP_CALL( SCIPcalcFlowCover(set->scip, refsol, POSTPROCESS, BOUNDSWITCH, ALLOWLOCAL, proofrow, \
6845  cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy, NULL, &islocal, &cutsuccess) );
6846  success = cutsuccess;
6847 
6848  /* apply MIR */
6850  NULL, NULL, MINFRAC, MAXFRAC, proofrow, cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy, NULL, \
6851  &islocal, &cutsuccess) );
6852  success = (success || cutsuccess);
6853 
6854  /* replace the current proof */
6855  if( success && !islocal && SCIPsetIsPositive(set, cutefficacy) && cutefficacy * nnz > proofefficiacy * cutnnz )
6856  {
6857  SCIP_PROOFSET* alternativeproofset;
6858  SCIP_Bool redundant;
6859  int nchgcoefs;
6860 
6861  SCIP_CALL( proofsetCreate(&alternativeproofset, blkmem) );
6862  alternativeproofset->conflicttype = (conflicttype == SCIP_CONFTYPE_INFEASLP ? SCIP_CONFTYPE_ALTINFPROOF : SCIP_CONFTYPE_ALTBNDPROOF);
6863 
6864  SCIP_CALL( proofsetAddSparseData(alternativeproofset, blkmem, cutcoefs, cutinds, cutnnz, cutrhs) );
6865 
6866  /* apply coefficient tightening */
6867  tightenCoefficients(set, alternativeproofset, &nchgcoefs, &redundant);
6868 
6869  if( !redundant )
6870  {
6871  SCIP_CALL( conflictInsertProofset(conflict, set, alternativeproofset) );
6872  }
6873  else
6874  {
6875  proofsetFree(&alternativeproofset, blkmem);
6876  }
6877  }
6878 
6879  SCIPsetFreeBufferArray(set, &cutinds);
6880  SCIPsetFreeBufferArray(set, &cutcoefs);
6881 
6882  SCIP_CALL( SCIPfreeSol(set->scip, &refsol) );
6883 
6884  return SCIP_OKAY;
6885 }
6886 
6887 /** tighten a given infeasibility proof a^Tx <= b with minact > b w.r.t. local bounds
6888  *
6889  * 1) Apply cut generating functions
6890  * - c-MIR
6891  * - Flow-cover
6892  * - TODO: implement other subadditive functions
6893  * 2) Remove continuous variables contributing with its global bound
6894  * - TODO: implement a variant of non-zero-cancellation
6895  */
6896 static
6898  SCIP_CONFLICT* conflict, /**< conflict analysis data */
6899  SCIP_SET* set, /**< global SCIP settings */
6900  SCIP_STAT* stat, /**< dynamic SCIP statistics */
6901  BMS_BLKMEM* blkmem, /**< block memory */
6902  SCIP_PROB* transprob, /**< transformed problem */
6903  SCIP_TREE* tree, /**< tree data */
6904  SCIP_AGGRROW* proofrow, /**< aggregated row representing the proof */
6905  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
6906  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
6907  SCIP_Bool initialproof /**< do we analyze the initial reason of infeasibility? */
6908  )
6909 {
6910  SCIP_VAR** vars;
6911  SCIP_Real* vals;
6912  int* inds;
6913  SCIP_PROOFSET* proofset;
6914  SCIP_Bool valid;
6915  SCIP_Bool redundant;
6916  int nnz;
6917  int nchgcoefs;
6918  int nbinvars;
6919  int ncontvars;
6920  int nintvars;
6921  int i;
6922 
6923  assert(conflict->proofset != NULL);
6924 
6925  vars = SCIPprobGetVars(transprob);
6926  nbinvars = 0;
6927  nintvars = 0;
6928  ncontvars = 0;
6929 
6930  inds = SCIPaggrRowGetInds(proofrow);
6931  nnz = SCIPaggrRowGetNNz(proofrow);
6932 
6933  /* count number of binary, integer, and continuous variables */
6934  for( i = 0; i < nnz; i++ )
6935  {
6936  assert(SCIPvarGetProbindex(vars[inds[i]]) == inds[i]);
6937 
6938  if( SCIPvarIsBinary(vars[inds[i]]) )
6939  ++nbinvars;
6940  else if( SCIPvarIsIntegral(vars[inds[i]]) )
6941  ++nintvars;
6942  else
6943  ++ncontvars;
6944  }
6945 
6946  SCIPsetDebugMsg(set, "start dualray tightening:\n");
6947  SCIPsetDebugMsg(set, "-> tighten dual ray: nvars=%d (bin=%d, int=%d, cont=%d)\n",
6948  nnz, nbinvars, nintvars, ncontvars);
6949  debugPrintViolationInfo(set, aggrRowGetMinActivity(transprob, proofrow, curvarlbs, curvarubs), SCIPaggrRowGetRhs(proofrow), NULL);
6950 
6951  /* try to find an alternative proof of local infeasibility that is stronger */
6952  if( set->conf_sepaaltproofs )
6953  {
6954  SCIP_CALL( separateAlternativeProofs(conflict, set, stat, transprob, tree, blkmem, proofrow, curvarlbs, curvarubs,
6955  conflict->conflictset->conflicttype) );
6956  }
6957 
6958  if( initialproof )
6959  proofset = conflict->proofset;
6960  else
6961  {
6962  SCIP_CALL( proofsetCreate(&proofset, blkmem) );
6963  SCIP_CALL( conflictInsertProofset(conflict, set, proofset) );
6964  }
6965 
6966  /* start with a proofset containing all variables with a non-zero coefficient in the dual proof */
6967  SCIP_CALL( proofsetAddAggrrow(proofset, set, blkmem, proofrow) );
6968  proofset->conflicttype = conflict->conflictset->conflicttype;
6969 
6970  /* get proof data */
6971  vals = proofsetGetVals(proofset);
6972  inds = proofsetGetInds(proofset);
6973  nnz = proofsetGetNVars(proofset);
6974 
6975  /* remove continuous variable contributing with their global bound
6976  *
6977  * todo: check whether we also want to do that for bound exceeding proofs, but then we cannot update the
6978  * conflict anymore
6979  */
6980  if( proofset->conflicttype == SCIP_CONFTYPE_INFEASLP )
6981  {
6982  /* remove all continuous variables that have equal global and local bounds (ub or lb depend on the sign)
6983  * from the proof
6984  */
6985 
6986  for( i = 0; i < nnz && nnz > 1; )
6987  {
6988  SCIP_Real val;
6989  int idx = inds[i];
6990 
6991  assert(vars[idx] != NULL);
6992 
6993  val = vals[i];
6994  assert(!SCIPsetIsZero(set, val));
6995 
6996  /* skip integral variables */
6997  if( SCIPvarGetType(vars[idx]) != SCIP_VARTYPE_CONTINUOUS && SCIPvarGetType(vars[idx]) != SCIP_VARTYPE_IMPLINT )
6998  {
6999  i++;
7000  continue;
7001  }
7002  else
7003  {
7004  SCIP_Real glbbd;
7005  SCIP_Real locbd;
7006 
7007  /* get appropriate global and local bounds */
7008  glbbd = (val < 0.0 ? SCIPvarGetUbGlobal(vars[idx]) : SCIPvarGetLbGlobal(vars[idx]));
7009  locbd = (val < 0.0 ? curvarubs[idx] : curvarlbs[idx]);
7010 
7011  if( !SCIPsetIsEQ(set, glbbd, locbd) )
7012  {
7013  i++;
7014  continue;
7015  }
7016 
7017  SCIPsetDebugMsg(set, "-> remove continuous variable <%s>: glb=[%g,%g], loc=[%g,%g], val=%g\n",
7018  SCIPvarGetName(vars[idx]), SCIPvarGetLbGlobal(vars[idx]), SCIPvarGetUbGlobal(vars[idx]),
7019  SCIPvarGetLbLocal(vars[idx]), SCIPvarGetUbLocal(vars[idx]), val);
7020 
7021  proofsetCancelVarWithBound(proofset, set, vars[idx], i, &valid);
7022  assert(valid); /* this should be always fulfilled at this place */
7023 
7024  --nnz;
7025  }
7026  }
7027  }
7028 
7029  /* apply coefficient tightening to initial proof */
7030  tightenCoefficients(set, proofset, &nchgcoefs, &redundant);
7031 
7032  /* it can happen that the constraints is almost globally redundant w.r.t to the maximal activity,
7033  * e.g., due to numerics. in this case, we want to discard the proof
7034  */
7035  if( redundant )
7036  {
7037 #ifndef NDEBUG
7038  SCIP_Real eps = MIN(0.01, 10.0*set->num_feastol);
7039  assert(proofset->rhs - getMaxActivity(transprob, proofset->vals, proofset->inds, proofset->nnz, NULL, NULL) < eps);
7040 #endif
7041  proofsetClear(proofset);
7042  }
7043  else if( nchgcoefs > 0 )
7044  {
7045  if( proofset->conflicttype == SCIP_CONFTYPE_INFEASLP )
7047  else if( proofset->conflicttype == SCIP_CONFTYPE_BNDEXCEEDING )
7049  }
7050 
7051  return SCIP_OKAY;
7052 }
7053 
7054 /** perform conflict analysis based on a dual unbounded ray
7055  *
7056  * given an aggregation of rows lhs <= a^Tx such that lhs > maxactivity. if the constraint has size one we add a
7057  * bound change instead of the constraint.
7058  */
7059 static
7061  SCIP_CONFLICT* conflict, /**< conflict analysis data */
7062  SCIP_SET* set, /**< global SCIP settings */
7063  SCIP_STAT* stat, /**< dynamic SCIP statistics */
7064  BMS_BLKMEM* blkmem, /**< block memory */
7065  SCIP_PROB* origprob, /**< original problem */
7066  SCIP_PROB* transprob, /**< transformed problem */
7067  SCIP_TREE* tree, /**< tree data */
7068  SCIP_REOPT* reopt, /**< reoptimization data */
7069  SCIP_LP* lp, /**< LP data */
7070  SCIP_AGGRROW* proofrow, /**< aggregated row representing the proof */
7071  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
7072  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
7073  SCIP_Bool initialproof, /**< do we analyze the initial reason of infeasibility? */
7074  SCIP_Bool* globalinfeasible, /**< pointer to store whether global infeasibility could be proven */
7075  SCIP_Bool* success /**< pointer to store success result */
7076  )
7077 {
7078  SCIP_Real rhs;
7079  SCIP_Real minact;
7080  int nnz;
7081 
7082  assert(set != NULL);
7083  assert(transprob != NULL);
7084 
7085  /* get sparse data */
7086  nnz = SCIPaggrRowGetNNz(proofrow);
7087  rhs = SCIPaggrRowGetRhs(proofrow);
7088 
7089  *globalinfeasible = FALSE;
7090  *success = FALSE;
7091 
7092  /* get minimal activity w.r.t. local bounds */
7093  minact = aggrRowGetMinActivity(transprob, proofrow, curvarlbs, curvarubs);
7094 
7095  /* only run is the proof proves local infeasibility */
7096  if( SCIPsetIsFeasLE(set, minact, rhs) )
7097  return SCIP_OKAY;
7098 
7099  /* if the farkas-proof is empty, the node and its sub tree can be cut off completely */
7100  if( nnz == 0 )
7101  {
7102  SCIPsetDebugMsg(set, " -> empty farkas-proof in depth %d cuts off sub tree at depth 0\n", SCIPtreeGetFocusDepth(tree));
7103 
7104  SCIP_CALL( SCIPnodeCutoff(tree->path[0], set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
7105 
7106  *globalinfeasible = TRUE;
7107  *success = TRUE;
7108 
7109  ++conflict->ndualrayinfsuccess;
7110 
7111  return SCIP_OKAY;
7112  }
7113 
7114  /* try to enforce the constraint based on a dual ray */
7115  SCIP_CALL( tightenDualproof(conflict, set, stat, blkmem, transprob, tree, proofrow, curvarlbs, curvarubs, initialproof) );
7116 
7117  if( *globalinfeasible )
7118  {
7119  SCIPsetDebugMsg(set, "detect global: cutoff root node\n");
7120  SCIP_CALL( SCIPnodeCutoff(tree->path[0], set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
7121  *success = TRUE;
7122 
7123  ++conflict->ndualrayinfsuccess;
7124  }
7125 
7126  return SCIP_OKAY;
7127 }
7128 
7129 /** try to find a subset of changed bounds leading to an infeasible LP
7130  *
7131  * 1. call undoBdchgsDualfarkas() or undoBdchgsDualsol()
7132  * -> update lb/ubchginfoposs arrays
7133  * -> store additional changes in bdchg and curvarlbs/ubs arrays
7134  * -> apply additional changes to the LPI
7135  * 2. (optional) if additional bound changes were undone:
7136  * -> resolve LP
7137  * -> goto 1.
7138  * 3. redo all bound changes in the LPI to restore the LPI to its original state
7139  * 4. analyze conflict
7140  * -> put remaining changed bounds (see lb/ubchginfoposs arrays) into starting conflict set
7141  */
7142 static
7144  SCIP_CONFLICT* conflict, /**< conflict data */
7145  SCIP_SET* set, /**< global SCIP settings */
7146  SCIP_STAT* stat, /**< problem statistics */
7147  SCIP_PROB* origprob, /**< original problem */
7148  SCIP_PROB* transprob, /**< transformed problem */
7149  SCIP_TREE* tree, /**< branch and bound tree */
7150  SCIP_REOPT* reopt, /**< reoptimization data */
7151  SCIP_LP* lp, /**< LP data */
7152  SCIP_LPI* lpi, /**< LPI data */
7153  BMS_BLKMEM* blkmem, /**< block memory */
7154  SCIP_Real* proofcoefs, /**< coefficients in the proof constraint */
7155  SCIP_Real* prooflhs, /**< lhs of the proof constraint */
7156  SCIP_Real* proofactivity, /**< maximal activity of the proof constraint */
7157  SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
7158  SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
7159  int* lbchginfoposs, /**< positions of currently active lower bound change information in variables' arrays */
7160  int* ubchginfoposs, /**< positions of currently active upper bound change information in variables' arrays */
7161  int* iterations, /**< pointer to store the total number of LP iterations used */
7162  SCIP_Bool marklpunsolved, /**< whether LP should be marked unsolved after analysis (needed for strong branching) */
7163  SCIP_Bool* dualraysuccess, /**< pointer to store success result of dualray analysis */
7164  SCIP_Bool* valid /**< pointer to store whether the result is still a valid proof */
7165  )
7166 {
7167  SCIP_LPBDCHGS* oldlpbdchgs;
7168  SCIP_LPBDCHGS* relaxedlpbdchgs;
7169  SCIP_Bool solvelp;
7170  SCIP_Bool resolve;
7171  int ncols;
7172 
7173  assert(set != NULL);
7174 
7175  /* get number of columns in the LP */
7176  ncols = SCIPlpGetNCols(lp);
7177 
7178  /* get temporary memory for remembering bound changes on LPI columns */
7179  SCIP_CALL( lpbdchgsCreate(&oldlpbdchgs, set, ncols) );
7180  SCIP_CALL( lpbdchgsCreate(&relaxedlpbdchgs, set, ncols) );
7181 
7182  /* undo as many bound changes as possible with the current LP solution */
7183  resolve = FALSE;
7184  if( (*valid) )
7185  {
7186  int currentdepth;
7187  currentdepth = SCIPtreeGetCurrentDepth(tree);
7188 
7189  if( SCIPlpiIsPrimalInfeasible(lpi) )
7190  {
7191  SCIP_CALL( undoBdchgsDualfarkas(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, \
7192  ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, *prooflhs, proofactivity) );
7193  }
7194  else
7195  {
7196  assert(SCIPlpiIsDualFeasible(lpi) || SCIPlpiIsObjlimExc(lpi));
7197  SCIP_CALL( undoBdchgsDualsol(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs, \
7198  oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, *prooflhs, proofactivity) );
7199  }
7200  }
7201 
7202  /* check if we want to solve the LP */
7203  assert(SCIPprobAllColsInLP(transprob, set, lp));
7204  solvelp = (set->conf_maxlploops != 0 && set->conf_lpiterations != 0);
7205 
7206  if( (*valid) && resolve && solvelp )
7207  {
7208  SCIP_RETCODE retcode;
7209  SCIP_ROW** rows;
7210  int* sidechginds;
7211  SCIP_Real* sidechgoldlhss;
7212  SCIP_Real* sidechgoldrhss;
7213  SCIP_Real* sidechgnewlhss;
7214  SCIP_Real* sidechgnewrhss;
7215  SCIP_Real lpiinfinity;
7216  SCIP_Bool globalinfeasible;
7217  int maxlploops;
7218  int lpiterations;
7219  int sidechgssize;
7220  int nsidechgs;
7221  int nrows;
7222  int nloops;
7223  int r;
7224 
7225  /* get infinity value of LP solver */
7226  lpiinfinity = SCIPlpiInfinity(lpi);
7227 
7228  /* temporarily disable objective limit and install an iteration limit */
7229  maxlploops = (set->conf_maxlploops >= 0 ? set->conf_maxlploops : INT_MAX);
7230  lpiterations = (set->conf_lpiterations >= 0 ? set->conf_lpiterations : INT_MAX);
7231  SCIP_CALL( SCIPlpiSetRealpar(lpi, SCIP_LPPAR_OBJLIM, lpiinfinity) );
7232  SCIP_CALL( SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, lpiterations) );
7233 
7234  /* get LP rows */
7235  rows = SCIPlpGetRows(lp);
7236  nrows = SCIPlpGetNRows(lp);
7237  assert(nrows == 0 || rows != NULL);
7238 
7239  /* get temporary memory for remembering side changes on LPI rows */
7240  SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechginds, nrows) );
7241  SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgoldlhss, nrows) );
7242  SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgoldrhss, nrows) );
7243  SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgnewlhss, nrows) );
7244  SCIP_CALL( SCIPsetAllocBufferArray(set, &sidechgnewrhss, nrows) );
7245  sidechgssize = nrows;
7246  nsidechgs = 0;
7247 
7248  /* remove all local rows by setting their sides to infinity;
7249  * finite sides are only changed to near infinity, such that the row's sense in the LP solver
7250  * is not affected (e.g. CPLEX cannot handle free rows)
7251  */
7252  for( r = 0; r < nrows; ++r )
7253  {
7254  assert(SCIProwGetLPPos(rows[r]) == r);
7255 
7256  if( SCIProwIsLocal(rows[r]) )
7257  {
7258  SCIPsetDebugMsg(set, " -> removing local row <%s> [%g,%g]\n",
7259  SCIProwGetName(rows[r]), SCIProwGetLhs(rows[r]), SCIProwGetRhs(rows[r]));
7260  SCIP_CALL( addSideRemoval(set, rows[r], lpiinfinity, &sidechginds, &sidechgoldlhss, &sidechgoldrhss,
7261  &sidechgnewlhss, &sidechgnewrhss, &sidechgssize, &nsidechgs) );
7262  }
7263  }
7264 
7265  /* apply changes of local rows to the LP solver */
7266  if( nsidechgs > 0 )
7267  {
7268  SCIP_CALL( SCIPlpiChgSides(lpi, nsidechgs, sidechginds, sidechgnewlhss, sidechgnewrhss) );
7269  }
7270 
7271  /* undo as many additional bound changes as possible by resolving the LP */
7272  assert((*valid));
7273  assert(resolve);
7274  nloops = 0;
7275  globalinfeasible = FALSE;
7276  while( (*valid) && resolve && nloops < maxlploops )
7277  {
7278  int iter;
7279 
7280  assert(!globalinfeasible);
7281 
7282  nloops++;
7283  resolve = FALSE;
7284 
7285  SCIPsetDebugMsg(set, "infeasible LP conflict analysis loop %d (changed col bounds: %d)\n", nloops, relaxedlpbdchgs->nbdchgs);
7286 
7287  /* apply bound changes to the LP solver */
7288  assert(relaxedlpbdchgs->nbdchgs >= 0);
7289  if( relaxedlpbdchgs->nbdchgs > 0 )
7290  {
7291  SCIPsetDebugMsg(set, " -> applying %d bound changes to the LP solver\n", relaxedlpbdchgs->nbdchgs);
7292  SCIP_CALL( SCIPlpiChgBounds(lpi, relaxedlpbdchgs->nbdchgs, relaxedlpbdchgs->bdchginds, \
7293  relaxedlpbdchgs->bdchglbs, relaxedlpbdchgs->bdchgubs) );
7294 
7295  /* reset conflict LP bound change data structure */
7296  lpbdchgsReset(relaxedlpbdchgs, ncols);
7297  }
7298 
7299  /* start LP timer */
7300  SCIPclockStart(stat->conflictlptime, set);
7301 
7302  /* resolve LP */
7303  retcode = SCIPlpiSolveDual(lpi);
7304 
7305  /* stop LP timer */
7306  SCIPclockStop(stat->conflictlptime, set);
7307 
7308  /* check return code of LP solving call */
7309  if( retcode == SCIP_LPERROR )
7310  {
7311  (*valid) = FALSE;
7312  break;
7313  }
7314  SCIP_CALL( retcode );
7315 
7316  /* count number of LP iterations */
7317  SCIP_CALL( SCIPlpiGetIterations(lpi, &iter) );
7318  (*iterations) += iter;
7319  stat->nconflictlps++;
7320  stat->nconflictlpiterations += iter;
7321  SCIPsetDebugMsg(set, " -> resolved LP in %d iterations (total: %" SCIP_LONGINT_FORMAT ") (infeasible:%u)\n",
7323 
7324  /* evaluate result */
7325  if( SCIPlpiIsDualFeasible(lpi) || SCIPlpiIsObjlimExc(lpi) )
7326  {
7327  SCIP_Real objval;
7328 
7329  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
7330  (*valid) = (objval >= lp->lpiobjlim && !SCIPlpDivingObjChanged(lp));
7331  }
7332  else
7333  (*valid) = SCIPlpiIsPrimalInfeasible(lpi);
7334 
7335  if( (*valid) )
7336  {
7337  int currentdepth;
7338  currentdepth = SCIPtreeGetCurrentDepth(tree);
7339 
7340  /* undo additional bound changes */
7341  if( SCIPlpiIsPrimalInfeasible(lpi) )
7342  {
7343  SCIP_AGGRROW* farkasrow;
7344  int* inds;
7345  int nnz;
7346  int v;
7347 
7348 #ifndef NDEBUG
7349  SCIP_VAR** vars = SCIPprobGetVars(transprob);
7350 #endif
7351 
7352  SCIP_CALL( SCIPaggrRowCreate(set->scip, &farkasrow) );
7353 
7354  /* the original LP exceeds the current cutoff bound, thus, we have not constructed the Farkas proof */
7355  SCIP_CALL( getFarkasProof(set, transprob, lp, lpi, farkasrow, proofactivity, curvarlbs, curvarubs, valid) );
7356 
7357  /* the constructed Farkas proof is not valid, we need to break here */
7358  if( !(*valid) )
7359  {
7360  SCIPaggrRowFree(set->scip, &farkasrow);
7361  break;
7362  }
7363 
7364  /* start dual ray analysis */
7365  if( set->conf_useinflp == 'd' || set->conf_useinflp == 'b' )
7366  {
7367  /* change the conflict type */
7368  SCIP_CONFTYPE oldconftype = conflict->conflictset->conflicttype;
7370 
7371  /* start dual ray analysis */
7372  SCIP_CALL( conflictAnalyzeDualProof(conflict, set, stat, blkmem, origprob, transprob, tree, reopt, lp, \
7373  farkasrow, curvarlbs, curvarubs, FALSE, &globalinfeasible, dualraysuccess) );
7374 
7375  conflict->conflictset->conflicttype = oldconftype;
7376  }
7377 
7378  if( globalinfeasible )
7379  {
7380  SCIPaggrRowFree(set->scip, &farkasrow);
7381  goto TERMINATE;
7382  }
7383 
7384  BMSclearMemoryArray(proofcoefs, SCIPprobGetNVars(transprob));
7385  (*prooflhs) = -SCIPaggrRowGetRhs(farkasrow);
7386  (*proofactivity) = -(*proofactivity);
7387 
7388  inds = SCIPaggrRowGetInds(farkasrow);
7389  nnz = SCIPaggrRowGetNNz(farkasrow);
7390 
7391  for( v = 0; v < nnz; v++ )
7392  {
7393  int i = inds[v];
7394 
7395  assert(SCIPvarGetProbindex(vars[i]) == inds[v]);
7396 
7397  proofcoefs[i] = -SCIPaggrRowGetProbvarValue(farkasrow, i);
7398  }
7399 
7400  /* free aggregation rows */
7401  SCIPaggrRowFree(set->scip, &farkasrow);
7402 
7403  SCIP_CALL( undoBdchgsDualfarkas(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, \
7404  ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, (*prooflhs), proofactivity) );
7405  }
7406  else
7407  {
7408  SCIP_AGGRROW* proofrow;
7409  int* inds;
7410  int nnz;
7411  int v;
7412 
7413 #ifndef NDEBUG
7414  SCIP_VAR** vars = SCIPprobGetVars(transprob);
7415 #endif
7416 
7417  assert(SCIPlpiIsDualFeasible(lpi) || SCIPlpiIsObjlimExc(lpi));
7418 
7419  SCIP_CALL( SCIPaggrRowCreate(set->scip, &proofrow) );
7420 
7421  SCIP_CALL( getDualProof(set, transprob, lp, lpi, proofrow, proofactivity, curvarlbs, curvarubs, valid) );
7422 
7423  /* the constructed dual proof is not valid, we need to break here */
7424  if( !(*valid) )
7425  {
7426  SCIPaggrRowFree(set->scip, &proofrow);
7427  break;
7428  }
7429  /* in contrast to the infeasible case we don't want to analyze the (probably identical) proof again. */
7430 
7431  BMSclearMemoryArray(proofcoefs, SCIPprobGetNVars(transprob));
7432  (*prooflhs) = -SCIPaggrRowGetRhs(proofrow);
7433  (*proofactivity) = -(*proofactivity);
7434 
7435  inds = SCIPaggrRowGetInds(proofrow);
7436  nnz = SCIPaggrRowGetNNz(proofrow);
7437 
7438  for( v = 0; v < nnz; v++ )
7439  {
7440  int i = inds[v];
7441 
7442  assert(SCIPvarGetProbindex(vars[i]) == inds[v]);
7443 
7444  proofcoefs[i] = -SCIPaggrRowGetProbvarValue(proofrow, i);
7445  }
7446 
7447  /* free aggregation rows */
7448  SCIPaggrRowFree(set->scip, &proofrow);
7449 
7450  SCIP_CALL( undoBdchgsDualsol(set, transprob, lp, currentdepth, curvarlbs, curvarubs, lbchginfoposs, \
7451  ubchginfoposs, oldlpbdchgs, relaxedlpbdchgs, valid, &resolve, proofcoefs, *prooflhs, proofactivity) );
7452  }
7453  }
7454  assert(!resolve || (*valid));
7455  assert(!resolve || relaxedlpbdchgs->nbdchgs > 0);
7456  SCIPsetDebugMsg(set, " -> finished infeasible LP conflict analysis loop %d (iter: %d, nbdchgs: %d)\n",
7457  nloops, iter, relaxedlpbdchgs->nbdchgs);
7458  }
7459 
7460  SCIPsetDebugMsg(set, "finished undoing bound changes after %d loops (valid=%u, nbdchgs: %d)\n",
7461  nloops, (*valid), oldlpbdchgs->nbdchgs);
7462 
7463  TERMINATE:
7464  /* reset variables to local bounds */
7465  if( oldlpbdchgs->nbdchgs > 0 )
7466  {
7467  SCIP_CALL( SCIPlpiChgBounds(lpi, oldlpbdchgs->nbdchgs, oldlpbdchgs->bdchginds, oldlpbdchgs->bdchglbs, oldlpbdchgs->bdchgubs) );
7468  }
7469 
7470  /* reset changes of local rows */
7471  if( nsidechgs > 0 )
7472  {
7473  SCIP_CALL( SCIPlpiChgSides(lpi, nsidechgs, sidechginds, sidechgoldlhss, sidechgoldrhss) );
7474  }
7475 
7476  /* mark the LP unsolved */
7477  if( oldlpbdchgs->nbdchgs > 0 || nsidechgs > 0 )
7478  {
7479  /* The LPI data are out of sync with LP data. Thus, the LP should be marked
7480  * unsolved. However, for strong branching calls, the LP has to have status 'solved'; in
7481  * this case, marklpunsolved is FALSE and synchronization is performed later. */
7482  if ( marklpunsolved )
7483  {
7484  lp->solved = FALSE;
7485  lp->primalfeasible = FALSE;
7486  lp->primalchecked = FALSE;
7487  lp->dualfeasible = FALSE;
7488  lp->dualchecked = FALSE;
7489  lp->lpobjval = SCIP_INVALID;
7491  }
7492  }
7493 
7494  /* reinstall old objective and iteration limits in LP solver */
7497 
7498  /* free temporary memory */
7499  SCIPsetFreeBufferArray(set, &sidechgnewrhss);
7500  SCIPsetFreeBufferArray(set, &sidechgnewlhss);
7501  SCIPsetFreeBufferArray(set, &sidechgoldrhss);
7502  SCIPsetFreeBufferArray(set, &sidechgoldlhss);
7503  SCIPsetFreeBufferArray(set, &sidechginds);
7504  }
7505 
7506  /* free temporary memory */
7507  lpbdchgsFree(&relaxedlpbdchgs, set);
7508  lpbdchgsFree(&oldlpbdchgs, set);
7509 
7510  return SCIP_OKAY;
7511 }
7512 
7513 /** actually performs analysis of infeasible LP */
7514 static
7516  SCIP_CONFLICT* conflict, /**< conflict analysis data */
7517  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
7518  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
7519  SCIP_SET* set, /**< global SCIP settings */
7520  SCIP_STAT* stat, /**< problem statistics */
7521  SCIP_PROB* transprob, /**< transformed problem */
7522  SCIP_PROB* origprob, /**< original problem */
7523  SCIP_TREE* tree, /**< branch and bound tree */
7524  SCIP_REOPT* reopt, /**< reoptimization data structure */
7525  SCIP_LP* lp, /**< LP data */
7526  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7527  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7528  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7529  SCIP_Bool diving, /**< are we in strong branching or diving mode? */
7530  SCIP_Bool* dualraysuccess, /**< pointer to store success result of dualray analysis */
7531  int* iterations, /**< pointer to store the total number of LP iterations used */
7532  int* nconss, /**< pointer to store the number of generated conflict constraints */
7533  int* nliterals, /**< pointer to store the number of literals in generated conflict constraints */
7534  int* nreconvconss, /**< pointer to store the number of generated reconvergence constraints */
7535  int* nreconvliterals, /**< pointer to store the number of literals generated reconvergence constraints */
7536  SCIP_Bool marklpunsolved /**< whether LP should be marked unsolved after analysis (needed for strong branching) */
7537  )
7538 {
7539  SCIP_VAR** vars;
7540  SCIP_AGGRROW* farkasrow;
7541  SCIP_LPI* lpi;
7542  SCIP_Bool valid;
7543  SCIP_Bool globalinfeasible;
7544  int* lbchginfoposs;
7545  int* ubchginfoposs;
7546  int nvars;
7547  int v;
7548  SCIP_Real* curvarlbs;
7549  SCIP_Real* curvarubs;
7550  SCIP_Real farkasactivity;
7551 
7552  assert(conflict != NULL);
7553  assert(conflict->nconflictsets == 0);
7554  assert(set != NULL);
7555  assert(SCIPprobAllColsInLP(transprob, set, lp)); /* LP conflict analysis is only valid, if all variables are known */
7556  assert(stat != NULL);
7557  assert(transprob != NULL);
7558  assert(lp != NULL);
7559  assert(lp->flushed);
7560  assert(lp->solved);
7561  assert(iterations != NULL);
7562  assert(nconss != NULL);
7563  assert(nliterals != NULL);
7564  assert(nreconvconss != NULL);
7565  assert(nreconvliterals != NULL);
7566 
7567  *iterations = 0;
7568  *nconss = 0;
7569  *nliterals = 0;
7570  *nreconvconss = 0;
7571  *nreconvliterals = 0;
7572 
7573  vars = transprob->vars;
7574  nvars = transprob->nvars;
7575 
7576  valid = TRUE;
7577 
7578  /* get LP solver interface */
7579  lpi = SCIPlpGetLPI(lp);
7582 
7583  if( !SCIPlpiIsPrimalInfeasible(lpi) )
7584  {
7585  SCIP_Real objval;
7586 
7587  assert(!SCIPlpDivingObjChanged(lp));
7588 
7589  /* make sure, a dual feasible solution exists, that exceeds the objective limit;
7590  * With FASTMIP setting, CPLEX does not apply the final pivot to reach the dual solution exceeding the objective
7591  * limit. Therefore, we have to either turn off FASTMIP and resolve the problem or continue solving it without
7592  * objective limit for at least one iteration. It seems that the strategy to continue with FASTMIP for one
7593  * additional simplex iteration yields better results.
7594  */
7595  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
7596  if( objval < lp->lpiobjlim )
7597  {
7598  SCIP_RETCODE retcode;
7599 
7600  /* temporarily disable objective limit and install an iteration limit */
7603 
7604  /* start LP timer */
7605  SCIPclockStart(stat->conflictlptime, set);
7606 
7607  /* resolve LP */
7608  retcode = SCIPlpiSolveDual(lpi);
7609 
7610  /* stop LP timer */
7611  SCIPclockStop(stat->conflictlptime, set);
7612 
7613  /* check return code of LP solving call */
7614  valid = (retcode != SCIP_LPERROR);
7615  if( valid )
7616  {
7617  int iter;
7618 
7619  SCIP_CALL( retcode );
7620 
7621  /* count number of LP iterations */
7622  SCIP_CALL( SCIPlpiGetIterations(lpi, &iter) );
7623  (*iterations) += iter;
7624  stat->nconflictlps++;
7625  stat->nconflictlpiterations += iter;
7626  SCIPsetDebugMsg(set, " -> resolved objlim exceeding LP in %d iterations (total: %" SCIP_LONGINT_FORMAT ") (infeasible:%u, objlim: %u, optimal:%u)\n",
7629  }
7630 
7631  /* reinstall old objective and iteration limits in LP solver */
7634 
7635  /* abort, if the LP produced an error */
7636  if( !valid )
7637  return SCIP_OKAY;
7638  }
7639  }
7641 
7642  if( !SCIPlpiIsPrimalInfeasible(lpi) )
7643  {
7644  SCIP_Real objval;
7645 
7646  assert(!SCIPlpDivingObjChanged(lp));
7647 
7648  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
7649  if( objval < lp->lpiobjlim )
7650  {
7651  SCIPsetDebugMsg(set, " -> LP does not exceed the cutoff bound: obj=%g, cutoff=%g\n", objval, lp->lpiobjlim);
7652  return SCIP_OKAY;
7653  }
7654  else
7655  {
7656  SCIPsetDebugMsg(set, " -> LP exceeds the cutoff bound: obj=%g, cutoff=%g\n", objval, lp->lpiobjlim);
7657  }
7658  }
7659 
7660  assert(valid);
7661 
7662  SCIP_CALL( SCIPaggrRowCreate(set->scip, &farkasrow) );
7663  SCIP_CALL( SCIPsetAllocBufferArray(set, &lbchginfoposs, transprob->nvars) );
7664  SCIP_CALL( SCIPsetAllocBufferArray(set, &ubchginfoposs, transprob->nvars) );
7665 
7666  farkasactivity = 0.0;
7667 
7668  /* get temporary memory for remembering variables' current bounds and corresponding bound change information
7669  * positions in variable's bound change information arrays
7670  */
7671  SCIP_CALL( SCIPsetAllocBufferArray(set, &curvarlbs, nvars) );
7672  SCIP_CALL( SCIPsetAllocBufferArray(set, &curvarubs, nvars) );
7673 
7674 
7675  /* get current bounds and current positions in lb/ubchginfos arrays of variables */
7676  valid = TRUE;
7677  for( v = 0; v < nvars && valid; ++v )
7678  {
7679  SCIP_VAR* var;
7680 
7681  var = vars[v];
7682 
7683  curvarlbs[v] = SCIPvarGetLbLP(var, set);
7684  curvarubs[v] = SCIPvarGetUbLP(var, set);
7685  lbchginfoposs[v] = var->nlbchginfos-1;
7686  ubchginfoposs[v] = var->nubchginfos-1;
7687  assert(diving || SCIPsetIsEQ(set, curvarlbs[v], SCIPvarGetLbLocal(var)));
7688  assert(diving || SCIPsetIsEQ(set, curvarubs[v], SCIPvarGetUbLocal(var)));
7689 
7690  /* check, if last bound changes were due to strong branching or diving */
7691  if( diving )
7692  {
7693  SCIP_Real lb;
7694  SCIP_Real ub;
7695 
7696  lb = SCIPvarGetLbLocal(var);
7697  ub = SCIPvarGetUbLocal(var);
7698  if( SCIPsetIsGT(set, curvarlbs[v], lb) )
7699  lbchginfoposs[v] = var->nlbchginfos;
7700  else if( SCIPsetIsLT(set, curvarlbs[v], lb) )
7701  {
7702  /* the bound in the diving LP was relaxed -> the LP is not a subproblem of the current node -> abort! */
7703  /**@todo we could still analyze such a conflict, but we would have to take care with our data structures */
7704  valid = FALSE;
7705  }
7706  if( SCIPsetIsLT(set, curvarubs[v], ub) )
7707  ubchginfoposs[v] = var->nubchginfos;
7708  else if( SCIPsetIsGT(set, curvarubs[v], ub) )
7709  {
7710  /* the bound in the diving LP was relaxed -> the LP is not a subproblem of the current node -> abort! */
7711  /**@todo we could still analyze such a conflict, but we would have to take care with our data structures */
7712  valid = FALSE;
7713  }
7714  }
7715  }
7716 
7717  if( !valid )
7718  goto TERMINATE;
7719 
7720  /* the LP is prooven to be infeasible */
7721  if( SCIPlpiIsPrimalInfeasible(lpi) )
7722  {
7723  SCIP_CALL( getFarkasProof(set, transprob, lp, lpi, farkasrow, &farkasactivity, curvarlbs, curvarubs, &valid) );
7724  }
7725  /* the LP is dual feasible and/or exceeds the current incumbant solution */
7726  else
7727  {
7728  assert(SCIPlpiIsDualFeasible(lpi) || SCIPlpiIsObjlimExc(lpi));
7729  SCIP_CALL( getDualProof(set, transprob, lp, lpi, farkasrow, &farkasactivity, curvarlbs, curvarubs, &valid) );
7730  }
7731 
7732  if( !valid )
7733  goto TERMINATE;
7734 
7735  globalinfeasible = FALSE;
7736 
7737  /* start dual proof analysis */
7738  if( ((set->conf_useinflp == 'b' || set->conf_useinflp == 'd') && conflict->conflictset->conflicttype == SCIP_CONFTYPE_INFEASLP)
7739  || ((set->conf_useboundlp == 'b' || set->conf_useboundlp == 'd') && conflict->conflictset->conflicttype == SCIP_CONFTYPE_BNDEXCEEDING) )
7740  {
7741  /* start dual ray analysis */
7742  SCIP_CALL( conflictAnalyzeDualProof(conflict, set, stat, blkmem, origprob, transprob, tree, reopt, lp, farkasrow, \
7743  curvarlbs, curvarubs, TRUE, &globalinfeasible, dualraysuccess) );
7744  }
7745 
7746  assert(valid);
7747 
7748  if( !globalinfeasible && (((set->conf_useinflp == 'b' || set->conf_useinflp == 'c') && conflict->conflictset->conflicttype == SCIP_CONFTYPE_INFEASLP)
7749  || ((set->conf_useboundlp == 'b' || set->conf_useboundlp == 'c') && conflict->conflictset->conflicttype == SCIP_CONFTYPE_BNDEXCEEDING)) )
7750  {
7751  SCIP_Real* farkascoefs;
7752  SCIP_Real farkaslhs;
7753  int* inds;
7754  int nnz;
7755 
7756 #ifdef SCIP_DEBUG
7757  {
7758  SCIP_Real objlim;
7759  SCIPsetDebugMsg(set, "analyzing conflict on infeasible LP (infeasible: %u, objlimexc: %u, optimal:%u) in depth %d (diving: %u)\n",
7761 
7762  SCIP_CALL( SCIPlpiGetRealpar(lpi, SCIP_LPPAR_OBJLIM, &objlim) );
7763  SCIPsetDebugMsg(set, " -> objective limit in LP solver: %g (in LP: %g)\n", objlim, lp->lpiobjlim);
7764  }
7765 #endif
7766 
7767  SCIP_CALL( SCIPsetAllocBufferArray(set, &farkascoefs, SCIPprobGetNVars(transprob)) );
7768  BMSclearMemoryArray(farkascoefs, SCIPprobGetNVars(transprob));
7769 
7770  farkaslhs = -SCIPaggrRowGetRhs(farkasrow);
7771  farkasactivity = -farkasactivity;
7772 
7773  inds = SCIPaggrRowGetInds(farkasrow);
7774  nnz = SCIPaggrRowGetNNz(farkasrow);
7775 
7776  for( v = 0; v < nnz; v++ )
7777  {
7778  int i = inds[v];
7779 
7780  assert(SCIPvarGetProbindex(vars[i]) == inds[v]);
7781 
7782  farkascoefs[i] = -SCIPaggrRowGetProbvarValue(farkasrow, i);
7783  }
7784 
7785  SCIP_CALL( runBoundHeuristic(conflict, set, stat, origprob, transprob, tree, reopt, lp, lpi, blkmem, farkascoefs,
7786  &farkaslhs, &farkasactivity, curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs, iterations, marklpunsolved,
7787  dualraysuccess, &valid) );
7788 
7789  SCIPsetFreeBufferArray(set, &farkascoefs);
7790 
7791  if( !valid )
7792  goto FLUSHPROOFSETS;
7793 
7794  /* analyze the conflict starting with remaining bound changes */
7795  SCIP_CALL( conflictAnalyzeRemainingBdchgs(conflict, blkmem, set, stat, transprob, tree, diving, \
7796  lbchginfoposs, ubchginfoposs, nconss, nliterals, nreconvconss, nreconvliterals) );
7797 
7798  /* flush conflict set storage */
7799  SCIP_CALL( SCIPconflictFlushConss(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, \
7800  eventqueue, cliquetable) );
7801  }
7802 
7803  FLUSHPROOFSETS:
7804  /* flush proof set */
7805  if( proofsetGetNVars(conflict->proofset) > 0 || conflict->nproofsets > 0 )
7806  {
7807  SCIP_CALL( conflictFlushProofset(conflict, conflictstore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, \
7808  branchcand, eventqueue, cliquetable) );
7809  }
7810 
7811  TERMINATE:
7812  SCIPsetFreeBufferArray(set, &curvarubs);
7813  SCIPsetFreeBufferArray(set, &curvarlbs);
7814  SCIPsetFreeBufferArray(set, &ubchginfoposs);
7815  SCIPsetFreeBufferArray(set, &lbchginfoposs);
7816  SCIPaggrRowFree(set->scip, &farkasrow);
7817 
7818  return SCIP_OKAY;
7819 }
7820 
7821 /** analyzes an infeasible LP to find out the bound changes on variables that were responsible for the infeasibility;
7822  * on success, calls standard conflict analysis with the responsible variables as starting conflict set, thus creating
7823  * a conflict constraint out of the resulting conflict set;
7824  * updates statistics for infeasible LP conflict analysis
7825  */
7826 static
7828  SCIP_CONFLICT* conflict, /**< conflict analysis data */
7829  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
7830  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
7831  SCIP_SET* set, /**< global SCIP settings */
7832  SCIP_STAT* stat, /**< problem statistics */
7833  SCIP_PROB* transprob, /**< transformed problem */
7834  SCIP_PROB* origprob, /**< original problem */
7835  SCIP_TREE* tree, /**< branch and bound tree */
7836  SCIP_REOPT* reopt, /**< reoptimization data structure */
7837  SCIP_LP* lp, /**< LP data */
7838  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7839  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7840  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7841  SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
7842  )
7843 {
7844  SCIP_Bool dualraysuccess = FALSE;
7845  SCIP_Longint olddualproofsuccess;
7846  int iterations;
7847  int nconss;
7848  int nliterals;
7849  int nreconvconss;
7850  int nreconvliterals;
7851 
7852  assert(conflict != NULL);
7853  assert(set != NULL);
7854  assert(lp != NULL);
7855  assert(SCIPprobAllColsInLP(transprob, set, lp)); /* LP conflict analysis is only valid, if all variables are known */
7856 
7857  assert(success == NULL || *success == FALSE);
7858 
7859  /* check, if infeasible LP conflict analysis is enabled */
7860  if( !set->conf_enable || set->conf_useinflp == 'o' )
7861  return SCIP_OKAY;
7862 
7863  /* check, if there are any conflict handlers to use a conflict set */
7864  if( set->nconflicthdlrs == 0 )
7865  return SCIP_OKAY;
7866 
7867  SCIPsetDebugMsg(set, "analyzing conflict on infeasible LP in depth %d (solstat: %d, objchanged: %u)\n",
7869 
7870  /* start timing */
7871  SCIPclockStart(conflict->inflpanalyzetime, set);
7872  conflict->ninflpcalls++;
7873 
7875 
7876  olddualproofsuccess = conflict->ndualrayinfsuccess;
7877 
7878  /* perform conflict analysis */
7879  SCIP_CALL( conflictAnalyzeLP(conflict, conflictstore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, \
7880  cliquetable, SCIPlpDiving(lp), &dualraysuccess, &iterations, &nconss, &nliterals, &nreconvconss, &nreconvliterals, TRUE) );
7881  conflict->ninflpsuccess += ((nconss > 0 || conflict->ndualrayinfsuccess > olddualproofsuccess) ? 1 : 0);
7882  conflict->ninflpiterations += iterations;
7883  conflict->ninflpconfconss += nconss;
7884  conflict->ninflpconfliterals += nliterals;
7885  conflict->ninflpreconvconss += nreconvconss;
7886  conflict->ninflpreconvliterals += nreconvliterals;
7887  if( success != NULL )
7888  *success = (nconss > 0 || conflict->ndualrayinfsuccess > olddualproofsuccess);
7889 
7890  /* stop timing */
7891  SCIPclockStop(conflict->inflpanalyzetime, set);
7892 
7893  return SCIP_OKAY;
7894 }
7895 
7896 /** analyzes a bound exceeding LP to find out the bound changes on variables that were responsible for exceeding the
7897  * primal bound;
7898  * on success, calls standard conflict analysis with the responsible variables as starting conflict set, thus creating
7899  * a conflict constraint out of the resulting conflict set;
7900  * updates statistics for bound exceeding LP conflict analysis
7901  */
7902 static
7904  SCIP_CONFLICT* conflict, /**< conflict analysis data */
7905  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
7906  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
7907  SCIP_SET* set, /**< global SCIP settings */
7908  SCIP_STAT* stat, /**< problem statistics */
7909  SCIP_PROB* transprob, /**< transformed problem */
7910  SCIP_PROB* origprob, /**< original problem */
7911  SCIP_TREE* tree, /**< branch and bound tree */
7912  SCIP_REOPT* reopt, /**< reoptimization data structure */
7913  SCIP_LP* lp, /**< LP data */
7914  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7915  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7916  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7917  SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
7918  )
7919 {
7920  SCIP_Bool dualraysuccess;
7921  SCIP_Longint oldnsuccess;
7922  int iterations;
7923  int nconss;
7924  int nliterals;
7925  int nreconvconss;
7926  int nreconvliterals;
7927 
7928  assert(conflict != NULL);
7929  assert(set != NULL);
7930  assert(lp != NULL);
7931  assert(!SCIPlpDivingObjChanged(lp));
7932  assert(SCIPprobAllColsInLP(transprob, set, lp)); /* LP conflict analysis is only valid, if all variables are known */
7933 
7934  assert(success == NULL || *success == FALSE);
7935 
7936  /* check, if bound exceeding LP conflict analysis is enabled */
7937  if( !set->conf_enable || set->conf_useboundlp == 'o')
7938  return SCIP_OKAY;
7939 
7940  /* check, if there are any conflict handlers to use a conflict set */
7941  if( set->nconflicthdlrs == 0 )
7942  return SCIP_OKAY;
7943 
7944  SCIPsetDebugMsg(set, "analyzing conflict on bound exceeding LP in depth %d (solstat: %d)\n",
7946 
7947  /* start timing */
7948  SCIPclockStart(conflict->boundlpanalyzetime, set);
7949  conflict->nboundlpcalls++;
7950 
7951  /* mark the conflict to depend on the cutoff bound */
7953  conflict->conflictset->usescutoffbound = TRUE;
7954 
7955  oldnsuccess = conflict->ndualraybndsuccess + conflict->ndualrayinfsuccess;
7956 
7957  /* perform conflict analysis */
7958  SCIP_CALL( conflictAnalyzeLP(conflict, conflictstore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, \
7959  cliquetable, SCIPlpDiving(lp), &dualraysuccess, &iterations, &nconss, &nliterals, &nreconvconss, &nreconvliterals, TRUE) );
7960  conflict->nboundlpsuccess += ((nconss > 0 || conflict->ndualraybndsuccess + conflict->ndualrayinfsuccess > oldnsuccess) ? 1 : 0);
7961  conflict->nboundlpiterations += iterations;
7962  conflict->nboundlpconfconss += nconss;
7963  conflict->nboundlpconfliterals += nliterals;
7964  conflict->nboundlpreconvconss += nreconvconss;
7965  conflict->nboundlpreconvliterals += nreconvliterals;
7966  if( success != NULL )
7967  *success = (nconss > 0 || conflict->ndualraybndsuccess + conflict->ndualrayinfsuccess > oldnsuccess);
7968 
7969  /* stop timing */
7970  SCIPclockStop(conflict->boundlpanalyzetime, set);
7971 
7972  return SCIP_OKAY;
7973 }
7974 
7975 /** analyzes an infeasible or bound exceeding LP to find out the bound changes on variables that were responsible for the
7976  * infeasibility or for exceeding the primal bound;
7977  * on success, calls standard conflict analysis with the responsible variables as starting conflict set, thus creating
7978  * a conflict constraint out of the resulting conflict set;
7979  * updates statistics for infeasible or bound exceeding LP conflict analysis;
7980  * may only be called if SCIPprobAllColsInLP()
7981  */
7983  SCIP_CONFLICT* conflict, /**< conflict analysis data */
7984  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
7985  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
7986  SCIP_SET* set, /**< global SCIP settings */
7987  SCIP_STAT* stat, /**< problem statistics */
7988  SCIP_PROB* transprob, /**< transformed problem */
7989  SCIP_PROB* origprob, /**< original problem */
7990  SCIP_TREE* tree, /**< branch and bound tree */
7991  SCIP_REOPT* reopt, /**< reoptimization data structure */
7992  SCIP_LP* lp, /**< LP data */
7993  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7994  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7995  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7996  SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
7997  )
7998 {
7999  SCIP_LPSOLVALS storedsolvals;
8000  SCIP_COLSOLVALS* storedcolsolvals;
8001  SCIP_ROWSOLVALS* storedrowsolvals;
8002  int c;
8003  int r;
8004 
8005  if( success != NULL )
8006  *success = FALSE;
8007 
8008  /* check if the conflict analysis is applicable */
8009  if( !set->conf_enable || (set->conf_useinflp == 'o' && set->conf_useboundlp == 'o') )
8010  return SCIP_OKAY;
8011 
8012  /* in rare cases, it might happen that the solution stati of the LP and the LPI are out of sync; in particular this
8013  * happens when a new incumbent which cuts off the current node is found during the LP solving loop; in this case the
8014  * LP has status objlimit, but if diving has been used, the LPI only has the basis information, but is not solved
8015  *
8016  * @todo: alternatively, solve the LPI
8017  */
8018  if( !SCIPlpiWasSolved(SCIPlpGetLPI(lp)) )
8019  return SCIP_OKAY;
8020 
8021  /* LP conflict analysis is only valid, if all variables are known */
8022  assert( SCIPprobAllColsInLP(transprob, set, lp) );
8024  || (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && set->lp_disablecutoff == 1) );
8025 
8026  /* save status */
8027  storedsolvals.lpsolstat = lp->lpsolstat;
8028  storedsolvals.lpobjval = lp->lpobjval;
8029  storedsolvals.primalfeasible = lp->primalfeasible;
8030  storedsolvals.primalchecked = lp->primalchecked;
8031  storedsolvals.dualfeasible = lp->dualfeasible;
8032  storedsolvals.dualchecked = lp->dualchecked;
8033  storedsolvals.solisbasic = lp->solisbasic;
8034  storedsolvals.lpissolved = lp->solved;
8035 
8036  /* store solution values */
8037  SCIP_CALL( SCIPsetAllocBufferArray(set, &storedcolsolvals, lp->ncols) );
8038  SCIP_CALL( SCIPsetAllocBufferArray(set, &storedrowsolvals, lp->nrows) );
8039  for (c = 0; c < lp->ncols; ++c)
8040  {
8041  SCIP_COL* col;
8042 
8043  col = lp->cols[c];
8044  assert( col != NULL );
8045 
8046  storedcolsolvals[c].primsol = col->primsol;
8047  storedcolsolvals[c].redcost = col->redcost;
8048  storedcolsolvals[c].basisstatus = col->basisstatus; /*lint !e641 !e732*/
8049  }
8050  for (r = 0; r < lp->nrows; ++r)
8051  {
8052  SCIP_ROW* row;
8053 
8054  row = lp->rows[r];
8055  assert( row != NULL );
8056 
8057  if ( lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
8058  storedrowsolvals[r].dualsol = row->dualfarkas;
8059  else
8060  {
8061  assert( lp->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT ||
8062  (SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL && set->lp_disablecutoff == 1) );
8063  storedrowsolvals[r].dualsol = row->dualsol;
8064  }
8065  storedrowsolvals[r].activity = row->activity;
8066  storedrowsolvals[r].basisstatus = row->basisstatus; /*lint !e641 !e732*/
8067  }
8068 
8069  /* check, if the LP was infeasible or bound exceeding */
8071  {
8072  SCIP_CALL( conflictAnalyzeInfeasibleLP(conflict, conflictstore, blkmem, set, stat, transprob, origprob, tree, \
8073  reopt, lp, branchcand, eventqueue, cliquetable, success) );
8074  }
8075  else
8076  {
8077  SCIP_CALL( conflictAnalyzeBoundexceedingLP(conflict, conflictstore, blkmem, set, stat, transprob, origprob, tree, \
8078  reopt, lp, branchcand, eventqueue, cliquetable, success) );
8079  }
8080 
8081  /* possibly restore solution values */
8083  {
8084  /* restore status */
8085  lp->lpsolstat = storedsolvals.lpsolstat;
8086  lp->lpobjval = storedsolvals.lpobjval;
8087  lp->primalfeasible = storedsolvals.primalfeasible;
8088  lp->primalchecked = storedsolvals.primalchecked;
8089  lp->dualfeasible = storedsolvals.dualfeasible;
8090  lp->dualchecked = storedsolvals.dualchecked;
8091  lp->solisbasic = storedsolvals.solisbasic;
8092  lp->solved = storedsolvals.lpissolved;
8093 
8094  for (c = 0; c < lp->ncols; ++c)
8095  {
8096  SCIP_COL* col;
8097 
8098  col = lp->cols[c];
8099  assert( col != NULL );
8100  col->primsol = storedcolsolvals[c].primsol;
8101  col->redcost = storedcolsolvals[c].redcost;
8102  col->basisstatus = storedcolsolvals[c].basisstatus; /*lint !e641 !e732*/
8103  }
8104  for (r = 0; r < lp->nrows; ++r)
8105  {
8106  SCIP_ROW* row;
8107 
8108  row = lp->rows[r];
8109  assert( row != NULL );
8110 
8111  if ( lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
8112  row->dualfarkas = storedrowsolvals[r].dualsol;
8113  else
8114  {
8115  assert( lp->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT );
8116  row->dualsol = storedrowsolvals[r].dualsol;
8117  }
8118  row->activity = storedrowsolvals[r].activity;
8119  row->basisstatus = storedrowsolvals[r].basisstatus; /*lint !e641 !e732*/
8120  }
8121  }
8122  SCIPsetFreeBufferArray(set, &storedrowsolvals);
8123  SCIPsetFreeBufferArray(set, &storedcolsolvals);
8124 
8125  return SCIP_OKAY;
8126 }
8127 
8128 /** gets time in seconds used for analyzing infeasible LP conflicts */
8130  SCIP_CONFLICT* conflict /**< conflict analysis data */
8131  )
8132 {
8133  assert(conflict != NULL);
8134 
8135  return SCIPclockGetTime(conflict->inflpanalyzetime);
8136 }
8137 
8138 /** gets number of calls to infeasible LP conflict analysis */
8140  SCIP_CONFLICT* conflict /**< conflict analysis data */
8141  )
8142 {
8143  assert(conflict != NULL);
8144 
8145  return conflict->ninflpcalls;
8146 }
8147 
8148 /** gets number of calls to infeasible LP conflict analysis that yield at least one conflict constraint */
8150  SCIP_CONFLICT* conflict /**< conflict analysis data */
8151  )
8152 {
8153  assert(conflict != NULL);
8154 
8155  return conflict->ninflpsuccess;
8156 }
8157 
8158 /** gets number of conflict constraints detected in infeasible LP conflict analysis */
8160  SCIP_CONFLICT* conflict /**< conflict analysis data */
8161  )
8162 {
8163  assert(conflict != NULL);
8164 
8165  return conflict->ninflpconfconss;
8166 }
8167 
8168 /** gets total number of literals in conflict constraints created in infeasible LP conflict analysis */
8170  SCIP_CONFLICT* conflict /**< conflict analysis data */
8171  )
8172 {
8173  assert(conflict != NULL);
8174 
8175  return conflict->ninflpconfliterals;
8176 }
8177 
8178 /** gets number of reconvergence constraints detected in infeasible LP conflict analysis */
8180  SCIP_CONFLICT* conflict /**< conflict analysis data */
8181  )
8182 {
8183  assert(conflict != NULL);
8184 
8185  return conflict->ninflpreconvconss;
8186 }
8187 
8188 /** gets total number of literals in reconvergence constraints created in infeasible LP conflict analysis */
8190  SCIP_CONFLICT* conflict /**< conflict analysis data */
8191  )
8192 {
8193  assert(conflict != NULL);
8194 
8195  return conflict->ninflpreconvliterals;
8196 }
8197 
8198 /** gets number of LP iterations in infeasible LP conflict analysis */
8200  SCIP_CONFLICT* conflict /**< conflict analysis data */
8201  )
8202 {
8203  assert(conflict != NULL);
8204 
8205  return conflict->ninflpiterations;
8206 }
8207 
8208 /** gets time in seconds used for analyzing bound exceeding LP conflicts */
8210  SCIP_CONFLICT* conflict /**< conflict analysis data */
8211  )
8212 {
8213  assert(conflict != NULL);
8214 
8215  return SCIPclockGetTime(conflict->boundlpanalyzetime);
8216 }
8217 
8218 /** gets number of calls to bound exceeding LP conflict analysis */
8220  SCIP_CONFLICT* conflict /**< conflict analysis data */
8221  )
8222 {
8223  assert(conflict != NULL);
8224 
8225  return conflict->nboundlpcalls;
8226 }
8227 
8228 /** gets number of calls to bound exceeding LP conflict analysis that yield at least one conflict constraint */
8230  SCIP_CONFLICT* conflict /**< conflict analysis data */
8231  )
8232 {
8233  assert(conflict != NULL);
8234 
8235  return conflict->nboundlpsuccess;
8236 }
8237 
8238 /** gets number of conflict constraints detected in bound exceeding LP conflict analysis */
8240  SCIP_CONFLICT* conflict /**< conflict analysis data */
8241  )
8242 {
8243  assert(conflict != NULL);
8244 
8245  return conflict->nboundlpconfconss;
8246 }
8247 
8248 /** gets total number of literals in conflict constraints created in bound exceeding LP conflict analysis */
8250  SCIP_CONFLICT* conflict /**< conflict analysis data */
8251  )
8252 {
8253  assert(conflict != NULL);
8254 
8255  return conflict->nboundlpconfliterals;
8256 }
8257 
8258 /** gets number of reconvergence constraints detected in bound exceeding LP conflict analysis */
8260  SCIP_CONFLICT* conflict /**< conflict analysis data */
8261  )
8262 {
8263  assert(conflict != NULL);
8264 
8265  return conflict->nboundlpreconvconss;
8266 }
8267 
8268 /** gets total number of literals in reconvergence constraints created in bound exceeding LP conflict analysis */
8270  SCIP_CONFLICT* conflict /**< conflict analysis data */
8271  )
8272 {
8273  assert(conflict != NULL);
8274 
8275  return conflict->nboundlpreconvliterals;
8276 }
8277 
8278 /** gets number of LP iterations in bound exceeding LP conflict analysis */
8280  SCIP_CONFLICT* conflict /**< conflict analysis data */
8281  )
8282 {
8283  assert(conflict != NULL);
8284 
8285  return conflict->nboundlpiterations;
8286 }
8287 
8288 
8289 
8290 
8291 /*
8292  * infeasible strong branching conflict analysis
8293  */
8294 
8295 /** analyses infeasible strong branching sub problems for conflicts */
8297  SCIP_CONFLICT* conflict, /**< conflict analysis data */
8298  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
8299  BMS_BLKMEM* blkmem, /**< block memory buffers */
8300  SCIP_SET* set, /**< global SCIP settings */
8301  SCIP_STAT* stat, /**< dynamic problem statistics */
8302  SCIP_PROB* transprob, /**< transformed problem */
8303  SCIP_PROB* origprob, /**< original problem */
8304  SCIP_TREE* tree, /**< branch and bound tree */
8305  SCIP_REOPT* reopt, /**< reoptimization data structure */
8306  SCIP_LP* lp, /**< LP data */
8307  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8308  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8309  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8310  SCIP_COL* col, /**< LP column with at least one infeasible strong branching subproblem */
8311  SCIP_Bool* downconflict, /**< pointer to store whether a conflict constraint was created for an
8312  * infeasible downwards branch, or NULL */
8313  SCIP_Bool* upconflict /**< pointer to store whether a conflict constraint was created for an
8314  * infeasible upwards branch, or NULL */
8315  )
8316 {
8317  int* cstat;
8318  int* rstat;
8319  SCIP_RETCODE retcode;
8320  SCIP_Bool resolve;
8321  SCIP_Real oldlb;
8322  SCIP_Real oldub;
8323  SCIP_Real newlb;
8324  SCIP_Real newub;
8325  SCIP_Bool dualraysuccess;
8326  int iter;
8327  int nconss;
8328  int nliterals;
8329  int nreconvconss;
8330  int nreconvliterals;
8331 
8332  assert(stat != NULL);
8333  assert(lp != NULL);
8334  assert(lp->flushed);
8335  assert(lp->solved);
8336  assert(SCIPprobAllColsInLP(transprob, set, lp)); /* LP conflict analysis is only valid, if all variables are known */
8337  assert(col != NULL);
8338  assert((col->sbdownvalid && SCIPsetIsGE(set, col->sbdown, lp->cutoffbound)
8339  && SCIPsetFeasCeil(set, col->primsol-1.0) >= col->lb - 0.5)
8340  || (col->sbupvalid && SCIPsetIsGE(set, col->sbup, lp->cutoffbound)
8341  && SCIPsetFeasFloor(set, col->primsol+1.0) <= col->ub + 0.5));
8342  assert(SCIPtreeGetCurrentDepth(tree) > 0);
8343 
8344  if( downconflict != NULL )
8345  *downconflict = FALSE;
8346  if( upconflict != NULL )
8347  *upconflict = FALSE;
8348 
8349  /* check, if infeasible LP conflict analysis is enabled */
8350  if( !set->conf_enable || !set->conf_usesb )
8351  return SCIP_OKAY;
8352 
8353  /* check, if there are any conflict handlers to use a conflict set */
8354  if( set->nconflicthdlrs == 0 )
8355  return SCIP_OKAY;
8356 
8357  /* inform the LPI that strong branch is (temporarily) finished */
8359 
8360  /* start timing */
8361  SCIPclockStart(conflict->sbanalyzetime, set);
8362 
8363  /* get temporary memory for storing current LP basis */
8364  SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, lp->nlpicols) );
8365  SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, lp->nlpirows) );
8366 
8367  /* get current LP basis */
8368  SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
8369 
8370  /* remember old bounds */
8371  oldlb = col->lb;
8372  oldub = col->ub;
8373 
8374  resolve = FALSE;
8375 
8376  /* is down branch infeasible? */
8377  if( col->sbdownvalid && SCIPsetIsGE(set, col->sbdown, lp->cutoffbound) )
8378  {
8379  newub = SCIPsetFeasCeil(set, col->primsol-1.0);
8380  if( newub >= col->lb - 0.5 )
8381  {
8382  SCIPsetDebugMsg(set, "analyzing conflict on infeasible downwards strongbranch for variable <%s>[%g,%g] in depth %d\n",
8384  SCIPtreeGetCurrentDepth(tree));
8385 
8387  conflict->nsbcalls++;
8388 
8389  /* change the upper bound */
8390  col->ub = newub;
8391  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, 1, &col->lpipos, &col->lb, &col->ub) );
8392 
8393  /* start LP timer */
8394  SCIPclockStart(stat->conflictlptime, set);
8395 
8396  /* resolve the LP */
8397  retcode = SCIPlpiSolveDual(lp->lpi);
8398 
8399  /* stop LP timer */
8400  SCIPclockStop(stat->conflictlptime, set);
8401 
8402  /* check return code of LP solving call */
8403  if( retcode != SCIP_LPERROR )
8404  {
8405  SCIP_CALL( retcode );
8406 
8407  /* count number of LP iterations */
8408  SCIP_CALL( SCIPlpiGetIterations(lp->lpi, &iter) );
8409  stat->nconflictlps++;
8410  stat->nconflictlpiterations += iter;
8411  conflict->nsbiterations += iter;
8412  SCIPsetDebugMsg(set, " -> resolved downwards strong branching LP in %d iterations\n", iter);
8413 
8414  /* perform conflict analysis on infeasible LP; last parameter guarantees status 'solved' on return */
8415  SCIP_CALL( conflictAnalyzeLP(conflict, conflictstore, blkmem, set, stat, transprob, origprob, tree, reopt, \
8416  lp, branchcand, eventqueue, cliquetable, TRUE, &dualraysuccess, &iter, &nconss, &nliterals, \
8417  &nreconvconss, &nreconvliterals, FALSE) );
8418  conflict->nsbsuccess += ((nconss > 0 || dualraysuccess) ? 1 : 0);
8419  conflict->nsbiterations += iter;
8420  conflict->nsbconfconss += nconss;
8421  conflict->nsbconfliterals += nliterals;
8422  conflict->nsbreconvconss += nreconvconss;
8423  conflict->nsbreconvliterals += nreconvliterals;
8424  if( downconflict != NULL )
8425  *downconflict = (nconss > 0);
8426  }
8427 
8428  /* reset the upper bound */
8429  col->ub = oldub;
8430  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, 1, &col->lpipos, &col->lb, &col->ub) );
8431 
8432  /* reset LP basis */
8433  SCIP_CALL( SCIPlpiSetBase(lp->lpi, cstat, rstat) );
8434 
8435  /* mark the LP to be resolved at the end */
8436  resolve = TRUE;
8437  }
8438  }
8439 
8440  /* is up branch infeasible? */
8441  if( col->sbupvalid && SCIPsetIsGE(set, col->sbup, lp->cutoffbound) )
8442  {
8443  newlb = SCIPsetFeasFloor(set, col->primsol+1.0);
8444  if( newlb <= col->ub + 0.5 )
8445  {
8446  SCIPsetDebugMsg(set, "analyzing conflict on infeasible upwards strongbranch for variable <%s>[%g,%g] in depth %d\n",
8448  SCIPtreeGetCurrentDepth(tree));
8449 
8451  conflict->nsbcalls++;
8452 
8453  /* change the lower bound */
8454  col->lb = newlb;
8455  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, 1, &col->lpipos, &col->lb, &col->ub) );
8456 
8457  /* start LP timer */
8458  SCIPclockStart(stat->conflictlptime, set);
8459 
8460  /* resolve the LP */
8461  retcode = SCIPlpiSolveDual(lp->lpi);
8462 
8463  /* stop LP timer */
8464  SCIPclockStop(stat->conflictlptime, set);
8465 
8466  /* check return code of LP solving call */
8467  if( retcode != SCIP_LPERROR )
8468  {
8469  SCIP_CALL( retcode );
8470 
8471  /* count number of LP iterations */
8472  SCIP_CALL( SCIPlpiGetIterations(lp->lpi, &iter) );
8473  stat->nconflictlps++;
8474  stat->nconflictlpiterations += iter;
8475  conflict->nsbiterations += iter;
8476  SCIPsetDebugMsg(set, " -> resolved upwards strong branching LP in %d iterations\n", iter);
8477 
8478  /* perform conflict analysis on infeasible LP; last parameter guarantees status 'solved' on return */
8479  SCIP_CALL( conflictAnalyzeLP(conflict, conflictstore, blkmem, set, stat, transprob, origprob, tree, reopt, \
8480  lp, branchcand, eventqueue, cliquetable, TRUE, &dualraysuccess, &iter, &nconss, &nliterals, \
8481  &nreconvconss, &nreconvliterals, FALSE) );
8482  conflict->nsbsuccess += ((nconss > 0 || dualraysuccess) ? 1 : 0);
8483  conflict->nsbiterations += iter;
8484  conflict->nsbconfconss += nconss;
8485  conflict->nsbconfliterals += nliterals;
8486  conflict->nsbreconvconss += nreconvconss;
8487  conflict->nsbreconvliterals += nreconvliterals;
8488  if( upconflict != NULL )
8489  *upconflict = (nconss > 0);
8490  }
8491 
8492  /* reset the lower bound */
8493  col->lb = oldlb;
8494  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, 1, &col->lpipos, &col->lb, &col->ub) );
8495 
8496  /* reset LP basis */
8497  SCIP_CALL( SCIPlpiSetBase(lp->lpi, cstat, rstat) );
8498 
8499  /* mark the LP to be resolved at the end */
8500  resolve = TRUE;
8501  }
8502  }
8503 
8504  /* free temporary memory for storing current LP basis */
8505  SCIPsetFreeBufferArray(set, &rstat);
8506  SCIPsetFreeBufferArray(set, &cstat);
8507 
8508  assert(lp->flushed);
8509 
8510  /* resolve LP if something has changed in order to synchronize LPI and LP */
8511  if ( resolve )
8512  {
8513  /* start LP timer */
8514  SCIPclockStart(stat->conflictlptime, set);
8515 
8516  /* resolve the LP */
8517  SCIP_CALL( SCIPlpiSolveDual(lp->lpi) );
8518 
8519  /* stop LP timer */
8520  SCIPclockStop(stat->conflictlptime, set);
8521  }
8522 
8523  /* stop timing */
8524  SCIPclockStop(conflict->sbanalyzetime, set);
8525 
8526  /* inform the LPI that strong branch starts (again) */
8528 
8529  return SCIP_OKAY;
8530 }
8531 
8532 /** gets time in seconds used for analyzing infeasible strong branching conflicts */
8534  SCIP_CONFLICT* conflict /**< conflict analysis data */
8535  )
8536 {
8537  assert(conflict != NULL);
8538 
8539  return SCIPclockGetTime(conflict->sbanalyzetime);
8540 }
8541 
8542 /** gets number of successful calls to infeasible dualray analysis */
8544  SCIP_CONFLICT* conflict /**< conflict analysis data */
8545  )
8546 {
8547  assert(conflict != NULL);
8548 
8549  return conflict->ndualrayinfsuccess;
8550 }
8551 
8552 /** gets number of globally valid dualray constraints */
8554  SCIP_CONFLICT* conflict /**< conflict analysis data */
8555  )
8556 {
8557  assert(conflict != NULL);
8558 
8559  return conflict->ndualrayinfglobal;
8560 }
8561 
8562 /** gets average length of infeasible dualrays */
8564  SCIP_CONFLICT* conflict /**< conflict analysis data */
8565  )
8566 {
8567  assert(conflict != NULL);
8568 
8569  return conflict->dualrayinfnnonzeros;
8570 }
8571 
8572 /** gets number of successfully analyzed dual proofs of boundexceeding LPs */
8574  SCIP_CONFLICT* conflict /**< conflict analysis data */
8575  )
8576 {
8577  assert(conflict != NULL);
8578 
8579  return conflict->ndualraybndsuccess;
8580 }
8581 
8582 /** gets number of globally applied dual proofs of boundexceeding LPs */
8584  SCIP_CONFLICT* conflict /**< conflict analysis data */
8585  )
8586 {
8587  assert(conflict != NULL);
8588 
8589  return conflict->ndualraybndglobal;
8590 }
8591 
8592 /** gets average length of dual proofs of boundexceeding LPs */
8594  SCIP_CONFLICT* conflict /**< conflict analysis data */
8595  )
8596 {
8597  assert(conflict != NULL);
8598 
8599  return conflict->dualraybndnnonzeros;
8600 }
8601 
8602 /** gets number of calls to infeasible strong branching conflict analysis */
8604  SCIP_CONFLICT* conflict /**< conflict analysis data */
8605  )
8606 {
8607  assert(conflict != NULL);
8608 
8609  return conflict->nsbcalls;
8610 }
8611 
8612 /** gets number of calls to infeasible strong branching conflict analysis that yield at least one conflict constraint */
8614  SCIP_CONFLICT* conflict /**< conflict analysis data */
8615  )
8616 {
8617  assert(conflict != NULL);
8618 
8619  return conflict->nsbsuccess;
8620 }
8621 
8622 /** gets number of conflict constraints detected in infeasible strong branching conflict analysis */
8624  SCIP_CONFLICT* conflict /**< conflict analysis data */
8625  )
8626 {
8627  assert(conflict != NULL);
8628 
8629  return conflict->nsbconfconss;
8630 }
8631 
8632 /** gets total number of literals in conflict constraints created in infeasible strong branching conflict analysis */
8634  SCIP_CONFLICT* conflict /**< conflict analysis data */
8635  )
8636 {
8637  assert(conflict != NULL);
8638 
8639  return conflict->nsbconfliterals;
8640 }
8641 
8642 /** gets number of reconvergence constraints detected in infeasible strong branching conflict analysis */
8644  SCIP_CONFLICT* conflict /**< conflict analysis data */
8645  )
8646 {
8647  assert(conflict != NULL);
8648 
8649  return conflict->nsbreconvconss;
8650 }
8651 
8652 /** gets total number of literals in reconvergence constraints created in infeasible strong branching conflict analysis */
8654  SCIP_CONFLICT* conflict /**< conflict analysis data */
8655  )
8656 {
8657  assert(conflict != NULL);
8658 
8659  return conflict->nsbreconvliterals;
8660 }
8661 
8662 /** gets number of LP iterations in infeasible strong branching conflict analysis */
8664  SCIP_CONFLICT* conflict /**< conflict analysis data */
8665  )
8666 {
8667  assert(conflict != NULL);
8668 
8669  return conflict->nsbiterations;
8670 }
8671 
8672 
8673 
8674 
8675 /*
8676  * pseudo solution conflict analysis
8677  */
8678 
8679 /** analyzes a pseudo solution with objective value exceeding the current cutoff to find out the bound changes on
8680  * variables that were responsible for the objective value degradation;
8681  * on success, calls standard conflict analysis with the responsible variables as starting conflict set, thus creating
8682  * a conflict constraint out of the resulting conflict set;
8683  * updates statistics for pseudo solution conflict analysis
8684  */
8686  SCIP_CONFLICT* conflict, /**< conflict analysis data */
8687  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
8688  SCIP_SET* set, /**< global SCIP settings */
8689  SCIP_STAT* stat, /**< problem statistics */
8690  SCIP_PROB* transprob, /**< transformed problem */
8691  SCIP_PROB* origprob, /**< original problem */
8692  SCIP_TREE* tree, /**< branch and bound tree */
8693  SCIP_REOPT* reopt, /**< reoptimization data structure */
8694  SCIP_LP* lp, /**< LP data */
8695  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8696  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8697  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8698  SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
8699  )
8700 {
8701  SCIP_VAR** vars;
8702  SCIP_VAR* var;
8703  SCIP_Real* curvarlbs;
8704  SCIP_Real* curvarubs;
8705  int* lbchginfoposs;
8706  int* ubchginfoposs;
8707  SCIP_Real* pseudocoefs;
8708  SCIP_Real pseudolhs;
8709  SCIP_Real pseudoact;
8710  int nvars;
8711  int v;
8712 
8713  assert(conflict != NULL);
8714  assert(conflict->nconflictsets == 0);
8715  assert(set != NULL);
8716  assert(stat != NULL);
8717  assert(transprob != NULL);
8718  assert(lp != NULL);
8719  assert(!SCIPsetIsInfinity(set, -SCIPlpGetPseudoObjval(lp, set, transprob)));
8720  assert(!SCIPsetIsInfinity(set, lp->cutoffbound));
8721 
8722  if( success != NULL )
8723  *success = FALSE;
8724 
8725  /* check, if pseudo solution conflict analysis is enabled */
8726  if( !set->conf_enable || !set->conf_usepseudo )
8727  return SCIP_OKAY;
8728 
8729  /* check, if there are any conflict handlers to use a conflict set */
8730  if( set->nconflicthdlrs == 0 )
8731  return SCIP_OKAY;
8732 
8733  SCIPsetDebugMsg(set, "analyzing pseudo solution (obj: %g) that exceeds objective limit (%g)\n",
8734  SCIPlpGetPseudoObjval(lp, set, transprob), lp->cutoffbound);
8735 
8737  conflict->conflictset->usescutoffbound = TRUE;
8738 
8739  /* start timing */
8740  SCIPclockStart(conflict->pseudoanalyzetime, set);
8741  conflict->npseudocalls++;
8742 
8743  vars = transprob->vars;
8744  nvars = transprob->nvars;
8745  assert(nvars == 0 || vars != NULL);
8746 
8747  /* The current primal bound c* gives an upper bound for the current pseudo objective value:
8748  * min{c^T x | lb <= x <= ub} <= c*.
8749  * We have to transform this row into a >= inequality in order to use methods above:
8750  * -c* <= max{-c^T x | lb <= x <= ub}.
8751  * In the local subproblem, this row is violated. We want to undo bound changes while still keeping the
8752  * row violated.
8753  */
8754 
8755  /* get temporary memory for remembering variables' current bounds and corresponding bound change information
8756  * positions in variable's bound change information arrays
8757  */
8758  SCIP_CALL( SCIPsetAllocBufferArray(set, &curvarlbs, nvars) );
8759  SCIP_CALL( SCIPsetAllocBufferArray(set, &curvarubs, nvars) );
8760  SCIP_CALL( SCIPsetAllocBufferArray(set, &lbchginfoposs, nvars) );
8761  SCIP_CALL( SCIPsetAllocBufferArray(set, &ubchginfoposs, nvars) );
8762 
8763  /* get temporary memory for infeasibility proof coefficients */
8764  SCIP_CALL( SCIPsetAllocBufferArray(set, &pseudocoefs, nvars) );
8765 
8766  /* use a slightly tighter cutoff bound, because solutions with equal objective value should also be declared
8767  * infeasible
8768  */
8769  pseudolhs = -(lp->cutoffbound - SCIPsetSumepsilon(set));
8770 
8771  /* store the objective values as infeasibility proof coefficients, and recalculate the pseudo activity */
8772  pseudoact = 0.0;
8773  for( v = 0; v < nvars; ++v )
8774  {
8775  var = vars[v];
8776  pseudocoefs[v] = -SCIPvarGetObj(var);
8777  curvarlbs[v] = SCIPvarGetLbLocal(var);
8778  curvarubs[v] = SCIPvarGetUbLocal(var);
8779  if( pseudocoefs[v] > 0.0 )
8780  pseudoact += pseudocoefs[v] * curvarubs[v];
8781  else
8782  pseudoact += pseudocoefs[v] * curvarlbs[v];
8783  lbchginfoposs[v] = var->nlbchginfos-1;
8784  ubchginfoposs[v] = var->nubchginfos-1;
8785  }
8786  assert(SCIPsetIsFeasEQ(set, pseudoact, -SCIPlpGetPseudoObjval(lp, set, transprob)));
8787  SCIPsetDebugMsg(set, " -> recalculated pseudo infeasibility proof: %g <= %g\n", pseudolhs, pseudoact);
8788 
8789  /* check, if the pseudo row is still violated (after recalculation of pseudo activity) */
8790  if( SCIPsetIsFeasGT(set, pseudolhs, pseudoact) )
8791  {
8792  int nconss;
8793  int nliterals;
8794  int nreconvconss;
8795  int nreconvliterals;
8796 
8797  /* undo bound changes without destroying the infeasibility proof */
8798  SCIP_CALL( undoBdchgsProof(set, transprob, SCIPtreeGetCurrentDepth(tree), pseudocoefs, pseudolhs, &pseudoact,
8799  curvarlbs, curvarubs, lbchginfoposs, ubchginfoposs, NULL, NULL, NULL, lp->lpi) );
8800 
8801  /* analyze conflict on remaining bound changes */
8802  SCIP_CALL( conflictAnalyzeRemainingBdchgs(conflict, blkmem, set, stat, transprob, tree, FALSE, \
8803  lbchginfoposs, ubchginfoposs, &nconss, &nliterals, &nreconvconss, &nreconvliterals) );
8804  conflict->npseudosuccess += (nconss > 0 ? 1 : 0);
8805  conflict->npseudoconfconss += nconss;
8806  conflict->npseudoconfliterals += nliterals;
8807  conflict->npseudoreconvconss += nreconvconss;
8808  conflict->npseudoreconvliterals += nreconvliterals;
8809  if( success != NULL )
8810  *success = (nconss > 0);
8811  }
8812 
8813  /* free temporary memory */
8814  SCIPsetFreeBufferArray(set, &pseudocoefs);
8815  SCIPsetFreeBufferArray(set, &ubchginfoposs);
8816  SCIPsetFreeBufferArray(set, &lbchginfoposs);
8817  SCIPsetFreeBufferArray(set, &curvarubs);
8818  SCIPsetFreeBufferArray(set, &curvarlbs);
8819 
8820  /* flush conflict set storage */
8821  SCIP_CALL( SCIPconflictFlushConss(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cliquetable) );
8822 
8823  /* stop timing */
8824  SCIPclockStop(conflict->pseudoanalyzetime, set);
8825 
8826  return SCIP_OKAY;
8827 }
8828 
8829 /** gets time in seconds used for analyzing pseudo solution conflicts */
8831  SCIP_CONFLICT* conflict /**< conflict analysis data */
8832  )
8833 {
8834  assert(conflict != NULL);
8835 
8836  return SCIPclockGetTime(conflict->pseudoanalyzetime);
8837 }
8838 
8839 /** gets number of calls to pseudo solution conflict analysis */
8841  SCIP_CONFLICT* conflict /**< conflict analysis data */
8842  )
8843 {
8844  assert(conflict != NULL);
8845 
8846  return conflict->npseudocalls;
8847 }
8848 
8849 /** gets number of calls to pseudo solution conflict analysis that yield at least one conflict constraint */
8851  SCIP_CONFLICT* conflict /**< conflict analysis data */
8852  )
8853 {
8854  assert(conflict != NULL);
8855 
8856  return conflict->npseudosuccess;
8857 }
8858 
8859 /** gets number of conflict constraints detected in pseudo solution conflict analysis */
8861  SCIP_CONFLICT* conflict /**< conflict analysis data */
8862  )
8863 {
8864  assert(conflict != NULL);
8865 
8866  return conflict->npseudoconfconss;
8867 }
8868 
8869 /** gets total number of literals in conflict constraints created in pseudo solution conflict analysis */
8871  SCIP_CONFLICT* conflict /**< conflict analysis data */
8872  )
8873 {
8874  assert(conflict != NULL);
8875 
8876  return conflict->npseudoconfliterals;
8877 }
8878 
8879 /** gets number of reconvergence constraints detected in pseudo solution conflict analysis */
8881  SCIP_CONFLICT* conflict /**< conflict analysis data */
8882  )
8883 {
8884  assert(conflict != NULL);
8885 
8886  return conflict->npseudoreconvconss;
8887 }
8888 
8889 /** gets total number of literals in reconvergence constraints created in pseudo solution conflict analysis */
8891  SCIP_CONFLICT* conflict /**< conflict analysis data */
8892  )
8893 {
8894  assert(conflict != NULL);
8895 
8896  return conflict->npseudoreconvliterals;
8897 }
8898 
8899 
8900 /** enables or disables all clocks of \p conflict, depending on the value of the flag */
8902  SCIP_CONFLICT* conflict, /**< the conflict analysis data for which all clocks should be enabled or disabled */
8903  SCIP_Bool enable /**< should the clocks of the conflict analysis data be enabled? */
8904  )
8905 {
8906  assert(conflict != NULL);
8907 
8908  SCIPclockEnableOrDisable(conflict->boundlpanalyzetime, enable);
8909  SCIPclockEnableOrDisable(conflict->dIBclock, enable);
8910  SCIPclockEnableOrDisable(conflict->inflpanalyzetime, enable);
8911  SCIPclockEnableOrDisable(conflict->propanalyzetime, enable);
8912  SCIPclockEnableOrDisable(conflict->pseudoanalyzetime, enable);
8913  SCIPclockEnableOrDisable(conflict->sbanalyzetime, enable);
8914 }
8915 
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
void SCIPconflictEnableOrDisableClocks(SCIP_CONFLICT *conflict, SCIP_Bool enable)
Definition: conflict.c:8901
SCIP_Longint SCIPconflictGetNStrongbranchSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:8613
static SCIP_Bool bdchginfoIsResolvable(SCIP_BDCHGINFO *bdchginfo)
Definition: conflict.c:3586
SCIP_Bool solisbasic
Definition: struct_lp.h:353
#define ALLOWLOCAL
Definition: conflict.c:148
static SCIP_RETCODE conflictInitProofset(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem)
Definition: conflict.c:892
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
static SCIP_RETCODE undoBdchgsDualsol(SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, int currentdepth, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, int *lbchginfoposs, int *ubchginfoposs, SCIP_LPBDCHGS *oldlpbdchgs, SCIP_LPBDCHGS *relaxedlpbdchgs, SCIP_Bool *valid, SCIP_Bool *resolve, SCIP_Real *dualcoefs, SCIP_Real duallhs, SCIP_Real *dualactivity)
Definition: conflict.c:6181
SCIP_CLOCK * propanalyzetime
SCIP_Bool lpissolved
Definition: struct_lp.h:116
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17997
int SCIPpqueueNElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1263
SCIP_Bool SCIPconflicthdlrIsInitialized(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:756
static SCIP_RETCODE addSideRemoval(SCIP_SET *set, SCIP_ROW *row, SCIP_Real lpiinfinity, int **sidechginds, SCIP_Real **sidechgoldlhss, SCIP_Real **sidechgoldrhss, SCIP_Real **sidechgnewlhss, SCIP_Real **sidechgnewrhss, int *sidechgssize, int *nsidechgs)
Definition: conflict.c:5564
void SCIPconflicthdlrSetInit(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTINIT((*conflictinit)))
Definition: conflict.c:668
SCIP_Real sbup
Definition: struct_lp.h:145
SCIP_Longint ninflpconfliterals
SCIP_Longint SCIPconflictGetNLocalChgBds(SCIP_CONFLICT *conflict)
Definition: conflict.c:3548
SCIP_Bool primalchecked
Definition: struct_lp.h:112
void SCIPaggrRowFree(SCIP *scip, SCIP_AGGRROW **aggrrow)
Definition: cuts.c:1570
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5776
static SCIP_Real aggrRowGetMinActivity(SCIP_PROB *transprob, SCIP_AGGRROW *aggrrow, SCIP_Real *curvarlbs, SCIP_Real *curvarubs)
Definition: conflict.c:2557
SCIP_RETCODE SCIPconflictAnalyzeLP(SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *success)
Definition: conflict.c:7982
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:449
#define NUMSTOP
Definition: conflict.c:6119
unsigned int repropagate
SCIP_Longint ninflpreconvconss
SCIP_Longint SCIPconflictGetNPropConflictConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:5477
const char * SCIPconflicthdlrGetDesc(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:722
#define MINFRAC
Definition: conflict.c:149
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5834
static int conflictCalcMaxsize(SCIP_SET *set, SCIP_PROB *prob)
Definition: conflict.c:2007
internal methods for storing primal CIP solutions
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:487
SCIP_RETCODE SCIPconflictAddBound(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx)
Definition: conflict.c:4133
SCIP_RETCODE SCIPvarIncVSIDS(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
Definition: var.c:14457
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17962
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19649
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:16992
int nubchginfos
Definition: struct_var.h:263
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:17676
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:130
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17068
internal methods for branch and bound tree
SCIP_BDCHGIDX bdchgidx
Definition: struct_var.h:112
static SCIP_BDCHGINFO * conflictRemoveCand(SCIP_CONFLICT *conflict)
Definition: conflict.c:4451
SCIP_Real conflictlb
Definition: struct_var.h:213
static SCIP_Bool isBoundchgUseless(SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo)
Definition: conflict.c:3976
SCIP_RETCODE SCIPaggrRowAddRow(SCIP *scip, SCIP_AGGRROW *aggrrow, SCIP_ROW *row, SCIP_Real weight, int sidetype)
Definition: cuts.c:1673
SCIP_Longint SCIPconflictGetNPropSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:5467
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19509
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17858
void SCIPconflicthdlrSetExit(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTEXIT((*conflictexit)))
Definition: conflict.c:679
SCIP_PQUEUE * bdchgqueue
int SCIPconsGetValidDepth(SCIP_CONS *cons)
Definition: cons.c:8069
SCIP_Bool primalfeasible
Definition: struct_lp.h:349
SCIP_Longint nsbcalls
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
static SCIP_Real calcBdchgScore(SCIP_Real prooflhs, SCIP_Real proofact, SCIP_Real proofactdelta, SCIP_Real proofcoef, int depth, int currentdepth, SCIP_VAR *var, SCIP_SET *set)
Definition: conflict.c:1336
#define SCIPsetAllocBuffer(set, ptr)
Definition: set.h:1875
int nlpicols
Definition: struct_lp.h:299
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6174
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17468
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17878
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
void SCIPconflicthdlrSetInitsol(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTINITSOL((*conflictinitsol)))
Definition: conflict.c:690
SCIP_Longint SCIPconflictGetNBoundexceedingLPConflictConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:8239
static SCIP_RETCODE tightenDualproof(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_AGGRROW *proofrow, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_Bool initialproof)
Definition: conflict.c:6897
SCIP_PARAMDATA * SCIPparamGetData(SCIP_PARAM *param)
Definition: paramset.c:661
static SCIP_RETCODE propagateLongProof(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_REOPT *reopt, SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real *coefs, int *inds, int nnz, SCIP_Real rhs, SCIP_CONFTYPE conflicttype)
Definition: conflict.c:2676
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
SCIP_Longint SCIPconflictGetNAppliedGlobalConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:3528
SCIP_Longint SCIPconflictGetNBoundexceedingLPIterations(SCIP_CONFLICT *conflict)
Definition: conflict.c:8279
SCIP_CLOCK * conflictlptime
Definition: struct_stat.h:152
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
#define SCIP_MAXSTRLEN
Definition: def.h:259
SCIP_Real SCIPconflicthdlrGetSetupTime(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:778
static void lpbdchgsReset(SCIP_LPBDCHGS *lpbdchgs, int ncols)
Definition: conflict.c:826
void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:627
static SCIP_RETCODE conflictCreateTmpBdchginfo(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound, SCIP_BDCHGINFO **bdchginfo)
Definition: conflict.c:1162
SCIP_Longint SCIPconflictGetNPseudoReconvergenceLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:8890
internal methods for clocks and timing issues
SCIP_Longint SCIPconflictGetNGlobalChgBds(SCIP_CONFLICT *conflict)
Definition: conflict.c:3518
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:125
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5899
SCIP_Longint nappliedlocliterals
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17056
static long bound
SCIP_CLOCK * inflpanalyzetime
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
SCIP_Real * bdchgubs
struct SCIP_ParamData SCIP_PARAMDATA
Definition: type_paramset.h:76
SCIP_Longint SCIPconflictGetNPseudoConflictLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:8870
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1888
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:15770
void SCIPconflicthdlrSetCopy(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTCOPY((*conflictcopy)))
Definition: conflict.c:646
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17332
SCIP_Longint SCIPconflictGetNInfeasibleLPSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:8149
static SCIP_RETCODE undoBdchgsProof(SCIP_SET *set, SCIP_PROB *prob, int currentdepth, SCIP_Real *proofcoefs, SCIP_Real prooflhs, SCIP_Real *proofact, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, int *lbchginfoposs, int *ubchginfoposs, SCIP_LPBDCHGS *oldlpbdchgs, SCIP_LPBDCHGS *relaxedlpbdchgs, SCIP_Bool *resolve, SCIP_LPI *lpi)
Definition: conflict.c:5919
SCIP_Longint nappliedglbliterals
SCIP_Longint SCIPconflictGetNPropCalls(SCIP_CONFLICT *conflict)
Definition: conflict.c:5457
SCIP_Longint SCIPconflictGetNDualrayInfSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:8543
SCIP_Longint npseudoreconvliterals
static void proofsetCancelVarWithBound(SCIP_PROOFSET *proofset, SCIP_SET *set, SCIP_VAR *var, int pos, SCIP_Bool *valid)
Definition: conflict.c:1094
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:16543
void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition: misc.c:485
static SCIP_RETCODE lpbdchgsCreate(SCIP_LPBDCHGS **lpbdchgs, SCIP_SET *set, int ncols)
Definition: conflict.c:804
SCIP_Longint SCIPconflictGetNStrongbranchIterations(SCIP_CONFLICT *conflict)
Definition: conflict.c:8663
SCIP_Real SCIPconflicthdlrGetTime(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:788
static SCIP_RETCODE conflictsetCalcInsertDepth(SCIP_CONFLICTSET *conflictset, SCIP_SET *set, SCIP_TREE *tree)
Definition: conflict.c:1734
interface methods for specific LP solvers
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16842
SCIP_Longint npropconfliterals
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5636
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
static SCIP_RETCODE conflictAddConflictBound(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd)
Definition: conflict.c:3933
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2305
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:243
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17838
void SCIPconsMarkConflict(SCIP_CONS *cons)
Definition: cons.c:6900
SCIP_COL ** cols
Definition: struct_lp.h:287
int startnconss
Definition: struct_prob.h:76
void SCIPgmlWriteClosing(FILE *file)
Definition: misc.c:687
int nlpirows
Definition: struct_lp.h:302
SCIP_Longint nappliedglbconss
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12342
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:14543
unsigned int nboundchgs
Definition: struct_var.h:123
datastructures for conflict analysis
SCIP_Longint npseudoreconvconss
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:350
SCIP_Longint SCIPconflictGetNInfeasibleLPReconvergenceConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:8179
SCIP_Longint SCIPconflictGetNInfeasibleLPReconvergenceLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:8189
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:16484
#define FALSE
Definition: def.h:64
static void skipRedundantBdchginfos(SCIP_VAR *var, int *lbchginfopos, int *ubchginfopos)
Definition: conflict.c:5887
methods for the aggregation rows
static SCIP_BDCHGINFO * conflictFirstCand(SCIP_CONFLICT *conflict)
Definition: conflict.c:4495
SCIP_RETCODE SCIPconflictAnalyze(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, int validdepth, SCIP_Bool *success)
Definition: conflict.c:5379
SCIP_Longint nlocchgbds
SCIP_Bool solved
Definition: struct_lp.h:348
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:280
SCIP_RETCODE SCIPconflicthdlrExec(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set, SCIP_NODE *node, SCIP_NODE *validnode, SCIP_BDCHGINFO **bdchginfos, SCIP_Real *relaxedbds, int nbdchginfos, SCIP_CONFTYPE conftype, SCIP_Bool usescutoffbound, SCIP_Bool resolved, SCIP_RESULT *result)
Definition: conflict.c:577
SCIP_Bool dualchecked
Definition: struct_lp.h:352
static SCIP_RETCODE undoBdchgsDualfarkas(SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, int currentdepth, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, int *lbchginfoposs, int *ubchginfoposs, SCIP_LPBDCHGS *oldlpbdchgs, SCIP_LPBDCHGS *relaxedlpbdchgs, SCIP_Bool *valid, SCIP_Bool *resolve, SCIP_Real *farkascoefs, SCIP_Real farkaslhs, SCIP_Real *farkasactivity)
Definition: conflict.c:6123
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5888
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Longint SCIPconflictGetNPropConflictLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:5487
SCIP_Real * relaxedbds
unsigned int basisstatus
Definition: struct_lp.h:240
SCIP_RETCODE SCIPcutGenerationHeuristicCMIR(SCIP *scip, SCIP_SOL *sol, SCIP_Bool postprocess, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, int maxtestdelta, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_AGGRROW *aggrrow, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, int *cutinds, int *cutnnz, SCIP_Real *cutefficacy, int *cutrank, SCIP_Bool *cutislocal, SCIP_Bool *success)
Definition: cuts.c:3954
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17510
int nlbchginfos
Definition: struct_var.h:261
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17973
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
void SCIPconflicthdlrSetPriority(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set, int priority)
Definition: conflict.c:742
SCIP_Real dualsol
Definition: struct_lp.h:98
SCIP_Real redcost
Definition: struct_lp.h:140
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1877
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:8302
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16969
SCIP_Longint npropcalls
unsigned int sbdownvalid
Definition: struct_lp.h:179
void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
Definition: misc.c:1249
SCIP_Longint dualrayinfnnonzeros
SCIP_RETCODE SCIPconflicthdlrExitsol(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set)
Definition: conflict.c:553
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5326
unsigned int basisstatus
Definition: struct_lp.h:170
SCIP_Longint nglbchgbds
SCIP_Real * bdchglbs
SCIP_Longint npropsuccess
SCIP_Real dualfarkas
Definition: struct_lp.h:206
#define EPSGE(x, y, eps)
Definition: def.h:178
int SCIPaggrRowGetNNz(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:2344
SCIP_Real SCIPaggrRowGetRhs(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:2374
void SCIPpqueueFree(SCIP_PQUEUE **pqueue)
Definition: misc.c:1160
static void conflictsetClear(SCIP_CONFLICTSET *conflictset)
Definition: conflict.c:1202
SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
Definition: lp.c:16757
SCIP_Bool diving
Definition: struct_lp.h:361
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_RETCODE SCIPconflictFree(SCIP_CONFLICT **conflict, BMS_BLKMEM *blkmem)
Definition: conflict.c:3727
SCIP_Longint SCIPconflictGetNAppliedLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:3508
SCIP_Real SCIPlpGetPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:12814
static SCIP_RETCODE conflictAddBound(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd)
Definition: conflict.c:4077
SCIP_RETCODE SCIPconflicthdlrCreate(SCIP_CONFLICTHDLR **conflicthdlr, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTCOPY((*conflictcopy)), SCIP_DECL_CONFLICTFREE((*conflictfree)), SCIP_DECL_CONFLICTINIT((*conflictinit)), SCIP_DECL_CONFLICTEXIT((*conflictexit)), SCIP_DECL_CONFLICTINITSOL((*conflictinitsol)), SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol)), SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
Definition: conflict.c:382
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:17808
static SCIP_RETCODE conflictQueueBound(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd)
Definition: conflict.c:3996
internal methods for handling parameter settings
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5910
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7352
void SCIPconflicthdlrSetExitsol(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTEXITSOL((*conflictexitsol)))
Definition: conflict.c:701
static SCIP_RETCODE conflictInsertProofset(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_PROOFSET *proofset)
Definition: conflict.c:1892
methods for creating output for visualization tools (VBC, BAK)
void SCIPclockEnableOrDisable(SCIP_CLOCK *clck, SCIP_Bool enable)
Definition: clock.c:250
SCIP_Real SCIPconflictGetGlobalApplTime(SCIP_CONFLICT *conflict)
Definition: conflict.c:5437
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1884
unsigned int basisstatus
Definition: struct_lp.h:100
#define BMSfreeMemory(ptr)
Definition: memory.h:127
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6152
static SCIP_RETCODE conflictFlushProofset(SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable)
Definition: conflict.c:3013
SCIP_Longint SCIPconflictGetNStrongbranchReconvergenceLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:8653
SCIP_Real SCIPconflictGetPseudoTime(SCIP_CONFLICT *conflict)
Definition: conflict.c:8830
#define SCIP_DECL_CONFLICTEXIT(x)
SCIP_Longint nappliedlocconss
SCIP_Longint SCIPconflictGetNInfeasibleLPConflictLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:8169
SCIP_Longint SCIPconflictGetNPropReconvergenceConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:5497
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:12615
SCIP_VISUAL * visual
Definition: struct_stat.h:165
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
int conflictlbcount
Definition: struct_var.h:264
internal methods for LP management
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17628
static void proofsetClear(SCIP_PROOFSET *proofset)
Definition: conflict.c:859
SCIP_Longint npseudosuccess
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1343
SCIP_Real SCIPconflictGetVarUb(SCIP_CONFLICT *conflict, SCIP_VAR *var)
Definition: conflict.c:4435
SCIP_Bool primalchecked
Definition: struct_lp.h:350
real eps
internal methods for branching and inference history
SCIP_Real SCIPconflictGetStrongbranchTime(SCIP_CONFLICT *conflict)
Definition: conflict.c:8533
SCIP_Longint SCIPconflictGetNAppliedLocalLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:3568
SCIP_Bool strongbranching
Definition: struct_lp.h:358
SCIP_Longint SCIPconflictGetNDualrayBndNonzeros(SCIP_CONFLICT *conflict)
Definition: conflict.c:8593
SCIP_Longint SCIPconflictGetNPseudoConflictConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:8860
SCIP_Longint ninflpiterations
#define POSTPROCESS
Definition: conflict.c:146
SCIP_Bool dualfeasible
Definition: struct_lp.h:113
SCIP_Longint SCIPconflictGetNDualrayInfGlobal(SCIP_CONFLICT *conflict)
Definition: conflict.c:8553
int SCIPconflictstoreGetNDualInfProofs(SCIP_CONFLICTSTORE *conflictstore)
SCIP_Bool SCIPconsIsGlobal(SCIP_CONS *cons)
Definition: cons.c:8215
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:16747
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12412
static SCIP_RETCODE conflictEnsureProofsetsMem(SCIP_CONFLICT *conflict, SCIP_SET *set, int num)
Definition: conflict.c:1843
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5870
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:163
internal methods for propagators
SCIP_Longint npropreconvliterals
static SCIP_Bool conflictsetIsRedundant(SCIP_CONFLICTSET *conflictset1, SCIP_CONFLICTSET *conflictset2)
Definition: conflict.c:1781
SCIP_RETCODE SCIPaggrRowAddObjectiveFunction(SCIP *scip, SCIP_AGGRROW *aggrrow, SCIP_Real rhs, SCIP_Real scale)
Definition: cuts.c:1817
int SCIPtreeGetFocusDepth(SCIP_TREE *tree)
Definition: tree.c:8227
#define SCIPdebugCheckConflict(blkmem, set, node, bdchginfos, relaxedbds, nliterals)
Definition: debug.h:258
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:501
SCIP_Longint npropconfconss
SCIP_Longint nboundlpcalls
SCIP_Real SCIPgetVarBdAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19789
SCIP_Real * vals
Definition: struct_lp.h:220
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:39
SCIP_Real conflictrelaxedub
Definition: struct_var.h:216
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18031
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
SCIP_Real avgnnz
Definition: struct_stat.h:115
SCIP_RETCODE SCIPnodeCutoff(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_REOPT *reopt, SCIP_LP *lp, BMS_BLKMEM *blkmem)
Definition: tree.c:1146
SCIP_RETCODE SCIPconflictAnalyzePseudo(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *success)
Definition: conflict.c:8685
void SCIPconflicthdlrSetFree(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTFREE((*conflictfree)))
Definition: conflict.c:657
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5816
#define BOUNDSWITCH
Definition: conflict.c:145
SCIP_CLOCK * setuptime
SCIP_RETCODE SCIPconflicthdlrExit(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set)
Definition: conflict.c:498
SCIP_CLOCK * pseudoanalyzetime
SCIP_RETCODE SCIPconflicthdlrInitsol(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set)
Definition: conflict.c:529
SCIP_DOMCHG * domchg
Definition: struct_tree.h:148
static void proofsetFree(SCIP_PROOFSET **proofset, BMS_BLKMEM *blkmem)
Definition: conflict.c:907
int lpiitlim
Definition: struct_lp.h:326
SCIP_Real lb
Definition: struct_lp.h:129
SCIP_Real dualsol
Definition: struct_lp.h:204
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:215
static SCIP_RETCODE detectImpliedBounds(SCIP_SET *set, SCIP_PROB *prob, SCIP_CONFLICTSET *conflictset, int *nbdchgs, int *nredvars, SCIP_Bool *redundant)
Definition: conflict.c:2175
static SCIP_RETCODE addCand(SCIP_SET *set, int currentdepth, SCIP_VAR *var, int lbchginfopos, int ubchginfopos, SCIP_Real proofcoef, SCIP_Real prooflhs, SCIP_Real proofact, SCIP_VAR ***cands, SCIP_Real **candscores, SCIP_Real **newbounds, SCIP_Real **proofactdeltas, int *candssize, int *ncands, int firstcand)
Definition: conflict.c:5751
#define SCIP_DECL_CONFLICTINITSOL(x)
SCIP_CLOCK * boundlpanalyzetime
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:443
SCIP_Longint SCIPconflictGetNInfeasibleLPConflictConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:8159
SCIP_Real sbdown
Definition: struct_lp.h:144
SCIP_Longint ninflpreconvliterals
#define SCIP_DECL_CONFLICTEXEC(x)
SCIP_BDCHGINFO ** tmpbdchginfos
SCIP_CLOCK * conflicttime
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:129
static SCIP_RETCODE separateAlternativeProofs(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_AGGRROW *proofrow, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_CONFTYPE conflicttype)
Definition: conflict.c:6772
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:526
SCIP_BOUNDTYPE SCIPboundtypeOpposite(SCIP_BOUNDTYPE boundtype)
Definition: lp.c:16395
internal methods for storing and manipulating the main problem
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
#define SCIPdebugPrintf
Definition: pub_message.h:80
SCIP_Longint ndualraybndglobal
static SCIP_RETCODE conflictsetAddBounds(SCIP_CONFLICT *conflict, SCIP_CONFLICTSET *conflictset, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BDCHGINFO **bdchginfos, int nbdchginfos)
Definition: conflict.c:1524
static SCIP_RETCODE conflictsetEnsureBdchginfosMem(SCIP_CONFLICTSET *conflictset, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: conflict.c:1292
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17818
SCIP_Longint SCIPconflictGetNBoundexceedingLPReconvergenceConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:8259
static SCIP_RETCODE tightenSingleVar(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real val, SCIP_Real rhs, SCIP_CONFTYPE prooftype)
Definition: conflict.c:2436
SCIP_Bool dualchecked
Definition: struct_lp.h:114
SCIP_COL ** cols
Definition: struct_lp.h:218
void SCIPclockReset(SCIP_CLOCK *clck)
Definition: clock.c:199
SCIP_Longint SCIPconflictGetNDualrayBndGlobal(SCIP_CONFLICT *conflict)
Definition: conflict.c:8583
SCIP_Longint nconflictlpiterations
Definition: struct_stat.h:70
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
static SCIP_Bool conflictMarkBoundCheckPresence(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd)
Definition: conflict.c:3844
SCIP_Bool SCIPsetIsRelEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6661
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:16593
SCIP_CONFLICTHDLRDATA * conflicthdlrdata
static SCIP_RETCODE createAndAddProofcons(SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_PROOFSET *proofset, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem)
Definition: conflict.c:2775
SCIP_NODE ** path
Definition: struct_tree.h:177
SCIP_Longint SCIPconflictGetNPseudoReconvergenceConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:8880
SCIP_ROW ** lpirows
Definition: struct_lp.h:284
unsigned int sbupvalid
Definition: struct_lp.h:181
SCIP_RETCODE SCIPsolSetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_VAR *var, SCIP_Real val)
Definition: sol.c:1027
SCIP_Longint SCIPconflictGetNAppliedLocalConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:3558
SCIP_Real lhs
Definition: struct_lp.h:195
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7986
static SCIP_RETCODE conflictEnsureConflictsetsMem(SCIP_CONFLICT *conflict, SCIP_SET *set, int num)
Definition: conflict.c:1867
static SCIP_RETCODE convertToActiveVar(SCIP_VAR **var, SCIP_SET *set, SCIP_BOUNDTYPE *boundtype, SCIP_Real *bound)
Definition: conflict.c:4042
SCIP_Longint npropreconvconss
unsigned int pos
Definition: struct_var.h:113
static SCIP_Real conflictsetCalcScore(SCIP_CONFLICTSET *conflictset, SCIP_SET *set)
Definition: conflict.c:1322
SCIP_PROOFSET * proofset
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
SCIP_Real SCIPconflictGetBoundexceedingLPTime(SCIP_CONFLICT *conflict)
Definition: conflict.c:8209
static SCIP_RETCODE conflictsetCreate(SCIP_CONFLICTSET **conflictset, BMS_BLKMEM *blkmem)
Definition: conflict.c:1220
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:428
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6352
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1881
SCIP_Real cutoffbound
Definition: struct_lp.h:274
SCIP_PROOFSET ** proofsets
static SCIP_RETCODE proofsetCreate(SCIP_PROOFSET **proofset, BMS_BLKMEM *blkmem)
Definition: conflict.c:872
SCIP_Longint SCIPconflictGetNStrongbranchReconvergenceConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:8643
int * SCIPaggrRowGetInds(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:2334
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:162
#define REALABS(x)
Definition: def.h:173
static SCIP_Real getMaxActivity(SCIP_PROB *transprob, SCIP_Real *coefs, int *inds, int nnz, SCIP_Real *curvarlbs, SCIP_Real *curvarubs)
Definition: conflict.c:2637
void SCIPsortedvecInsertIntPtrReal(int *intarray, void **ptrarray, SCIP_Real *realarray, int keyval, void *field1val, SCIP_Real field2val, int *len, int *pos)
SCIP_Longint ninflpcalls
SCIP_Longint nconflictlps
Definition: struct_stat.h:193
void SCIPaggrRowRemoveZeros(SCIP *scip, SCIP_AGGRROW *aggrrow, SCIP_Bool *valid)
Definition: cuts.c:2269
void SCIPgmlWriteEdge(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:583
SCIP_RETCODE SCIPconflicthdlrFree(SCIP_CONFLICTHDLR **conflicthdlr, SCIP_SET *set)
Definition: conflict.c:434
SCIP_Longint SCIPconflictGetNStrongbranchConflictLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:8633
struct SCIP_ConflicthdlrData SCIP_CONFLICTHDLRDATA
Definition: type_conflict.h:40
SCIP_DECL_SORTPTRCOMP(SCIPconflicthdlrComp)
Definition: conflict.c:336
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_Real activity
Definition: struct_lp.h:99
static SCIP_Real * proofsetGetVals(SCIP_PROOFSET *proofset)
Definition: conflict.c:958
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18017
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6262
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:16767
#define SCIP_DECL_CONFLICTCOPY(x)
Definition: type_conflict.h:77
SCIP_Longint SCIPconflictGetNPseudoSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:8850
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:16494
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18006
SCIP_RETCODE SCIPsetAddIntParam(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: set.c:2813
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5798
SCIP_Real vsidsweight
Definition: struct_stat.h:118
SCIP_LPI * SCIPlpGetLPI(SCIP_LP *lp)
Definition: lp.c:16919
static SCIP_RETCODE conflictsetAddBound(SCIP_CONFLICTSET *conflictset, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd)
Definition: conflict.c:1454
SCIP_LPI * lpi
Definition: struct_lp.h:282
SCIP_Longint SCIPconflictGetNInfeasibleLPCalls(SCIP_CONFLICT *conflict)
Definition: conflict.c:8139
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17928
static SCIP_RETCODE conflictAddConflictset(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, int validdepth, SCIP_Bool diving, SCIP_Bool repropagate, SCIP_Bool *success, int *nliterals)
Definition: conflict.c:4549
static SCIP_CONFTYPE proofsetGetConftype(SCIP_PROOFSET *proofset)
Definition: conflict.c:991
void * SCIPpqueueRemove(SCIP_PQUEUE *pqueue)
Definition: misc.c:1208
SCIP_CLOCK * sbanalyzetime
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6218
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:125
static SCIP_RETCODE conflictAnalyzeRemainingBdchgs(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_Bool diving, int *lbchginfoposs, int *ubchginfoposs, int *nconss, int *nliterals, int *nreconvconss, int *nreconvliterals)
Definition: conflict.c:6238
SCIP_RETCODE SCIPclockCreate(SCIP_CLOCK **clck, SCIP_CLOCKTYPE clocktype)
Definition: clock.c:160
methods commonly used for presolving
SCIP_Longint nboundlpsuccess
SCIP_RETCODE SCIPconflicthdlrInit(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set)
Definition: conflict.c:461
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6186
static SCIP_RETCODE conflictAnalyzeBoundexceedingLP(SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *success)
Definition: conflict.c:7903
SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
SCIP_CONFLICTSET * conflictset
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:446
SCIP_Longint nboundlpreconvconss
internal methods for problem variables
static SCIP_RETCODE conflictAnalyzeDualProof(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_AGGRROW *proofrow, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_Bool initialproof, SCIP_Bool *globalinfeasible, SCIP_Bool *success)
Definition: conflict.c:7060
void SCIPsortedvecDelPosIntPtrReal(int *intarray, void **ptrarray, SCIP_Real *realarray, int pos, int *len)
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5921
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
public data structures and miscellaneous methods
void SCIPnodePropagateAgain(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree)
Definition: tree.c:1206
#define SCIP_Bool
Definition: def.h:61
#define SCIPsetFreeBuffer(set, ptr)
Definition: set.h:1882
SCIP_Real redcost
Definition: struct_lp.h:87
SCIP_Real SCIPsetSumepsilon(SCIP_SET *set)
Definition: set.c:5668
SCIP_Real * vals
SCIP_Real SCIPaggrRowCalcEfficacyNorm(SCIP *scip, SCIP_AGGRROW *aggrrow)
Definition: cuts.c:1963
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:435
int SCIPconflicthdlrGetPriority(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:732
SCIP_RETCODE SCIPpropResolvePropagation(SCIP_PROP *prop, SCIP_SET *set, SCIP_VAR *infervar, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT *result)
Definition: prop.c:682
SCIP_Bool SCIPcutsTightenCoefficients(SCIP *scip, SCIP_Bool cutislocal, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, int *cutinds, int *cutnnz, int *nchgcoefs)
Definition: cuts.c:1337
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17918
int ncontvars
Definition: struct_prob.h:65
unsigned int depth
Definition: struct_tree.h:149
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
SCIP_Longint SCIPconflictGetNDualrayInfNonzeros(SCIP_CONFLICT *conflict)
Definition: conflict.c:8563
SCIP_Longint dualraybndnnonzeros
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
SCIP_Bool SCIPconflictApplicable(SCIP_SET *set)
Definition: conflict.c:3623
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17001
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6112
SCIP_RETCODE SCIPcalcFlowCover(SCIP *scip, SCIP_SOL *sol, SCIP_Bool postprocess, SCIP_Real boundswitch, SCIP_Bool allowlocal, SCIP_AGGRROW *aggrrow, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, int *cutinds, int *cutnnz, SCIP_Real *cutefficacy, int *cutrank, SCIP_Bool *cutislocal, SCIP_Bool *success)
Definition: cuts.c:7087
static SCIP_RETCODE proofsetAddAggrrow(SCIP_PROOFSET *proofset, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_AGGRROW *aggrrow)
Definition: conflict.c:1053
void SCIPclockFree(SCIP_CLOCK **clck)
Definition: clock.c:175
SCIP_Bool SCIPlpDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:17002
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3217
SCIP_RETCODE SCIPconflictAnalyzeStrongbranch(SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_COL *col, SCIP_Bool *downconflict, SCIP_Bool *upconflict)
Definition: conflict.c:8296
#define MAX(x, y)
Definition: tclique_def.h:75
unsigned int basisstatus
Definition: struct_lp.h:88
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8006
#define SCIPdebugCheckConflictFrontier(blkmem, set, node, bdchginfo, bdchginfos, relaxedbds, nliterals, bdchgqueue, forcedbdchgqueue)
Definition: debug.h:259
methods for debugging
SCIP_Real SCIPconflictstoreGetAvgNnzDualBndProofs(SCIP_CONFLICTSTORE *conflictstore)
SCIP_CONFTYPE conflicttype
static SCIP_RETCODE incVSIDS(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BOUNDTYPE boundtype, SCIP_Real value, SCIP_Real weight)
Definition: conflict.c:2025
#define SCIPsetDebugMsg
Definition: set.h:1913
SCIP_Real conflictub
Definition: struct_var.h:214
SCIP_PQUEUE * forcedbdchgqueue
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:38535
SCIP_Real oldbound
Definition: struct_var.h:108
SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
Definition: prob.c:2262
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17124
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17868
SCIP_RETCODE SCIPconflictstoreAddDualraycons(SCIP_CONFLICTSTORE *conflictstore, SCIP_CONS *dualproof, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_REOPT *reopt)
SCIP_Longint SCIPconflictGetNStrongbranchConflictConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:8623
static void conflictsetCalcConflictDepth(SCIP_CONFLICTSET *conflictset)
Definition: conflict.c:1690
static SCIP_DECL_PARAMCHGD(paramChgdConflicthdlrPriority)
Definition: conflict.c:349
#define EPSLE(x, y, eps)
Definition: def.h:176
void SCIPsortLongPtrRealRealBool(SCIP_Longint *longarray, void **ptrarray, SCIP_Real *realarray, SCIP_Real *realarray2, SCIP_Bool *boolarray, int len)
void ** SCIPpqueueElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1274
SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
SCIP_Longint ndualrayinfglobal
static SCIP_RETCODE updateStatistics(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_CONFLICTSET *conflictset, int insertdepth)
Definition: conflict.c:2056
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
int SCIPconflictGetNConflicts(SCIP_CONFLICT *conflict)
Definition: conflict.c:3488
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16990
SCIP_Longint SCIPconflictGetNBoundexceedingLPCalls(SCIP_CONFLICT *conflict)
Definition: conflict.c:8219
void SCIPsortIntPtrReal(int *intarray, void **ptrarray, SCIP_Real *realarray, int len)
Constraint handler for linear constraints in their most general form, .
#define MAXFRAC
Definition: conflict.c:150
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17044
SCIP_Longint nboundlpreconvliterals
SCIP_Real ub
Definition: struct_lp.h:130
SCIP_Longint nsbconfconss
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6196
SCIP_Longint nsbconfliterals
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
SCIP_Longint SCIPconflictGetNBoundexceedingLPReconvergenceLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:8269
SCIP_RETCODE SCIPvarIncNActiveConflicts(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real length)
Definition: var.c:14593
SCIP_ROW ** rows
Definition: struct_lp.h:289
SCIP_Longint nboundlpiterations
#define debugPrintViolationInfo(...)
Definition: conflict.c:6725
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2240
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17985
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:887
int conflictubcount
Definition: struct_var.h:265
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:17696
SCIP_Longint npseudoconfliterals
SCIP_Longint ninflpconfconss
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15926
#define SCIP_REAL_MAX
Definition: def.h:150
static SCIP_RETCODE conflictsetCopy(SCIP_CONFLICTSET **targetconflictset, BMS_BLKMEM *blkmem, SCIP_CONFLICTSET *sourceconflictset, int nadditionalelems)
Definition: conflict.c:1240
int SCIPparamGetInt(SCIP_PARAM *param)
Definition: paramset.c:716
SCIP_Real rhs
Definition: struct_lp.h:196
SCIP_Longint SCIPconflictGetNPseudoCalls(SCIP_CONFLICT *conflict)
Definition: conflict.c:8840
SCIP_Real constant
Definition: struct_lp.h:194
SCIP_Longint SCIPconflictGetNDualrayBndSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:8573
static void lpbdchgsFree(SCIP_LPBDCHGS **lpbdchgs, SCIP_SET *set)
Definition: conflict.c:839
#define SCIP_REAL_MIN
Definition: def.h:151
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6341
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:16450
SCIP_CONFTYPE conflicttype
static SCIP_RETCODE ensureSidechgsSize(SCIP_SET *set, int **sidechginds, SCIP_Real **sidechgoldlhss, SCIP_Real **sidechgoldrhss, SCIP_Real **sidechgnewlhss, SCIP_Real **sidechgnewrhss, int *sidechgssize, int num)
Definition: conflict.c:5525
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:153
void SCIPconflicthdlrSetData(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
Definition: conflict.c:635
SCIP_Real SCIPconflictGetInfeasibleLPTime(SCIP_CONFLICT *conflict)
Definition: conflict.c:8129
SCIP_RETCODE SCIPconflictCreate(SCIP_CONFLICT **conflict, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: conflict.c:3639
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:16328
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3162
void SCIPvisualFoundConflict(SCIP_VISUAL *visual, SCIP_STAT *stat, SCIP_NODE *node)
Definition: visual.c:599
SCIP_Longint SCIPconflictGetNBoundexceedingLPSuccess(SCIP_CONFLICT *conflict)
Definition: conflict.c:8229
static SCIP_RETCODE conflictAnalyzeLP(SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool diving, SCIP_Bool *dualraysuccess, int *iterations, int *nconss, int *nliterals, int *nreconvconss, int *nreconvliterals, SCIP_Bool marklpunsolved)
Definition: conflict.c:7515
SCIP_LPSOLSTAT lpsolstat
Definition: struct_lp.h:109
unsigned int boundtype
Definition: struct_var.h:115
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:16254
SCIP_Longint lastconflictnode
Definition: struct_stat.h:101
internal methods for conflict analysis
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1891
static SCIP_RETCODE conflictAddConflictCons(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_CONFLICTSET *conflictset, int insertdepth, SCIP_Bool *success)
Definition: conflict.c:3131
SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1181
static const SCIP_Real scalars[]
Definition: lp.c:5618
SCIP_Longint nsbsuccess
int lpipos
Definition: struct_lp.h:164
static SCIP_RETCODE getDualProof(SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, SCIP_LPI *lpi, SCIP_AGGRROW *farkasrow, SCIP_Real *farkasact, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_Bool *valid)
Definition: conflict.c:6527
SCIP_RETCODE SCIPpqueueCreate(SCIP_PQUEUE **pqueue, int initsize, SCIP_Real sizefac, SCIP_DECL_SORTPTRCOMP((*ptrcomp)))
Definition: misc.c:1135
static int * proofsetGetInds(SCIP_PROOFSET *proofset)
Definition: conflict.c:947
void SCIPsetSortConflicthdlrs(SCIP_SET *set)
Definition: set.c:3807
SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition: tree.c:2021
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17908
static SCIP_RETCODE conflictAnalyzeInfeasibleLP(SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *success)
Definition: conflict.c:7827
unsigned int redundant
Definition: struct_var.h:117
static SCIP_RETCODE ensureCandsSize(SCIP_SET *set, SCIP_VAR ***cands, SCIP_Real **candscores, SCIP_Real **newbounds, SCIP_Real **proofactdeltas, int *candssize, int num)
Definition: conflict.c:5714
SCIP_Longint nsbreconvliterals
static void conflictsetFree(SCIP_CONFLICTSET **conflictset, BMS_BLKMEM *blkmem)
Definition: conflict.c:1276
SCIP_Longint nboundlpconfliterals
SCIP_Bool flushed
Definition: struct_lp.h:347
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27761
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
int nrows
Definition: struct_lp.h:315
static SCIP_RETCODE conflictInsertConflictset(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CONFLICTSET **conflictset)
Definition: conflict.c:1912
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:712
SCIP_VAR * var
Definition: struct_var.h:110
public methods for message output
SCIP_RETCODE SCIPconflictInit(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_CONFTYPE conftype, SCIP_Bool usescutoffbound)
Definition: conflict.c:3775
#define USEVBDS
Definition: conflict.c:147
SCIP_Real * conflictsetscores
SCIP_RETCODE SCIPconflictAddRelaxedBound(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedbd)
Definition: conflict.c:4194
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5852
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16781
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
struct SCIP_LPi SCIP_LPI
Definition: type_lpi.h:96
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:16673
static SCIP_RETCODE addBdchg(SCIP_SET *set, SCIP_VAR *var, SCIP_Real newlb, SCIP_Real newub, SCIP_LPBDCHGS *oldlpbdchgs, SCIP_LPBDCHGS *relaxedlpbdchgs, SCIP_LPI *lpi)
Definition: conflict.c:5633
SCIP_Real lpobjval
Definition: struct_lp.h:261
SCIP_Real primsol
Definition: struct_lp.h:86
#define SCIP_Real
Definition: def.h:149
internal methods for problem statistics
SCIP_Bool solisbasic
Definition: struct_lp.h:115
SCIP_VAR ** vars
Definition: struct_prob.h:55
enum SCIP_ConflictType SCIP_CONFTYPE
Definition: type_conflict.h:56
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17938
SCIP_Longint npseudocalls
SCIP_Real lpiobjlim
Definition: struct_lp.h:275
SCIP_Longint SCIPconflictGetNStrongbranchCalls(SCIP_CONFLICT *conflict)
Definition: conflict.c:8603
SCIP_Longint SCIPconflictGetNInfeasibleLPIterations(SCIP_CONFLICT *conflict)
Definition: conflict.c:8199
SCIP_Real SCIPconflictGetVarLb(SCIP_CONFLICT *conflict, SCIP_VAR *var)
Definition: conflict.c:4418
#define SCIPsetDebugMsgPrint
Definition: set.h:1914
SCIP_RETCODE SCIPconflictFlushConss(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable)
Definition: conflict.c:3279
SCIP_Longint ndualraybndsuccess
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2350
SCIP_RETCODE SCIPconflictIsVarUsed(SCIP_CONFLICT *conflict, SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool *used)
Definition: conflict.c:4358
#define BMSallocMemory(ptr)
Definition: memory.h:101
#define SCIP_INVALID
Definition: def.h:169
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:109
SCIP_CLOCK * dIBclock
SCIP_RETCODE SCIPconflictstoreAddDualsolcons(SCIP_CONFLICTSTORE *conflictstore, SCIP_CONS *dualproof, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_REOPT *reopt, SCIP_Real scale, SCIP_Bool updateside)
#define SCIP_DECL_CONFLICTINIT(x)
Definition: type_conflict.h:93
internal methods for constraints and constraint handlers
SCIP_RETCODE SCIPaggrRowCreate(SCIP *scip, SCIP_AGGRROW **aggrrow)
Definition: cuts.c:1538
static SCIP_Bool checkRedundancy(SCIP_SET *set, SCIP_CONFLICTSET *conflictset)
Definition: conflict.c:2110
SCIP_Real primsol
Definition: struct_lp.h:139
SCIP_Longint nsbiterations
SCIP_Longint SCIPconflictGetNAppliedGlobalLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:3538
SCIP_Longint nboundlpconfconss
static SCIP_RETCODE conflictAnalyze(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_Bool diving, int validdepth, SCIP_Bool mustresolve, int *nconss, int *nliterals, int *nreconvconss, int *nreconvliterals)
Definition: conflict.c:5099
static SCIP_Real getMinActivity(SCIP_PROB *transprob, SCIP_Real *coefs, int *inds, int nnz, SCIP_Real *curvarlbs, SCIP_Real *curvarubs)
Definition: conflict.c:2597
int SCIPconflictstoreGetNDualBndProofs(SCIP_CONFLICTSTORE *conflictstore)
#define SCIP_Longint
Definition: def.h:134
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17950
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6495
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:13468
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16959
void SCIPconflicthdlrEnableOrDisableClocks(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_Bool enable)
Definition: conflict.c:766
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6240
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16827
SCIP_Longint npseudoconfconss
SCIP_RETCODE SCIPshrinkDisjunctiveVarSet(SCIP *scip, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_Bool *boundtypes, SCIP_Bool *redundants, int nvars, int *nredvars, int *nglobalred, SCIP_Bool *setredundant, SCIP_Bool *glbinfeas, SCIP_Bool fullshortening)
Definition: presolve.c:969
SCIP_Real SCIPconflictstoreGetAvgNnzDualInfProofs(SCIP_CONFLICTSTORE *conflictstore)
static SCIP_RETCODE getFarkasProof(SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, SCIP_LPI *lpi, SCIP_AGGRROW *farkasrow, SCIP_Real *farkasact, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_Bool *valid)
Definition: conflict.c:6377
SCIP_Bool dualfeasible
Definition: struct_lp.h:351
static void conflictFreeTmpBdchginfos(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem)
Definition: conflict.c:1186
SCIP_Longint SCIPconflictGetNAppliedConss(SCIP_CONFLICT *conflict)
Definition: conflict.c:3498
static INLINE SCIP_Real SCIPaggrRowGetProbvarValue(SCIP_AGGRROW *aggrrow, int probindex)
Definition: cuts.h:234
SCIP_Real newbound
Definition: struct_var.h:109
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17342
SCIP_Longint SCIPconflictGetNBoundexceedingLPConflictLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:8249
void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
Definition: misc.c:671
SCIP_RETCODE SCIPprobAddCons(SCIP_PROB *prob, SCIP_SET *set, SCIP_STAT *stat, SCIP_CONS *cons)
Definition: prob.c:1266
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:15800
SCIP_BDCHGINFO ** bdchginfos
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6169
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:433
static int proofsetGetNVars(SCIP_PROOFSET *proofset)
Definition: conflict.c:980
SCIP_Longint SCIPconflictGetNPropReconvergenceLiterals(SCIP_CONFLICT *conflict)
Definition: conflict.c:5507
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17898
unsigned int usescutoffbound
static void tightenCoefficients(SCIP_SET *set, SCIP_PROOFSET *proofset, int *nchgcoefs, SCIP_Bool *redundant)
Definition: conflict.c:6730
SCIP_CONFLICTSET ** conflictsets
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:112
SCIP_Real SCIPconflictGetPropTime(SCIP_CONFLICT *conflict)
Definition: conflict.c:5447
common defines and data types used in all packages of SCIP
SCIP_Longint nnodes
Definition: struct_stat.h:71
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:419
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12057
#define SCIP_DECL_CONFLICTFREE(x)
Definition: type_conflict.h:85
SCIP_NODE * root
Definition: struct_tree.h:175
void SCIPaggrRowClear(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:1938
static SCIP_RETCODE conflictResolveBound(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_BDCHGINFO *bdchginfo, SCIP_Real relaxedbd, int validdepth, SCIP_Bool *resolved)
Definition: conflict.c:4648
SCIP_CONFLICTHDLRDATA * SCIPconflicthdlrGetData(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:625
SCIP_RETCODE SCIPconflicthdlrCopyInclude(SCIP_CONFLICTHDLR *conflicthdlr, SCIP_SET *set)
Definition: conflict.c:363
static SCIP_RETCODE conflictEnsureTmpbdchginfosMem(SCIP_CONFLICT *conflict, SCIP_SET *set, int num)
Definition: conflict.c:1138
SCIP_Bool primalfeasible
Definition: struct_lp.h:111
static SCIP_RETCODE conflictCreateReconvergenceConss(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_Bool diving, int validdepth, SCIP_BDCHGINFO *firstuip, int *nreconvconss, int *nreconvliterals)
Definition: conflict.c:4861
SCIP_RETCODE SCIPsetConflicthdlrPriority(SCIP *scip, SCIP_CONFLICTHDLR *conflicthdlr, int priority)
Definition: scip.c:6853
void SCIPpqueueClear(SCIP_PQUEUE *pqueue)
Definition: misc.c:1171
#define SCIP_ALLOC(x)
Definition: def.h:361
#define SCIPABORT()
Definition: def.h:322
SCIP_LPSOLSTAT lpsolstat
Definition: struct_lp.h:334
int SCIPcolGetLPPos(SCIP_COL *col)
Definition: lp.c:16295
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16853
const char * SCIPprobGetName(SCIP_PROB *prob)
Definition: prob.c:2296
SCIP_Longint ndualrayinfsuccess
int ncols
Definition: struct_lp.h:309
static void conflictClear(SCIP_CONFLICT *conflict)
Definition: conflict.c:3763
static SCIP_Bool bdchginfoIsInvalid(SCIP_CONFLICT *conflict, SCIP_BDCHGINFO *bdchginfo)
Definition: conflict.c:1411
SCIP_Real lpobjval
Definition: struct_lp.h:110
SCIP_Longint nsbreconvconss
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:439
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
unsigned int local
Definition: struct_lp.h:249
SCIP_Real activity
Definition: struct_lp.h:205
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
static SCIP_RETCODE runBoundHeuristic(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_Real *proofcoefs, SCIP_Real *prooflhs, SCIP_Real *proofactivity, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, int *lbchginfoposs, int *ubchginfoposs, int *iterations, SCIP_Bool marklpunsolved, SCIP_Bool *dualraysuccess, SCIP_Bool *valid)
Definition: conflict.c:7143
SCIP_Bool * usedcols
int len
Definition: struct_lp.h:226
SCIP callable library.
static SCIP_RETCODE proofsetAddSparseData(SCIP_PROOFSET *proofset, BMS_BLKMEM *blkmem, SCIP_Real *vals, int *inds, int nnz, SCIP_Real rhs)
Definition: conflict.c:1002
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16949
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:242
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37878
SCIP_Longint ninflpsuccess
#define SCIP_DECL_CONFLICTEXITSOL(x)
SCIP_RETCODE SCIPconsResolvePropagation(SCIP_CONS *cons, SCIP_SET *set, SCIP_VAR *infervar, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT *result)
Definition: cons.c:7099
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17888
static SCIP_Real proofsetGetRhs(SCIP_PROOFSET *proofset)
Definition: conflict.c:969