Scippy

SCIP

Solving Constraint Integer Programs

conflict_resolution.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file conflict_resolution.c
26 * @ingroup OTHER_CFILES
27 * @brief Methods for generalized resolution conflict analysis.
28 * @author Gioni Mexi
29 *
30 * This file implements a conflict analysis method based on generalized resolution,
31 * as detailed in the paper:
32 *
33 * Gioni Mexi, et al. "Cut-based Conflict Analysis in Mixed Integer Programming."
34 * arXiv preprint arXiv:2410.15110 (2024).
35 *
36 * The generalized resolution conflict analysis procedure starts with an initial
37 * conflict row and it iteratively aggregates this row with a reason row—the row
38 * that propagated the bound change causing the conflict. The aggregation
39 * cancels the coefficient of the resolving variable. This process continues
40 * until a first unique implication point (FUIP) is reached. If the aggregation
41 * does not yield a valid (infeasible) row, the algorithm attempts to reduce the
42 * reason row (e.g., using MIR reduction) and retries the aggregation. Once a
43 * valid conflict row with negative slack is generated, a conflict constraint is
44 * constructed and added to the problem.
45 *
46 */
47/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
48
50#include "scip/clock.h"
51#include "scip/conflict.h"
53#include "scip/cons.h"
54#include "scip/cons_linear.h"
55#include "scip/cuts.h"
56#include "scip/history.h"
57#include "scip/prob.h"
58#include "scip/prop.h"
59#include "scip/pub_cons.h"
60#include "scip/pub_conflict.h"
61#include "scip/pub_lp.h"
62#include "scip/pub_message.h"
63#include "scip/pub_misc.h"
64#include "scip/pub_var.h"
65#include "scip/scip_conflict.h"
66#include "scip/scip_cons.h"
67#include "scip/scip_mem.h"
68#include "scip/scip_prob.h"
69#include "scip/scip_sol.h"
70#include "scip/scip_var.h"
71#include "scip/set.h"
72#include "scip/sol.h"
74#include "scip/struct_lp.h"
75#include "scip/struct_prob.h"
76#include "scip/struct_set.h"
77#include "scip/struct_stat.h"
78#include "scip/tree.h"
79#include "scip/var.h"
80
81#include <string.h>
82#ifndef _WIN32
83#include <strings.h> /*lint --e{766}*/
84#endif
85
86/* parameters for MIR cuts*/
87#define BOUNDSWITCH 0.51 /**< threshold for bound switching - see cuts.c */
88#define POSTPROCESS FALSE /**< apply postprocessing after MIR calculation - see SCIPcalcMIR() */
89#define USEVBDS FALSE /**< use variable bounds - see SCIPcalcMIR() */
90#define FIXINTEGRALRHS FALSE /**< try to generate an integral rhs - see SCIPcalcMIR() */
91#define MINFRAC 0.05 /**< minimal fractionality of floor(rhs) - see cuts.c */
92#define MAXFRAC 0.999 /**< maximal fractionality of floor(rhs) - see cuts.c */
93
94#define EPS 1e-06
95
96/** creates a copy of the given generalized resolution row, allocating an additional amount of memory */
97static
99 SCIP_CONFLICTROW** targetrow, /**< pointer to store the generalized resolution row */
100 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
101 SCIP_CONFLICTROW* sourcerow /**< source generalized resolution row */
102 )
103{
104 int targetsize;
105 int nvars;
106
107 assert(targetrow != NULL);
108 assert(sourcerow != NULL);
109
110 targetsize = sourcerow->nnz;
111 nvars = sourcerow->nvars;
112 SCIP_ALLOC( BMSallocBlockMemory(blkmem, targetrow) );
113 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetrow)->inds, targetsize) );
114 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*targetrow)->vals, nvars) );
115
116 /* copy all data from source to target */
117 BMScopyMemoryArray((*targetrow)->inds, sourcerow->inds, targetsize);
118 BMScopyMemoryArray((*targetrow)->vals, sourcerow->vals, nvars);
119
120 /* copy all other data */
121 (*targetrow)->lhs = sourcerow->lhs;
122 (*targetrow)->slack = sourcerow->slack;
123 (*targetrow)->coefquotient = sourcerow->coefquotient;
124 (*targetrow)->nvars = nvars;
125 (*targetrow)->nnz = targetsize;
126 (*targetrow)->size = targetsize;
127 (*targetrow)->validdepth = sourcerow->validdepth;
128 (*targetrow)->conflictdepth = sourcerow->conflictdepth;
129 (*targetrow)->repropdepth = sourcerow->repropdepth;
130 (*targetrow)->insertdepth = sourcerow->insertdepth;
131 (*targetrow)->usescutoffbound = sourcerow->usescutoffbound;
132 (*targetrow)->isbinary = sourcerow->isbinary;
133 (*targetrow)->conflicttype = sourcerow->conflicttype;
134
135 return SCIP_OKAY;
136}
137
138/** replaces a generalized resolution row by another; allocate an additional amount of memory if needed */
139static
141 SCIP_CONFLICTROW* targetrow, /**< pointer to store the generalized resolution row */
142 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
143 SCIP_CONFLICTROW* sourcerow /**< source generalized resolution row */
144 )
145{
146 int sourcennzs;
147 int targetsize;
148 int nvars;
149
150 assert(targetrow != NULL);
151 assert(sourcerow != NULL);
152
153 nvars = sourcerow->nvars;
154 sourcennzs = sourcerow->nnz;
155 targetsize = targetrow->size;
156
157 /* allocate additional memory for the indices array if needed */
158 if( targetsize < sourcennzs )
159 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &targetrow->inds, targetsize, sourcennzs) );
160
161 /* copy all data from source to target */
162 BMScopyMemoryArray(targetrow->inds, sourcerow->inds, sourcennzs);
163 BMScopyMemoryArray(targetrow->vals, sourcerow->vals, nvars);
164
165 targetrow->lhs = sourcerow->lhs;
166 targetrow->slack = sourcerow->slack;
167 targetrow->coefquotient = sourcerow->coefquotient;
168 targetrow->nvars = sourcerow->nvars;
169 targetrow->nnz = sourcennzs;
170 targetrow->size = MAX(sourcennzs, targetsize);
171 targetrow->validdepth = sourcerow->validdepth;
172 targetrow->conflictdepth = sourcerow->conflictdepth;
173 targetrow->repropdepth = sourcerow->repropdepth;
174 targetrow->insertdepth = sourcerow->insertdepth;
175 targetrow->usescutoffbound = sourcerow->usescutoffbound;
176 targetrow->isbinary = sourcerow->isbinary;
177 targetrow->conflicttype = sourcerow->conflicttype;
178
179 return SCIP_OKAY;
180}
181
182/** resizes conflict rows array to be able to store at least num entries */
183static
185 SCIP_CONFLICT* conflict, /**< conflict analysis data */
186 SCIP_SET* set, /**< global SCIP settings */
187 int num /**< minimal number of slots in array */
188 )
189{
190 assert(conflict != NULL);
191 assert(set != NULL);
192
193 if( num > conflict->conflictrowssize )
194 {
195 int newsize;
196
197 newsize = SCIPsetCalcMemGrowSize(set, num);
198 SCIP_ALLOC( BMSreallocMemoryArray(&conflict->conflictrows, newsize) );
199 conflict->conflictrowssize = newsize;
200 }
201 assert(num <= conflict->conflictrowssize);
202
203 return SCIP_OKAY;
204}
205
206/** add conflict row to the array of all conflicts rows */
207static
209 SCIP_CONFLICT* conflict, /**< conflict analysis data */
210 SCIP_SET* set, /**< global SCIP settings */
211 SCIP_CONFLICTROW** conflictrow /**< conflict row to add */
212 )
213{
214 assert(conflict != NULL);
215 assert(conflictrow != NULL);
216
217 /* insert resolution into the conflictrows array */
218 SCIP_CALL( conflictEnsureConflictRowsMem(conflict, set, conflict->nconflictrows + 1) );
219
220 SCIPsetDebugMsgPrint(set, "inserting conflict row (valid depth: %d, conf depth: %d, reprop depth: %d):\n",
221 (*conflictrow)->validdepth, (*conflictrow)->conflictdepth, (*conflictrow)->repropdepth);
222
223 conflict->conflictrows[conflict->nconflictrows] = *conflictrow;
224 ++conflict->nconflictrows;
225
226 /* ownership of pointer is now in the conflictrows array */
227 *conflictrow = NULL;
228
229 return SCIP_OKAY;
230}
231
232/** gets number of conflict constraints found during propagation with the generalized resolution conflict analysis */
234 SCIP_CONFLICT* conflict /**< conflict analysis data */
235 )
236{
237 assert(conflict != NULL);
238
239 return conflict->nresconfconss;
240}
241
242/** gets number of calls to generalized resolution conflict analysis that yield at least one conflict constraint */
244 SCIP_CONFLICT* conflict /**< conflict analysis data */
245 )
246{
247 assert(conflict != NULL);
248
249 return conflict->nressuccess;
250}
251
252
253/** gets number of calls to generalized resolution conflict analysis terminating because of large coefficients */
255 SCIP_CONFLICT* conflict /**< conflict analysis data */
256 )
257{
258 assert(conflict != NULL);
259
260 return conflict->nreslargecoefs;
261}
262
263/** gets number of calls to generalized resolution conflict analysis terminating because of long conflicts */
265 SCIP_CONFLICT* conflict /**< conflict analysis data */
266 )
267{
268 assert(conflict != NULL);
269
270 return conflict->nreslongconfs;
271}
272
273/** gets number of calls to generalized resolution conflict analysis */
275 SCIP_CONFLICT* conflict /**< conflict analysis data */
276 )
277{
278 assert(conflict != NULL);
279
280 return conflict->nrescalls;
281}
282
283
284#ifdef SCIP_DEBUG
285/* Enum definition for the types of rows */
286typedef enum {
287 CONFLICT_ROWTYPE, /**< infeasible row at the current state */
288 REASON_ROWTYPE, /**< reason row for the bound change that led to the infeasibility */
289 REDUCED_REASON_ROWTYPE, /**< reason row after applying reason reduction */
290 RESOLVED_CONFLICT_ROWTYPE, /**< resolved infeasible row (after adding the conflict and reason rows) */
291 CONTINUOUS_REASON_ROWTYPE /**< reason row for a bound change on a continuous variable */
292} ConflictRowType;
293
294/** prints a generalized resolution row */
295static
296void printConflictRow(
297 SCIP_CONFLICTROW* row, /**< generalized resolution row to print */
298 SCIP_SET* set, /**< global SCIP settings */
299 SCIP_VAR** vars, /**< array of variables */
300 int type /**< row type */
301 )
302{
303 int nnzs;
304 int v;
305 int i;
306
307 assert(vars != NULL);
308
309 switch(type)
310 {
311 case CONFLICT_ROWTYPE:
312 SCIPsetDebugMsgPrint(set, "Conflict Row: \n");
313 break;
314 case RESOLVED_CONFLICT_ROWTYPE:
315 SCIPsetDebugMsgPrint(set, "Resolved Conflict Row: \n");
316 break;
317 case REASON_ROWTYPE:
318 SCIPsetDebugMsgPrint(set, "Reason Row: \n");
319 break;
320 case REDUCED_REASON_ROWTYPE:
321 SCIPsetDebugMsgPrint(set, "Reduced Reason Row: \n");
322 break;
323 case CONTINUOUS_REASON_ROWTYPE:
324 SCIPsetDebugMsgPrint(set, "Continuous Reason Row: \n");
325 break;
326 default:
327 break;
328 }
329 for( i = 0; i < row->nnz; i++ )
330 {
331 v = row->inds[i];
332 assert(SCIPvarGetProbindex(vars[v]) == v);
333 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
334 SCIPsetDebugMsgPrint(set, " %f<%s>[B]", row->vals[v], SCIPvarGetName(vars[v]));
335 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_INTEGER )
336 SCIPsetDebugMsgPrint(set, " %f<%s>[I]", row->vals[v], SCIPvarGetName(vars[v]));
337 else
338 SCIPsetDebugMsgPrint(set, " %f<%s>[C]", row->vals[v], SCIPvarGetName(vars[v]));
339 /* print the row in a readable way */
340 if ((i + 1) % 5 == 0)
342 }
343 SCIPsetDebugMsgPrint(set, " >= %f\n", row->lhs);
344
345 /* just to check there are no other nonzeros in the dense array */
346 nnzs = 0;
347 for( i = 0; i < row->nvars; i++ )
348 {
349 if( !SCIPsetIsZero(set, row->vals[i]) )
350 nnzs++;
351 }
352 assert(nnzs == row->nnz);
353}
354
355/** print aggregated row */
356static
357void printAggrrow(
358 SCIP_AGGRROW* aggrrow,
359 SCIP_SET* set,
360 SCIP_VAR** vars /**< array of variables */
361 )
362{
363 int i;
364 SCIP_Real QUAD(rhs);
365 SCIP_Real QUAD(val);
366 assert(aggrrow != NULL);
367
368 assert(vars != NULL);
369 SCIPquadprecProdQD(rhs, aggrrow->rhs, 1.0);
370
371 SCIPsetDebugMsgPrint(set, "Aggregated Row: ");
372 for( i = 0; i < aggrrow->nnz; i++ )
373 {
374 QUAD_ARRAY_LOAD(val, aggrrow->vals, aggrrow->inds[i]);
375 if( SCIPvarGetType(vars[aggrrow->inds[i]]) == SCIP_VARTYPE_BINARY )
376 SCIPsetDebugMsgPrint(set, " %+g<%s>[B]", QUAD_TO_DBL(val), SCIPvarGetName(vars[aggrrow->inds[i]]));
377 else if( SCIPvarGetType(vars[aggrrow->inds[i]]) == SCIP_VARTYPE_INTEGER )
378 SCIPsetDebugMsgPrint(set, " %+g<%s>[I]", QUAD_TO_DBL(val), SCIPvarGetName(vars[aggrrow->inds[i]]));
379 else
380 SCIPsetDebugMsgPrint(set, " %+g<%s>[C]", QUAD_TO_DBL(val), SCIPvarGetName(vars[aggrrow->inds[i]]));
381 }
382 SCIPsetDebugMsgPrint(set, " <= %+.15g\n", QUAD_TO_DBL(rhs));
383}
384
385/** print a single bound change */
386static
387void printSingleBoundChange(
388 SCIP_SET* set, /**< global SCIP settings */
389 SCIP_BDCHGINFO* bdchginfo /**< bound change to print */
390 )
391{
392 SCIP_VAR* var;
393 var = SCIPbdchginfoGetVar(bdchginfo);
394 SCIPsetDebugMsgPrint(set, " \t -> Bound change <%s> %s %.15g [status:%d, type:%d, depth:%d, pos:%d, reason:<%s>, global bounds:[%.15g,%.15g], local bounds:[%.15g,%.15g]] \n",
395 SCIPvarGetName(var),
396 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
397 SCIPbdchginfoGetNewbound(bdchginfo),
399 SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
405}
406
407/** prints all bound changes in the queue in debug mode
408 */
409static
410void printAllBoundChanges(
411 SCIP_CONFLICT* conflict, /**< conflict analysis data */
412 SCIP_SET* set, /**< global SCIP settings */
413 SCIP_Bool continuousbdchgqueue/**< print the continuous bdchg queue */
414 )
415{
416 SCIP_PQUEUE* bdchgqueue;
417 SCIP_BDCHGINFO* bdchginfo;
418 SCIP_VAR* var;
419 int i;
420
421 assert(conflict != NULL);
422
423 bdchgqueue = continuousbdchgqueue ? conflict->continuousbdchgqueue : conflict->resbdchgqueue;
424
425 SCIPsetDebugMsgPrint(set, "Bound changes in %s bound change queue: \n", continuousbdchgqueue ? "continuous" : "resolution");
426
427 if( SCIPpqueueNElems(bdchgqueue) == 0 )
428 {
429 SCIPsetDebugMsgPrint(set, " \t -> The bound change queue is empty\n");
430 return;
431 }
432
433 for( i = 0; i < SCIPpqueueNElems(bdchgqueue); ++i )
434 {
435 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueElems(bdchgqueue)[i]);
436 var = bdchginfo->var;
437 SCIPsetDebugMsgPrint(set, " \t -> Bound change %d: <%s> %s %.15g [status:%d, type:%d, depth:%d, pos:%d, reason:<%s>, global bounds:[%.15g,%.15g], local bounds:[%.15g,%.15g]] \n",
438 i, SCIPvarGetName(var),
439 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
440 SCIPbdchginfoGetNewbound(bdchginfo),
442 SCIPbdchginfoGetDepth(bdchginfo), SCIPbdchginfoGetPos(bdchginfo),
447 : "none")),
450 }
451 SCIPsetDebugMsgPrint(set, "End of bound changes in queue. \n");
452}
453
454/** print the type of the non resolvable reason */
455static
456void printNonResolvableReasonType(
457 SCIP_SET* set, /**< global SCIP settings */
458 SCIP_BDCHGINFO* bdchginfo /**< bound change to check */
459 )
460{
461 SCIP_BOUNDCHGTYPE bdchgtype;
462
463 bdchgtype = SCIPbdchginfoGetChgtype(bdchginfo);
464 if( bdchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
465 {
466 SCIPsetDebugMsgPrint(set, " \t -> Not resolvable bound change: branching \n");
467 }
468 else if( bdchgtype == SCIP_BOUNDCHGTYPE_PROPINFER )
469 {
470 SCIP_PROP* reasonprop;
471 reasonprop = SCIPbdchginfoGetInferProp(bdchginfo);
472
473 SCIPsetDebugMsgPrint(set, " \t -> Not resolvable bound change: propagation %s \n",
474 reasonprop != NULL ? SCIPpropGetName(reasonprop) : "none");
475 }
476 else
477 {
478 assert(bdchgtype == SCIP_BOUNDCHGTYPE_CONSINFER);
479 SCIPsetDebugMsgPrint(set, " \t -> Not resolvable bound change: constraint %s \n", SCIPconsGetName(SCIPbdchginfoGetInferCons(bdchginfo)));
480 }
481}
482
483#endif
484
485/** calculates the maximal size of conflict sets to be used */
486static
488 SCIP_SET* set, /**< global SCIP settings */
489 SCIP_PROB* prob /**< problem data */
490 )
491{
492 int maxsize;
493
494 assert(set != NULL);
495 assert(prob != NULL);
496
497 maxsize = (int)(set->conf_maxvarsfracres * (prob->nvars - prob->ncontvars));
498 maxsize = MAX(maxsize, set->conf_minmaxvars);
499 return maxsize;
500}
501
502/** perform activity based coefficient tightening on a semi-sparse or sparse row defined with a left hand side */
503static
505 SCIP_SET* set, /**< global SCIP settings */
506 SCIP_VAR** vars, /**< array of variables */
507 SCIP_Bool localbounds, /**< do we use local bounds? */
508 SCIP_Real* rowcoefs, /**< dense row of coefficients */
509 int* rowinds, /**< indices of the variables in the row */
510 int* rownnz, /**< number of non-zeros in the row */
511 SCIP_Real* rowlhs, /**< left hand side of the row */
512 int* nchgcoefs, /**< number of changed coefficients */
513 SCIP_Bool* redundant /**< pointer to store whether the row is redundant */
514 )
515{
516 int i;
517 int nintegralvars;
518 SCIP_Real* absvals;
519 SCIP_Real QUAD(minacttmp);
520 SCIP_Real minact;
521 SCIP_Real maxabsval;
522
523 assert(nchgcoefs != NULL);
524
525 maxabsval = 0.0;
526 QUAD_ASSIGN(minacttmp, 0.0);
527
528 assert(vars != NULL);
529 nintegralvars = SCIPgetNVars(set->scip) - SCIPgetNContVars(set->scip);
530 SCIP_CALL_ABORT( SCIPallocBufferArray(set->scip, &absvals, *rownnz) );
531
532 assert(nchgcoefs != NULL);
533 *nchgcoefs = 0;
534
535 if( redundant != NULL )
536 *redundant = FALSE;
537
538 /* compute activity of the row and get the absolute values of the coefficients */
539 for( i = 0; i < *rownnz; ++i )
540 {
541 SCIP_VAR* var;
542 int idx;
543 int coefidx;
544
545 idx = rowinds[i];
546 var = vars[idx];
547 coefidx = idx;
548
549 assert(idx >= 0 && idx < SCIPgetNVars(set->scip));
550 assert(var != NULL);
551
552 if( rowcoefs[coefidx] > 0.0 )
553 {
554 SCIP_Real lb = localbounds ? SCIPvarGetLbLocal(var) : SCIPvarGetLbGlobal(var);
555
556 if( SCIPsetIsInfinity(set, -lb) )
557 goto TERMINATE_TIGHTENING;
558
559 if( idx < nintegralvars )
560 {
561 maxabsval = MAX(maxabsval, rowcoefs[coefidx]);
562 absvals[i] = rowcoefs[coefidx];
563 }
564 else
565 absvals[i] = 0.0;
566
567 SCIPquadprecSumQD(minacttmp, minacttmp, lb * rowcoefs[coefidx]);
568 }
569 else
570 {
571 SCIP_Real ub = localbounds ? SCIPvarGetUbLocal(var) : SCIPvarGetUbGlobal(var);
572
573 if( SCIPsetIsInfinity(set, ub) )
574 goto TERMINATE_TIGHTENING;
575
576 if( idx < nintegralvars )
577 {
578 maxabsval = MAX(maxabsval, -rowcoefs[coefidx]);
579 absvals[i] = -rowcoefs[coefidx];
580 }
581 else
582 absvals[i] = 0.0;
583
584 SCIPquadprecSumQD(minacttmp, minacttmp, ub * rowcoefs[coefidx]);
585 }
586 }
587
588 minact = QUAD_TO_DBL(minacttmp);
589
590 /* row is redundant if minact is infinity */
591 if( SCIPsetIsInfinity(set, minact ) )
592 {
593 if( redundant != NULL )
594 *redundant = TRUE;
595 goto TERMINATE_TIGHTENING;
596 }
597 /* no coefficients can be tightened */
598 if( SCIPsetIsInfinity(set, -minact ) )
599 {
600 goto TERMINATE_TIGHTENING;
601 }
602
603 /* propagating constraint cannot be redundant */
604 assert(!SCIPsetIsGE(set, minact, *rowlhs));
605
606 /* terminate, because coefficient tightening cannot be performed; also
607 excludes the case in which no integral variable is present */
608 /* for lhs terminate if minact + maxabsval < rowlhs */
609 if( SCIPsetIsLT(set, minact + maxabsval, *rowlhs) )
610 goto TERMINATE_TIGHTENING;
611
612 SCIPsortDownRealInt(absvals, rowinds, *rownnz);
613
614 SCIPfreeBufferArray(set->scip, &absvals);
615
616 /* loop over the integral variables and try to tighten the coefficients; see cons_linear for more details */
617 for( i = 0; i < *rownnz; ++i )
618 {
619 SCIP_VAR* var;
620 int idx;
621 int coefidx;
622
623 idx = rowinds[i];
624 var = vars[idx];
625 coefidx = idx;
626
627 assert(idx >= 0 && idx < SCIPgetNVars(set->scip));
628 assert(var != NULL);
629
630 /* due to sorting, we can exit if we reached a continuous variable: all further integral variables have 0 coefficents anyway */
631 if( idx >= nintegralvars )
632 break;
633
634 assert(SCIPvarIsIntegral(var));
635
636 if( rowcoefs[coefidx] < 0.0 && SCIPsetIsGE(set, minact - rowcoefs[coefidx], *rowlhs) )
637 {
638 SCIP_Real newcoef = minact - (*rowlhs);
639 SCIP_Real ub = localbounds ? SCIPvarGetUbLocal(var) : SCIPvarGetUbGlobal(var);
640
641 assert(SCIPsetIsGE(set, newcoef + EPS, rowcoefs[coefidx]) || SCIPsetIsRelGE(set, newcoef, rowcoefs[coefidx]));
642 assert(!SCIPsetIsPositive(set, newcoef));
643
644 if( newcoef > rowcoefs[coefidx] )
645 {
646 SCIP_Real QUAD(delta);
647 SCIP_Real QUAD(newlhs);
648
649 SCIPquadprecSumDD(delta, newcoef, -rowcoefs[coefidx]);
650 SCIPquadprecProdQD(delta, delta, ub);
651
652 SCIPquadprecSumQD(newlhs, delta, *rowlhs);
653 SCIPdebugPrintf("tightened coefficient from %g to %g; lhs changed from %g to %g; the bounds are [%g,%g]\n",
654 rowcoefs[coefidx], newcoef, (*rowlhs), QUAD_TO_DBL(newlhs),
655 localbounds ? SCIPvarGetUbLocal(var) : SCIPvarGetUbGlobal(var), ub);
656
657 *rowlhs = QUAD_TO_DBL(newlhs);
658
659 ++(*nchgcoefs);
660
661 if( SCIPsetIsNegative(set, newcoef) )
662 {
663 SCIPquadprecSumQQ(minacttmp, minacttmp, delta);
664 minact = QUAD_TO_DBL(minacttmp);
665 rowcoefs[coefidx] = newcoef;
666 }
667 else
668 {
669 --(*rownnz);
670 rowcoefs[coefidx] = 0.0;
671 rowinds[i] = rowinds[*rownnz];
672 continue;
673 }
674 }
675 }
676 else if( rowcoefs[coefidx] > 0.0 && SCIPsetIsGE(set, minact + rowcoefs[coefidx], *rowlhs) )
677 {
678 SCIP_Real newcoef = (*rowlhs) - minact;
679 SCIP_Real lb = localbounds ? SCIPvarGetLbLocal(var) : SCIPvarGetLbGlobal(var);
680
681 assert(SCIPsetIsLE(set, newcoef, rowcoefs[coefidx] + EPS) || SCIPsetIsRelLE(set, newcoef, rowcoefs[coefidx]));
682 assert(!SCIPsetIsNegative(set, newcoef));
683
684 if( newcoef < rowcoefs[coefidx] )
685 {
686 SCIP_Real QUAD(delta);
687 SCIP_Real QUAD(newlhs);
688
689 SCIPquadprecSumDD(delta, newcoef, -rowcoefs[coefidx]);
690 SCIPquadprecProdQD(delta, delta, lb);
691
692 SCIPquadprecSumQD(newlhs, delta, *rowlhs);
693 SCIPdebugPrintf("tightened coefficient from %g to %g; lhs changed from %g to %g; the bounds are [%g,%g]\n",
694 rowcoefs[coefidx], newcoef, (*rowlhs), QUAD_TO_DBL(newlhs), lb,
695 localbounds ? SCIPvarGetUbLocal(var) : SCIPvarGetUbGlobal(var));
696
697 *rowlhs = QUAD_TO_DBL(newlhs);
698
699 ++(*nchgcoefs);
700
701 if( SCIPsetIsPositive(set, newcoef) )
702 {
703 SCIPquadprecSumQQ(minacttmp, minacttmp, delta);
704 minact = QUAD_TO_DBL(minacttmp);
705 rowcoefs[coefidx] = newcoef;
706 }
707 else
708 {
709 --(*rownnz);
710 rowcoefs[coefidx] = 0.0;
711 rowinds[i] = rowinds[*rownnz];
712 continue;
713 }
714 }
715 }
716 else /* due to sorting we can stop completely if the precondition was not fulfilled for this variable */
717 break;
718 }
719
720 TERMINATE_TIGHTENING:
721 SCIPfreeBufferArrayNull(set->scip, &absvals);
722
723 return SCIP_OKAY;
724}
725
726/** check if the generalized resolution row has a relaxation only variable */
727static
729 SCIP_SET* set, /**< global SCIP settings */
730 SCIP_VAR** vars, /**< array of variables */
731 SCIP_CONFLICTROW* row /**< generalized resolution row */
732 )
733{
734 int i;
735
736 assert(set != NULL);
737 assert(vars != NULL);
738 assert(row != NULL);
739
740 for( i = 0; i < row->nnz; ++i )
741 {
742 SCIP_VAR* var;
743
744 var = vars[row->inds[i]];
745 assert(var != NULL);
746
747 if( SCIPvarIsRelaxationOnly(var) )
748 return TRUE;
749 }
750 return FALSE;
751}
752
753/** check if a generalized resolution row has only binary variables */
754static
756 SCIP_SET* set, /**< global SCIP settings */
757 SCIP_VAR** vars, /**< array of variables */
758 SCIP_CONFLICTROW* row /**< generalized resolution row */
759 )
760{
761 int i;
762
763 assert(set != NULL);
764 assert(vars != NULL);
765 assert(row != NULL);
766
767 for( i = 0; i < row->nnz; ++i )
768 {
769 SCIP_VAR* var;
770
771 var = vars[row->inds[i]];
772 assert(var != NULL);
773
774 if( !SCIPvarIsBinary(var) )
775 return FALSE;
776 }
777 return TRUE;
778}
779
780/** Removes a variable with zero coefficient in the generalized resolution row */
781static
783 SCIP_CONFLICTROW* row, /**< generalized resolution row */
784 SCIP_SET* set, /**< global SCIP settings */
785 int pos /**< position of variable in conflict row */
786 )
787{
788 int idx;
789
790 idx = row->inds[pos];
791
792 assert(row != NULL);
793 assert(pos >= 0 && pos < row->nnz);
794 assert(SCIPsetIsZero(set, row->vals[idx]));
795
796 --row->nnz;
797 row->vals[idx] = 0.0;
798 row->inds[pos] = row->inds[row->nnz];
799}
800
801/** Removes all variables with zero coefficient (< 1e-09) in the generalized resolution row */
802static
804 SCIP_CONFLICTROW* row, /**< generalized resolution row */
805 SCIP_SET* set /**< global SCIP settings */
806 )
807{
808 int idx;
809 assert(row != NULL);
810 for( int i = row->nnz - 1; i >= 0; --i )
811 {
812 idx = row->inds[i];
813 if( SCIPsetIsZero(set, row->vals[idx]) )
815 }
816}
817
818
819/** complement and apply MIR to a 0-1 reason constraint lhs <= a^T x */
820static
822 SCIP_SET* set, /**< global SCIP settings */
823 SCIP_VAR** vars, /**< array of variables */
824 SCIP_CONFLICTROW* reasonrow, /**< reason row */
825 int* fixsides, /**< dense array of variables fixed to a bound */
826 SCIP_BDCHGIDX* currbdchgidx, /**< current bound change index */
827 int idxreason, /**< index in the reason */
828 SCIP_Real divisor /**< the divisor of the row */
829 )
830{
831 SCIP_Real deltaoldlhs;
832 SCIP_Real deltanewlhs;
833 SCIP_Real oldlhs;
834 SCIP_Real newlhs;
835 SCIP_Real fraclhs;
836 SCIP_Real resvarcoef;
837 int varidx;
838
839 assert(set != NULL);
840 assert(vars != NULL);
841 assert(reasonrow != NULL);
842 assert(reasonrow->inds != NULL);
843 assert(reasonrow->vals != NULL);
844 assert(reasonrow->nnz > 0);
845
846 assert(SCIPsetIsGT(set, divisor, 0.0));
847
848 if( !isBinaryConflictRow(set, vars, reasonrow) )
849 return SCIP_OKAY;
850
851 SCIPsetDebugMsgPrint(set, "MIR on 0-1 constraint with LHS %f and divisor %f\n" , reasonrow->lhs, divisor);
852
853 /* complement and apply MIR to the reason constraint lhs <= a^T x
854 * say the idxreason is k, and a_k > 0 (so this reason constraint fixes x_k to 1).
855 * Then we complement as follows:
856 * - if a_i > 0 and x_i is not fixed to 0, we complement it
857 * - if a_i < 0 and x_i is fixed to 1, we complement it
858 * whenever we complement a variable x_i, we need to modify the lhs with -a_i
859 * Then we compute the fractionality of the lhs f(lhs) and do the following:
860 * The coefficient of ~x_i is going to be -a_i, which after division is going to be -a_i/divisor; and after MIR,
861 * it becomes CEIL(-a_i / divisor) if f(-a_i/divisor) >= f(lhs) or FLOOR(-a_i / divisor)+f(-a_i/divisor)/f(lhs) otherwise.
862 * Complementing this again (to go back to x_i) the new coefficient of x_i is going to be -CEIL(-a_i / divisor)
863 * or FLOOR(-a_i / divisor)+f(-a_i/divisor)/f(lhs) otherwise. It is going to
864 * contribute the same amount to the lhs of the resulting constraint.
865 * So we keep to lhs deltas, one for complementing in the original space, and another for complementing after we do C-G
866 *
867 * On the other hand, if a_k < 0 (so this reason constraint fixes x_k to 0), then we complement x_k (so modify the lhs by -a_k)
868 * and then we are in the previous case. However, at the end, we need to complement back, which means that we modify the lhs by -1
869 */
870
871 /* first handle x_k and initialize lhs deltas */
872 varidx = idxreason;
873 resvarcoef = reasonrow->vals[varidx];
874 if( resvarcoef < 0.0 )
875 {
876 deltaoldlhs = -reasonrow->vals[varidx];
877 deltanewlhs = -1.0;
878 reasonrow->vals[varidx] = -1.0;
879 }
880 else
881 {
882 deltaoldlhs = 0.0;
883 deltanewlhs = 0.0;
884 reasonrow->vals[varidx] = 1.0;
885 }
886
887 /* compute the delta for the left hand side after complementation in order to apply MIR
888 * In a second loop set the new coefficients for the other variables and compute the lhs delta after complementation */
889 for( int i = 0; i < reasonrow->nnz; ++i )
890 {
891 varidx = reasonrow->inds[i];
892 SCIP_VAR* currentvar;
893 SCIP_Real coef;
894
895 if( varidx == idxreason )
896 continue;
897
898 coef = reasonrow->vals[varidx];
899 currentvar = vars[varidx];
900
901 assert(SCIPvarIsBinary(currentvar));
902
903 /* complementation offset */
904 if( (coef > 0.0 && (SCIPgetVarUbAtIndex(set->scip, currentvar, currbdchgidx, TRUE) > 0.5 && fixsides[varidx] != 1) ) ||
905 (coef < 0.0 && (SCIPgetVarLbAtIndex(set->scip, currentvar, currbdchgidx, TRUE) > 0.5 || fixsides[varidx] == -1)))
906 {
907 deltaoldlhs += -coef;
908 }
909 }
910 oldlhs = reasonrow->lhs;
911 newlhs = (oldlhs + deltaoldlhs) / divisor;
912 fraclhs = newlhs - SCIPsetFloor(set, newlhs);
913
914 if( fraclhs < MINFRAC || fraclhs > MAXFRAC )
915 {
916 reasonrow->vals[idxreason] = resvarcoef;
917 SCIPsetDebugMsgPrint(set, "skip MIR because the fractionality of the lhs %f is not in [%f,%f]\n", fraclhs, MINFRAC, MAXFRAC);
918 return SCIP_OKAY;
919 }
920
921 /* set the new coefficients for the other variables and compute the lhs deltas */
922 for( int i = 0; i < reasonrow->nnz; ++i )
923 {
924 varidx = reasonrow->inds[i];
925 SCIP_VAR* currentvar;
926 SCIP_Real newcoef;
927 SCIP_Real coef;
928 SCIP_Real fraccoef;
929
930 if( varidx == idxreason )
931 continue;
932
933 coef = reasonrow->vals[varidx] / divisor;
934 fraccoef = coef - SCIPsetFloor(set, coef);
935 currentvar = vars[varidx];
936
937 if( (coef > 0.0 && (SCIPgetVarUbAtIndex(set->scip, currentvar, currbdchgidx, TRUE) > 0.5 && fixsides[varidx] != 1) ) ||
938 (coef < 0.0 && (SCIPgetVarLbAtIndex(set->scip, currentvar, currbdchgidx, TRUE) > 0.5 || fixsides[varidx] == -1)))
939 {
940 if( (1.0 - fraccoef) >= fraclhs )
941 {
942 newcoef = -SCIPsetCeil(set, -coef);
943
944 reasonrow->vals[varidx] = newcoef;
945 deltanewlhs += newcoef;
946 }
947 else
948 {
949 newcoef = -SCIPsetFloor(set, -coef) - (1 - fraccoef) / fraclhs;
950
951 reasonrow->vals[varidx] = newcoef;
952 deltanewlhs += newcoef;
953 }
954 }
955 else
956 {
957 if( fraccoef >= fraclhs )
958 reasonrow->vals[varidx] = SCIPsetCeil(set, coef);
959 else
960 reasonrow->vals[varidx] = SCIPsetFloor(set, coef) + fraccoef / fraclhs;
961 }
962 }
963
964 newlhs = SCIPsetCeil(set, newlhs) + deltanewlhs;
965 reasonrow->lhs = newlhs;
966
967 /* remove variables with zero coefficient. */
968 conflictRowRemoveZeroVars(reasonrow, set);
969
970 return SCIP_OKAY;
971}
972
973/* linear combination row1 = row1 + scale * row2 */
974static
976 SCIP_SET* set, /**< global SCIP settings */
977 SCIP_CONFLICTROW* row1, /**< first row (aggregated row) */
978 SCIP_CONFLICTROW* row2, /**< second row */
979 SCIP_Real scale /**< scale factor for second row */
980 )
981{
982 int i;
983
984 assert(set != NULL);
985 assert(row1 != NULL);
986 assert(row2 != NULL);
987 assert(scale > 0.0);
988
989 /* add conflict and reason conflict rows; */
990 for( i = 0; i < row2->nnz; ++i )
991 {
992 int idx;
993 idx = row2->inds[i];
994 assert(idx >= 0);
995 if( SCIPsetIsZero(set, row1->vals[idx]) )
996 {
997 row1->inds[row1->nnz] = idx;
998 row1->vals[idx] = scale * row2->vals[idx];
999 row1->nnz++;
1000 }
1001 else
1002 row1->vals[idx] = row1->vals[idx] + scale * row2->vals[idx];
1003 }
1004 row1->lhs = row1->lhs + scale * row2->lhs;
1005
1006 /* remove variables with zero coefficient. */
1008}
1009
1010/** returns whether a bound change is resolvable or not */
1011static
1013 SCIP_BDCHGINFO* bdchginfo /**< bound change to check */
1014 )
1015{
1016 SCIP_CONSHDLR *conshdlr;
1017 SCIP_BOUNDCHGTYPE bdchgtype;
1018 const char* conshdlrname;
1019
1020 bdchgtype = SCIPbdchginfoGetChgtype(bdchginfo);
1021
1022 /* branching */
1023 if( bdchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
1024 return FALSE;
1025 /* propagation */
1026 else if( bdchgtype == SCIP_BOUNDCHGTYPE_PROPINFER )
1027 return FALSE;
1028 /* constraint */
1029 assert(bdchgtype == SCIP_BOUNDCHGTYPE_CONSINFER);
1030 conshdlr = SCIPconsGetHdlr(SCIPbdchginfoGetInferCons(bdchginfo));
1031 conshdlrname = SCIPconshdlrGetName(conshdlr);
1032
1033 if( strcmp(conshdlrname, "nonlinear") == 0 )
1034 return FALSE;
1035
1036 return TRUE;
1037}
1038
1039/** returns whether there exists a resolvable bound change or not */
1040static
1042 SCIP_CONFLICT* conflict /**< conflict analysis data */
1043 )
1044{
1045 SCIP_BDCHGINFO* bdchginfo;
1046 int i;
1047
1048 /* loop through bound change and check if there exists a resolvable bound change */
1049 for( i = 0; i < SCIPpqueueNElems(conflict->resbdchgqueue); ++i )
1050 {
1051 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueElems(conflict->resbdchgqueue)[i]);
1052 if( isResolvableBdchg(bdchginfo) )
1053 return TRUE;
1054 }
1055 return FALSE;
1056}
1057
1058/** returns whether a bound change is relevant for the infeasibility of the conflict row.
1059 * A bound change is relevant if:
1060 * - It is an upper bound change with a positive row coefficient,
1061 * - It is a lower bound change with a negative row coefficient
1062 */
1063static
1065 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1066 SCIP_BDCHGINFO* bdchginfo, /**< bound change to check */
1067 int initial /**< whether we are in the initialization of conflict analysis */
1068 )
1069{
1070 SCIP_CONFLICTROW* conflictrow;
1071 SCIP_VAR* var;
1072 int idx;
1073
1074 conflictrow = conflict->conflictrow;
1075
1076 /* the initial bound change is always relevant */
1077 if( initial )
1078 return TRUE;
1079 /* if the conflict row is empty, we have a global infeasibility */
1080 else if( conflictrow->nnz == 0 )
1081 return FALSE;
1082
1083 var = SCIPbdchginfoGetVar(bdchginfo);
1084 idx = SCIPvarGetProbindex(var);
1085
1086 if( (conflictrow->vals[idx] > 0 ) && (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER) )
1087 return TRUE;
1088 else if( (conflictrow->vals[idx] < 0 ) && (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER) )
1089 return TRUE;
1090 return FALSE;
1091}
1092
1093/** returns next conflict analysis bound change candidate from the queue without removing it */
1094static
1096 SCIP_SET* set, /**< global SCIP settings */
1097 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1098 int initial /**< whether we are in the initialization of conflict analysis */
1099 )
1100{
1101 SCIP_BDCHGINFO* bdchginfo;
1102
1103 assert(conflict != NULL);
1104
1105 /* get next potential candidate */
1106 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueFirst(conflict->resbdchgqueue));
1107
1108 /* check if this candidate is relevant for the conflict */
1109 if( bdchginfo != NULL && !isBdchgConflictRelevant(conflict, bdchginfo, initial) )
1110 {
1111 SCIP_VAR* var;
1112
1113 var = SCIPbdchginfoGetVar(bdchginfo);
1114
1115 SCIPsetDebugMsgPrint(set, "\t -> bound change info [%d:%d<%s> %s %g] is invalid -> pop it from the queue\n",
1116 SCIPbdchginfoGetDepth(bdchginfo),
1117 SCIPbdchginfoGetPos(bdchginfo),
1118 SCIPvarGetName(var),
1119 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
1120 SCIPbdchginfoGetNewbound(bdchginfo));
1121
1122 /* remove the bound change info from the queue if it is not relevant */
1123 (void)(SCIPpqueueRemove(conflict->resbdchgqueue));
1124
1127 else
1129
1130 /* call method recursively to get next conflict analysis candidate */
1131 bdchginfo = conflictFirstCand(set, conflict, initial);
1132 }
1133
1134 assert(bdchginfo == NULL || !SCIPbdchginfoIsRedundant(bdchginfo));
1135
1136 return bdchginfo;
1137}
1138
1139/** removes and returns next conflict analysis bound change candidate from the queue */
1140static
1142 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1143 int initial /**< whether we are in the initialization of conflict analysis */
1144 )
1145{
1146 SCIP_BDCHGINFO* bdchginfo;
1147
1148 assert(conflict != NULL);
1149
1150 bdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->resbdchgqueue));
1151
1152 assert(!SCIPbdchginfoIsRedundant(bdchginfo));
1153
1154 /* if we have a candidate this one should be valid for the current conflict analysis */
1155 assert(isBdchgConflictRelevant(conflict, bdchginfo, initial));
1156
1157 return bdchginfo;
1158}
1159
1160/** return TRUE if generalized resolution conflict analysis is applicable */
1162 SCIP_SET* set /**< global SCIP settings */
1163 )
1164{
1165 /* check, if generalized resolution conflict analysis is enabled */
1166 if( !set->conf_enable || !set->conf_usegenres )
1167 return FALSE;
1168
1169 return TRUE;
1170}
1171
1172/** creates a generalized resolution row */
1173static
1175 SCIP_CONFLICTROW** row, /**< generalized resolution row */
1176 BMS_BLKMEM* blkmem /**< block memory of transformed problem */
1177 )
1178{
1179 assert(row != NULL);
1180
1181 SCIP_ALLOC( BMSallocBlockMemory(blkmem, row) );
1182 (*row)->vals = NULL;
1183 (*row)->inds = NULL;
1184 (*row)->lhs = 0.0;
1185 (*row)->slack = 0.0;
1186 (*row)->coefquotient = 0.0;
1187 (*row)->nvars = 0;
1188 (*row)->nnz = 0;
1189 (*row)->size = 0;
1190 (*row)->validdepth = 0;
1191 (*row)->conflictdepth = 0;
1192 (*row)->repropdepth = 0;
1193 (*row)->insertdepth = 0;
1194 (*row)->usescutoffbound = FALSE;
1195 (*row)->isbinary = FALSE;
1196 (*row)->conflicttype = SCIP_CONFTYPE_PROPAGATION;
1197
1198 return SCIP_OKAY;
1199}
1200
1201/** creates conflict and reason rows */
1203 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1204 BMS_BLKMEM* blkmem /**< block memory of transformed problem */
1205 )
1206{
1207 assert(conflict != NULL);
1208 assert(blkmem != NULL);
1209
1210 SCIP_CALL( conflictRowCreate(&conflict->conflictrow, blkmem) );
1211 SCIP_CALL( conflictRowCreate(&conflict->resolvedconflictrow, blkmem) );
1212
1213 SCIP_CALL( conflictRowCreate(&conflict->reasonrow, blkmem) );
1214 SCIP_CALL( conflictRowCreate(&conflict->reducedreasonrow, blkmem) );
1215
1216 return SCIP_OKAY;
1217}
1218
1219/** frees a generalized resolution row */
1221 SCIP_CONFLICTROW** row, /**< conflict row */
1222 BMS_BLKMEM* blkmem /**< block memory */
1223 )
1224{
1225 assert(row != NULL);
1226 assert(*row != NULL);
1227 assert(blkmem != NULL);
1228
1229 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->vals, (*row)->nvars);
1230 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->inds, (*row)->size);
1231 BMSfreeBlockMemory(blkmem, row);
1232 (*row) = NULL;
1233}
1234
1235/** frees all conflict rows and arrays that track unresolvable (fixed) variables */
1236static
1238 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1239 BMS_BLKMEM* blkmem, /**< block memory */
1240 SCIP_SET* set, /**< global SCIP settings */
1241 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
1242 int* fixsides /**< dense array of variables fixed to a bound */
1243 )
1244{
1245 SCIPsetFreeBufferArray(set, &fixsides);
1246 SCIPsetFreeBufferArray(set, &fixbounds);
1247
1248 /* free all conflict rows */
1249 for (int i = 0; i < conflict->nconflictrows; i++) {
1250 SCIPconflictRowFree(&conflict->conflictrows[i], blkmem);
1251 }
1252 conflict->nconflictrows = 0;
1253}
1254
1255/** resets the data structure of a generalized resolution row */
1256static
1258 BMS_BLKMEM* blkmem, /**< block memory */
1259 SCIP_CONFLICTROW* row, /**< generalized resolution row */
1260 int nvars /**< number of variables in the problem */
1261 )
1262{
1263 int i;
1264 assert(row != NULL);
1265
1266 /* this is necesseary to avoid memory leaks if the number of variables in the problem changes */
1267 if( row->vals != NULL && row->nvars != nvars )
1268 BMSfreeBlockMemoryArrayNull(blkmem, &row->vals, row->nvars);
1269 if( row->vals == NULL )
1270 BMSallocBlockMemoryArray(blkmem, &row->vals, nvars );
1271
1272 for( i = 0 ; i < nvars; ++i )
1273 row->vals[i] = 0.0;
1274
1275 row->nvars = nvars;
1276 row->nnz = 0;
1277 row->lhs = 0.0;
1278 row->slack = 0.0;
1279 row->coefquotient = 0.0;
1280 row->validdepth = 0;
1281 row->conflictdepth = 0;
1282 row->repropdepth = 0;
1283 row->insertdepth = 0;
1285 row->usescutoffbound = FALSE;
1286 row->isbinary = FALSE;
1287}
1288
1289/** calculates the slack (maxact - rhs) for a generalized resolution row given a set of bounds and coefficients */
1290static
1292 SCIP_SET* set, /**< global SCIP settings */
1293 SCIP_VAR** vars, /**< array of variables */
1294 SCIP_CONFLICTROW* row, /**< generalized resolution row */
1295 SCIP_BDCHGINFO* currbdchginfo, /**< current bound change */
1296 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
1297 int* fixsides /**< dense array of variables fixed to a bound */
1298 )
1299{
1300 SCIP_BDCHGIDX * currbdchgidx;
1301 SCIP_Real QUAD(slack);
1302 int i;
1303
1304 assert(vars != NULL);
1305
1306#ifdef SCIP_MORE_DEBUG
1307 SCIPsetDebugMsgPrint(set, "Calculating slack for row at depth %d position %d \n", SCIPbdchginfoGetDepth(currbdchginfo), SCIPbdchginfoGetPos(currbdchginfo));
1308#endif
1309 QUAD_ASSIGN(slack, 0.0);
1310 if( currbdchginfo == NULL )
1311 currbdchgidx = NULL;
1312 else
1313 currbdchgidx = SCIPbdchginfoGetIdx(currbdchginfo);
1314 for( i = 0; i < row->nnz; i++ )
1315 {
1316 SCIP_Real coef;
1318 SCIP_Real QUAD(delta);
1319 int v;
1320 v = row->inds[i];
1321
1322 assert(SCIPvarGetProbindex(vars[v]) == v);
1323
1324 coef = row->vals[v];
1325
1326 /* get the latest bound change before currbdchgidx */
1327 if( coef > 0.0 )
1328 {
1329 if( fixsides != NULL && fixsides[v] == 1 ) /* if the variable is fixed */
1330 {
1331 assert(fixbounds != NULL);
1332 bound = fixbounds[v];
1333 }
1334 else
1335 {
1336 bound = SCIPgetVarUbAtIndex(set->scip, vars[v], currbdchgidx, TRUE);
1337 }
1338 SCIPquadprecProdDD(delta, coef, bound);
1339 }
1340 else
1341 {
1342 if( fixsides != NULL && fixsides[v] == -1 ) /* if the variable is fixed */
1343 {
1344 assert(fixbounds != NULL);
1345 bound = fixbounds[v];
1346 }
1347 else
1348 {
1349 bound = SCIPgetVarLbAtIndex(set->scip, vars[v], currbdchgidx, TRUE);
1350 }
1351 SCIPquadprecProdDD(delta, coef, bound);
1352 }
1353 SCIPquadprecSumQQ(slack, slack, delta);
1354#ifdef SCIP_MORE_DEBUG
1355 SCIPsetDebugMsgPrint(set, "var: %s, coef: %f, bound: %f global bounds:[%.15g,%.15g], current bounds:[%.15g,%.15g] \n",
1356 SCIPvarGetName(vars[v]), coef, bound, SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]),
1357 SCIPgetVarLbAtIndex(set->scip, vars[v], currbdchgidx, TRUE), SCIPgetVarUbAtIndex(set->scip, vars[v],
1358 currbdchgidx, TRUE));
1359 SCIPsetDebugMsgPrint(set, "slack: %f \n",QUAD_TO_DBL(slack) );
1360#endif
1361 }
1362 SCIPquadprecSumQD(slack, slack, -row->lhs);
1363#ifdef SCIP_MORE_DEBUG
1364 SCIPsetDebugMsgPrint(set, "Row slack: %f \n",QUAD_TO_DBL(slack) );
1365#endif
1366 row->slack = QUAD_TO_DBL(slack);
1367 return SCIP_OKAY;
1368}
1369
1370/**
1371 * reduces the reason row by applying MIR. In the reference solution, each variable is set to
1372 * the value that was used for the propagation of currbdchginfo.
1373 */
1374static
1376 SCIP_SET* set, /**< global SCIP settings */
1377 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
1378 SCIP_VAR** vars, /**< array of variables */
1379 int nvars, /**< number of variables */
1380 SCIP_CONFLICTROW* reasonrow, /**< reason row */
1381 SCIP_BDCHGINFO* currbdchginfo, /**< current bound change to resolve */
1382 int varidx, /**< index of the variable to resolve */
1383 SCIP_Real divisor /**< the divisor of the row */
1384 )
1385{
1386 SCIP_SOL* refsol;
1387 SCIP_AGGRROW* aggrrow;
1388 SCIP_BDCHGIDX* currbdchgidx;
1389 int* cutinds;
1390 SCIP_Real* cutcoefs;
1391 int* rowinds;
1392 SCIP_Real* rowvals;
1393
1394 int cutnnz;
1395 int rownnz;
1396 SCIP_Real cutrhs;
1397 SCIP_Real rowrhs;
1398
1399 assert(set != NULL);
1400 assert(vars != NULL);
1401 assert(reasonrow != NULL);
1402 assert(reasonrow->inds != NULL);
1403 assert(reasonrow->vals != NULL);
1404 assert(reasonrow->nnz > 0);
1405
1406 assert(SCIPsetIsGT(set, divisor, 0.0));
1407
1408 if( !SCIPvarIsIntegral(vars[varidx]) )
1409 return SCIP_OKAY;
1410
1411 SCIPsetDebugMsgPrint(set, "Apply MIR on general constraint with LHS %f and divisor %f\n" , reasonrow->lhs, divisor);
1412
1413 currbdchgidx = SCIPbdchginfoGetIdx(currbdchginfo);
1414 /* creating the aggregation row. There will be only a single row in this aggregation, since it is only used to
1415 * compute the MIR coefficients
1416 */
1417 SCIP_CALL( SCIPaggrRowCreate(set->scip, &aggrrow) );
1418
1419 SCIP_CALL( SCIPcreateSol(set->scip, &refsol, NULL) );
1420
1421 /* initialize arrays for cut indices, cut coefficients, row indices, row values */
1422 SCIP_CALL( SCIPsetAllocBufferArray(set, &cutinds, reasonrow->nnz) );
1423 SCIP_CALL( SCIPsetAllocBufferArray(set, &cutcoefs, reasonrow->nnz) );
1424 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowinds, reasonrow->nnz) );
1425 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowvals, reasonrow->nnz) );
1426
1427 /* set all variables to zero in the reference solution */
1428 for( int i = 0; i < nvars; ++i )
1429 SCIP_CALL( SCIPsetSolVal(set->scip, refsol, vars[i], 0.0) );
1430
1431 /* create a sparse row of the form ax <= b from the reason */
1432 rowrhs = -reasonrow->lhs;
1433 rownnz = reasonrow->nnz;
1434 for( int i = 0; i < rownnz; ++i )
1435 {
1436 int idx;
1437 SCIP_Real coef;
1438 idx = reasonrow->inds[i];
1439 coef = reasonrow->vals[idx];
1440 rowinds[i] = idx;
1441 rowvals[i] = -coef;
1442 /* We set the solution to the values used in propagation */
1443 if( idx == varidx )
1444 {
1445 SCIP_Real fracval;
1446 SCIP_Real bnd;
1447 SCIP_CALL( computeSlack(set, vars, reasonrow, currbdchginfo, NULL, NULL) );
1448 if( coef > 0.0 )
1449 {
1450 fracval = SCIPgetVarUbAtIndex(set->scip, vars[idx], currbdchgidx, FALSE) - reasonrow->slack / coef;
1451 bnd = SCIPvarGetUbGlobal(vars[idx]);
1452 fracval = MIN(fracval, bnd);
1453 }
1454 else
1455 {
1456 assert(coef < 0.0);
1457 fracval = SCIPgetVarLbAtIndex(set->scip, vars[idx], currbdchgidx, FALSE) - reasonrow->slack / coef;
1458 bnd = SCIPvarGetLbGlobal(vars[idx]);
1459 fracval = MAX(fracval, bnd);
1460 }
1461 SCIP_CALL( SCIPsetSolVal(set->scip, refsol, vars[idx], fracval) );
1462 }
1463 else
1464 {
1465 if( coef > 0.0 )
1466 SCIP_CALL( SCIPsetSolVal(set->scip, refsol, vars[idx], SCIPgetVarUbAtIndex(set->scip, vars[idx], currbdchgidx, FALSE)) );
1467 else
1468 SCIP_CALL( SCIPsetSolVal(set->scip, refsol, vars[idx], SCIPgetVarLbAtIndex(set->scip, vars[idx], currbdchgidx, FALSE)) );
1469 }
1470 }
1471
1472 SCIP_Bool cutislocal = FALSE;
1473 SCIP_Bool success;
1474
1475 SCIP_CALL( SCIPaggrRowAddCustomCons(set->scip, aggrrow, rowinds, rowvals, rownnz, rowrhs, 1.0 / divisor, 1, FALSE) );
1476
1477 SCIPdebug(printAggrrow(aggrrow, set, vars));
1478
1479 /* apply MIR */
1481 MINFRAC, MAXFRAC, 1.0, aggrrow, cutcoefs, &cutrhs, cutinds, &cutnnz, NULL, NULL, &cutislocal, &success) );
1482
1483 if( success )
1484 {
1485 assert(!cutislocal);
1486 conflictRowClear(blkmem, reasonrow, nvars);
1487 reasonrow->nnz = cutnnz;
1488 reasonrow->lhs = -cutrhs;
1489 for( int i = 0; i < cutnnz; ++i )
1490 {
1491 reasonrow->inds[i] = cutinds[i];
1492 reasonrow->vals[cutinds[i]] = -cutcoefs[i];
1493 }
1494 }
1495
1496 /* remove variables with zero coefficient. Loop backwards */
1497 conflictRowRemoveZeroVars(reasonrow, set);
1498
1499 SCIPaggrRowFree(set->scip, &aggrrow);
1500 SCIP_CALL( SCIPfreeSol(set->scip, &refsol) );
1501 SCIPsetFreeBufferArray(set, &cutinds);
1502 SCIPsetFreeBufferArray(set, &cutcoefs);
1503 SCIPsetFreeBufferArray(set, &rowinds);
1504 SCIPsetFreeBufferArray(set, &rowvals);
1505
1506 return SCIP_OKAY;
1507}
1508
1509/** weaken variable in a generalized resolution row */
1510static
1512 SCIP_CONFLICTROW* row, /**< generalized resolution row */
1513 SCIP_SET* set, /**< global SCIP settings */
1514 SCIP_VAR* var, /**< variable to weaken */
1515 int pos /**< position in array of indices */
1516 )
1517{
1518 int idx;
1519
1520 assert(row != NULL);
1521 assert(var != NULL);
1522 assert(pos >= 0 && pos < row->nvars);
1523 assert(!SCIPsetIsZero(set, row->vals[row->inds[pos]]));
1524
1525 idx = row->inds[pos];
1526
1527 SCIPdebugMessage("weaken variable <%s> in the row \n", SCIPvarGetName(var));
1528
1529 /* weaken with global upper bound */
1530 if( SCIPsetIsGT(set, row->vals[idx], 0.0) )
1531 row->lhs -= row->vals[idx] * SCIPvarGetUbGlobal(var);
1532 /* weaken with global lower bound */
1533 else if(SCIPsetIsLT(set, row->vals[idx], 0.0))
1534 row->lhs -= row->vals[idx] * SCIPvarGetLbGlobal(var);
1535
1536 --row->nnz;
1537 row->vals[idx] = 0.0;
1538 row->inds[pos] = row->inds[row->nnz];
1539}
1540
1541/** weaken generalized resolution row by setting variables to their global bounds */
1542static
1544 SCIP_CONFLICTROW* row, /**< generalized resolution row */
1545 SCIP_SET* set, /**< global SCIP settings */
1546 SCIP_VAR** vars, /**< array of variables */
1547 SCIP_BDCHGIDX* currbdchgidx, /**< current bound change index */
1548 int* fixsides /**< dense array of variables fixed to a bound */
1549 )
1550{
1551 int i;
1552 int nvarsweakened;
1553
1554 assert(row != NULL);
1555 assert(set != NULL);
1556 assert(vars != NULL);
1557 assert(currbdchgidx != NULL);
1558
1559 nvarsweakened = 0;
1560
1561 for( i = row->nnz - 1; i >= 0; --i )
1562 {
1563 SCIP_VAR* vartoweaken;
1564 int idx;
1565
1566 idx = row->inds[i];
1567 vartoweaken = vars[idx];
1568
1569 if( row->vals[idx] > 0.0 )
1570 {
1571 SCIP_Real ub;
1572
1573 ub = SCIPgetVarUbAtIndex(set->scip, vartoweaken, currbdchgidx, TRUE);
1574
1575 if( SCIPsetIsEQ(set, ub, SCIPvarGetUbGlobal(vartoweaken)) && (fixsides == NULL || fixsides[idx] == 0) )
1576 {
1577 weakenVarConflictRow(row, set, vartoweaken, i);
1578 ++nvarsweakened;
1579 }
1580 }
1581 else
1582 {
1583 SCIP_Real lb;
1584
1585 lb = SCIPgetVarLbAtIndex(set->scip, vartoweaken, currbdchgidx, TRUE);
1586
1587 if( SCIPsetIsEQ(set, lb, SCIPvarGetLbGlobal(vartoweaken)) && (fixsides == NULL || fixsides[idx] == 0) )
1588 {
1589 weakenVarConflictRow(row, set, vartoweaken, i);
1590 ++nvarsweakened;
1591 }
1592 }
1593 }
1594
1595 SCIPdebugMessage("weakened %d variables in the conflict row \n", nvarsweakened);
1596}
1597
1598/** weaken all continuous variables in a generalized resolution row */
1599static
1601 SCIP_CONFLICTROW* row, /**< generalized resolution row */
1602 SCIP_SET* set, /**< global SCIP settings */
1603 SCIP_VAR** vars, /**< array of variables */
1604 int residx /**< index of variable we are resolving on */
1605 )
1606{
1607 int i;
1608 int nvarsweakened;
1609
1610 assert(row != NULL);
1611 assert(set != NULL);
1612 assert(vars != NULL);
1613
1614 nvarsweakened = 0;
1615
1616 for( i = row->nnz - 1; i >= 0; --i )
1617 {
1618 SCIP_VAR* vartoweaken;
1619 int idx;
1620
1621 idx = row->inds[i];
1622 vartoweaken = vars[idx];
1623
1624 /* avoid weakening the variable we are resolving on */
1625 if( idx == residx )
1626 continue;
1627 else if( row->vals[idx] > 0.0 && !SCIPvarIsIntegral(vartoweaken) )
1628 {
1629 weakenVarConflictRow(row, set, vartoweaken, i);
1630 ++nvarsweakened;
1631 }
1632 else if( row->vals[idx] < 0.0 && !SCIPvarIsIntegral(vartoweaken) )
1633 {
1634 weakenVarConflictRow(row, set, vartoweaken, i);
1635 ++nvarsweakened;
1636 }
1637 }
1638
1639 SCIPdebugMessage("weakened %d continuous variables in the row \n", nvarsweakened);
1640
1641 return SCIP_OKAY;
1642}
1643
1644
1645/** returns the quotient of the largest and smallest value in a semi-sparse array */
1646static
1648 SCIP_SET* set, /**< global SCIP settings */
1649 int* inds, /**< array of indices */
1650 SCIP_Real* vals, /**< dense array of values */
1651 int nnz /**< number of nonzeros */
1652 )
1653{
1654 int i;
1655 SCIP_Real minval;
1656 SCIP_Real maxval;
1657
1658 assert(vals != NULL);
1659
1660 if( nnz == 0 )
1661 return 0.0;
1662
1663 minval = SCIPsetInfinity(set);
1664 maxval = -SCIPsetInfinity(set);
1665
1666 for( i = 0; i < nnz; i++ )
1667 {
1668 int idx;
1669 idx = inds[i];
1670 minval = MIN(minval, vals[idx]);
1671 maxval = MAX(maxval, vals[idx]);
1672 }
1673 return REALABS(maxval / minval);
1674}
1675
1676/** for every variable in the row, except the inferred variable, add bound changes */
1677static
1679 SCIP_SET* set, /**< global SCIP settings */
1680 SCIP_VAR** vars, /**< array of variables */
1681 SCIP_CONFLICTROW* conflictrow, /**< conflict row */
1682 SCIP_BDCHGIDX* inferbdchgidx /**< bound change index (time stamp of bound change), or NULL for current time */
1683 )
1684{
1685 int i;
1686
1687 assert(vars != NULL);
1688
1689 /* scan through the row and add bound changes that make the constraint infeasible */
1690 for( i = 0; i < conflictrow->nnz; i++ )
1691 {
1692 SCIP_Real coef;
1693 int v;
1694 v = conflictrow->inds[i];
1695
1696 assert(SCIPvarGetProbindex(vars[v]) == v);
1697
1698 coef = conflictrow->vals[v];
1699
1700 if( coef > 0.0 )
1701 {
1702 SCIP_Real bnd;
1703 if( SCIPvarGetNBdchgInfosUb(vars[v]) > 0 )
1704 {
1705 bnd = SCIPgetVarUbAtIndex(set->scip, vars[v], inferbdchgidx, FALSE);
1706 if( SCIPsetIsLT(set, bnd, SCIPvarGetUbGlobal(vars[v])) )
1707 {
1708 SCIP_CALL( SCIPaddConflictUb(set->scip, vars[v], inferbdchgidx) );
1709 }
1710 }
1711 }
1712 else
1713 {
1714 SCIP_Real bnd;
1715 if( SCIPvarGetNBdchgInfosLb(vars[v]) > 0 )
1716 {
1717 bnd = SCIPgetVarLbAtIndex(set->scip, vars[v], inferbdchgidx, FALSE);
1718 if( SCIPsetIsGT(set, bnd, SCIPvarGetLbGlobal(vars[v])) )
1719 {
1720 SCIP_CALL( SCIPaddConflictLb(set->scip, vars[v], inferbdchgidx) );
1721 }
1722 }
1723 }
1724 }
1725 return SCIP_OKAY;
1726}
1727
1728/** add all slack reducing continuous bound changes to the continuous bound change queue */
1729static
1731 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1732 SCIP_VAR** vars, /**< array of variables */
1733 SCIP_CONFLICTROW* row, /**< conflict row */
1734 SCIP_BDCHGIDX* inferbdchgidx /**< bound change index of latest continuous bound change */
1735 )
1736{
1737 SCIP_PQUEUE* continuousbdchgqueue;
1738 int i;
1739
1740 assert(vars != NULL);
1741
1742 continuousbdchgqueue = conflict->continuousbdchgqueue;
1743
1744 /* make sure that the continuous bound change queue is empty */
1745 if( SCIPpqueueNElems(conflict->continuousbdchgqueue) != 0 )
1747
1748 /* For a row of the form ax >= b, we can add all continuous bound changes before inferbdchgidx that reduce the slack
1749 * for each continuous variable x_k with coefficient a_k:
1750 * - a_k > 0: then add bound changes (if not already present). Uses SCIPvarGetUbchgInfo() to get the latest
1751 * bound change used in the slack of row.
1752 * - a_k < 0: then add bound changes (if not already present). Uses SCIPvarGetLbchgInfo() to get the latest
1753 * bound change used in the slack of row.
1754 */
1755 for( i = 0; i < row->nnz; i++ )
1756 {
1757 SCIP_Real coef;
1758 int v;
1759
1760 v = row->inds[i];
1761
1762 assert(SCIPvarGetProbindex(vars[v]) == v);
1763
1764 if( SCIPvarIsIntegral(vars[v]) )
1765 continue;
1766
1767 coef = row->vals[v];
1768
1769 if( coef > 0.0 )
1770 {
1771 SCIP_BDCHGINFO* bdchginfo = SCIPvarGetUbchgInfo(vars[v], inferbdchgidx, FALSE);
1772 if( bdchginfo != NULL )
1773 {
1774 assert((SCIPbdchginfoGetDepth(bdchginfo) < SCIPbdchgidxGetDepth(inferbdchgidx)) ||
1775 (SCIPbdchginfoGetDepth(bdchginfo) == SCIPbdchgidxGetDepth(inferbdchgidx) && SCIPbdchginfoGetPos(bdchginfo) < SCIPbdchgidxGetPos(inferbdchgidx)));
1776 SCIP_CALL( SCIPpqueueInsert(continuousbdchgqueue, (void*)bdchginfo) );
1777 }
1778 }
1779 else
1780 {
1781 SCIP_BDCHGINFO* bdchginfo = SCIPvarGetLbchgInfo(vars[v], inferbdchgidx, FALSE);
1782 if( bdchginfo != NULL )
1783 {
1784 assert((SCIPbdchginfoGetDepth(bdchginfo) < SCIPbdchgidxGetDepth(inferbdchgidx)) ||
1785 (SCIPbdchginfoGetDepth(bdchginfo) == SCIPbdchgidxGetDepth(inferbdchgidx) && SCIPbdchginfoGetPos(bdchginfo) < SCIPbdchgidxGetPos(inferbdchgidx)));
1786 SCIP_CALL( SCIPpqueueInsert(continuousbdchgqueue, (void*)bdchginfo) );
1787 }
1788 }
1789 }
1790 return SCIP_OKAY;
1791}
1792
1793/** increases the conflict score of the variable in the given direction */
1794static
1796 SCIP_VAR* var, /**< problem variable */
1797 BMS_BLKMEM* blkmem, /**< block memory */
1798 SCIP_SET* set, /**< global SCIP settings */
1799 SCIP_STAT* stat, /**< dynamic problem statistics */
1800 SCIP_BOUNDTYPE boundtype, /**< type of bound for which the score should be increased */
1801 SCIP_Real value, /**< value of the bound */
1802 SCIP_Real weight /**< weight of this VSIDS updates */
1803 )
1804{
1805 SCIP_BRANCHDIR branchdir;
1806
1807 assert(var != NULL);
1808 assert(stat != NULL);
1809
1810 /* weight the VSIDS by the given weight */
1811 weight *= stat->vsidsweight;
1812
1813 if( SCIPsetIsZero(set, weight) )
1814 return SCIP_OKAY;
1815
1816 branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
1817 SCIP_CALL( SCIPvarIncVSIDS(var, blkmem, set, stat, branchdir, value, weight) );
1818 SCIPhistoryIncVSIDS(stat->glbhistory, branchdir, weight);
1819 SCIPhistoryIncVSIDS(stat->glbhistorycrun, branchdir, weight);
1820
1821 return SCIP_OKAY;
1822}
1823
1824/** update conflict statistics */
1825static
1827 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1828 SCIP_VAR** vars, /**< array of variables */
1829 BMS_BLKMEM* blkmem, /**< block memory */
1830 SCIP_SET* set, /**< global SCIP settings */
1831 SCIP_STAT* stat, /**< dynamic problem statistics */
1832 SCIP_CONFLICTROW* conflictrow, /**< conflict row to add to the tree */
1833 int insertdepth /**< depth level at which the conflict set should be added */
1834 )
1835{
1836 if( insertdepth > 0 )
1837 {
1838 conflict->nappliedlocconss++;
1839 conflict->nappliedlocliterals += conflictrow->nnz;
1840 }
1841 else
1842 {
1843 int i;
1844 int conflictlength;
1845 conflictlength = conflictrow->nnz;
1846
1847 assert(vars != NULL);
1848
1849 for( i = 0; i < conflictlength; i++ )
1850 {
1851 int idx;
1852 SCIP_VAR* var;
1853 SCIP_BRANCHDIR branchdir;
1854 SCIP_BOUNDTYPE boundtype;
1856
1857 assert(stat != NULL);
1858
1859 idx = conflictrow->inds[i];
1860 var = vars[idx];
1861
1862 assert(!SCIPsetIsZero(set, conflictrow->vals[idx]));
1863
1864 boundtype = conflictrow->vals[idx] > 0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER;
1865 bound = conflictrow->vals[idx] > 0 ? SCIPvarGetLbLocal(var) : SCIPvarGetUbLocal(var);
1866
1867 branchdir = (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS); /*lint !e641*/
1868
1869 SCIP_CALL( SCIPvarIncNActiveConflicts(var, blkmem, set, stat, branchdir, bound, (SCIP_Real)conflictlength) );
1870 SCIPhistoryIncNActiveConflicts(stat->glbhistory, branchdir, (SCIP_Real)conflictlength);
1871 SCIPhistoryIncNActiveConflicts(stat->glbhistorycrun, branchdir, (SCIP_Real)conflictlength);
1872
1873 /* each variable which is part of the conflict gets an increase in the VSIDS */
1874 SCIP_CALL( incVSIDS(var, blkmem, set, stat, boundtype, bound, set->conf_conflictweight) );
1875 }
1876 conflict->nappliedglbconss++;
1877 conflict->nappliedglbliterals += conflictrow->nnz;
1878 }
1879
1880 return SCIP_OKAY;
1881}
1882
1883/** creates a conflict constraint and tries to add it to the storage */
1884static
1886 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1887 BMS_BLKMEM* blkmem, /**< block memory */
1888 SCIP_SET* set, /**< global SCIP settings */
1889 SCIP_STAT* stat, /**< dynamic problem statistics */
1890 SCIP_VAR** vars, /**< array of variables */
1891 SCIP_TREE* tree, /**< branch and bound tree */
1892 SCIP_REOPT* reopt, /**< reoptimization data structure */
1893 SCIP_LP* lp, /**< current LP data */
1894 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1895 SCIP_CONFLICTROW* conflictrow, /**< conflict row to add to the tree */
1896 int insertdepth, /**< depth level at which the conflict set should be added */
1897 SCIP_Bool* success /**< pointer to store whether the addition was successful */
1898 )
1899{
1900 SCIP_VAR** consvars;
1901 SCIP_CONS* cons;
1902 SCIP_CONS* upgdcons;
1903
1904 char consname[SCIP_MAXSTRLEN];
1905
1906 SCIP_Real* vals;
1907 SCIP_Real lhs;
1908 int i;
1909
1910 assert(vars != NULL);
1911 assert(conflictrow->nnz > 0);
1912
1913 SCIP_CALL( SCIPallocBufferArray(set->scip, &consvars, conflictrow->nnz) );
1914 SCIP_CALL( SCIPallocBufferArray(set->scip, &vals, conflictrow->nnz) );
1915
1916 lhs = conflictrow->lhs;
1917
1918 for( i = 0; i < conflictrow->nnz; ++i )
1919 {
1920 int idx;
1921 idx = conflictrow->inds[i];
1922 assert(conflictrow->vals[idx]);
1923 consvars[i] = vars[idx];
1924 vals[i] = conflictrow->vals[idx];
1925 }
1926
1927 /* create a constraint out of the conflict set */
1928 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "confres_%" SCIP_LONGINT_FORMAT, conflict->nresconfconss);
1929 SCIP_CALL( SCIPcreateConsLinear(set->scip, &cons, consname, conflictrow->nnz, consvars, vals,
1930 lhs, SCIPsetInfinity(set), FALSE, FALSE, FALSE, FALSE, TRUE, (SCIPnodeGetDepth(tree->path[conflictrow->validdepth]) > 0 ),
1931 FALSE, set->conf_dynamic, set->conf_removable, FALSE) );
1932
1933 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
1934 SCIP_CALL( SCIPupgradeConsLinear(set->scip, cons, &upgdcons) );
1935 if( upgdcons != NULL )
1936 {
1937 SCIP_CALL( SCIPreleaseCons(set->scip, &cons) );
1938 cons = upgdcons;
1939 }
1940
1941 /* check if the constraint is valid for the debug solution */
1942 SCIP_CALL( SCIPdebugCheckConss(set->scip, &cons, 1) );
1943
1944 /* update statistics */
1945 SCIP_CALL( updateStatistics(conflict, vars, blkmem, set, stat, conflictrow, conflictrow->validdepth) );
1946
1947 /* add conflict to SCIP */
1948 SCIP_CALL( SCIPaddConflict(set->scip, tree->path[insertdepth], &cons, tree->path[conflictrow->validdepth], conflictrow->conflicttype, conflictrow->usescutoffbound) );
1949 *success = TRUE;
1950 /* free temporary memory */
1951 SCIPfreeBufferArray(set->scip, &consvars);
1952 SCIPfreeBufferArray(set->scip, &vals);
1953
1954 return SCIP_OKAY;
1955}/*lint !e715*/
1956
1957/** create conflict constraints out of conflict row and add them to the problem */
1959 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1960 BMS_BLKMEM* blkmem, /**< block memory */
1961 SCIP_SET* set, /**< global SCIP settings */
1962 SCIP_STAT* stat, /**< dynamic problem statistics */
1963 SCIP_PROB* transprob, /**< transformed problem */
1964 SCIP_PROB* origprob, /**< original problem */
1965 SCIP_TREE* tree, /**< branch and bound tree */
1966 SCIP_REOPT* reopt, /**< reoptimization data structure */
1967 SCIP_LP* lp, /**< current LP data */
1968 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1969 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1970 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1971 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1972 SCIP_CONFLICTROW* conflictrow, /**< conflict row to add to the tree */
1973 SCIP_Bool* success /**< true if the conflict is added to the problem */
1974 )
1975{
1976 SCIP_VAR** vars;
1977 int focusdepth;
1978 int maxsize;
1979
1980 vars = SCIPprobGetVars(transprob);
1981
1982 focusdepth = SCIPtreeGetFocusDepth(tree);
1983
1984 assert(conflict != NULL);
1985 assert(set != NULL);
1986 assert(stat != NULL);
1987 assert(transprob != NULL);
1988 assert(tree != NULL);
1989 assert(conflictrow != NULL);
1990 assert(conflictrow->validdepth == 0);
1991 assert(vars != NULL);
1992 assert(success != NULL);
1993
1994 assert(focusdepth <= SCIPtreeGetCurrentDepth(tree));
1995 assert(SCIPtreeGetCurrentDepth(tree) == tree->pathlen-1);
1996
1997 /* calculate the maximal size of each accepted conflict set */
1998 maxsize = 2 * conflictCalcResMaxsize(set, transprob);
1999
2000 SCIPsetDebugMsgPrint(set, "flushing conflict constraint at focus depth %d (id: %d, vd: %d, cd: %d, rd: %d, maxsize: %d)\n",
2001 focusdepth, conflictrow->insertdepth, conflictrow->validdepth, conflictrow->conflictdepth, conflictrow->repropdepth, maxsize);
2002
2003 *success = FALSE;
2004
2005 /* do not add long conflicts */
2006 if( conflictrow->nnz > maxsize )
2007 {
2008 conflict->nreslongconfs++;
2009 SCIPsetDebugMsgPrint(set, " \t -> conflict row is too long: %d > %d nnzs\n", conflictrow->nnz, maxsize);
2010 }
2011 /* if the conflict row is empty and the lhs positive, the node and its sub-
2012 * tree in the conflict row's valid depth can be cut off completely
2013 */
2014 else if( conflictrow->nnz == 0 && SCIPsetIsGT(set, conflictrow->lhs, 0.0) )
2015 {
2016 SCIPsetDebugMsgPrint(set, " \t -> empty conflict row with lhs %f in depth %d cuts off sub tree at depth %d\n",
2017 conflictrow->lhs, focusdepth, conflictrow->validdepth);
2018 *success = TRUE;
2019 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictrow->validdepth], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
2020 }
2021 /* in case the conflict set contains only one bound change which is globally valid we apply that bound change
2022 * directly (except if we are in strong branching or diving - in this case a bound change would yield an unflushed LP
2023 * and is not handled when restoring the information)
2024 *
2025 * @note A bound change can only be applied if it is related to the active node or if is a global bound
2026 * change. Bound changes which are related to any other node cannot be handled at point due to the internal
2027 * data structure
2028 */
2029 else if( !hasRelaxationOnlyVar(set, vars, conflictrow) && conflictrow->nnz == 1 && conflictrow->insertdepth == 0 && !lp->strongbranching && !lp->diving )
2030 {
2031 SCIP_VAR* var;
2033 SCIP_BOUNDTYPE boundtype;
2034 int idx;
2035
2036 idx = conflictrow->inds[0];
2037 var = vars[idx];
2038 assert(!SCIPsetIsZero(set, conflictrow->vals[idx]));
2039 assert(var != NULL);
2040
2041 boundtype = conflictrow->vals[idx] > 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
2042
2043 /* Since the conflictrow is in the form a*x >= b:
2044 * For integer variables:
2045 * coef > 0: The lower bound change is equal to ceil(lhs / coef)
2046 * coef < 0: The upper bound change is equal to floor(lhs / coef)
2047 * For continuous variables we do not round the bound change
2048 */
2049 bound = conflictrow->lhs / conflictrow->vals[idx];
2050 if( SCIPvarIsIntegral(var) )
2051 bound = conflictrow->vals[idx] > 0.0 ? SCIPsetCeil(set, bound) : SCIPsetFloor(set, bound);
2052
2053 /* todo: rethink the logic and add asserts. Also find a better way
2054 * to inform the statistics that a constraint is added "indirectly", also
2055 * update number of global bound changes from conflict analysis */
2057 {
2058 SCIPsetDebugMsgPrint(set, " \t -> Bound %s >= %f contradicts with the global upper bound %s <= %f\n",
2060 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictrow->validdepth], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
2061 }
2062 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, bound, SCIPvarGetLbGlobal(var)) )
2063 {
2064 SCIPsetDebugMsgPrint(set, " \t -> Bound %s <= %f contradicts with the global lower bound %s >= %f\n",
2066 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictrow->validdepth], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
2067 }
2068 else
2069 {
2070 SCIPsetDebugMsg(set, " -> apply global bound change: <%s> %s %g\n",
2071 SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", bound);
2072 SCIP_CALL( SCIPnodeAddBoundchg(tree->path[conflictrow->validdepth], blkmem, set, stat, transprob, origprob, tree,
2073 reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, bound, boundtype, FALSE) );
2074 }
2075
2076 *success = TRUE;
2077 SCIP_CALL( updateStatistics(conflict, vars, blkmem, set, stat, conflictrow, conflictrow->validdepth) );
2078 }
2079 /* generate the linear constraint */
2080 else if( !hasRelaxationOnlyVar(set, vars, conflictrow) )
2081 {
2082 /* todo use the right insert depth and not valid depth */
2083 SCIP_CALL( createAndAddConflictCon(conflict, blkmem, set, stat, vars, \
2084 tree, reopt, lp, cliquetable, conflictrow, conflictrow->insertdepth, success) );
2085 conflict->nappliedglbresconss++;
2086 SCIPsetDebugMsgPrint(set, " \t -> conflict row added (cdpt:%d, fdpt:%d, insert:%d, valid:%d, conf: %d, reprop: %d, len:%d):\n",
2088 conflictrow->insertdepth, conflictrow->validdepth, conflictrow->conflictdepth,
2089 conflictrow->repropdepth, conflictrow->nnz);
2090 }
2091 else
2092 {
2093 SCIPsetDebugMsgPrint(set, " \t -> conflict row has relaxation only variable \n");
2094 return SCIP_OKAY;
2095 }
2096
2097 return SCIP_OKAY;
2098}/*lint !e715*/
2099
2100/** adds given data as row to the generalized resolution row */
2101static
2103 SCIP_CONFLICTROW* resolutionrow, /**< generalized resolution row */
2104 BMS_BLKMEM* blkmem, /**< block memory */
2105 SCIP_Real* vals, /**< variable coefficients */
2106 int* inds, /**< variable array */
2107 int nnz, /**< size of variable and coefficient array */
2108 SCIP_Real lhs, /**< left-hand side of conflict row */
2109 SCIP_Bool reverse /**< reverse coefficients */
2110 )
2111{
2112 int i;
2113 int idx;
2114
2115 assert(resolutionrow != NULL);
2116 assert(resolutionrow->vals != NULL);
2117 assert(blkmem != NULL);
2118
2119 if( resolutionrow->size == 0 )
2120 {
2121 assert(resolutionrow->inds == NULL);
2122
2123 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &resolutionrow->inds, nnz) );
2124 resolutionrow->size = nnz;
2125 }
2126 else
2127 {
2128 assert(resolutionrow->vals != NULL);
2129 assert(resolutionrow->inds != NULL);
2130
2131 if( resolutionrow->size < nnz )
2132 {
2133 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &resolutionrow->inds, resolutionrow->size, nnz) );
2134 resolutionrow->size = nnz;
2135 }
2136 }
2137
2138 if( reverse )
2139 {
2140 for( i = 0; i < nnz; i++ )
2141 {
2142 idx = inds[i];
2143 resolutionrow->vals[idx] = -vals[i];
2144 resolutionrow->inds[i] = inds[i];
2145 }
2146 }
2147 else
2148 {
2149 for( i = 0; i < nnz; i++ )
2150 {
2151 idx = inds[i];
2152 resolutionrow->vals[idx] = vals[i];
2153 resolutionrow->inds[i] = inds[i];
2154 }
2155 }
2156
2157 resolutionrow->lhs = lhs;
2158 resolutionrow->nnz = nnz;
2159
2160 return SCIP_OKAY;
2161}
2162
2163/** compute scale for the reason constraint such that the resolving variable cancels out */
2164static
2166 SCIP_SET* set, /**< global SCIP settings */
2167 SCIP_CONFLICTROW* conflictrow, /**< conflict row */
2168 SCIP_CONFLICTROW* reasonrow, /**< reason row */
2169 int residx /**< index of variable to resolve */
2170 )
2171{
2172 SCIP_Real coefconf;
2173 SCIP_Real coefreas;
2174 SCIP_Real scale;
2175
2176 coefconf = conflictrow->vals[residx];
2177 coefreas = reasonrow->vals[residx];
2178
2179 assert(!SCIPsetIsZero(set, coefreas) && !SCIPsetIsZero(set, coefconf));
2180 assert(coefconf * coefreas < 0);
2181
2182 scale = REALABS( coefconf / coefreas );
2183 return scale;
2184}
2185
2186/** compute the resolved conflict row resolvedrow = row1 + scale * row2 */
2187static
2189 SCIP_SET* set, /**< global SCIP settings */
2190 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2191 SCIP_CONFLICTROW* row1, /**< conflict row */
2192 SCIP_CONFLICTROW* row2, /**< reason conflict row */
2193 SCIP_CONFLICTROW* resolvedrow, /**< resolved conflict row */
2194 BMS_BLKMEM* blkmem, /**< block memory */
2195 int residx, /**< index of variable to resolve */
2196 SCIP_Bool* success /**< apply resolution */
2197 )
2198{
2199 int i;
2200 SCIP_Real scale;
2201 SCIP_Real largestcoef;
2202 SCIP_Real smallestcoef;
2203
2204 int newsize;
2205 int newnnz;
2206
2207 SCIPsetDebugMsgPrint(set, "Nonzeros in first row: %d, slack: %f \n", row1->nnz, row1->slack);
2208 SCIPsetDebugMsgPrint(set, "Nonzeros in second row: %d, slack: %f \n", row2->nnz, row2->slack);
2209
2210 *success = FALSE;
2211
2212 scale = computeScaleReason(set, row1, row2, residx);
2213
2214 if( SCIPsetIsGE(set, scale, set->conf_maxcoefquot) )
2215 {
2216 SCIPsetDebugMsgPrint(set, "Scale %f exceeds max allowed scale %f \n", scale, set->conf_maxcoefquot);
2217 conflict->nreslargecoefs++;
2218 return SCIP_OKAY;
2219 }
2220
2221 SCIP_CALL( conflictRowReplace(resolvedrow, blkmem, row1) );
2222
2223 newsize = resolvedrow->nnz + row2->nnz;
2224 if( resolvedrow->size < newsize )
2225 {
2226 assert(resolvedrow->vals != NULL);
2227 assert(resolvedrow->inds != NULL);
2228
2229 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &resolvedrow->inds, resolvedrow->size, newsize ) );
2230 resolvedrow->size = newsize;
2231 }
2232
2233 /* add the reason conflict row to the resolved conflict row */
2234 linearCombRows(set, resolvedrow, row2, scale);
2235
2236 newnnz = resolvedrow->nnz;
2237
2238 largestcoef = -SCIPsetInfinity(set);
2239 smallestcoef = SCIPsetInfinity(set);
2240 /* remove coefficients that are almost zero (1e-09 tolerance), loop backwards */
2241 for( i = newnnz - 1; i >= 0 ; i-- )
2242 {
2243 int idx;
2244 idx = resolvedrow->inds[i];
2245 assert(!SCIPsetIsZero(set, resolvedrow->vals[idx]));
2246
2247 smallestcoef = MIN(smallestcoef, resolvedrow->vals[idx]);
2248 largestcoef = MAX(largestcoef, resolvedrow->vals[idx]);
2249 }
2250
2251 SCIPsetDebugMsgPrint(set, "Nonzeros in resolved row: %d \n", resolvedrow->nnz);
2252
2253 /* check if the quotient of coefficients in the resolvent exceeds the max allowed quotient */
2254 resolvedrow->coefquotient = (resolvedrow->nnz > 0) ? fabs(largestcoef / smallestcoef) : 0.0;
2255 if( SCIPsetIsGT(set, resolvedrow->coefquotient, set->conf_maxcoefquot) )
2256 {
2257 conflict->nreslargecoefs++;
2258 SCIPsetDebugMsgPrint(set, "Quotient %f exceeds max allowed quotient", (resolvedrow->nnz > 0) ? fabs(largestcoef / smallestcoef) : 0.0);
2259 return SCIP_OKAY;
2260 }
2261
2262 *success = TRUE;
2263
2264 return SCIP_OKAY;
2265}
2266
2267
2268/** reduce the reason constraint */
2269static
2271 SCIP_SET* set, /**< global SCIP settings */
2272 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2273 SCIP_VAR** vars, /**< array of variables */
2274 int nvars, /**< number of variables */
2275 SCIP_CONFLICTROW* rowtoreduce, /**< the row to reduce */
2276 SCIP_BDCHGINFO* currbdchginfo, /**< current bound change to resolve */
2277 int residx, /**< index of variable to resolve */
2278 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
2279 int* fixsides /**< dense array of variables fixed to a bound */
2280 )
2281{
2282 SCIP_Real coefinrow;
2283 SCIP_BDCHGIDX* currbdchgidx;
2284
2285 currbdchgidx = SCIPbdchginfoGetIdx(currbdchginfo);
2286
2287 coefinrow = fabs(rowtoreduce->vals[residx]);
2288
2289 if( isBinaryConflictRow(set, vars, rowtoreduce) )
2290 SCIP_CALL( ComplementedMirLhs(set, vars, rowtoreduce, fixsides, currbdchgidx, residx, coefinrow) );
2291 else
2292 SCIP_CALL( MirReduction(set, blkmem, vars, nvars, rowtoreduce, currbdchginfo, residx, coefinrow) );
2293
2294 SCIP_CALL( computeSlack(set, vars, rowtoreduce, currbdchginfo, fixbounds, fixsides) );
2295
2296 /* check that the variable we are resolving is still in the reason row */
2297 assert(!SCIPsetIsZero(set, rowtoreduce->vals[residx]));
2298
2299 SCIPdebug(printConflictRow(rowtoreduce, set, vars, REDUCED_REASON_ROWTYPE));
2300
2301 return SCIP_OKAY;
2302}
2303
2304/** reason row from an LP row */
2305static
2307 SCIP_SET* set, /**< global SCIP settings */
2308 BMS_BLKMEM* blkmem, /**< block memory */
2309 SCIP_ROW* row, /**< row to add */
2310 SCIP_CONFLICTROW* reasonrow, /**< reason row */
2311 SCIP_BDCHGINFO* bdchginfo /**< bound change to resolve */
2312 )
2313{
2314 SCIP_COL** cols;
2315 SCIP_VAR* vartoresolve;
2316 SCIP_Real* vals;
2317 int* inds;
2318 SCIP_Real lhs;
2319 SCIP_Real rowlhs;
2320 SCIP_Real rowrhs;
2321 int nnz;
2322 int varidx;
2323 int i;
2324 SCIP_Bool changesign;
2325 SCIP_Bool isincon;
2326
2327 assert(reasonrow != NULL);
2328 assert(set != NULL);
2329
2330 nnz = SCIProwGetNNonz(row);
2331 assert(nnz > 0);
2332
2333 rowlhs = SCIProwGetLhs(row) - SCIProwGetConstant(row);
2334 rowrhs = SCIProwGetRhs(row) - SCIProwGetConstant(row);
2335
2336 vartoresolve = SCIPbdchginfoGetVar(bdchginfo);
2337 varidx = SCIPvarGetProbindex(vartoresolve);
2338
2339 vals = SCIProwGetVals(row);
2340 cols = SCIProwGetCols(row);
2341
2342 SCIP_CALL( SCIPsetAllocBufferArray(set, &inds, nnz ) );
2343
2344 isincon = FALSE;
2345 changesign = FALSE;
2346 for( i = 0; i < nnz; i++ )
2347 {
2348 SCIP_VAR* var;
2349
2350 var = SCIPcolGetVar(cols[i]);
2351 inds[i] = SCIPvarGetProbindex(var);
2352 if( inds[i] == varidx )
2353 {
2354 assert(var == vartoresolve);
2355 if( (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER && vals[i] < 0) ||
2356 (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER && vals[i] > 0) )
2357 {
2358 if( strcmp(SCIPconshdlrGetName(bdchginfo->inferencedata.reason.cons->conshdlr), "knapsack") != 0 )
2359 assert(!SCIPsetIsInfinity(set, rowrhs));
2360 changesign = TRUE;
2361 }
2362 else if( (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER && vals[i] > 0 ) ||
2363 (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER && vals[i] < 0))
2364 {
2365 if( strcmp(SCIPconshdlrGetName(bdchginfo->inferencedata.reason.cons->conshdlr), "knapsack") != 0 )
2366 assert(!SCIPsetIsInfinity(set, -rowlhs));
2367 changesign = FALSE;
2368 }
2369 else
2370 {
2371 SCIPABORT();
2372 }
2373 isincon = TRUE;
2374 }
2375 }
2376 assert(isincon);
2377 SCIP_UNUSED(isincon);
2378
2379 if( changesign )
2380 lhs = -rowrhs;
2381 else
2382 lhs = rowlhs;
2383
2384 assert(inds != NULL);
2385 assert(vals != NULL);
2386
2387 SCIP_CALL( conflictRowAddSemiSparseData(reasonrow, blkmem, vals, inds, nnz, lhs, changesign) );
2388
2390
2391 return SCIP_OKAY;
2392}
2393
2394/** add a row to the conflict row */
2395static
2397 SCIP_SET* set, /**< global SCIP settings */
2398 BMS_BLKMEM* blkmem, /**< block memory */
2399 SCIP_ROW* row, /**< row to add */
2400 SCIP_CONFLICTROW* conflictrow, /**< conflict row */
2401 SCIP_BDCHGINFO* bdchginfo /**< bound change to resolve */
2402 )
2403{
2404 SCIP_COL** cols;
2405 SCIP_VAR* var;
2406 SCIP_Real* vals;
2407 int* inds;
2408 SCIP_Real lhs;
2409 SCIP_Real rowlhs;
2410 SCIP_Real rowrhs;
2411 int nnz;
2412 int varidx;
2413 int i;
2414 SCIP_Bool changesign;
2415 SCIP_Bool isincon;
2416 assert(conflictrow != NULL);
2417 assert(set != NULL);
2418
2419 nnz = SCIProwGetNNonz(row);
2420 assert(nnz > 0);
2421
2422 rowlhs = SCIProwGetLhs(row) - SCIProwGetConstant(row);
2423 rowrhs = SCIProwGetRhs(row) - SCIProwGetConstant(row);
2424
2425 var = SCIPbdchginfoGetVar(bdchginfo);
2426 varidx = SCIPvarGetProbindex(var);
2427
2428 vals = SCIProwGetVals(row);
2429 cols = SCIProwGetCols(row);
2430
2431 SCIP_CALL( SCIPsetAllocBufferArray(set, &inds, nnz ) );
2432
2433 isincon = FALSE;
2434 changesign = FALSE;
2435 for( i = 0; i < nnz; i++ )
2436 {
2437 var = SCIPcolGetVar(cols[i]);
2438 inds[i] = SCIPvarGetProbindex(var);
2439 if( inds[i] == varidx )
2440 {
2441 if( (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER && vals[i] > 0 ) ||
2442 (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER && vals[i] < 0))
2443 {
2444 changesign = TRUE;
2445 }
2446 else if( (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER && vals[i] < 0 ) ||
2447 (SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_UPPER && vals[i] > 0))
2448 {
2449 changesign = FALSE;
2450 }
2451 else
2452 {
2453 SCIPABORT();
2454 }
2455 isincon = TRUE;
2456 }
2457 }
2458
2459 assert(isincon);
2460 SCIP_UNUSED(isincon);
2461
2462 if( changesign )
2463 lhs = -rowrhs;
2464 else
2465 lhs = rowlhs;
2466
2467 assert(inds != NULL);
2468 assert(vals != NULL);
2469
2470 SCIP_CALL( conflictRowAddSemiSparseData(conflictrow, blkmem, vals, inds, nnz, lhs, changesign) );
2471
2473
2474 return SCIP_OKAY;
2475}
2476
2477/** get the reason for the given bound change */
2478static
2480 BMS_BLKMEM* blkmem, /**< block memory */
2481 SCIP_VAR** vars, /**< array of variables */
2482 SCIP_SET* set, /**< global SCIP settings */
2483 SCIP_BDCHGINFO* currbdchginfo, /**< bound change to resolve */
2484 SCIP_CONFLICTROW* reasonrow, /**< reason row for the bound change */
2485 int residx, /**< index of the bound change to resolve */
2486 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
2487 int* fixsides, /**< dense array of variables fixed to a bound */
2488 SCIP_Bool* success /**< pointer to store whether we could get a linear reason */
2489 )
2490{
2491 assert(success != NULL);
2492 assert(reasonrow != NULL);
2493
2494 *success = FALSE;
2495
2496 if( isResolvableBdchg(currbdchginfo) && SCIPbdchginfoGetChgtype(currbdchginfo) == SCIP_BOUNDCHGTYPE_CONSINFER )
2497 {
2498 SCIP_CONS* reasoncon;
2499 SCIP_ROW* reasonlprow = NULL;
2500
2501 reasoncon = SCIPbdchginfoGetInferCons(currbdchginfo);
2502
2503 if( !SCIPconsIsGlobal(reasoncon) )
2504 {
2505 SCIPsetDebugMsgPrint(set, "Reason constraint is not global \n");
2506 return SCIP_OKAY;
2507 }
2508
2509 /* get the corresponding reason row */
2510 SCIP_CALL( SCIPconsCreateRow(set->scip, reasoncon, &reasonlprow) );
2511
2512 if( reasonlprow == NULL )
2513 {
2514 SCIPsetDebugMsgPrint(set, "Could not create row for reason constraint \n");
2515 return SCIP_OKAY;
2516 }
2517
2518 /* get the conflict row of the reason row */
2519 SCIP_CALL( reasonRowFromLpRow(set, blkmem, reasonlprow, reasonrow, currbdchginfo) );
2520 *success = TRUE;
2521 /* it may happen that some specialized propagation took place and the real reason is not the constraint
2522 e.g. negated cliques in cons_knapsack or ranged row propagation in cons_linear. */
2523
2524 /* this happens if the reason is a negated clique found in the knapsack constraint handler */
2525 if( strcmp(SCIPconshdlrGetName(reasoncon->conshdlr), "knapsack") != 0 )
2526 {
2527 assert(!SCIPsetIsInfinity(set, -reasonrow->lhs) || !SCIPsetIsInfinity(set, reasonrow->lhs));
2528 }
2529 else if( SCIPsetIsInfinity(set, -reasonrow->lhs) || SCIPsetIsInfinity(set, reasonrow->lhs) )
2530 {
2531 *success = FALSE;
2532 return SCIP_OKAY;
2533 }
2534
2535 SCIP_CALL( computeSlack(set, vars, reasonrow, currbdchginfo, fixbounds, fixsides) );
2536
2537 /* If the slack is greater than 0, we check that the reason actually propagated the variable we resolve.
2538 It propagates a variable x_i if (slack - a_i * ( boundusedinslack - oldbound)) < 0 */
2539 if( SCIPsetIsGT(set, reasonrow->slack, 0.0) )
2540 {
2541 SCIP_VAR* var;
2542 SCIP_BDCHGIDX* currbdchgidx;
2543 SCIP_Real coef;
2544 SCIP_Real boundusedinslack;
2545
2546 currbdchgidx = SCIPbdchginfoGetIdx(currbdchginfo);
2547 var = SCIPbdchginfoGetVar(currbdchginfo);
2548 assert(var != NULL);
2549 assert(SCIPvarGetProbindex(var) == residx);
2550
2551 coef = reasonrow->vals[residx];
2552 boundusedinslack = coef > 0 ? SCIPgetVarUbAtIndex(set->scip, var, currbdchgidx, TRUE) : SCIPgetVarLbAtIndex(set->scip, var, currbdchgidx, TRUE);
2553
2554 if( !SCIPsetIsLT(set, reasonrow->slack - coef * (boundusedinslack - SCIPbdchginfoGetOldbound(currbdchginfo)), 0.0) )
2555 {
2556 SCIPsetDebugMsgPrint(set, "Reason row does not propagate because of non-linear propagation \n");
2557 *success = FALSE;
2558 return SCIP_OKAY;
2559 }
2560 }
2561 }
2562 else
2563 {
2564 SCIPsetDebugMsgPrint(set, "Could not obtain a reason row \n");
2565 *success = FALSE;
2566 }
2567
2568 return SCIP_OKAY;
2569}
2570
2571/** get the conflict row for the given bound change from the LP row. */
2572static
2574 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2575 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2576 SCIP_SET* set, /**< global SCIP settings */
2577 SCIP_PROB* prob, /**< problem data */
2578 SCIP_ROW* initialconflictrow, /**< row of constraint that detected the conflict */
2579 SCIP_BDCHGINFO* currbdchginfo, /**< bound change to resolve */
2580 int maxsize, /**< maximal size of conflict rows */
2581 SCIP_Bool* success /**< pointer to store whether we could get a conflict row */
2582 )
2583{
2584 SCIP_VAR** vars;
2585 SCIP_CONFLICTROW* conflictrow;
2586 SCIP_BDCHGIDX* currbdchgidx;
2587
2588 vars = prob->vars;
2589 assert(vars != NULL);
2590
2591 conflictrow = conflict->conflictrow;
2592 currbdchgidx = SCIPbdchginfoGetIdx(currbdchginfo);
2593 assert(currbdchgidx != NULL);
2594
2595 assert(success != NULL);
2596 *success = FALSE;
2597 /* first try to create the conflict row from the infeasible LP row */
2598 if( initialconflictrow != NULL )
2599 {
2600 SCIPsetDebugMsgPrint(set, "Initial LP Row: %s \n", SCIProwGetName(initialconflictrow));
2601 SCIP_CALL( conflictRowFromLpRow(set, blkmem, initialconflictrow, conflictrow, currbdchginfo) );
2602
2603 /* if the conflict row is too large, we try to weaken it */
2604 if( conflictrow->nnz > maxsize )
2605 {
2606 assert(conflictrow->nnz == SCIProwGetNNonz(initialconflictrow));
2607 SCIPsetDebugMsgPrint(set, "Number of nonzeros in conflict is larger than maxsize %d > %d\n", conflictrow->nnz, maxsize);
2608 SCIPsetDebugMsgPrint(set, "Try to shorten the conflict row by applying weakening \n");
2609
2610 weakenConflictRow(conflictrow, set, vars, currbdchgidx, NULL);
2611
2612 if( conflictrow->nnz > maxsize )
2613 {
2614 SCIPsetDebugMsgPrint(set, "Conflict row is still too large after weakening %d > %d\n", conflictrow->nnz, maxsize);
2615 conflict->nreslongconfs++;
2616 return SCIP_OKAY;
2617 }
2618 }
2619
2620 /* set the slack */
2621 SCIP_CALL( computeSlack(set, vars, conflictrow, currbdchginfo, NULL, NULL) );
2622 }
2623
2624 /* The conflict row might not be infeasible.
2625 * This may not be true is if the conflict is found by some non-linear propagation argument:
2626 * - by a negated clique in the knapsack constraint handler
2627 * - by propagating a ranged row with a gcd argument
2628 */
2629 if( initialconflictrow == NULL || SCIPsetIsGE(set, conflictrow->slack, 0.0) )
2630 {
2631 SCIPsetDebugMsgPrint(set, "Initial conflict could not be retrieved \n");
2632 return SCIP_OKAY;
2633 }
2634
2635 /* check once more if the initial conflict is too long */
2636 if( conflictrow->nnz > maxsize )
2637 {
2638 conflict->nreslongconfs++;
2639 return SCIP_OKAY;
2640 }
2641
2642 assert(SCIPsetIsLT(set, conflictrow->slack, 0.0));
2643 *success = TRUE;
2644
2645 return SCIP_OKAY;
2646}
2647
2648/** execute resolution; reduce reason if necessary */
2649static
2651 SCIP_CONFLICT * conflict, /**< conflict analysis data */
2652 SCIP_SET* set, /**< global SCIP settings */
2653 SCIP_VAR** vars, /**< array of variables */
2654 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2655 SCIP_BDCHGINFO* currbdchginfo, /**< current bound change to resolve */
2656 int residx, /**< index of variable to resolve */
2657 int maxsize, /**< maximal size of conflict rows */
2658 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
2659 int* fixsides, /**< dense array of variables fixed to a bound */
2660 SCIP_Bool* successresolution /**< pointer to store whether the resolution was successful */
2661 )
2662{
2663 SCIP_CONFLICTROW* conflictrow;
2664 SCIP_CONFLICTROW* reasonrow;
2665 SCIP_CONFLICTROW* reducedreasonrow;
2666 SCIP_CONFLICTROW* resolvedconflictrow;
2667
2668 int nvars;
2669
2670 assert(conflict != NULL);
2671
2672 conflictrow = conflict->conflictrow;
2673 reasonrow = conflict->reasonrow;
2674 reducedreasonrow = conflict->reducedreasonrow;
2675 resolvedconflictrow = conflict->resolvedconflictrow;
2676
2677 *successresolution = FALSE;
2678
2679 nvars = SCIPgetNVars(set->scip);
2680 assert(!SCIPsetIsZero(set, reasonrow->vals[residx]));
2681
2682 /* try to resolve without reducing the reason row */
2683 SCIPsetDebugMsgPrint(set, "Resolve %s without reducing the reason row \n", SCIPvarGetName(vars[residx]));
2684 SCIP_CALL( rescaleAndResolve(set, conflict, conflictrow, reasonrow, resolvedconflictrow, blkmem,
2685 residx, successresolution) );
2686
2687 if( !(*successresolution) )
2688 return SCIP_OKAY;
2689
2690 SCIP_CALL( computeSlack(set, vars, resolvedconflictrow, currbdchginfo, fixbounds, fixsides) );
2691
2692 /* return if the reduction is off */
2693 if( set->conf_reduction == 'o' )
2694 return SCIP_OKAY;
2695
2696 /* if the resolvent is not infeasible under the local domain, try to reduce the reason row */
2697 if( SCIPsetIsGE(set, resolvedconflictrow->slack, 0.0) )
2698 {
2699 /* copy the original reason here */
2700 SCIP_CALL( conflictRowReplace(reducedreasonrow, blkmem, reasonrow) );
2701
2702 /* apply reduction to the reason row */
2703 SCIP_CALL( reduceReason(set, blkmem, vars, nvars, reducedreasonrow, currbdchginfo, residx, fixbounds, fixsides) );
2704
2705 /* after reduction resolve again */
2706 SCIPsetDebugMsgPrint(set, "Resolve %s after reducing the reason row \n", SCIPvarGetName(vars[residx]));
2707 SCIP_CALL( rescaleAndResolve(set, conflict, conflictrow, reducedreasonrow, resolvedconflictrow, blkmem,
2708 residx, successresolution) );
2709
2710 if( !(*successresolution) )
2711 return SCIP_OKAY;
2712
2713 SCIP_CALL( computeSlack(set, vars, resolvedconflictrow, currbdchginfo, fixbounds, fixsides) );
2714
2715 /* mixed binary case reduction */
2716 if( set->conf_mbreduction && SCIPsetIsGE(set, resolvedconflictrow->slack, 0.0) )
2717 {
2718 SCIP_BDCHGINFO* continuousbdchginfo;
2719 SCIP_Bool successgetreason;
2720 SCIP_Real coefresidx;
2721
2722 /* now both the reducedreasonrow and reasonrow are the rows before the reduction */
2723 SCIP_CALL( conflictRowReplace(reducedreasonrow, blkmem, reasonrow) );
2724
2725 coefresidx = reducedreasonrow->vals[residx];
2726
2727 /* In the following the reducedreasonrow is the aggregation of the different reasonrows of continuous bound changes */
2728 SCIP_CALL( slackReducingContinuousBdchgQueue(conflict, vars, reducedreasonrow, SCIPbdchginfoGetIdx(currbdchginfo)) );
2729
2730 if( SCIPpqueueNElems(conflict->continuousbdchgqueue) > 0 )
2731 {
2732 SCIPsetDebugMsgPrint(set, "Slack-reducing continuous variables in the reason row \n");
2733 SCIPdebug(printConflictRow(reducedreasonrow, set, vars, REASON_ROWTYPE));
2734 }
2735 else
2736 return SCIP_OKAY;
2737
2738 int nresconts = 0;
2739
2740 while( SCIPpqueueNElems(conflict->continuousbdchgqueue) > 0 )
2741 {
2742 nresconts++;
2743 if( nresconts > maxsize / 2 || reducedreasonrow->nnz > maxsize )
2744 {
2745 (*successresolution) = FALSE;
2746 conflict->nreslongconfs++;
2747 return SCIP_OKAY;
2748 }
2749 SCIPdebug(printAllBoundChanges(conflict, set, TRUE));
2750 continuousbdchginfo = (SCIP_BDCHGINFO*)(SCIPpqueueRemove(conflict->continuousbdchgqueue));
2751 assert(continuousbdchginfo != NULL);
2752
2753 int varidx = SCIPvarGetProbindex(SCIPbdchginfoGetVar(continuousbdchginfo));
2754
2755 /* get reason row of the latest bdchginfo */
2756 conflictRowClear(blkmem, reasonrow, nvars);
2757 SCIP_CALL( getReasonRow(blkmem, vars, set, continuousbdchginfo, reasonrow, varidx, fixbounds, fixsides,
2758 &successgetreason) );
2759 if( !successgetreason )
2760 {
2761 (*successresolution) = FALSE;
2762 return SCIP_OKAY;
2763 }
2764
2765 SCIPdebug(printConflictRow(reasonrow, set, vars, CONTINUOUS_REASON_ROWTYPE));
2766
2767 SCIPsetDebugMsgPrint(set, "Resolve slack-reducing continuous variable %s \n", SCIPvarGetName(vars[varidx]));
2768
2769 /* resolve the continuous variable */
2770 SCIP_CALL( rescaleAndResolve(set, conflict, reducedreasonrow, reasonrow, resolvedconflictrow, blkmem,
2771 varidx, successresolution) );
2772
2773 if( !(*successresolution) )
2774 return SCIP_OKAY;
2775
2776 /* if the coefficient of the variable we are resolving changed sign, then we have a new conflict constraint */
2777 if( SCIPsetIsLE(set, coefresidx * resolvedconflictrow->vals[residx], 0.0) )
2778 {
2779#ifndef SCIP_DEBUG
2780 SCIPsetDebugMsgPrint(set, "The sign of the coefficient of the variable we are resolving changed \n");
2781 SCIP_CALL( computeSlack(set, vars, resolvedconflictrow, currbdchginfo, fixbounds, fixsides) );
2782 assert(SCIPsetIsLT(set, resolvedconflictrow->slack, 0.0) || !isBinaryConflictRow(set, vars, reducedreasonrow));
2783#endif
2784 return SCIP_OKAY;
2785 }
2786
2787 SCIP_CALL( conflictRowReplace(reducedreasonrow, blkmem, resolvedconflictrow) );
2788
2789 SCIPdebug(printConflictRow(reducedreasonrow, set, vars, REDUCED_REASON_ROWTYPE));
2790 SCIP_CALL( slackReducingContinuousBdchgQueue(conflict, vars, reducedreasonrow, SCIPbdchginfoGetIdx(continuousbdchginfo)) );
2791 }
2792
2793 /* after the loop we can weaken all continuous variables with their global bounds */
2794 SCIP_CALL( weakenContinuousVarsConflictRow(reducedreasonrow, set, vars, residx) );
2795
2796 /* after resolving the continuous variables we resolve once more if the constraint is binary */
2797 if( nresconts > 0 )
2798 {
2799 /* apply reduction to the reason row */
2800 SCIP_CALL( reduceReason(set, blkmem, vars, nvars, reducedreasonrow, currbdchginfo, residx, fixbounds, fixsides) );
2801
2802 SCIPsetDebugMsgPrint(set, "Resolve %s after reducing the reason row \n", SCIPvarGetName(vars[residx]));
2803 /* after all reductions resolve one final time */
2804 SCIP_CALL( rescaleAndResolve(set, conflict, conflictrow, reducedreasonrow, resolvedconflictrow, blkmem,
2805 residx, successresolution) );
2806
2807 SCIP_CALL( computeSlack(set, vars, resolvedconflictrow, currbdchginfo, fixbounds, fixsides) );
2808 }
2809 }
2810 }
2811
2812 return SCIP_OKAY;
2813}
2814
2815/** If a bound change cannot be resolved, it is treated as a branching decision.
2816 * Subsequent bound changes for that variable are ignored by recording the variable's
2817 * index in fixsides and its bound type in fixbounds (1 for upper, -1 for lower).
2818 */
2819static
2821 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2822 SCIP_SET* set, /**< global SCIP settings */
2823 SCIP_VAR** vars, /**< array of variables */
2824 SCIP_BDCHGINFO** currbdchginfo, /**< pointer to current bound change to resolve */
2825 int* currbdchgdepth, /**< pointer to store the depth of the bound change */
2826 int nressteps, /**< number of bound changes that have been resolved so far */
2827 SCIP_Real* fixbounds, /**< dense array of fixed bounds */
2828 int* fixsides, /**< dense array of variables fixed to a bound */
2829 SCIP_Bool* success /**< pointer to store whether the bound change was ignored */
2830 )
2831{
2832 SCIP_VAR* var;
2833 int varidx;
2834 SCIP_BOUNDTYPE boundtype;
2835 SCIP_BOUNDCHGTYPE bdchgtype;
2836
2837 assert(conflict != NULL);
2838 assert(set != NULL);
2839 assert(vars != NULL);
2840 assert(*currbdchginfo != NULL);
2841 assert(currbdchgdepth != NULL);
2842 assert(fixbounds != NULL);
2843 assert(fixsides != NULL);
2844
2845 *success = FALSE;
2846
2847 /* If the bound change is due to constraint inference, ensure it comes from a global constraint */
2849 {
2850 SCIP_CONS* reasoncon = SCIPbdchginfoGetInferCons(*currbdchginfo);
2851 if( !SCIPconsIsGlobal(reasoncon) )
2852 return SCIP_OKAY;
2853 }
2854
2855 if( !existsResolvablebdchginfo(conflict) )
2856 return SCIP_OKAY;
2857
2858 var = SCIPbdchginfoGetVar(*currbdchginfo);
2859 varidx = SCIPvarGetProbindex(var);
2860
2861 /* If a bound for this variable has already been ignored, abort */
2862 if( fixsides[varidx] != 0 )
2863 return SCIP_OKAY;
2864
2865 boundtype = SCIPbdchginfoGetBoundtype(*currbdchginfo);
2866 bdchgtype = SCIPbdchginfoGetChgtype(*currbdchginfo);
2867
2868 /* Record the ignored bound change: 1 for upper, -1 for lower */
2869 fixsides[varidx] = (boundtype == SCIP_BOUNDTYPE_UPPER) ? 1 : -1;
2870 fixbounds[varidx] = SCIPbdchginfoGetNewbound(*currbdchginfo);
2871
2872 /* Reset conflict bounds to allow weaker bounds to be added later */
2873 if( boundtype == SCIP_BOUNDTYPE_LOWER )
2874 conflict->conflictvarslbs[varidx] = SCIP_REAL_MIN;
2875 else
2876 conflict->conflictvarsubs[varidx] = SCIP_REAL_MAX;
2877
2878 SCIPsetDebugMsgPrint(set, "ignoring the latest bound change of variable %s to %f\n",
2879 SCIPvarGetName(var), SCIPbdchginfoGetNewbound(*currbdchginfo));
2880
2881 if( nressteps == 0 )
2882 SCIP_CALL( updateBdchgQueue(set, vars, conflict->conflictrow, SCIPbdchginfoGetIdx(*currbdchginfo)) );
2883
2884 *currbdchginfo = conflictFirstCand(set, conflict, FALSE);
2885 assert(*currbdchginfo != NULL);
2886
2887 /* Extract the latest bound change from the candidate queue */
2888 *currbdchginfo = conflictRemoveCand(conflict, FALSE);
2889
2890 /* If no resolution step has been applied and the bound change is a branching decision,
2891 * update the last bound change depth.
2892 */
2893 if( nressteps == 0 && bdchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
2894 *currbdchgdepth = SCIPbdchginfoGetDepth(*currbdchginfo);
2895 else if( !set->conf_fixandcontinue )
2896 return SCIP_OKAY;
2897
2898#ifndef SCIP_DEBUG
2899 SCIP_CALL( computeSlack(set, vars, conflict->conflictrow, *currbdchginfo, fixbounds, fixsides) );
2900 assert(SCIPsetIsLT(set, conflict->conflictrow->slack, 0.0));
2901#endif
2902
2903 *success = TRUE;
2904 return SCIP_OKAY;
2905}
2906
2907/** add the conflict rows to the problem */
2908static
2910 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2911 BMS_BLKMEM* blkmem, /**< block memory */
2912 SCIP_SET* set, /**< global SCIP settings */
2913 SCIP_STAT* stat, /**< dynamic problem statistics */
2914 SCIP_PROB* transprob, /**< transformed problem */
2915 SCIP_PROB* origprob, /**< original problem */
2916 SCIP_TREE* tree, /**< branch and bound tree */
2917 SCIP_REOPT* reopt, /**< reoptimization data structure */
2918 SCIP_LP* lp, /**< current LP data */
2919 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2920 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2921 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
2922 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2923 int nconstoadd, /**< number of conflict constraints to add */
2924 int* nconss, /**< pointer to store the number of generated conflict constraints */
2925 int* nconfvars /**< pointer to store the number of variables in generated conflict constraints */
2926 )
2927{
2928 int i;
2929
2930 for( i = 0; i < nconstoadd; i++ )
2931 {
2932 SCIP_CONFLICTROW* conflictrowtoadd;
2933
2934 conflictrowtoadd = conflict->conflictrows[i];
2935 assert(SCIPsetIsLT(set, conflictrowtoadd->slack, 0.0));
2936
2937 if( SCIPsetIsLT(set, conflictrowtoadd->coefquotient, set->conf_maxcoefquot) )
2938 {
2939 SCIP_Bool success;
2940
2941 SCIP_CALL( SCIPconflictAddConflictCon(conflict, blkmem, set, stat, transprob, origprob, tree, reopt,
2942 lp, branchcand, eventqueue, eventfilter, cliquetable, conflictrowtoadd, &success) );
2943 if( success )
2944 {
2945 (*nconss)++;
2946 (*nconfvars) += conflictrowtoadd->nnz;
2947 }
2948 }
2949 }
2950 return SCIP_OKAY;
2951}
2952
2953/** Analyzes conflicting bound changes added via SCIPconflictAddBound().
2954 * This function performs generalized resolution conflict analysis by iteratively aggregating the
2955 * infeasible conflict row (conflictrow) with the reason row (reasonrow) that propagated the bound change.
2956 * In each iteration, the coefficient of the resolving variable is cancelled. If the aggregation does not
2957 * yield an infeasible row, MIR reduction is applied to the reason row and the aggregation is retried,
2958 * continuing until a first unique implication point (FUIP) is reached. On success, a linear conflict
2959 * constraint that explains the infeasibility is added to the problem.
2960 */
2962 SCIP_CONFLICT* conflict, /**< conflict analysis data */
2963 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2964 SCIP_SET* set, /**< global SCIP settings */
2965 SCIP_STAT* stat, /**< problem statistics */
2966 SCIP_PROB* transprob, /**< transformed problem */
2967 SCIP_PROB* origprob, /**< original problem */
2968 SCIP_TREE* tree, /**< branch and bound tree */
2969 SCIP_REOPT* reopt, /**< reoptimization data structure */
2970 SCIP_LP* lp, /**< LP data */
2971 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2972 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2973 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
2974 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2975 SCIP_ROW* initialconflictrow, /**< row of constraint that detected the conflict */
2976 int validdepth, /**< minimal depth level at which the initial conflict set is valid */
2977 int* nconss, /**< pointer to store the number of generated conflict constraints */
2978 int* nconfvars /**< pointer to store the number of variables in generated conflict constraints */
2979 )
2980{
2981 SCIP_CONFLICTROW *conflictrow;
2982 SCIP_CONFLICTROW *resolvedconflictrow;
2983
2984 SCIP_BDCHGINFO* bdchginfo;
2985 SCIP_BDCHGINFO* nextbdchginfo;
2986 SCIP_BDCHGIDX* bdchgidx;
2987
2988 int bdchgdepth;
2989 int lastuipdepth;
2990 int maxsize;
2991 int nchgcoefs;
2992 int nressteps;
2993 int nfuips;
2994 SCIP_Real* fixbounds;
2995 int* fixsides;
2996 SCIP_Bool successresolution;
2997 SCIP_Bool successgetconflict;
2998 SCIP_Bool successgetreason;
2999 int nvars;
3000 int i;
3001
3002 SCIP_VAR** vars;
3003 SCIP_VAR* vartoresolve;
3004 int residx;
3005
3006 assert(conflict != NULL);
3007 assert(set != NULL);
3008 assert(stat != NULL);
3009 assert(0 <= validdepth && validdepth <= SCIPtreeGetCurrentDepth(tree));
3011 assert(nconss != NULL);
3012 assert(nconfvars != NULL);
3013 assert(conflict->nconflictrows == 0);
3014
3015 assert(SCIPtreeGetCurrentDepth(tree) == tree->pathlen-1);
3016 assert(SCIPtreeGetFocusDepth(tree) <= SCIPtreeGetCurrentDepth(tree));
3017
3018 lastuipdepth = -1;
3019
3020 *nconss = 0;
3021 *nconfvars = 0;
3022
3023 /* todo implement local conflict analysis */
3024 if( validdepth > 0)
3025 return SCIP_OKAY;
3026
3027 vars = SCIPprobGetVars(transprob);
3028 nvars = transprob->nvars;
3029
3030 conflictrow = conflict->conflictrow;
3031 resolvedconflictrow = conflict->resolvedconflictrow;
3032
3033 /* clear the conflict, reason, resolved conflict rows */
3034 conflictRowClear(blkmem, conflict->conflictrow, nvars);
3035 conflictRowClear(blkmem, conflict->resolvedconflictrow, nvars);
3036 conflictRowClear(blkmem, conflict->reasonrow, nvars);
3037 conflictRowClear(blkmem, conflict->reducedreasonrow, nvars);
3038
3039 /* last bound change that led to infeasibility */
3040 bdchginfo = conflictFirstCand(set, conflict, TRUE);
3041
3042 /* if no bound change exists or none of them was infered by a resolvable
3043 constraint then we terminate */
3044 if( bdchginfo == NULL || !existsResolvablebdchginfo(conflict) )
3045 {
3046#ifdef SCIP_DEBUG
3047 /* if at least one bound change is in the queue, print them all */
3048 if( bdchginfo != NULL )
3049 printAllBoundChanges(conflict, set, FALSE);
3050#endif
3051 SCIPsetDebugMsgPrint(set, "Conflict analysis not applicable since no resolvable bounds exist \n");
3052 return SCIP_OKAY;
3053 }
3054
3055 /* remove the last bound change */
3056 bdchginfo = conflictRemoveCand(conflict, TRUE);
3057 bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
3058 bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
3059
3060 vartoresolve = SCIPbdchginfoGetVar(bdchginfo);
3061
3062 /* check if the variable we are resolving is active */
3063 assert(SCIPvarIsActive(vartoresolve));
3064
3065 /* calculate the maximal size of each accepted conflict set */
3066 maxsize = 2 * conflictCalcResMaxsize(set, transprob);
3067
3068 /* sets the initial conflictrow */
3069 SCIP_CALL( getConflictRow(conflict, blkmem, set, transprob, initialconflictrow, bdchginfo, maxsize, &successgetconflict) );
3070 /* if we could not get the conflict row, then we abort */
3071 if( !successgetconflict )
3072 {
3073 SCIPsetDebugMsgPrint(set, "Conflict analysis not applicable since no conflict row could be created \n");
3074 return SCIP_OKAY;
3075 }
3076
3077 /* before we resolve any bound change the resolved conflict row is the same as the conflict row */
3078 SCIP_CALL( conflictRowReplace(resolvedconflictrow, blkmem, conflictrow) );
3079
3080 /* Apply coefficient tightening to the conflict constraint should never hurt */
3081 SCIP_CALL( tightenCoefs(set, vars, FALSE, conflictrow->vals, conflictrow->inds,
3082 &conflictrow->nnz, &conflictrow->lhs, &nchgcoefs, NULL) );
3083
3084 if( nchgcoefs > 0 )
3085 {
3086 /* remove variables with zero coefficients from the conflict row */
3087 conflictRowRemoveZeroVars(conflictrow, set);
3088
3089 SCIP_CALL( computeSlack(set, vars, conflictrow, bdchginfo, NULL, NULL) );
3090 /* the slack after coefficient tightening must also be negative */
3091 assert(SCIPsetIsLT(set, conflictrow->slack, 0.0));
3092 }
3093
3094 conflictrow->coefquotient = getQuotLargestSmallestCoef(set, conflictrow->inds, conflictrow->vals, conflictrow->nnz);
3095
3096 nressteps = 0;
3097 nfuips = 0;
3098
3099 /* initialize indices and bounds for the unresolvable bound changes */
3100 SCIP_CALL( SCIPsetAllocBufferArray(set, &fixsides, nvars) );
3101 SCIP_CALL( SCIPsetAllocBufferArray(set, &fixbounds, nvars) );
3102
3103 /* set value in fixsides to 0 to indicate that a variable is not fixed
3104 * if a variable is set at an upper bound, then the value is 1
3105 * if a variable is set at a lower bound, then the value is -1
3106 */
3107 for( i = 0; i < nvars; ++i )
3108 fixsides[i] = 0;
3109
3110 /* main loop:
3111 * --------------------------------
3112 * - we start with the initial conflict row and the first bound change to
3113 * resolve
3114 * --------------------------------
3115 * - Fix & Continue: if we can't explain/resolve the bound change, i.e. the reason
3116 * is a branching or non-linear then we ignore(fix) it and continue with the
3117 * next bound change. We have to ignore all other bound changes for
3118 * this variable (resolve with no-good)
3119 * - if the bound change is resolvable:
3120 * - get the reason row for the bound change
3121 * - if needed apply the MIR reduction to the reason
3122 * - take the linear combination of the conflict row and the reason row
3123 * - apply coefficient tightening to the resolved row
3124 * - if there is no other bound change in the queue from the same depth level
3125 * then we are at a UIP
3126 * - keep this constraint and either terminate 1-FUIP resolution or continue
3127 * with the next bound change
3128 */
3129 while( TRUE ) /*lint !e716*/
3130 {
3131#ifdef SCIP_DEBUG
3132 {
3133 SCIPsetDebugMsgPrint(set, "\nResolution Iteration: %d \n", nressteps);
3134 SCIPsetDebugMsgPrint(set, "Current bound change already removed from the queue: \n");
3135 printSingleBoundChange(set, bdchginfo);
3136 printAllBoundChanges(conflict, set, FALSE);
3137 }
3138#endif
3139
3140 if( !isResolvableBdchg(bdchginfo) )
3141 {
3142 SCIP_Bool successfixing;
3143
3144#ifdef SCIP_DEBUG
3145 printNonResolvableReasonType(set, bdchginfo);
3146#endif
3147 SCIP_CALL( markBdchgAsFixed(conflict, set, vars, &bdchginfo, &bdchgdepth, nressteps,
3148 fixbounds, fixsides, &successfixing) );
3149 if( !successfixing )
3150 goto TERMINATE_RESOLUTION_LOOP;
3151
3152 assert(bdchginfo != NULL);
3153
3154 /* get the current bound change index */
3155 bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
3156
3157 vartoresolve = SCIPbdchginfoGetVar(bdchginfo);
3158 /* check if the variable we are resolving is active */
3159 assert(SCIPvarIsActive(vartoresolve));
3160 }
3161
3162 /* here is the generalized resolution iteration */
3163 else
3164 {
3165 residx = SCIPvarGetProbindex(vartoresolve);
3166
3167 conflictRowClear(blkmem, conflict->reasonrow, nvars);
3168
3169 /* get reason row of the latest bdchginfo */
3170 SCIP_CALL( getReasonRow(blkmem, vars, set, bdchginfo, conflict->reasonrow, residx, fixbounds, fixsides,
3171 &successgetreason) );
3172 if( !successgetreason )
3173 {
3174 SCIPsetDebugMsgPrint(set, "Could not obtain reason row for bound change \n");
3175 goto TERMINATE_RESOLUTION_LOOP;
3176 }
3177
3178 SCIPdebug(printConflictRow(conflictrow, set, vars, CONFLICT_ROWTYPE));
3179 SCIPdebug(printConflictRow(conflict->reasonrow, set, vars, REASON_ROWTYPE));
3180
3181 successresolution = FALSE;
3182
3183 /* call resolution */
3184 SCIPsetDebugMsgPrint(set, " Applying resolution with resolving variable <%s>\n", SCIPvarGetName(vartoresolve));
3185 SCIP_CALL( executeResolutionStep(conflict, set, vars, blkmem, bdchginfo, residx, maxsize, fixbounds, fixsides, &successresolution ) );
3186
3187 /* todo we can strengthen the conflict row by applying MIR */
3188 if( successresolution )
3189 SCIP_CALL( conflictRowReplace(conflictrow, blkmem, resolvedconflictrow) );
3190 else
3191 goto TERMINATE_RESOLUTION_LOOP;
3192
3193 /* we must reset the conflict lower and upper bound to be able to add weaker bounds later */
3195 conflict->conflictvarslbs[residx] = SCIP_REAL_MIN;
3196 else
3197 conflict->conflictvarsubs[residx] = SCIP_REAL_MAX;
3198
3199 if( conflictrow->nnz > maxsize )
3200 {
3201 SCIPsetDebugMsgPrint(set, "Number of nonzeros in conflict is larger than maxsize %d > %d\n",
3202 conflictrow->nnz, maxsize);
3203 weakenConflictRow(conflictrow, set, vars, bdchgidx, fixsides);
3204 if( conflictrow->nnz > maxsize )
3205 {
3206 conflict->nreslongconfs++;
3207 goto TERMINATE_RESOLUTION_LOOP;
3208 }
3209#ifdef SCIP_DEBUG
3210 SCIP_Real oldslack;
3211 oldslack = conflictrow->slack;
3212 SCIP_CALL( computeSlack(set, vars, conflictrow, bdchginfo, fixbounds, fixsides) );
3213 assert(SCIPsetIsEQ(set, conflictrow->slack, oldslack));
3214#endif
3215 }
3216
3217 SCIPsetDebugMsgPrint(set, "Slack of resolved row: %f \n", conflictrow->slack);
3218
3219 SCIPdebug(printConflictRow(conflictrow, set, vars, RESOLVED_CONFLICT_ROWTYPE));
3220
3221 /* A positive slack means that the conflict row is not infeasible anymore.
3222 * Unfortunately we cannot guarrante that the slack becomes zero after reducing
3223 * the reason (even if we have only binary variables).
3224 * Two issues are non-linear propagations, e.g.
3225 * - Knapsack constraints that use negated cliques in the propagation
3226 * - Ranged row propagation (gcd argument)
3227 */
3228 if( SCIPsetIsGE(set, conflictrow->slack, 0.0) )
3229 goto TERMINATE_RESOLUTION_LOOP;
3230
3231 nressteps++;
3232
3233 /* apply coefficient tightening to the resolved constraint should never hurt */
3234 SCIP_CALL( tightenCoefs(set, vars, FALSE, conflictrow->vals, conflictrow->inds,
3235 &conflictrow->nnz, &conflictrow->lhs, &nchgcoefs, NULL) );
3236 if( nchgcoefs > 0 )
3237 {
3238 SCIP_Real previousslack;
3239
3240 /* remove variables with zero coefficients from the conflict row */
3241 conflictRowRemoveZeroVars(conflictrow, set);
3242
3243 /* The new slack should always be less or equal to the old slack */
3244 previousslack = conflictrow->slack;
3245 SCIP_CALL( computeSlack(set, vars, conflictrow, bdchginfo, fixbounds, fixsides) );
3246 SCIPsetDebugMsgPrint(set, "Tightened %d coefficients in the resolved constraint, old slack %f, new slack %f \n", nchgcoefs, previousslack, conflictrow->slack);
3247 assert(SCIPsetIsLE(set, conflictrow->slack, previousslack + EPS) || SCIPsetIsRelLE(set, conflictrow->slack, previousslack));
3248 SCIPdebug(printConflictRow(conflictrow, set, vars, CONFLICT_ROWTYPE));
3249 }
3250
3251 /* if we reached this point the conflict constraint must have negative slack */
3252 assert(SCIPsetIsLT(set, conflictrow->slack, 0.0));
3253
3254 SCIP_CALL( updateBdchgQueue(set, vars, conflictrow, bdchgidx) );
3255
3256 /* get the next bound change */
3257 bdchginfo = conflictFirstCand(set, conflict, FALSE);
3258
3259 /* if no bound change exists the we should stop */
3260 /* in case we have applied resolution steps we keep the last conflict constraint */
3261 if( bdchginfo == NULL )
3262 {
3263 /* this can happen only if we already have resolved and some
3264 and it means that we have already reached a FUIP */
3265 SCIPsetDebugMsgPrint(set, " reached UIP in depth %d \n", bdchgdepth);
3266 /* add the previous conflict in the list of conflict rows */
3267 conflictrow->validdepth = validdepth;
3268 conflictrow->conflictdepth = bdchgdepth;
3269 conflictrow->insertdepth = validdepth;
3270 conflictrow->repropdepth = MAX(0, validdepth);
3271 SCIP_CONFLICTROW* tmpconflictrow;
3272 SCIP_CALL( conflictRowCopy(&tmpconflictrow, blkmem, conflictrow) );
3273 SCIP_CALL( conflictInsertConflictRow(conflict, set, &tmpconflictrow) );
3274 goto TERMINATE_RESOLUTION_LOOP;
3275 }
3276
3277 bdchginfo = conflictRemoveCand(conflict, FALSE);
3278 bdchgidx = SCIPbdchginfoGetIdx(bdchginfo);
3279 vartoresolve = SCIPbdchginfoGetVar(bdchginfo);
3280 bdchgdepth = SCIPbdchginfoGetDepth(bdchginfo);
3281
3282 residx = SCIPvarGetProbindex(vartoresolve);
3283
3284 assert(!SCIPsetIsZero(set, conflictrow->vals[residx]));
3285
3286 /* get the bound change before bdchginfo */
3287 nextbdchginfo = conflictFirstCand(set, conflict, FALSE);
3288
3289 /* check if the variable we are resolving is active */
3290 assert(SCIPvarIsActive(vartoresolve));
3291
3292 assert(nextbdchginfo == NULL || SCIPbdchginfoGetDepth(nextbdchginfo) <= bdchgdepth);
3293
3294 /* when at an UIP add the previous conflict in the list of conflict rows */
3295 if( (nextbdchginfo == NULL || SCIPbdchginfoGetDepth(nextbdchginfo) != bdchgdepth )
3296 && SCIPbdchginfoGetDepth(bdchginfo) != lastuipdepth)
3297 {
3298 SCIPsetDebugMsgPrint(set, " reached UIP in depth %d \n", bdchgdepth);
3299 /* add the previous conflict in the list of conflict rows */
3300 conflictrow->validdepth = validdepth;
3301 conflictrow->conflictdepth = bdchgdepth;
3302 conflictrow->insertdepth = validdepth;
3303 conflictrow->repropdepth = (nextbdchginfo == NULL) ? 0 : SCIPbdchginfoGetDepth(nextbdchginfo);
3304 SCIP_CONFLICTROW* tmpconflictrow;
3305 SCIP_CALL( conflictRowCopy(&tmpconflictrow, blkmem, conflictrow) );
3306 SCIP_CALL( conflictInsertConflictRow(conflict, set, &tmpconflictrow) );
3307 lastuipdepth = bdchgdepth;
3308 nfuips++;
3309 /* stop after conf_resfuiplevels UIPs */
3310 if( set->conf_resfuiplevels > 0 && nfuips >= set->conf_resfuiplevels )
3311 goto TERMINATE_RESOLUTION_LOOP;
3312 }
3313 }
3314 }
3315
3316 TERMINATE_RESOLUTION_LOOP:
3317
3318 if( conflict->nconflictrows > 0 )
3319 {
3320 int nconstoadd;
3321
3322 nconstoadd = (set->conf_resfuiplevels > 0) ? MIN(set->conf_resfuiplevels, conflict->nconflictrows) : conflict->nconflictrows;
3323
3324 SCIP_CALL( addConflictRows(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
3325 eventfilter, cliquetable, nconstoadd, nconss, nconfvars) );
3326 }
3327
3328 freeConflictResources(conflict, blkmem, set, fixbounds, fixsides);
3329
3330 return SCIP_OKAY;
3331}
3332
3333/** analyzes conflicting bound changes that were added with calls to SCIPconflictAddBound(), and on success,
3334 * creates a linear constraint that explains the infeasibility
3335 */
3337 SCIP_CONFLICT* conflict, /**< conflict analysis data */
3338 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3339 SCIP_SET* set, /**< global SCIP settings */
3340 SCIP_STAT* stat, /**< problem statistics */
3341 SCIP_PROB* transprob, /**< transformed problem */
3342 SCIP_PROB* origprob, /**< original problem */
3343 SCIP_TREE* tree, /**< branch and bound tree */
3344 SCIP_REOPT* reopt, /**< reoptimization data structure */
3345 SCIP_LP* lp, /**< LP data */
3346 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3347 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3348 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
3349 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3350 SCIP_ROW* initialconflictrow, /**< row of constraint that detected the conflict */
3351 int validdepth, /**< minimal depth level at which the initial conflict set is valid */
3352 SCIP_Bool* success /**< pointer to store whether a conflict constraint was created, or NULL */
3353 )
3354{
3355 int nconss;
3356 int nconfvars;
3357 int i;
3358
3359 /* check if generalized resolution conflict analysis is applicable */
3361 return SCIP_OKAY;
3362
3363 assert(conflict != NULL);
3364 assert(set != NULL);
3365 assert(origprob != NULL);
3366 assert(transprob != NULL);
3367
3368 if( success != NULL )
3369 *success = FALSE;
3370
3371 SCIPsetDebugMsgPrint(set, "Starting resolution based conflict analysis after infeasible propagation in depth %d\n",
3373
3374 /* start timing */
3375 SCIPclockStart(conflict->resanalyzetime, set);
3376
3377 conflict->nrescalls++;
3378
3379 /* setting this to true adds bound changes only to the resolution bdchg queue */
3380 conflict->bdchgonlyresqueue = TRUE;
3381
3382 /* analyze the conflict set, and create a conflict constraint on success */
3383 SCIP_CALL( conflictAnalyzeResolution(conflict, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
3384 eventfilter, cliquetable, initialconflictrow, validdepth, &nconss, &nconfvars) );
3385
3386 conflict->nressuccess += (nconss > 0 ? 1 : 0);
3387 conflict->nresconfconss += nconss;
3388 conflict->nresconfvariables += nconfvars;
3389
3390 if( success != NULL )
3391 *success = (nconss > 0);
3392
3393 /* free all conflictrows */
3394 for( i = 0; i < conflict->nconflictrows; i++ )
3395 SCIPconflictRowFree(&conflict->conflictrows[i], blkmem);
3396
3397 conflict->nconflictrows = 0;
3398 conflict->bdchgonlyresqueue = FALSE;
3399
3400 /* clear the bound change queues */
3401 SCIPpqueueClear(conflict->resbdchgqueue);
3403
3404 /* stop timing */
3405 SCIPclockStop(conflict->resanalyzetime, set);
3406 SCIPsetDebugMsgPrint(set, "resolution based conflict analysis added %d constraints \n \n", nconss);
3407
3408 return SCIP_OKAY;
3409}
static long bound
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:360
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:290
internal methods for clocks and timing issues
internal methods for conflict analysis
static void conflictRowRemoveZeroVars(SCIP_CONFLICTROW *row, SCIP_SET *set)
static SCIP_RETCODE conflictEnsureConflictRowsMem(SCIP_CONFLICT *conflict, SCIP_SET *set, int num)
static SCIP_Real getQuotLargestSmallestCoef(SCIP_SET *set, int *inds, SCIP_Real *vals, int nnz)
static void conflictRowClear(BMS_BLKMEM *blkmem, SCIP_CONFLICTROW *row, int nvars)
static SCIP_RETCODE updateStatistics(SCIP_CONFLICT *conflict, SCIP_VAR **vars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_CONFLICTROW *conflictrow, int insertdepth)
static void weakenConflictRow(SCIP_CONFLICTROW *row, SCIP_SET *set, SCIP_VAR **vars, SCIP_BDCHGIDX *currbdchgidx, int *fixsides)
static void weakenVarConflictRow(SCIP_CONFLICTROW *row, SCIP_SET *set, SCIP_VAR *var, int pos)
static SCIP_RETCODE conflictInsertConflictRow(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_CONFLICTROW **conflictrow)
static SCIP_Bool isBdchgConflictRelevant(SCIP_CONFLICT *conflict, SCIP_BDCHGINFO *bdchginfo, int initial)
void SCIPconflictRowFree(SCIP_CONFLICTROW **row, BMS_BLKMEM *blkmem)
static void linearCombRows(SCIP_SET *set, SCIP_CONFLICTROW *row1, SCIP_CONFLICTROW *row2, SCIP_Real scale)
static SCIP_Real computeScaleReason(SCIP_SET *set, SCIP_CONFLICTROW *conflictrow, SCIP_CONFLICTROW *reasonrow, int residx)
#define BOUNDSWITCH
SCIP_RETCODE SCIPconflictAddConflictCon(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_CONFLICTROW *conflictrow, SCIP_Bool *success)
static int conflictCalcResMaxsize(SCIP_SET *set, SCIP_PROB *prob)
static SCIP_RETCODE updateBdchgQueue(SCIP_SET *set, SCIP_VAR **vars, SCIP_CONFLICTROW *conflictrow, SCIP_BDCHGIDX *inferbdchgidx)
static SCIP_Bool isResolvableBdchg(SCIP_BDCHGINFO *bdchginfo)
#define MAXFRAC
static SCIP_Bool existsResolvablebdchginfo(SCIP_CONFLICT *conflict)
static SCIP_RETCODE weakenContinuousVarsConflictRow(SCIP_CONFLICTROW *row, SCIP_SET *set, SCIP_VAR **vars, int residx)
#define POSTPROCESS
SCIP_RETCODE conflictAnalyzeResolution(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_ROW *initialconflictrow, int validdepth, int *nconss, int *nconfvars)
SCIP_Longint SCIPconflictGetNResConflictConss(SCIP_CONFLICT *conflict)
static void conflictRowRemoveZeroVar(SCIP_CONFLICTROW *row, SCIP_SET *set, int pos)
static SCIP_RETCODE conflictRowReplace(SCIP_CONFLICTROW *targetrow, BMS_BLKMEM *blkmem, SCIP_CONFLICTROW *sourcerow)
static SCIP_BDCHGINFO * conflictFirstCand(SCIP_SET *set, SCIP_CONFLICT *conflict, int initial)
SCIP_Longint SCIPconflictGetNResLargeCoefs(SCIP_CONFLICT *conflict)
static SCIP_RETCODE addConflictRows(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, int nconstoadd, int *nconss, int *nconfvars)
static SCIP_RETCODE MirReduction(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **vars, int nvars, SCIP_CONFLICTROW *reasonrow, SCIP_BDCHGINFO *currbdchginfo, int varidx, SCIP_Real divisor)
static SCIP_RETCODE getReasonRow(BMS_BLKMEM *blkmem, SCIP_VAR **vars, SCIP_SET *set, SCIP_BDCHGINFO *currbdchginfo, SCIP_CONFLICTROW *reasonrow, int residx, SCIP_Real *fixbounds, int *fixsides, SCIP_Bool *success)
static SCIP_RETCODE conflictRowFromLpRow(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_CONFLICTROW *conflictrow, SCIP_BDCHGINFO *bdchginfo)
SCIP_Longint SCIPconflictGetNResSuccess(SCIP_CONFLICT *conflict)
#define EPS
SCIP_Longint SCIPconflictGetNResCalls(SCIP_CONFLICT *conflict)
static SCIP_Bool hasRelaxationOnlyVar(SCIP_SET *set, SCIP_VAR **vars, SCIP_CONFLICTROW *row)
static SCIP_RETCODE conflictRowAddSemiSparseData(SCIP_CONFLICTROW *resolutionrow, BMS_BLKMEM *blkmem, SCIP_Real *vals, int *inds, int nnz, SCIP_Real lhs, SCIP_Bool reverse)
SCIP_RETCODE SCIPconflictInitRows(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem)
#define FIXINTEGRALRHS
static SCIP_RETCODE getConflictRow(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_ROW *initialconflictrow, SCIP_BDCHGINFO *currbdchginfo, int maxsize, SCIP_Bool *success)
static SCIP_RETCODE ComplementedMirLhs(SCIP_SET *set, SCIP_VAR **vars, SCIP_CONFLICTROW *reasonrow, int *fixsides, SCIP_BDCHGIDX *currbdchgidx, int idxreason, SCIP_Real divisor)
static SCIP_RETCODE slackReducingContinuousBdchgQueue(SCIP_CONFLICT *conflict, SCIP_VAR **vars, SCIP_CONFLICTROW *row, SCIP_BDCHGIDX *inferbdchgidx)
#define USEVBDS
static void freeConflictResources(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *fixbounds, int *fixsides)
static SCIP_RETCODE incVSIDS(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BOUNDTYPE boundtype, SCIP_Real value, SCIP_Real weight)
static SCIP_RETCODE reduceReason(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **vars, int nvars, SCIP_CONFLICTROW *rowtoreduce, SCIP_BDCHGINFO *currbdchginfo, int residx, SCIP_Real *fixbounds, int *fixsides)
SCIP_Longint SCIPconflictGetNResLongConflicts(SCIP_CONFLICT *conflict)
SCIP_Bool SCIPconflictResolutionApplicable(SCIP_SET *set)
static SCIP_Bool isBinaryConflictRow(SCIP_SET *set, SCIP_VAR **vars, SCIP_CONFLICTROW *row)
#define MINFRAC
static SCIP_RETCODE conflictRowCopy(SCIP_CONFLICTROW **targetrow, BMS_BLKMEM *blkmem, SCIP_CONFLICTROW *sourcerow)
static SCIP_BDCHGINFO * conflictRemoveCand(SCIP_CONFLICT *conflict, int initial)
static SCIP_RETCODE computeSlack(SCIP_SET *set, SCIP_VAR **vars, SCIP_CONFLICTROW *row, SCIP_BDCHGINFO *currbdchginfo, SCIP_Real *fixbounds, int *fixsides)
static SCIP_RETCODE tightenCoefs(SCIP_SET *set, SCIP_VAR **vars, SCIP_Bool localbounds, SCIP_Real *rowcoefs, int *rowinds, int *rownnz, SCIP_Real *rowlhs, int *nchgcoefs, SCIP_Bool *redundant)
SCIP_RETCODE SCIPconflictAnalyzeResolution(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_ROW *initialconflictrow, int validdepth, SCIP_Bool *success)
static SCIP_RETCODE markBdchgAsFixed(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_VAR **vars, SCIP_BDCHGINFO **currbdchginfo, int *currbdchgdepth, int nressteps, SCIP_Real *fixbounds, int *fixsides, SCIP_Bool *success)
static SCIP_RETCODE executeResolutionStep(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_VAR **vars, BMS_BLKMEM *blkmem, SCIP_BDCHGINFO *currbdchginfo, int residx, int maxsize, SCIP_Real *fixbounds, int *fixsides, SCIP_Bool *successresolution)
static SCIP_RETCODE createAndAddConflictCon(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **vars, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_CONFLICTROW *conflictrow, int insertdepth, SCIP_Bool *success)
static SCIP_RETCODE rescaleAndResolve(SCIP_SET *set, SCIP_CONFLICT *conflict, SCIP_CONFLICTROW *row1, SCIP_CONFLICTROW *row2, SCIP_CONFLICTROW *resolvedrow, BMS_BLKMEM *blkmem, int residx, SCIP_Bool *success)
static SCIP_RETCODE reasonRowFromLpRow(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_CONFLICTROW *reasonrow, SCIP_BDCHGINFO *bdchginfo)
static SCIP_RETCODE conflictRowCreate(SCIP_CONFLICTROW **row, BMS_BLKMEM *blkmem)
Methods for generalized resolution conflict analysis.
internal methods for constraints and constraint handlers
Constraint handler for linear constraints in their most general form, .
methods for the aggregation rows
#define SCIPquadprecProdDD(r, a, b)
Definition: dbldblarith.h:58
#define SCIPquadprecProdQD(r, a, b)
Definition: dbldblarith.h:63
#define SCIPquadprecSumQD(r, a, b)
Definition: dbldblarith.h:62
#define QUAD_ASSIGN(a, constant)
Definition: dbldblarith.h:51
#define QUAD(x)
Definition: dbldblarith.h:47
#define SCIPquadprecSumDD(r, a, b)
Definition: dbldblarith.h:60
#define SCIPquadprecSumQQ(r, a, b)
Definition: dbldblarith.h:67
#define QUAD_ARRAY_LOAD(r, a, idx)
Definition: dbldblarith.h:54
#define QUAD_TO_DBL(x)
Definition: dbldblarith.h:49
#define SCIPdebugCheckConss(scip, conss, nconss)
Definition: debug.h:296
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_UNUSED(x)
Definition: def.h:409
#define SCIP_REAL_MAX
Definition: def.h:158
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_ALLOC(x)
Definition: def.h:366
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_CALL_ABORT(x)
Definition: def.h:334
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define SCIPABORT()
Definition: def.h:327
#define SCIP_REAL_MIN
Definition: def.h:159
#define REALABS(x)
Definition: def.h:182
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
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)
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2569
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS **cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3806
void ** SCIPpqueueElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1540
void SCIPpqueueClear(SCIP_PQUEUE *pqueue)
Definition: misc.c:1335
SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1396
int SCIPpqueueNElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1529
void * SCIPpqueueRemove(SCIP_PQUEUE *pqueue)
Definition: misc.c:1495
void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
Definition: misc.c:1515
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17425
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4316
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8409
SCIP_Bool SCIPconsIsGlobal(SCIP_CONS *cons)
Definition: cons.c:8618
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8389
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_RETCODE SCIPcalcMIR(SCIP *scip, SCIP_SOL *sol, SCIP_Bool postprocess, SCIP_Real boundswitch, int vartypeusevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real scale, 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:7923
SCIP_RETCODE SCIPaggrRowCreate(SCIP *scip, SCIP_AGGRROW **aggrrow)
Definition: cuts.c:2668
SCIP_RETCODE SCIPaggrRowAddCustomCons(SCIP *scip, SCIP_AGGRROW *aggrrow, int *inds, SCIP_Real *vals, int len, SCIP_Real rhs, SCIP_Real weight, int rank, SCIP_Bool local)
Definition: cuts.c:3143
void SCIPaggrRowFree(SCIP *scip, SCIP_AGGRROW **aggrrow)
Definition: cuts.c:2700
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip_mem.h:137
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:8493
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:951
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17686
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:17607
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17632
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17696
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17745
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17652
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17642
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:516
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:1252
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip_sol.c:1571
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:25057
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:23642
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24979
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:22629
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:25013
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24959
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:25001
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24969
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2872
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:23662
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24929
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24909
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24939
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:23600
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:22685
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2736
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:24736
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24949
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24919
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:24716
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:674
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:635
internal methods for branching and inference history
memory allocation routines
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:127
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:468
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
SCIP_RETCODE SCIPconsCreateRow(SCIP *scip, SCIP_CONS *cons, SCIP_ROW **row)
Definition: misc_linear.c:599
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2913
internal methods for storing and manipulating the main problem
internal methods for propagators
public methods for conflict analysis handlers
public methods for managing constraints
public methods for LP management
public methods for message output
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugMessage
Definition: pub_message.h:96
#define SCIPdebugPrintf
Definition: pub_message.h:99
public data structures and miscellaneous methods
public methods for problem variables
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for memory management
public methods for global and local (sub)problems
public methods for solutions
public methods for SCIP variables
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6716
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6617
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6728
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:7017
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6648
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6577
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6537
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6380
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6557
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6515
SCIP_Bool SCIPsetIsRelGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:7559
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6597
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6637
SCIP_Bool SCIPsetIsRelLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:7511
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:6080
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6659
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1782
#define SCIPsetDebugMsgPrint
Definition: set.h:1812
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1775
#define SCIPsetDebugMsg
Definition: set.h:1811
internal methods for storing primal CIP solutions
SCIP_Real * vals
Definition: struct_cuts.h:42
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:126
SCIP_VAR * var
Definition: struct_var.h:125
SCIP_Real coefquotient
unsigned int isbinary
SCIP_CONFTYPE conflicttype
unsigned int usescutoffbound
SCIP_Real * conflictvarsubs
SCIP_Longint nappliedglbconss
SCIP_CONFLICTROW ** conflictrows
SCIP_PQUEUE * resbdchgqueue
SCIP_Longint nappliedglbliterals
SCIP_Longint nresconfconss
SCIP_Longint nappliedglbresconss
SCIP_CONFLICTROW * resolvedconflictrow
SCIP_CONFLICTROW * reducedreasonrow
SCIP_Longint nreslongconfs
SCIP_Longint nresconfvariables
SCIP_Longint nappliedlocconss
SCIP_CLOCK * resanalyzetime
SCIP_PQUEUE * continuousbdchgqueue
SCIP_CONFLICTROW * conflictrow
SCIP_Bool bdchgonlyresqueue
SCIP_CONFLICTROW * reasonrow
SCIP_Longint nrescalls
SCIP_Real * conflictvarslbs
SCIP_Longint nressuccess
SCIP_Longint nreslargecoefs
SCIP_Longint nappliedlocliterals
SCIP_CONSHDLR * conshdlr
Definition: struct_cons.h:50
SCIP_Bool strongbranching
Definition: struct_lp.h:383
SCIP_Bool diving
Definition: struct_lp.h:386
int ncontvars
Definition: struct_prob.h:80
SCIP_VAR ** vars
Definition: struct_prob.h:67
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:195
SCIP_Real vsidsweight
Definition: struct_stat.h:134
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:196
SCIP_NODE ** path
Definition: struct_tree.h:190
datastructures for conflict analysis
data structures for LP management
datastructures for storing and manipulating the main problem
datastructures for global SCIP settings
datastructures for problem statistics
Definition: heur_padm.c:135
int SCIPtreeGetFocusDepth(SCIP_TREE *tree)
Definition: tree.c:9404
SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition: tree.c:2539
SCIP_RETCODE SCIPnodeCutoff(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_REOPT *reopt, SCIP_LP *lp, BMS_BLKMEM *blkmem)
Definition: tree.c:1259
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:9479
internal methods for branch and bound tree
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:62
@ SCIP_BRANCHDIR_DOWNWARDS
Definition: type_history.h:43
@ SCIP_BRANCHDIR_UPWARDS
Definition: type_history.h:44
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:48
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:60
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:135
@ SCIP_VARTYPE_INTEGER
Definition: type_var.h:65
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:64
@ SCIP_BOUNDCHGTYPE_PROPINFER
Definition: type_var.h:133
@ SCIP_BOUNDCHGTYPE_BRANCHING
Definition: type_var.h:131
@ SCIP_BOUNDCHGTYPE_CONSINFER
Definition: type_var.h:132
SCIP_RETCODE SCIPvarIncVSIDS(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
Definition: var.c:21103
int SCIPbdchgidxGetDepth(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:24859
SCIP_RETCODE SCIPvarIncNActiveConflicts(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real length)
Definition: var.c:21239
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:24849
internal methods for problem variables