Scippy

SCIP

Solving Constraint Integer Programs

conflict_dualproofanalysis.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_dualproofanalysis.c
26 * @ingroup OTHER_CFILES
27 * @brief internal methods for dual proof conflict analysis
28 * @author Timo Berthold
29 * @author Jakob Witzig
30 * @author Sander Borst
31 *
32 * In dual proof analysis, an infeasible LP relaxation is analysed.
33 * Using the dual solution, a valid constraint is derived that is violated
34 * by all values in the domain. This constraint is added to the problem
35 * and can then be used for domain propagation. More details can be found in [1]
36 *
37 * [1] J. Witzig, T. Berthold, en S. Heinz, ‘Computational aspects of infeasibility analysis in mixed integer programming’,
38 * Math. Prog. Comp., mrt. 2021, doi: 10.1007/s12532-021-00202-0.
39 */
40
41/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
42
43#include "lpi/lpi.h"
44#include "scip/certificate.h"
45#include "scip/clock.h"
48#include "scip/conflictstore.h"
49#include "scip/cons.h"
50#include "scip/cons_linear.h"
52#include "scip/cuts.h"
53#include "scip/history.h"
54#include "scip/lp.h"
55#include "scip/presolve.h"
56#include "scip/prob.h"
57#include "scip/prop.h"
58#include "scip/pub_conflict.h"
59#include "scip/pub_cons.h"
60#include "scip/pub_lp.h"
61#include "scip/pub_message.h"
62#include "scip/pub_misc.h"
63#include "scip/pub_misc_sort.h"
64#include "scip/pub_paramset.h"
65#include "scip/pub_prop.h"
66#include "scip/pub_tree.h"
67#include "scip/pub_var.h"
69#include "scip/scip_conflict.h"
70#include "scip/scip_cons.h"
71#include "scip/scip_exact.h"
72#include "scip/scip_mem.h"
73#include "scip/scip_sol.h"
74#include "scip/scip_var.h"
75#include "scip/set.h"
76#include "scip/sol.h"
78#include "scip/struct_lp.h"
79#include "scip/struct_prob.h"
80#include "scip/struct_set.h"
81#include "scip/struct_stat.h"
82#include "scip/struct_tree.h"
83#include "scip/struct_var.h"
85#include "scip/tree.h"
86#include "scip/var.h"
87#include "scip/visual.h"
88
89#define BOUNDSWITCH 0.51 /**< threshold for bound switching - see cuts.c */
90#define POSTPROCESS FALSE /**< apply postprocessing to the cut - see cuts.c */
91#define VARTYPEUSEVBDS 0 /**< We do not allow variable bound substitution - see cuts.c for more information. */
92#define ALLOWLOCAL FALSE /**< allow to generate local cuts - see cuts. */
93#define MINFRAC 0.05 /**< minimal fractionality of floor(rhs) - see cuts.c */
94#define MAXFRAC 0.999 /**< maximal fractionality of floor(rhs) - see cuts.c */
95
96
97/*
98 * Proof Sets
99 */
100
101/** return the char associated with the type of the variable */
102static
104 SCIP_VAR* var /**< variable */
105 )
106{
107 SCIP_VARTYPE vartype = SCIPvarGetType(var);
108
109 return (!SCIPvarIsIntegral(var) ? 'C' :
110 (vartype == SCIP_VARTYPE_BINARY ? 'B' :
111 (vartype == SCIP_VARTYPE_INTEGER ? 'I' : 'M')));
112}
113
114/** resets the data structure of a proofset */
115static
117 SCIP_PROOFSET* proofset /**< proof set */
118 )
119{
120 assert(proofset != NULL);
121
122 proofset->nnz = 0;
123 proofset->rhs = 0.0;
124 proofset->validdepth = 0;
127}
128
129/** creates a proofset */
130static
132 SCIP_PROOFSET** proofset, /**< proof set */
133 BMS_BLKMEM* blkmem /**< block memory of transformed problem */
134 )
135{
136 assert(proofset != NULL);
137
138 SCIP_ALLOC( BMSallocBlockMemory(blkmem, proofset) );
139 (*proofset)->vals = NULL;
140 (*proofset)->inds = NULL;
141 (*proofset)->rhs = 0.0;
142 (*proofset)->nnz = 0;
143 (*proofset)->size = 0;
144 (*proofset)->validdepth = 0;
145 (*proofset)->conflicttype = SCIP_CONFTYPE_UNKNOWN;
146 (*proofset)->certificateline = SCIP_LONGINT_MAX;
147
148 return SCIP_OKAY;
149}
150
151/** frees a proofset */
153 SCIP_PROOFSET** proofset, /**< proof set */
154 BMS_BLKMEM* blkmem /**< block memory */
155 )
156{
157 assert(proofset != NULL);
158 assert(*proofset != NULL);
159 assert(blkmem != NULL);
160
161 BMSfreeBlockMemoryArrayNull(blkmem, &(*proofset)->vals, (*proofset)->size);
162 BMSfreeBlockMemoryArrayNull(blkmem, &(*proofset)->inds, (*proofset)->size);
163 BMSfreeBlockMemory(blkmem, proofset);
164 (*proofset) = NULL;
165}
166
167/** return the indices of variables in the proofset */
168static
170 SCIP_PROOFSET* proofset /**< proof set */
171 )
172{
173 assert(proofset != NULL);
174
175 return proofset->inds;
176}
177
178/** return coefficient of variable in the proofset with given probindex */
179static
181 SCIP_PROOFSET* proofset /**< proof set */
182 )
183{
184 assert(proofset != NULL);
185
186 return proofset->vals;
187}
188
189/** return the right-hand side if a proofset */
190static
192 SCIP_PROOFSET* proofset /**< proof set */
193 )
194{
195 assert(proofset != NULL);
196
197 return proofset->rhs;
198}
199
200/** returns the number of variables in the proofset */
202 SCIP_PROOFSET* proofset /**< proof set */
203 )
204{
205 assert(proofset != NULL);
206
207 return proofset->nnz;
208}
209
210/** returns the number of variables in the proofset */
211static
213 SCIP_PROOFSET* proofset /**< proof set */
214 )
215{
216 assert(proofset != NULL);
217
218 return proofset->conflicttype;
219}
220
221/** adds given data as aggregation row to the proofset */
222static
224 SCIP_PROOFSET* proofset, /**< proof set */
225 BMS_BLKMEM* blkmem, /**< block memory */
226 SCIP_Real* vals, /**< variable coefficients */
227 int* inds, /**< variable array */
228 int nnz, /**< size of variable and coefficient array */
229 SCIP_Real rhs /**< right-hand side of the aggregation row */
230 )
231{
232 assert(proofset != NULL);
233 assert(blkmem != NULL);
234
235 if( proofset->size == 0 )
236 {
237 assert(proofset->vals == NULL);
238 assert(proofset->inds == NULL);
239
240 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &proofset->vals, vals, nnz) );
241 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &proofset->inds, inds, nnz) );
242
243 proofset->size = nnz;
244 }
245 else
246 {
247 int i;
248
249 assert(proofset->vals != NULL);
250 assert(proofset->inds != NULL);
251
252 if( proofset->size < nnz )
253 {
254 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &proofset->vals, proofset->size, nnz) );
255 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &proofset->inds, proofset->size, nnz) );
256 proofset->size = nnz;
257 }
258
259 for( i = 0; i < nnz; i++ )
260 {
261 proofset->vals[i] = vals[i];
262 proofset->inds[i] = inds[i];
263 }
264 }
265
266 proofset->rhs = rhs;
267 proofset->nnz = nnz;
268
269 return SCIP_OKAY;
270}
271
272/** adds an aggregation row to the proofset */
273static
275 SCIP_PROOFSET* proofset, /**< proof set */
276 SCIP_SET* set, /**< global SCIP settings */
277 BMS_BLKMEM* blkmem, /**< block memory */
278 SCIP_AGGRROW* aggrrow /**< aggregation row to add */
279 )
280{
281 SCIP_Real* vals;
282 int* inds;
283 int nnz;
284 int i;
285
286 assert(proofset != NULL);
287 assert(set != NULL);
288
289 inds = SCIPaggrRowGetInds(aggrrow);
290 assert(inds != NULL);
291
292 nnz = SCIPaggrRowGetNNz(aggrrow);
293 assert(nnz > 0);
294
295 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, nnz) );
296
297 for( i = 0; i < nnz; i++ )
298 {
299 if( !set->exact_enable )
300 vals[i] = SCIPaggrRowGetProbvarValue(aggrrow, inds[i]);
301 else
302 vals[i] = aggrrow->vals[inds[i]];
303 }
304
305 SCIP_CALL( proofsetAddSparseData(proofset, blkmem, vals, inds, nnz, SCIPaggrRowGetRhs(aggrrow)) );
306
308
309 if( set->exact_enable && SCIPisCertified(set->scip) )
310 {
311 assert(aggrrow->certificateline != SCIP_LONGINT_MAX);
312 assert(proofset->certificateline == SCIP_LONGINT_MAX);
313 proofset->certificateline = (SCIP_Longint)aggrrow->certificateline;
314 }
315
316 return SCIP_OKAY;
317}
318
319/** Removes a given variable @p var from position @p pos from the proofset and updates the right-hand side according
320 * to sign of the coefficient, i.e., rhs -= coef * bound, where bound = lb if coef >= 0 and bound = ub, otherwise.
321 *
322 * @note: The list of non-zero indices and coefficients will be updated by swapping the last non-zero index to @p pos.
323 */
324static
326 SCIP_PROOFSET* proofset,
327 SCIP_SET* set,
328 SCIP_VAR* var,
329 int pos,
330 SCIP_Bool* valid
331 )
332{
333 assert(proofset != NULL);
334 assert(var != NULL);
335 assert(pos >= 0 && pos < proofset->nnz);
336 assert(valid != NULL);
337
338 *valid = TRUE;
339
340 /* cancel with lower bound */
341 if( proofset->vals[pos] > 0.0 )
342 {
343 proofset->rhs -= proofset->vals[pos] * SCIPvarGetLbGlobal(var);
344 }
345 /* cancel with upper bound */
346 else
347 {
348 assert(proofset->vals[pos] < 0.0);
349 proofset->rhs -= proofset->vals[pos] * SCIPvarGetUbGlobal(var);
350 }
351
352 --proofset->nnz;
353
354 proofset->vals[pos] = proofset->vals[proofset->nnz];
355 proofset->inds[pos] = proofset->inds[proofset->nnz];
356 proofset->vals[proofset->nnz] = 0.0;
357 proofset->inds[proofset->nnz] = 0;
358
359 if( SCIPsetIsInfinity(set, proofset->rhs) )
360 *valid = FALSE;
361}
362
363/** creates and clears the proofset */
365 SCIP_CONFLICT* conflict, /**< conflict analysis data */
366 BMS_BLKMEM* blkmem /**< block memory of transformed problem */
367 )
368{
369 assert(conflict != NULL);
370 assert(blkmem != NULL);
371
372 SCIP_CALL( proofsetCreate(&conflict->proofset, blkmem) );
373
374 return SCIP_OKAY;
375}
376
377/** resizes proofsets array to be able to store at least num entries */
378static
380 SCIP_CONFLICT* conflict, /**< conflict analysis data */
381 SCIP_SET* set, /**< global SCIP settings */
382 int num /**< minimal number of slots in array */
383 )
384{
385 assert(conflict != NULL);
386 assert(set != NULL);
387
388 if( num > conflict->proofsetssize )
389 {
390 int newsize;
391
392 newsize = SCIPsetCalcMemGrowSize(set, num);
393 SCIP_ALLOC( BMSreallocMemoryArray(&conflict->proofsets, newsize) );
394 conflict->proofsetssize = newsize;
395 }
396 assert(num <= conflict->proofsetssize);
397
398 return SCIP_OKAY;
399}
400
401/** add a proofset to the list of all proofsets */
402static
404 SCIP_CONFLICT* conflict, /**< conflict analysis data */
405 SCIP_SET* set, /**< global SCIP settings */
406 SCIP_PROOFSET* proofset /**< proof set to add */
407 )
408{
409 assert(conflict != NULL);
410 assert(proofset != NULL);
411
412 /* insert proofset into the sorted proofsets array */
413 SCIP_CALL( conflictEnsureProofsetsMem(conflict, set, conflict->nproofsets + 1) );
414
415 conflict->proofsets[conflict->nproofsets] = proofset;
416 ++conflict->nproofsets;
417
418 return SCIP_OKAY;
419}
420
421/** tighten the bound of a singleton variable in a constraint
422 *
423 * if the bound is contradicting with a global bound we cannot tighten the bound directly.
424 * in this case we need to create and add a constraint of size one such that propagating this constraint will
425 * enforce the infeasibility.
426 */
427static
429 SCIP_CONFLICT* conflict, /**< conflict analysis data */
430 SCIP_SET* set, /**< global SCIP settings */
431 SCIP_STAT* stat, /**< dynamic SCIP statistics */
432 SCIP_TREE* tree, /**< tree data */
433 BMS_BLKMEM* blkmem, /**< block memory */
434 SCIP_PROB* origprob, /**< original problem */
435 SCIP_PROB* transprob, /**< transformed problem */
436 SCIP_REOPT* reopt, /**< reoptimization data */
437 SCIP_LP* lp, /**< LP data */
438 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
439 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
440 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
441 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
442 SCIP_VAR* var, /**< problem variable */
443 SCIP_Real val, /**< coefficient of the variable */
444 SCIP_Real rhs, /**< rhs of the constraint */
445 SCIP_CONFTYPE prooftype, /**< type of the proof */
446 int validdepth /**< depth where the bound change is valid */
447 )
448{
449 SCIP_Real newbound;
450 SCIP_Bool applyglobal;
451 SCIP_BOUNDTYPE boundtype;
452
453 assert(tree != NULL);
454 assert(validdepth >= 0);
455
456 applyglobal = (validdepth <= SCIPtreeGetEffectiveRootDepth(tree));
457
458 /* if variable and coefficient are integral the rhs can be rounded down */
459 if( SCIPvarIsIntegral(var) && SCIPsetIsIntegral(set, val) )
460 newbound = SCIPsetFeasFloor(set, rhs)/val;
461 else
462 newbound = rhs/val;
463
464 boundtype = (val > 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
465 SCIPvarAdjustBd(var, set, boundtype, &newbound);
466
467 /* skip numerical unstable bound changes */
468 if( applyglobal
469 && ((boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsLE(set, newbound, SCIPvarGetLbGlobal(var)))
470 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsGE(set, newbound, SCIPvarGetUbGlobal(var)))) )
471 {
472 return SCIP_OKAY;
473 }
474
475 /* the new bound contradicts a global bound, we can cutoff the root node immediately */
476 if( applyglobal
477 && ((boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, SCIPvarGetUbGlobal(var)))
478 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, SCIPvarGetLbGlobal(var)))) )
479 {
480 SCIPsetDebugMsg(set, "detected global infeasibility at var <%s>: locdom=[%g,%g] glbdom=[%g,%g] new %s bound=%g\n",
483 (boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper"), newbound);
484 SCIP_CALL( SCIPnodeCutoff(tree->path[0], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
485 }
486 else
487 {
488 if( lp->strongbranching || !applyglobal )
489 {
490 SCIP_CONS* cons;
491 SCIP_Real conslhs;
492 SCIP_Real consrhs;
493 char name[SCIP_MAXSTRLEN];
494
495 SCIPsetDebugMsg(set, "add constraint <%s>[%c] %s %g to node #%lld in depth %d\n",
496 SCIPvarGetName(var), varGetChar(var), boundtype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", newbound,
497 SCIPnodeGetNumber(tree->path[validdepth]), validdepth);
498
499 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "pc_fix_%s", SCIPvarGetName(var));
500
501 if( boundtype == SCIP_BOUNDTYPE_UPPER )
502 {
503 conslhs = -SCIPsetInfinity(set);
504 consrhs = newbound;
505 }
506 else
507 {
508 conslhs = newbound;
509 consrhs = SCIPsetInfinity(set);
510 }
511
512 SCIP_CALL( SCIPcreateConsLinear(set->scip, &cons, name, 0, NULL, NULL, conslhs, consrhs,
513 FALSE, FALSE, FALSE, FALSE, TRUE, !applyglobal, FALSE, TRUE, TRUE, FALSE) );
514
515 SCIP_CALL( SCIPaddCoefLinear(set->scip, cons, var, 1.0) );
516
517 if( applyglobal ) /*lint !e774*/
518 {
519 SCIP_CALL( SCIPprobAddCons(transprob, set, stat, cons) );
520 }
521 else
522 {
523 SCIP_CALL( SCIPnodeAddCons(tree->path[validdepth], blkmem, set, stat, tree, cons) );
524 }
525
526 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
527 }
528 else
529 {
530 assert(applyglobal);
531
532 SCIPsetDebugMsg(set, "change global %s bound of <%s>[%c]: %g -> %g\n",
533 (boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper"),
534 SCIPvarGetName(var), varGetChar(var),
536 newbound);
537
538 SCIP_CALL( SCIPnodeAddBoundchg(tree->path[0], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
539 eventqueue, eventfilter, cliquetable, var, newbound, boundtype, FALSE) );
540
541 /* mark the node in the validdepth to be propagated again */
542 SCIPnodePropagateAgain(tree->path[0], set, stat, tree);
543 }
544 }
545
546 if( applyglobal )
547 ++conflict->nglbchgbds;
548 else
549 ++conflict->nlocchgbds;
550
551 if( prooftype == SCIP_CONFTYPE_INFEASLP || prooftype == SCIP_CONFTYPE_ALTINFPROOF )
552 {
553 ++conflict->dualproofsinfnnonzeros; /* we count a global bound reduction as size 1 */
554 ++conflict->ndualproofsinfsuccess;
555 ++conflict->ninflpsuccess;
556
557 if( applyglobal )
558 ++conflict->ndualproofsinfglobal;
559 else
560 ++conflict->ndualproofsinflocal;
561 }
562 else
563 {
564 ++conflict->dualproofsbndnnonzeros; /* we count a global bound reduction as size 1 */
565 ++conflict->ndualproofsbndsuccess;
566 ++conflict->nboundlpsuccess;
567
568 if( applyglobal )
569 ++conflict->ndualproofsbndglobal;
570 else
571 ++conflict->ndualproofsbndlocal;
572 }
573
574 return SCIP_OKAY;
575}
576
577/** calculates the minimal activity of a given set of bounds and coefficients */
578static
580 SCIP_SET* set, /**< global SCIP settings */
581 SCIP_PROB* transprob, /**< transformed problem data */
582 SCIP_Real* coefs, /**< coefficients in sparse representation */
583 int* inds, /**< non-zero indices */
584 int nnz, /**< number of non-zero indices */
585 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables (or NULL for global bounds) */
586 SCIP_Real* curvarubs /**< current upper bounds of active problem variables (or NULL for global bounds) */
587 )
588{
589 SCIP_VAR** vars;
590 SCIP_Real QUAD(minact);
591 int i;
592
593 assert(coefs != NULL);
594 assert(inds != NULL);
595
596 vars = SCIPprobGetVars(transprob);
597 assert(vars != NULL);
598
599 QUAD_ASSIGN(minact, 0.0);
600
601 for( i = 0; i < nnz; i++ )
602 {
603 SCIP_Real val;
604 SCIP_Real QUAD(delta);
605 int v = inds[i];
606
607 assert(SCIPvarGetProbindex(vars[v]) == v);
608
609 val = coefs[i];
610
611 if( val > 0.0 )
612 {
613 SCIP_Real bnd;
614
615 assert(curvarlbs == NULL || !SCIPsetIsInfinity(set, -curvarlbs[v]));
616
617 bnd = (curvarlbs == NULL ? SCIPvarGetLbGlobal(vars[v]) : curvarlbs[v]);
618
619 if( SCIPsetIsInfinity(set, -bnd) )
620 return -SCIPsetInfinity(set);
621
622 SCIPquadprecProdDD(delta, val, bnd);
623 }
624 else
625 {
626 SCIP_Real bnd;
627
628 assert(curvarubs == NULL || !SCIPsetIsInfinity(set, curvarubs[v]));
629
630 bnd = (curvarubs == NULL ? SCIPvarGetUbGlobal(vars[v]) : curvarubs[v]);
631
632 if( SCIPsetIsInfinity(set, bnd) )
633 return -SCIPsetInfinity(set);
634
635 SCIPquadprecProdDD(delta, val, bnd);
636 }
637
638 /* update minimal activity */
639 SCIPquadprecSumQQ(minact, minact, delta);
640 }
641
642 /* check whether the minmal activity is infinite */
643 if( SCIPsetIsInfinity(set, QUAD_TO_DBL(minact)) )
644 return SCIPsetInfinity(set);
645 if( SCIPsetIsInfinity(set, -QUAD_TO_DBL(minact)) )
646 return -SCIPsetInfinity(set);
647
648 return QUAD_TO_DBL(minact);
649}
650
651/** calculates the minimal activity of a given set of bounds and coefficients */
652static
654 SCIP_SET* set, /**< global SCIP settings */
655 SCIP_PROB* transprob, /**< transformed problem data */
656 SCIP_Real* coefs, /**< coefficients in sparse representation */
657 int* inds, /**< non-zero indices */
658 int nnz, /**< number of non-zero indices */
659 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables (or NULL for global bounds) */
660 SCIP_Real* curvarubs /**< current upper bounds of active problem variables (or NULL for global bounds) */
661 )
662{
663 SCIP_VAR** vars;
664 SCIP_Real QUAD(maxact);
665 int i;
666
667 assert(coefs != NULL);
668 assert(inds != NULL);
669
670 vars = SCIPprobGetVars(transprob);
671 assert(vars != NULL);
672
673 QUAD_ASSIGN(maxact, 0.0);
674
675 for( i = 0; i < nnz; i++ )
676 {
677 SCIP_Real val;
678 SCIP_Real QUAD(delta);
679 int v = inds[i];
680
681 assert(SCIPvarGetProbindex(vars[v]) == v);
682
683 val = coefs[i];
684
685 if( val < 0.0 )
686 {
687 SCIP_Real bnd;
688
689 assert(curvarlbs == NULL || !SCIPsetIsInfinity(set, -curvarlbs[v]));
690
691 bnd = (curvarlbs == NULL ? SCIPvarGetLbGlobal(vars[v]) : curvarlbs[v]);
692
693 if( SCIPsetIsInfinity(set, -bnd) )
694 return SCIPsetInfinity(set);
695
696 SCIPquadprecProdDD(delta, val, bnd);
697 }
698 else
699 {
700 SCIP_Real bnd;
701
702 assert(curvarubs == NULL || !SCIPsetIsInfinity(set, curvarubs[v]));
703
704 bnd = (curvarubs == NULL ? SCIPvarGetUbGlobal(vars[v]) : curvarubs[v]);
705
706 if( SCIPsetIsInfinity(set, bnd) )
707 return SCIPsetInfinity(set);
708
709 SCIPquadprecProdDD(delta, val, bnd);
710 }
711
712 /* update maximal activity */
713 SCIPquadprecSumQQ(maxact, maxact, delta);
714 }
715
716 /* check whether the maximal activity got infinite */
717 if( SCIPsetIsInfinity(set, QUAD_TO_DBL(maxact)) )
718 return SCIPsetInfinity(set);
719 if( SCIPsetIsInfinity(set, -QUAD_TO_DBL(maxact)) )
720 return -SCIPsetInfinity(set);
721
722 return QUAD_TO_DBL(maxact);
723}
724
725/** propagate a long proof */
726static
728 SCIP_CONFLICT* conflict, /**< conflict analysis data */
729 SCIP_SET* set, /**< global SCIP settings */
730 SCIP_STAT* stat, /**< dynamic SCIP statistics */
731 SCIP_REOPT* reopt, /**< reoptimization data */
732 SCIP_TREE* tree, /**< tree data */
733 BMS_BLKMEM* blkmem, /**< block memory */
734 SCIP_PROB* origprob, /**< original problem */
735 SCIP_PROB* transprob, /**< transformed problem */
736 SCIP_LP* lp, /**< LP data */
737 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
738 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
739 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
740 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
741 SCIP_Real* coefs, /**< coefficients in sparse representation */
742 int* inds, /**< non-zero indices */
743 int nnz, /**< number of non-zero indices */
744 SCIP_Real rhs, /**< right-hand side */
745 SCIP_CONFTYPE conflicttype, /**< type of the conflict */
746 int validdepth /**< depth where the proof is valid */
747 )
748{
749 SCIP_VAR** vars;
750 SCIP_Real minact;
751 int i;
752
753 assert(coefs != NULL);
754 assert(inds != NULL);
755 assert(nnz >= 0);
756
757 vars = SCIPprobGetVars(transprob);
758 minact = getMinActivity(set, transprob, coefs, inds, nnz, NULL, NULL);
759
760 /* we cannot find global tightenings */
761 if( SCIPsetIsInfinity(set, -minact) )
762 return SCIP_OKAY;
763
764 for( i = 0; i < nnz; i++ )
765 {
766 SCIP_VAR* var;
767 SCIP_Real val;
768 SCIP_Real resminact;
769 SCIP_Real lb;
770 SCIP_Real ub;
771 int pos;
772
773 pos = inds[i];
774 val = coefs[i];
775 var = vars[pos];
776 lb = SCIPvarGetLbGlobal(var);
777 ub = SCIPvarGetUbGlobal(var);
778
779 assert(!SCIPsetIsZero(set, val));
780
781 resminact = minact;
782
783 /* we got a potential new upper bound */
784 if( val > 0.0 )
785 {
786 SCIP_Real newub;
787
788 resminact -= (val * lb);
789 newub = (rhs - resminact)/val;
790
791 if( SCIPsetIsInfinity(set, newub) )
792 continue;
793
794 /* we cannot tighten the upper bound */
795 if( SCIPsetIsGE(set, newub, ub) )
796 continue;
797
798 SCIP_CALL( tightenSingleVar(conflict, set, stat, tree, blkmem, origprob, transprob, reopt, lp, branchcand,
799 eventqueue, eventfilter, cliquetable, var, val, rhs-resminact, conflicttype, validdepth) );
800 }
801 /* we got a potential new lower bound */
802 else
803 {
804 SCIP_Real newlb;
805
806 resminact -= (val * ub);
807 newlb = (rhs - resminact)/val;
808
809 if( SCIPsetIsInfinity(set, -newlb) )
810 continue;
811
812 /* we cannot tighten the lower bound */
813 if( SCIPsetIsLE(set, newlb, lb) )
814 continue;
815
816 SCIP_CALL( tightenSingleVar(conflict, set, stat, tree, blkmem, origprob, transprob, reopt, lp, branchcand,
817 eventqueue, eventfilter, cliquetable, var, val, rhs-resminact, conflicttype, validdepth) );
818 }
819
820 /* the minimal activity should stay unchanged because we tightened the bound that doesn't contribute to the
821 * minimal activity
822 */
823 assert(SCIPsetIsEQ(set, minact, getMinActivity(set, transprob, coefs, inds, nnz, NULL, NULL)));
824 }
825
826 return SCIP_OKAY;
827}
828
829/** creates a proof constraint and tries to add it to the storage */
830static
832 SCIP_CONFLICT* conflict, /**< conflict analysis data */
833 SCIP_CONFLICTSTORE* conflictstore, /**< conflict pool data */
834 SCIP_PROOFSET* proofset, /**< proof set */
835 SCIP_SET* set, /**< global SCIP settings */
836 SCIP_STAT* stat, /**< dynamic SCIP statistics */
837 SCIP_PROB* origprob, /**< original problem */
838 SCIP_PROB* transprob, /**< transformed problem */
839 SCIP_TREE* tree, /**< tree data */
840 SCIP_REOPT* reopt, /**< reoptimization data */
841 SCIP_LP* lp, /**< LP data */
842 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
843 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
844 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
845 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
846 BMS_BLKMEM* blkmem /**< block memory */
847 )
848{
849 SCIP_CONS* cons;
850 SCIP_CONS* upgdcons;
851 SCIP_VAR** vars;
852 SCIP_Real* coefs;
853 int* inds;
854 SCIP_Real rhs;
855 SCIP_Real fillin;
856 SCIP_Real globalminactivity;
857 SCIP_Bool applyglobal;
858 SCIP_Bool toolong;
859 SCIP_Bool contonly;
860 SCIP_Bool hasrelaxvar;
861 SCIP_CONFTYPE conflicttype;
862 char name[SCIP_MAXSTRLEN];
863 int nnz;
864 int i;
865
866 assert(conflict != NULL);
867 assert(conflictstore != NULL);
868 assert(proofset != NULL);
869 assert(proofset->validdepth == 0 || proofset->validdepth < SCIPtreeGetFocusDepth(tree));
870
871 nnz = SCIPproofsetGetNVars(proofset);
872
873 if( nnz == 0 )
874 return SCIP_OKAY;
875
876 vars = SCIPprobGetVars(transprob);
877
878 rhs = proofsetGetRhs(proofset);
879 assert(!SCIPsetIsInfinity(set, rhs));
880
881 coefs = proofsetGetVals(proofset);
882 assert(coefs != NULL);
883
884 inds = proofsetGetInds(proofset);
885 assert(inds != NULL);
886
887 conflicttype = proofsetGetConftype(proofset);
888
889 applyglobal = (proofset->validdepth <= SCIPtreeGetEffectiveRootDepth(tree));
890
891 if( applyglobal )
892 {
893 SCIP_Real globalmaxactivity = getMaxActivity(set, transprob, coefs, inds, nnz, NULL, NULL);
894
895 /* check whether the alternative proof is redundant */
896 if( SCIPsetIsLE(set, globalmaxactivity, rhs) )
897 return SCIP_OKAY;
898
899 /* check whether the constraint proves global infeasibility */
900 globalminactivity = getMinActivity(set, transprob, coefs, inds, nnz, NULL, NULL);
901 if( SCIPsetIsGT(set, globalminactivity, rhs) )
902 {
903 SCIPsetDebugMsg(set, "detect global infeasibility: minactivity=%g, rhs=%g\n", globalminactivity, rhs);
904
905 SCIP_CALL( SCIPnodeCutoff(tree->path[proofset->validdepth], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
906
907 goto UPDATESTATISTICS;
908 }
909 }
910
911 if( set->conf_minmaxvars >= nnz )
912 toolong = FALSE;
913 else
914 {
915 SCIP_Real maxnnz;
916
917 if( transprob->startnconss < 100 )
918 maxnnz = 0.85 * transprob->nvars;
919 else
920 maxnnz = (SCIP_Real)transprob->nvars;
921
922 fillin = nnz;
923 if( conflicttype == SCIP_CONFTYPE_INFEASLP || conflicttype == SCIP_CONFTYPE_ALTINFPROOF )
924 {
925 fillin += SCIPconflictstoreGetNDualInfProofs(conflictstore) * SCIPconflictstoreGetAvgNnzDualInfProofs(conflictstore);
926 fillin /= (SCIPconflictstoreGetNDualInfProofs(conflictstore) + 1.0);
927 toolong = (fillin > MIN(2.0 * stat->avgnnz, maxnnz));
928 }
929 else
930 {
931 assert(conflicttype == SCIP_CONFTYPE_BNDEXCEEDING || conflicttype == SCIP_CONFTYPE_ALTBNDPROOF);
932
933 fillin += SCIPconflictstoreGetNDualBndProofs(conflictstore) * SCIPconflictstoreGetAvgNnzDualBndProofs(conflictstore);
934 fillin /= (SCIPconflictstoreGetNDualBndProofs(conflictstore) + 1.0);
935 toolong = (fillin > MIN(1.5 * stat->avgnnz, maxnnz));
936 }
937
938 toolong = (toolong && (nnz > set->conf_maxvarsfac * transprob->nvars));
939 }
940
941 /* don't store global dual proofs that are too long / have too many non-zeros */
942 if( !set->exact_enable && toolong )
943 {
944 if( applyglobal )
945 {
946 SCIP_CALL( propagateLongProof(conflict, set, stat, reopt, tree, blkmem, origprob, transprob, lp, branchcand,
947 eventqueue, eventfilter, cliquetable, coefs, inds, nnz, rhs, conflicttype, proofset->validdepth) );
948 }
949 return SCIP_OKAY;
950 }
951
952 /* check if conflict contains variables that are invalid after a restart to label it appropriately */
953 hasrelaxvar = FALSE;
954 contonly = TRUE;
955 for( i = 0; i < nnz && (!hasrelaxvar || contonly); ++i )
956 {
957 hasrelaxvar |= SCIPvarIsRelaxationOnly(vars[inds[i]]);
958
959 if( SCIPvarIsIntegral(vars[inds[i]]) )
960 contonly = FALSE;
961 }
962
963 if( !applyglobal && contonly )
964 return SCIP_OKAY;
965
966 if( conflicttype == SCIP_CONFTYPE_INFEASLP || conflicttype == SCIP_CONFTYPE_ALTINFPROOF )
967 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "dualproof_inf_%" SCIP_LONGINT_FORMAT, conflict->ndualproofsinfsuccess);
968 else if( conflicttype == SCIP_CONFTYPE_BNDEXCEEDING || conflicttype == SCIP_CONFTYPE_ALTBNDPROOF )
969 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "dualproof_bnd_%" SCIP_LONGINT_FORMAT, conflict->ndualproofsbndsuccess);
970 else
971 return SCIP_INVALIDCALL;
972
973 SCIPdebugMessage("Create constraint from dual ray analysis\n");
974
975 if( !set->exact_enable )
976 {
977 SCIP_CALL( SCIPcreateConsLinear(set->scip, &cons, name, 0, NULL, NULL, -SCIPsetInfinity(set), rhs,
978 FALSE, FALSE, FALSE, FALSE, TRUE, !applyglobal,
979 FALSE, TRUE, TRUE, FALSE) );
980
981 for( i = 0; i < nnz; i++ )
982 {
983 int v = inds[i];
984 SCIP_CALL( SCIPaddCoefLinear(set->scip, cons, vars[v], coefs[i]) );
985 }
986 }
987 /* in exact solving mode we don't store global dual proofs that are too long / have too many non-zeros */
988 else if( !toolong )
989 {
990 SCIP_RATIONAL* lhs_exact;
991 SCIP_RATIONAL* rhs_exact;
992 SCIP_RATIONAL** coefs_exact;
993 SCIP_VAR** consvars;
994
995 SCIP_CALL( SCIPrationalCreateBuffer(SCIPbuffer(set->scip), &lhs_exact) );
996 SCIP_CALL( SCIPrationalCreateBuffer(SCIPbuffer(set->scip), &rhs_exact) );
998 SCIPrationalSetReal(rhs_exact, rhs);
999 SCIP_CALL( SCIPrationalCreateBufferArray(SCIPbuffer(set->scip), &coefs_exact, nnz) );
1000 SCIP_CALL( SCIPallocBufferArray(set->scip, &consvars, nnz) );
1001
1002 assert(nnz > 0);
1003
1004 for( i = 0; i < nnz; i++ )
1005 {
1006 consvars[i] = vars[inds[i]];
1007 SCIPrationalSetReal(coefs_exact[i], coefs[i]);
1008 assert(!SCIPrationalIsAbsInfinity(coefs_exact[i]));
1009 }
1010
1011 SCIP_CALL( SCIPcreateConsExactLinear(set->scip, &cons, name, nnz, consvars, coefs_exact, lhs_exact, rhs_exact,
1012 FALSE, FALSE, FALSE, FALSE, TRUE, !applyglobal, FALSE, TRUE, TRUE, FALSE) );
1013
1014 if( SCIPisCertified(set->scip) )
1015 {
1017 }
1018
1019 SCIPfreeBufferArray(set->scip, &consvars);
1020 SCIPrationalFreeBufferArray(SCIPbuffer(set->scip), &coefs_exact, nnz);
1021 SCIPrationalFreeBuffer(SCIPbuffer(set->scip), &rhs_exact);
1022 SCIPrationalFreeBuffer(SCIPbuffer(set->scip), &lhs_exact);
1023 }
1024 else
1025 {
1026 assert(set->exact_enable && toolong);
1027 return SCIP_OKAY;
1028 }
1029
1030 /* do not upgrade linear constraints of size 1 */
1031 if( !set->exact_enable && nnz > 1 )
1032 {
1033 upgdcons = NULL;
1034 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
1035 SCIP_CALL( SCIPupgradeConsLinear(set->scip, cons, &upgdcons) );
1036 if( upgdcons != NULL )
1037 {
1038 SCIP_CONSHDLR* conshdlr;
1039
1040 conshdlr = SCIPconsGetHdlr(upgdcons);
1041 assert(conshdlr != NULL);
1042
1043 /* only upgrade constraint if it can report number of variables (needed by
1044 * SCIPconflictstoreAddDualraycons() and SCIPconflictstoreAddDualsolcons())
1045 */
1046 if( conshdlr->consgetnvars == NULL )
1047 {
1048 SCIP_CALL( SCIPreleaseCons(set->scip, &upgdcons) );
1049 }
1050 else
1051 {
1052 SCIP_CALL( SCIPreleaseCons(set->scip, &cons) );
1053 cons = upgdcons;
1054
1055 if( conflicttype == SCIP_CONFTYPE_INFEASLP )
1056 conflicttype = SCIP_CONFTYPE_ALTINFPROOF;
1057 else if( conflicttype == SCIP_CONFTYPE_BNDEXCEEDING )
1058 conflicttype = SCIP_CONFTYPE_ALTBNDPROOF;
1059 }
1060 }
1061 }
1062
1063 /* mark constraint to be a conflict */
1065
1066 /* add constraint to storage */
1067 if( conflicttype == SCIP_CONFTYPE_INFEASLP || conflicttype == SCIP_CONFTYPE_ALTINFPROOF )
1068 {
1069 /* add dual proof to storage */
1070 SCIP_CALL( SCIPconflictstoreAddDualraycons(conflictstore, cons, blkmem, set, stat, transprob, reopt, hasrelaxvar) );
1071 }
1072 else
1073 {
1074 SCIP_Real scale = 1.0;
1075 SCIP_Bool updateside = FALSE;
1076
1077 /* In some cases the constraint could not be updated to a more special type. However, it is possible that
1078 * constraint got scaled. Therefore, we need to be very careful when updating the lhs/rhs after the incumbent
1079 * solution has improved.
1080 */
1081 if( conflicttype == SCIP_CONFTYPE_BNDEXCEEDING )
1082 {
1083 SCIP_Real side;
1084
1085#ifndef NDEBUG
1086 SCIP_CONSHDLR* conshdlr = SCIPconsGetHdlr(cons);
1087
1088 assert(conshdlr != NULL);
1089 assert(strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0 || set->exact_enable );
1090 assert(strcmp(SCIPconshdlrGetName(conshdlr), "exactlinear") == 0 || !set->exact_enable );
1091#endif
1092 side = set->exact_enable ? SCIPrationalRoundReal(SCIPgetLhsExactLinear(set->scip, cons), SCIP_R_ROUND_NEAREST) : SCIPgetLhsLinear(set->scip, cons);
1093
1094 if( !SCIPsetIsInfinity(set, -side) )
1095 {
1096 if( SCIPsetIsZero(set, side) )
1097 {
1098 scale = -1.0;
1099 }
1100 else
1101 {
1102 scale = proofsetGetRhs(proofset) / side;
1103 assert(SCIPsetIsNegative(set, scale));
1104 }
1105 }
1106 else
1107 {
1108 side = set->exact_enable ? SCIPrationalRoundReal(SCIPgetRhsExactLinear(set->scip, cons), SCIP_R_ROUND_NEAREST) : SCIPgetRhsLinear(set->scip, cons);
1109 assert(!SCIPsetIsInfinity(set, side));
1110
1111 if( SCIPsetIsZero(set, side) )
1112 {
1113 scale = 1.0;
1114 }
1115 else
1116 {
1117 scale = proofsetGetRhs(proofset) / side;
1118 assert(SCIPsetIsPositive(set, scale));
1119 }
1120 }
1121 updateside = TRUE;
1122 }
1123
1124 /* add dual proof to storage */
1125 SCIP_CALL( SCIPconflictstoreAddDualsolcons(conflictstore, cons, blkmem, set, stat, transprob, reopt, scale, updateside, hasrelaxvar) );
1126 }
1127
1128 if( applyglobal ) /*lint !e774*/
1129 {
1130 /* add the constraint to the global problem */
1131 SCIP_CALL( SCIPprobAddCons(transprob, set, stat, cons) );
1132 }
1133 else
1134 {
1135 SCIP_CALL( SCIPnodeAddCons(tree->path[proofset->validdepth], blkmem, set, stat, tree, cons) );
1136 }
1137
1138 SCIPsetDebugMsg(set, "added proof-constraint to node %p (#%lld) in depth %d (nproofconss %d)\n",
1139 (void*)tree->path[proofset->validdepth], SCIPnodeGetNumber(tree->path[proofset->validdepth]),
1140 proofset->validdepth,
1141 (conflicttype == SCIP_CONFTYPE_INFEASLP || conflicttype == SCIP_CONFTYPE_ALTINFPROOF)
1143
1144 /* release the constraint */
1145 SCIP_CALL( SCIPreleaseCons(set->scip, &cons) );
1146
1147 UPDATESTATISTICS:
1148 /* update statistics */
1149 if( conflicttype == SCIP_CONFTYPE_INFEASLP || conflicttype == SCIP_CONFTYPE_ALTINFPROOF )
1150 {
1151 conflict->dualproofsinfnnonzeros += nnz;
1152 if( applyglobal ) /*lint !e774*/
1153 ++conflict->ndualproofsinfglobal;
1154 else
1155 ++conflict->ndualproofsinflocal;
1156 ++conflict->ndualproofsinfsuccess;
1157 }
1158 else
1159 {
1160 assert(conflicttype == SCIP_CONFTYPE_BNDEXCEEDING || conflicttype == SCIP_CONFTYPE_ALTBNDPROOF);
1161 conflict->dualproofsbndnnonzeros += nnz;
1162 if( applyglobal ) /*lint !e774*/
1163 ++conflict->ndualproofsbndglobal;
1164 else
1165 ++conflict->ndualproofsbndlocal;
1166
1167 ++conflict->ndualproofsbndsuccess;
1168 }
1169 return SCIP_OKAY;
1170}
1171
1172/** create proof constraints out of proof sets */
1174 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1175 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
1176 BMS_BLKMEM* blkmem, /**< block memory */
1177 SCIP_SET* set, /**< global SCIP settings */
1178 SCIP_STAT* stat, /**< dynamic problem statistics */
1179 SCIP_PROB* transprob, /**< transformed problem after presolve */
1180 SCIP_PROB* origprob, /**< original problem */
1181 SCIP_TREE* tree, /**< branch and bound tree */
1182 SCIP_REOPT* reopt, /**< reoptimization data structure */
1183 SCIP_LP* lp, /**< current LP data */
1184 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1185 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1186 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1187 SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
1188 )
1189{
1190 assert(conflict != NULL);
1191
1193 {
1194 /**@todo implement special handling of conflicts with one variable also for exact solving mode */
1195 /* only one variable has a coefficient different to zero, we add this bound change instead of a constraint */
1196 if( !set->exact_enable && SCIPproofsetGetNVars(conflict->proofset) == 1 )
1197 {
1198 SCIP_VAR** vars;
1199 SCIP_Real* coefs;
1200 int* inds;
1201 SCIP_Real rhs;
1202
1203 vars = SCIPprobGetVars(transprob);
1204
1205 coefs = proofsetGetVals(conflict->proofset);
1206 inds = proofsetGetInds(conflict->proofset);
1207 rhs = proofsetGetRhs(conflict->proofset);
1208
1209 SCIP_CALL( tightenSingleVar(conflict, set, stat, tree, blkmem, origprob, transprob, reopt, lp,
1210 branchcand, eventqueue, eventfilter, cliquetable, vars[inds[0]], coefs[0], rhs,
1211 conflict->proofset->conflicttype, conflict->proofset->validdepth) );
1212 }
1213 else
1214 {
1215 SCIP_Bool skipinitialproof = FALSE;
1216
1217 /* prefer an infeasibility proof
1218 *
1219 * todo: check whether this is really what we want
1220 */
1221 if( set->conf_prefinfproof && proofsetGetConftype(conflict->proofset) == SCIP_CONFTYPE_BNDEXCEEDING )
1222 {
1223 int i;
1224
1225 for( i = 0; i < conflict->nproofsets; i++ )
1226 {
1228 {
1229 skipinitialproof = TRUE;
1230 break;
1231 }
1232 }
1233 }
1234
1235 if( !skipinitialproof )
1236 {
1237 /* create and add the original proof */
1238 SCIP_CALL( createAndAddProofcons(conflict, conflictstore, conflict->proofset, set, stat, origprob, transprob,
1239 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, blkmem) );
1240 }
1241 }
1242
1243 /* clear the proof set anyway */
1244 proofsetClear(conflict->proofset);
1245 }
1246
1247 if( conflict->nproofsets > 0 )
1248 {
1249 int i;
1250
1251 for( i = 0; i < conflict->nproofsets; i++ )
1252 {
1253 assert(conflict->proofsets[i] != NULL);
1254 assert(proofsetGetConftype(conflict->proofsets[i]) != SCIP_CONFTYPE_UNKNOWN);
1255
1256 /**@todo implement special handling of conflicts with one variable also for exact solving mode */
1257 /* only one variable has a coefficient different to zero, we add this bound change instead of a constraint */
1258 if( !set->exact_enable && SCIPproofsetGetNVars(conflict->proofsets[i]) == 1 )
1259 {
1260 SCIP_VAR** vars;
1261 SCIP_Real* coefs;
1262 int* inds;
1263 SCIP_Real rhs;
1264
1265 vars = SCIPprobGetVars(transprob);
1266
1267 coefs = proofsetGetVals(conflict->proofsets[i]);
1268 inds = proofsetGetInds(conflict->proofsets[i]);
1269 rhs = proofsetGetRhs(conflict->proofsets[i]);
1270
1271 SCIP_CALL( tightenSingleVar(conflict, set, stat, tree, blkmem, origprob, transprob, reopt, lp,
1272 branchcand, eventqueue, eventfilter, cliquetable, vars[inds[0]], coefs[0], rhs,
1273 conflict->proofsets[i]->conflicttype, conflict->proofsets[i]->validdepth) );
1274 }
1275 else
1276 {
1277 /* create and add proof constraint */
1278 SCIP_CALL( createAndAddProofcons(conflict, conflictstore, conflict->proofsets[i], set, stat, origprob,
1279 transprob, tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, blkmem) );
1280 }
1281 }
1282
1283 /* free all proofsets */
1284 for( i = 0; i < conflict->nproofsets; i++ )
1285 SCIPproofsetFree(&conflict->proofsets[i], blkmem);
1286
1287 conflict->nproofsets = 0;
1288 }
1289
1290 return SCIP_OKAY;
1291}
1292
1293
1294
1295#ifdef SCIP_DEBUG
1296/** print violation for debugging */
1297static
1299 SCIP_SET* set, /**< global SCIP settings */
1300 SCIP_Real minact, /**< min activity */
1301 SCIP_Real rhs, /**< right hand side */
1302 const char* infostr /**< additional info for this debug message, or NULL */
1303 )
1304{
1305 SCIPsetDebugMsg(set, "-> %sminact=%.15g rhs=%.15g violation=%.15g\n",infostr != NULL ? infostr : "" , minact, rhs, minact - rhs);
1306}
1307#else
1308#define debugPrintViolationInfo(...) /**/
1309#endif
1310
1311/** apply coefficient tightening
1312 *
1313 * @todo implement coefficient tightening for conflicts in exact solving mode
1314 */
1315static
1317 SCIP_SET* set, /**< global SCIP settings */
1318 SCIP_PROOFSET* proofset, /**< proof set */
1319 int* nchgcoefs, /**< pointer to store number of changed coefficients */
1320 SCIP_Bool* redundant /**< pointer to store whether the proof set is redundant */
1321 )
1322{
1323#ifdef SCIP_DEBUG
1324 SCIP_Real absmax = 0.0;
1325 SCIP_Real absmin = SCIPsetInfinity(set);
1326 int i;
1327
1328 for( i = 0; i < proofset->nnz; i++ )
1329 {
1330 absmax = MAX(absmax, REALABS(proofset->vals[i]));
1331 absmin = MIN(absmin, REALABS(proofset->vals[i]));
1332 }
1333#endif
1334
1335 (*redundant) = SCIPcutsTightenCoefficients(set->scip, FALSE, proofset->vals, &proofset->rhs, proofset->inds, &proofset->nnz, nchgcoefs);
1336
1337#ifdef SCIP_DEBUG
1338 {
1339 SCIP_Real newabsmax = 0.0;
1340 SCIP_Real newabsmin = SCIPsetInfinity(set);
1341
1342 for( i = 0; i < proofset->nnz; i++ )
1343 {
1344 newabsmax = MAX(newabsmax, REALABS(proofset->vals[i]));
1345 newabsmin = MIN(newabsmin, REALABS(proofset->vals[i]));
1346 }
1347
1348 SCIPsetDebugMsg(set, "coefficient tightening: [%.15g,%.15g] -> [%.15g,%.15g] (nnz: %d, nchg: %d rhs: %.15g)\n",
1349 absmin, absmax, newabsmin, newabsmax, SCIPproofsetGetNVars(proofset), *nchgcoefs, proofsetGetRhs(proofset));
1350 printf("coefficient tightening: [%.15g,%.15g] -> [%.15g,%.15g] (nnz: %d, nchg: %d rhs: %.15g)\n",
1351 absmin, absmax, newabsmin, newabsmax, SCIPproofsetGetNVars(proofset), *nchgcoefs, proofsetGetRhs(proofset));
1352 }
1353#endif
1354}
1355
1356/** try to generate alternative proofs by applying subadditive functions */
1357static
1359 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1360 SCIP_SET* set, /**< global SCIP settings */
1361 SCIP_STAT* stat, /**< dynamic SCIP statistics */
1362 SCIP_PROB* transprob, /**< transformed problem */
1363 SCIP_TREE* tree, /**< tree data */
1364 BMS_BLKMEM* blkmem, /**< block memory */
1365 SCIP_AGGRROW* proofrow, /**< proof rows data */
1366 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
1367 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
1368 SCIP_CONFTYPE conflicttype /**< type of the conflict */
1369 )
1370{
1371 SCIP_VAR** vars;
1372 SCIP_SOL* refsol;
1373 SCIP_Real* cutcoefs;
1374 SCIP_Real cutefficacy;
1375 SCIP_Real cutrhs;
1376 SCIP_Real proofefficacy;
1377 SCIP_Real efficacynorm;
1378 SCIP_Bool islocal;
1379 SCIP_Bool cutsuccess;
1380 SCIP_Bool success;
1381 SCIP_Bool infdelta;
1382 int* cutinds;
1383 int* inds;
1384 int cutnnz;
1385 int nnz;
1386 int nvars;
1387 int i;
1388
1389 vars = SCIPprobGetVars(transprob);
1390 nvars = SCIPprobGetNVars(transprob);
1391
1392 inds = SCIPaggrRowGetInds(proofrow);
1393 nnz = SCIPaggrRowGetNNz(proofrow);
1394
1395 proofefficacy = SCIPaggrRowGetMinActivity(set, transprob, proofrow, curvarlbs, curvarubs, &infdelta);
1396
1397 if( infdelta )
1398 return SCIP_OKAY;
1399
1400 proofefficacy -= SCIPaggrRowGetRhs(proofrow);
1401
1402 efficacynorm = SCIPaggrRowCalcEfficacyNorm(set->scip, proofrow);
1403 proofefficacy /= MAX(1e-6, efficacynorm);
1404
1405 /* create reference solution */
1406 SCIP_CALL( SCIPcreateSol(set->scip, &refsol, NULL) );
1407
1408 /* initialize with average solution */
1409 for( i = 0; i < nvars; i++ )
1410 {
1411 SCIP_CALL( SCIPsolSetVal(refsol, set, stat, tree, vars[i], SCIPvarGetAvgSol(vars[i])) );
1412 }
1413
1414 /* set all variables that are part of the proof to its active local bound */
1415 for( i = 0; i < nnz; i++ )
1416 {
1417 SCIP_Real val = SCIPaggrRowGetProbvarValue(proofrow, inds[i]);
1418
1419 if( val > 0.0 )
1420 {
1421 SCIP_CALL( SCIPsolSetVal(refsol, set, stat, tree, vars[inds[i]], curvarubs[inds[i]]) );
1422 }
1423 else
1424 {
1425 SCIP_CALL( SCIPsolSetVal(refsol, set, stat, tree, vars[inds[i]], curvarlbs[inds[i]]) );
1426 }
1427 }
1428
1429 SCIP_CALL( SCIPsetAllocBufferArray(set, &cutcoefs, nvars) );
1430 SCIP_CALL( SCIPsetAllocBufferArray(set, &cutinds, nvars) );
1431
1432 cutnnz = 0;
1433 cutefficacy = -SCIPsetInfinity(set);
1434
1435 /* apply flow cover */
1436 SCIP_CALL( SCIPcalcFlowCover(set->scip, refsol, POSTPROCESS, BOUNDSWITCH, ALLOWLOCAL, proofrow, \
1437 cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy, NULL, &islocal, &cutsuccess) );
1438 success = cutsuccess;
1439
1440 /* apply MIR */
1442 NULL, NULL, MINFRAC, MAXFRAC, proofrow, cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy, NULL, \
1443 &islocal, &cutsuccess) );
1444 success = (success || cutsuccess);
1445
1446 /* replace the current proof */
1447 if( success && !islocal && SCIPsetIsPositive(set, cutefficacy) && cutefficacy * nnz > proofefficacy * cutnnz )
1448 {
1449 SCIP_PROOFSET* alternativeproofset;
1450 SCIP_Bool redundant;
1451 int nchgcoefs;
1452
1453 SCIP_CALL( proofsetCreate(&alternativeproofset, blkmem) );
1455
1456 SCIP_CALL( proofsetAddSparseData(alternativeproofset, blkmem, cutcoefs, cutinds, cutnnz, cutrhs) );
1457
1458 /* apply coefficient tightening */
1459 tightenCoefficients(set, alternativeproofset, &nchgcoefs, &redundant);
1460
1461 if( !redundant )
1462 {
1463 SCIP_CALL( conflictInsertProofset(conflict, set, alternativeproofset) );
1464 }
1465 else
1466 {
1467 SCIPproofsetFree(&alternativeproofset, blkmem);
1468 }
1469 } /*lint !e438*/
1470
1471 SCIPsetFreeBufferArray(set, &cutinds);
1472 SCIPsetFreeBufferArray(set, &cutcoefs);
1473
1474 SCIP_CALL( SCIPfreeSol(set->scip, &refsol) );
1475
1476 return SCIP_OKAY;
1477}
1478
1479/** tighten a given infeasibility proof a^Tx <= b with minact > b w.r.t. local bounds
1480 *
1481 * 1) Apply cut generating functions
1482 * - c-MIR
1483 * - Flow-cover
1484 * - TODO: implement other subadditive functions
1485 * 2) Remove continuous variables contributing with its global bound
1486 * - TODO: implement a variant of non-zero-cancellation
1487 */
1488static
1490 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1491 SCIP_SET* set, /**< global SCIP settings */
1492 SCIP_STAT* stat, /**< dynamic SCIP statistics */
1493 BMS_BLKMEM* blkmem, /**< block memory */
1494 SCIP_PROB* transprob, /**< transformed problem */
1495 SCIP_TREE* tree, /**< tree data */
1496 SCIP_AGGRROW* proofrow, /**< aggregated row representing the proof */
1497 int validdepth, /**< depth where the proof is valid */
1498 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
1499 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
1500 SCIP_Bool initialproof /**< do we analyze the initial reason of infeasibility? */
1501 )
1502{
1503 SCIP_VAR** vars;
1504 SCIP_Real* vals;
1505 int* inds;
1506 SCIP_PROOFSET* proofset;
1507 SCIP_Bool redundant = FALSE;
1508 int nnz;
1509 int nchgcoefs;
1510 int nbinvars;
1511 int ncontvars;
1512 int nintvars;
1513 int i;
1514
1515 assert(conflict->proofset != NULL);
1516 assert(curvarlbs != NULL);
1517 assert(curvarubs != NULL);
1518
1519 vars = SCIPprobGetVars(transprob);
1520 nbinvars = 0;
1521 nintvars = 0;
1522 ncontvars = 0;
1523 nchgcoefs = 0;
1524
1525 inds = SCIPaggrRowGetInds(proofrow);
1526 nnz = SCIPaggrRowGetNNz(proofrow);
1527
1528 /* count number of binary, integer, and continuous variables */
1529 for( i = 0; i < nnz; i++ )
1530 {
1531 assert(SCIPvarGetProbindex(vars[inds[i]]) == inds[i]);
1532
1533 if( SCIPvarIsBinary(vars[inds[i]]) )
1534 ++nbinvars;
1535 else if( SCIPvarIsIntegral(vars[inds[i]]) )
1536 ++nintvars;
1537 else
1538 ++ncontvars;
1539 }
1540
1541 SCIPsetDebugMsg(set, "start dual proof tightening:\n");
1542 SCIPsetDebugMsg(set, "-> tighten dual proof: nvars=%d (bin=%d, int=%d, cont=%d)\n",
1543 nnz, nbinvars, nintvars, ncontvars);
1544 debugPrintViolationInfo(set, SCIPaggrRowGetMinActivity(set, transprob, proofrow, curvarlbs, curvarubs, NULL), SCIPaggrRowGetRhs(proofrow), NULL);
1545
1546 /* try to find an alternative proof of local infeasibility that is stronger */
1547 if( !set->exact_enable && set->conf_sepaaltproofs )
1548 {
1549 SCIP_CALL( separateAlternativeProofs(conflict, set, stat, transprob, tree, blkmem, proofrow, curvarlbs, curvarubs,
1550 conflict->conflictset->conflicttype) );
1551 }
1552
1553 if( initialproof )
1554 proofset = conflict->proofset;
1555 else
1556 {
1557 SCIP_CALL( proofsetCreate(&proofset, blkmem) );
1558 }
1559
1560 /* start with a proofset containing all variables with a non-zero coefficient in the dual proof */
1561 SCIP_CALL( proofsetAddAggrrow(proofset, set, blkmem, proofrow) );
1562 proofset->conflicttype = conflict->conflictset->conflicttype;
1563 proofset->validdepth = validdepth;
1564
1565 /* get proof data */
1566 vals = proofsetGetVals(proofset);
1567 inds = proofsetGetInds(proofset);
1568 nnz = SCIPproofsetGetNVars(proofset);
1569
1570#ifndef NDEBUG
1571 for( i = 0; i < nnz; i++ )
1572 {
1573 int idx = inds[i];
1574 if( vals[i] > 0.0 )
1575 assert(!SCIPsetIsInfinity(set, -curvarlbs[idx]));
1576 if( vals[i] < 0.0 )
1577 assert(!SCIPsetIsInfinity(set, curvarubs[idx]));
1578 }
1579#endif
1580
1581 /* remove continuous variable contributing with their global bound
1582 *
1583 * todo: check whether we also want to do that for bound exceeding proofs, but then we cannot update the
1584 * conflict anymore
1585 */
1586 if( !set->exact_enable && proofset->conflicttype == SCIP_CONFTYPE_INFEASLP )
1587 {
1588 /* remove all continuous variables that have equal global and local bounds (ub or lb depend on the sign)
1589 * from the proof
1590 */
1591
1592 for( i = 0; i < nnz && nnz > 1; )
1593 {
1594 SCIP_Real val;
1595 int idx = inds[i];
1596
1597 assert(vars[idx] != NULL);
1598
1599 val = vals[i];
1600 assert(!SCIPsetIsZero(set, val));
1601
1602 /* skip integral variables */
1603 if( SCIPvarIsNonimpliedIntegral(vars[idx]) )
1604 {
1605 i++;
1606 continue;
1607 }
1608 else
1609 {
1610 SCIP_Real glbbd;
1611 SCIP_Real locbd;
1612 SCIP_Bool valid;
1613
1614 /* get appropriate global and local bounds */
1615 glbbd = (val < 0.0 ? SCIPvarGetUbGlobal(vars[idx]) : SCIPvarGetLbGlobal(vars[idx]));
1616 locbd = (val < 0.0 ? curvarubs[idx] : curvarlbs[idx]);
1617
1618 if( !SCIPsetIsEQ(set, glbbd, locbd) )
1619 {
1620 i++;
1621 continue;
1622 }
1623
1624 SCIPsetDebugMsg(set, "-> remove continuous variable <%s>: glb=[%g,%g], loc=[%g,%g], val=%g\n",
1625 SCIPvarGetName(vars[idx]), SCIPvarGetLbGlobal(vars[idx]), SCIPvarGetUbGlobal(vars[idx]),
1626 curvarlbs[idx], curvarubs[idx], val);
1627
1628 proofsetCancelVarWithBound(proofset, set, vars[idx], i, &valid);
1629 assert(valid); /* this should be always fulfilled at this place */
1630
1631 --nnz;
1632 }
1633 }
1634 }
1635
1636 /* apply coefficient tightening to initial proof */
1637 if( !set->exact_enable )
1638 tightenCoefficients(set, proofset, &nchgcoefs, &redundant);
1639
1640 /* it can happen that the constraints is almost globally redundant w.r.t to the maximal activity,
1641 * e.g., due to numerics. in this case, we want to discard the proof
1642 */
1643 if( !set->exact_enable && redundant )
1644 {
1645#ifndef NDEBUG
1646 SCIP_Real eps = MIN(0.01, 10.0*set->num_feastol);
1647 assert(proofset->rhs - getMaxActivity(set, transprob, proofset->vals, proofset->inds, proofset->nnz, NULL, NULL) < eps);
1648#endif
1649 if( initialproof )
1650 {
1651 proofsetClear(proofset);
1652 }
1653 else
1654 {
1655 SCIPproofsetFree(&proofset, blkmem);
1656 }
1657 }
1658 else
1659 {
1660 if( !initialproof )
1661 {
1662 SCIP_CALL( conflictInsertProofset(conflict, set, proofset) );
1663 }
1664
1665 if( nchgcoefs > 0 )
1666 {
1667 if( proofset->conflicttype == SCIP_CONFTYPE_INFEASLP )
1669 else if( proofset->conflicttype == SCIP_CONFTYPE_BNDEXCEEDING )
1671 }
1672 }
1673
1674 return SCIP_OKAY;
1675}
1676
1677/** perform conflict analysis based on a dual unbounded ray
1678 *
1679 * given an aggregation of rows lhs <= a^Tx such that lhs > maxactivity. if the constraint has size one we add a
1680 * bound change instead of the constraint.
1681 */
1683 SCIP_CONFLICT* conflict, /**< conflict analysis data */
1684 SCIP_SET* set, /**< global SCIP settings */
1685 SCIP_STAT* stat, /**< dynamic SCIP statistics */
1686 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1687 BMS_BLKMEM* blkmem, /**< block memory */
1688 SCIP_PROB* origprob, /**< original problem */
1689 SCIP_PROB* transprob, /**< transformed problem */
1690 SCIP_TREE* tree, /**< tree data */
1691 SCIP_REOPT* reopt, /**< reoptimization data */
1692 SCIP_LP* lp, /**< LP data */
1693 SCIP_AGGRROW* proofrow, /**< aggregated row representing the proof */
1694 int validdepth, /**< valid depth of the dual proof */
1695 SCIP_Real* curvarlbs, /**< current lower bounds of active problem variables */
1696 SCIP_Real* curvarubs, /**< current upper bounds of active problem variables */
1697 SCIP_Bool initialproof, /**< do we analyze the initial reason of infeasibility? */
1698 SCIP_Bool* globalinfeasible, /**< pointer to store whether global infeasibility could be proven */
1699 SCIP_Bool* success /**< pointer to store success result */
1700 )
1701{
1702 SCIP_Real rhs;
1703 SCIP_Real minact;
1704 SCIP_Bool infdelta;
1705 int nnz;
1706
1707 assert(set != NULL);
1708 assert(transprob != NULL);
1709 assert(validdepth >= 0);
1710 assert(validdepth == 0 || validdepth < SCIPtreeGetFocusDepth(tree));
1711
1712 /* get sparse data */
1713 nnz = SCIPaggrRowGetNNz(proofrow);
1714 rhs = SCIPaggrRowGetRhs(proofrow);
1715
1716 *globalinfeasible = FALSE;
1717 *success = FALSE;
1718
1719 /* get minimal activity w.r.t. local bounds */
1720 minact = SCIPaggrRowGetMinActivity(set, transprob, proofrow, curvarlbs, curvarubs, &infdelta);
1721
1722 if( infdelta )
1723 return SCIP_OKAY;
1724
1725 /* only run is the proof proves local infeasibility */
1726 if( SCIPsetIsFeasLE(set, minact, rhs) )
1727 return SCIP_OKAY;
1728
1729 /* if the farkas-proof is empty, the node and its sub tree can be cut off completely */
1730 if( nnz == 0 )
1731 {
1732 SCIPsetDebugMsg(set, " -> empty farkas-proof in depth %d cuts off sub tree at depth %d\n", SCIPtreeGetFocusDepth(tree), validdepth);
1733
1734 SCIP_CALL( SCIPnodeCutoff(tree->path[validdepth], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
1735
1736 *globalinfeasible = TRUE;
1737 *success = TRUE;
1738
1739 ++conflict->ndualproofsinfsuccess;
1740
1741 return SCIP_OKAY;
1742 }
1743
1744 /* try to enforce the constraint based on a dual ray */
1745 SCIP_CALL( tightenDualproof(conflict, set, stat, blkmem, transprob, tree, proofrow, validdepth,
1746 curvarlbs, curvarubs, initialproof) );
1747
1748 if( *globalinfeasible )
1749 {
1750 SCIPsetDebugMsg(set, "detect global: cutoff root node\n");
1751 SCIP_CALL( SCIPnodeCutoff(tree->path[0], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
1752 *success = TRUE;
1753
1754 ++conflict->ndualproofsinfsuccess;
1755 }
1756
1757 return SCIP_OKAY;
1758}
SCIP_CERTIFICATE * SCIPgetCertificate(SCIP *scip)
methods for certificate output
internal methods for clocks and timing issues
#define BOUNDSWITCH
#define MAXFRAC
void SCIPproofsetFree(SCIP_PROOFSET **proofset, BMS_BLKMEM *blkmem)
static char varGetChar(SCIP_VAR *var)
#define POSTPROCESS
static SCIP_RETCODE tightenDualproof(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_AGGRROW *proofrow, int validdepth, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_Bool initialproof)
static SCIP_Real * proofsetGetVals(SCIP_PROOFSET *proofset)
#define ALLOWLOCAL
static SCIP_CONFTYPE proofsetGetConftype(SCIP_PROOFSET *proofset)
static SCIP_RETCODE conflictEnsureProofsetsMem(SCIP_CONFLICT *conflict, SCIP_SET *set, int num)
static SCIP_Real getMaxActivity(SCIP_SET *set, SCIP_PROB *transprob, SCIP_Real *coefs, int *inds, int nnz, SCIP_Real *curvarlbs, SCIP_Real *curvarubs)
#define VARTYPEUSEVBDS
static int * proofsetGetInds(SCIP_PROOFSET *proofset)
static SCIP_RETCODE createAndAddProofcons(SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_PROOFSET *proofset, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem)
static SCIP_Real getMinActivity(SCIP_SET *set, SCIP_PROB *transprob, SCIP_Real *coefs, int *inds, int nnz, SCIP_Real *curvarlbs, SCIP_Real *curvarubs)
static SCIP_RETCODE separateAlternativeProofs(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_AGGRROW *proofrow, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_CONFTYPE conflicttype)
SCIP_RETCODE SCIPconflictInitProofset(SCIP_CONFLICT *conflict, BMS_BLKMEM *blkmem)
static SCIP_RETCODE proofsetAddAggrrow(SCIP_PROOFSET *proofset, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_AGGRROW *aggrrow)
#define MINFRAC
static SCIP_RETCODE propagateLongProof(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_REOPT *reopt, SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Real *coefs, int *inds, int nnz, SCIP_Real rhs, SCIP_CONFTYPE conflicttype, int validdepth)
#define debugPrintViolationInfo(...)
static void proofsetCancelVarWithBound(SCIP_PROOFSET *proofset, SCIP_SET *set, SCIP_VAR *var, int pos, SCIP_Bool *valid)
static void tightenCoefficients(SCIP_SET *set, SCIP_PROOFSET *proofset, int *nchgcoefs, SCIP_Bool *redundant)
SCIP_RETCODE SCIPconflictFlushProofset(SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable)
static SCIP_RETCODE tightenSingleVar(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real val, SCIP_Real rhs, SCIP_CONFTYPE prooftype, int validdepth)
static void proofsetClear(SCIP_PROOFSET *proofset)
SCIP_RETCODE SCIPconflictAnalyzeDualProof(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_AGGRROW *proofrow, int validdepth, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_Bool initialproof, SCIP_Bool *globalinfeasible, SCIP_Bool *success)
static SCIP_RETCODE proofsetCreate(SCIP_PROOFSET **proofset, BMS_BLKMEM *blkmem)
static SCIP_Real proofsetGetRhs(SCIP_PROOFSET *proofset)
int SCIPproofsetGetNVars(SCIP_PROOFSET *proofset)
static SCIP_RETCODE proofsetAddSparseData(SCIP_PROOFSET *proofset, BMS_BLKMEM *blkmem, SCIP_Real *vals, int *inds, int nnz, SCIP_Real rhs)
static SCIP_RETCODE conflictInsertProofset(SCIP_CONFLICT *conflict, SCIP_SET *set, SCIP_PROOFSET *proofset)
internal methods for dual proof conflict analysis
SCIP_Real SCIPaggrRowGetMinActivity(SCIP_SET *set, SCIP_PROB *transprob, SCIP_AGGRROW *aggrrow, SCIP_Real *curvarlbs, SCIP_Real *curvarubs, SCIP_Bool *infdelta)
methods and datastructures for conflict analysis
SCIP_RETCODE SCIPconflictstoreAddDualraycons(SCIP_CONFLICTSTORE *conflictstore, SCIP_CONS *dualproof, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_REOPT *reopt, SCIP_Bool hasrelaxvar)
int SCIPconflictstoreGetNDualInfProofs(SCIP_CONFLICTSTORE *conflictstore)
SCIP_Real SCIPconflictstoreGetAvgNnzDualInfProofs(SCIP_CONFLICTSTORE *conflictstore)
int SCIPconflictstoreGetNDualBndProofs(SCIP_CONFLICTSTORE *conflictstore)
SCIP_Real SCIPconflictstoreGetAvgNnzDualBndProofs(SCIP_CONFLICTSTORE *conflictstore)
SCIP_RETCODE SCIPconflictstoreAddDualsolcons(SCIP_CONFLICTSTORE *conflictstore, SCIP_CONS *dualproof, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_REOPT *reopt, SCIP_Real scale, SCIP_Bool updateside, SCIP_Bool hasrelaxvar)
internal methods for storing conflicts
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6439
SCIP_RETCODE SCIPconsMarkConflict(SCIP_CONS *cons)
Definition: cons.c:7293
internal methods for constraints and constraint handlers
Constraint handler for linear constraints in their most general form, .
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 QUAD_ASSIGN(a, constant)
Definition: dbldblarith.h:51
#define QUAD(x)
Definition: dbldblarith.h:47
#define SCIPquadprecSumQQ(r, a, b)
Definition: dbldblarith.h:67
#define QUAD_TO_DBL(x)
Definition: dbldblarith.h:49
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_ALLOC(x)
Definition: def.h:366
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define REALABS(x)
Definition: def.h:182
#define SCIP_LONGINT_MAX
Definition: def.h:142
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_RATIONAL * SCIPgetLhsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
SCIP_RATIONAL * SCIPgetRhsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsExactLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_RATIONAL **vals, SCIP_RATIONAL *lhs, SCIP_RATIONAL *rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPhashmapInsertLong(SCIP_HASHMAP *hashmap, void *origin, SCIP_Longint image)
Definition: misc.c:3215
SCIP_Bool SCIPisCertified(SCIP *scip)
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4316
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8409
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_RETCODE SCIPcutGenerationHeuristicCMIR(SCIP *scip, SCIP_SOL *sol, SCIP_Bool postprocess, SCIP_Real boundswitch, int vartypeusevbds, SCIP_Bool allowlocal, int maxtestdelta, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_AGGRROW *aggrrow, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, int *cutinds, int *cutnnz, SCIP_Real *cutefficacy, int *cutrank, SCIP_Bool *cutislocal, SCIP_Bool *success)
Definition: cuts.c:8339
SCIP_Bool SCIPcutsTightenCoefficients(SCIP *scip, SCIP_Bool cutislocal, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, int *cutinds, int *cutnnz, int *nchgcoefs)
Definition: cuts.c:2466
SCIP_Real SCIPaggrRowGetRhs(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:4068
int * SCIPaggrRowGetInds(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:4028
int SCIPaggrRowGetNNz(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:4038
static INLINE SCIP_Real SCIPaggrRowGetProbvarValue(SCIP_AGGRROW *aggrrow, int probindex)
Definition: cuts.h:297
SCIP_RETCODE SCIPcalcFlowCover(SCIP *scip, SCIP_SOL *sol, SCIP_Bool postprocess, SCIP_Real boundswitch, SCIP_Bool allowlocal, SCIP_AGGRROW *aggrrow, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, int *cutinds, int *cutnnz, SCIP_Real *cutefficacy, int *cutrank, SCIP_Bool *cutislocal, SCIP_Bool *success)
Definition: cuts.c:11645
SCIP_Real SCIPaggrRowCalcEfficacyNorm(SCIP *scip, SCIP_AGGRROW *aggrrow)
Definition: cuts.c:3243
BMS_BUFMEM * SCIPbuffer(SCIP *scip)
Definition: scip_mem.c:72
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:8483
SCIP_Bool SCIPrationalIsAbsInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1680
void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
Definition: rational.cpp:603
void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:473
SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:123
void SCIPrationalSetNegInfinity(SCIP_RATIONAL *res)
Definition: rational.cpp:630
SCIP_Real SCIPrationalRoundReal(SCIP_RATIONAL *rational, SCIP_ROUNDMODE_RAT roundmode)
Definition: rational.cpp:2110
SCIP_RETCODE SCIPrationalCreateBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***rational, int size)
Definition: rational.cpp:214
void SCIPrationalFreeBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***ratbufarray, int size)
Definition: rational.cpp:518
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_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_Bool SCIPvarIsNonimpliedIntegral(SCIP_VAR *var)
Definition: var.c:23506
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:23662
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:19827
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:23600
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
internal methods for branching and inference history
internal methods for LP management
interface methods for specific LP solvers
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:462
#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 BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
real eps
methods commonly used for presolving
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2868
SCIP_RETCODE SCIPprobAddCons(SCIP_PROB *prob, SCIP_SET *set, SCIP_STAT *stat, SCIP_CONS *cons)
Definition: prob.c:1507
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 SCIPdebugMessage
Definition: pub_message.h:96
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for handling parameter settings
public methods for propagators
public methods for branch and bound tree
public methods for problem variables
public methods for certified solving
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for exact solving
public methods for memory management
public methods for solutions
public methods for SCIP variables
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6617
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6993
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_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:7124
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 SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6597
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6670
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6637
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 SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1775
#define SCIPsetDebugMsg
Definition: set.h:1811
SCIP_RETCODE SCIPsolSetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_VAR *var, SCIP_Real val)
Definition: sol.c:1490
internal methods for storing primal CIP solutions
SCIP_Longint certificateline
Definition: struct_cuts.h:53
SCIP_Real * vals
Definition: struct_cuts.h:42
SCIP_HASHMAP * rowdatahash
SCIP_CONFTYPE conflicttype
SCIP_Longint ndualproofsbndglobal
SCIP_PROOFSET * proofset
SCIP_Longint ndualproofsinfsuccess
SCIP_PROOFSET ** proofsets
SCIP_Longint ndualproofsinflocal
SCIP_Longint nglbchgbds
SCIP_Longint dualproofsbndnnonzeros
SCIP_Longint nlocchgbds
SCIP_Longint ndualproofsinfglobal
SCIP_Longint ninflpsuccess
SCIP_Longint ndualproofsbndsuccess
SCIP_Longint dualproofsinfnnonzeros
SCIP_Longint nboundlpsuccess
SCIP_CONFLICTSET * conflictset
SCIP_Longint ndualproofsbndlocal
SCIP_Bool strongbranching
Definition: struct_lp.h:383
int startnconss
Definition: struct_prob.h:91
SCIP_Longint certificateline
SCIP_Real * vals
SCIP_CONFTYPE conflicttype
SCIP_Real avgnnz
Definition: struct_stat.h:131
SCIP_NODE ** path
Definition: struct_tree.h:190
data structures for certificate output
datastructures for conflict analysis
data structures for LP management
datastructures for storing and manipulating the main problem
datastructures for global SCIP settings
datastructures for problem statistics
data structures for branch and bound tree
datastructures for problem variables
Definition: heur_padm.c:135
int SCIPtreeGetFocusDepth(SCIP_TREE *tree)
Definition: tree.c:9404
SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition: tree.c:2539
void SCIPnodePropagateAgain(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree)
Definition: tree.c:1368
SCIP_RETCODE SCIPnodeCutoff(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_REOPT *reopt, SCIP_LP *lp, BMS_BLKMEM *blkmem)
Definition: tree.c:1259
int SCIPtreeGetEffectiveRootDepth(SCIP_TREE *tree)
Definition: tree.c:9518
SCIP_RETCODE SCIPnodeAddCons(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_CONS *cons)
Definition: tree.c:1696
internal methods for branch and bound tree
@ SCIP_CONFTYPE_ALTINFPROOF
Definition: type_conflict.h:65
@ SCIP_CONFTYPE_BNDEXCEEDING
Definition: type_conflict.h:64
@ SCIP_CONFTYPE_ALTBNDPROOF
Definition: type_conflict.h:66
@ SCIP_CONFTYPE_INFEASLP
Definition: type_conflict.h:63
@ SCIP_CONFTYPE_UNKNOWN
Definition: type_conflict.h:61
enum SCIP_ConflictType SCIP_CONFTYPE
Definition: type_conflict.h:68
@ 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_R_ROUND_NEAREST
Definition: type_rational.h:59
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_INVALIDCALL
Definition: type_retcode.h:51
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_VARTYPE_INTEGER
Definition: type_var.h:65
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:64
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:10012
internal methods for problem variables
methods for creating output for visualization tools (VBC, BAK)