Scippy

SCIP

Solving Constraint Integer Programs

certificate.cpp
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 certificate.cpp
26 * @ingroup OTHER_CFILES
27 * @brief methods for certificate output
28 * @author Ambros Gleixner
29 * @author Daniel Steffy
30 * @author Leon Eifler
31 */
32
33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34#include <stdio.h>
35#include <assert.h>
36#include <string.h>
37#include <map>
38
39#include "lpiexact/lpiexact.h"
40#include "scip/def.h"
42#include "scip/lp.h"
43#include "scip/lpexact.h"
44#include "scip/misc.h"
45#include "scip/pub_cons.h"
46#include "scip/pub_lpexact.h"
47#include "scip/pub_misc.h"
48#include "scip/pub_message.h"
49#include "scip/pub_tree.h"
50#include "scip/pub_var.h"
51#include "scip/prob.h"
52#include "scip/cuts.h"
55#include "scip/scip_exact.h"
56#include "scip/scip_general.h"
57#include "scip/scip_lp.h"
58#include "scip/scip_mem.h"
59#include "scip/scip_message.h"
60#include "scip/scip_numerics.h"
61#include "scip/scip_prob.h"
62#include "scip/scip_probing.h"
63#include "scip/scip_sol.h"
64#include "scip/scip_solve.h"
66#include "scip/scip_tree.h"
67#include "scip/set.h"
68#include "scip/sol.h"
70#include "scip/struct_lpexact.h"
71#include "scip/struct_scip.h"
72#include "scip/struct_stat.h"
73#include "scip/struct_var.h"
74#include "scip/var.h"
75#include "scip/certificate.h"
76
77#define SCIP_HASHSIZE_CERTIFICATE 500 /**< size of hash map for certificate -> nodesdata mapping used for certificate output */
78#define SCIP_MB_TO_CHAR_RATE 1048576.0 /**< conversion rate from MB to characters */
79
80/** updates file size and returns whether maximum file size has been reached */
81static
83 SCIP_CERTIFICATE* certificate, /**< certificate information */
84 SCIP_Real nchars /**< number of characters printed */
85 )
86{
87 if( certificate->filesize < certificate->maxfilesize )
88 certificate->filesize += nchars/(SCIP_MB_TO_CHAR_RATE);
89 if( certificate->filesize < certificate->maxfilesize )
90 return TRUE;
91 return FALSE;
92}
93
94/** checks whether node is a left node or not */
95static
97 SCIP_CERTIFICATE* certificate, /**< certificate information */
98 SCIP_NODE* node /**< node from branch and bound tree */
99 )
100{
102 SCIP_CERTNODEDATA* nodedataparent;
103
104 assert(certificate != NULL);
105 assert(SCIPcertificateIsEnabled(certificate));
106
107 assert(node != NULL);
109
110 assert(SCIPhashmapExists(certificate->nodedatahash, node));
112
113 if( SCIPnodeGetParent(node) == NULL )
114 return FALSE;
115
116 assert(SCIPhashmapExists(certificate->nodedatahash, node));
117 nodedataparent = (SCIP_CERTNODEDATA*)SCIPhashmapGetImage(certificate->nodedatahash, SCIPnodeGetParent(node));
118
119 assert(nodedata->assumptionindex_self != -1);
120 if( nodedataparent->assumptionindex_left == nodedata->assumptionindex_self )
121 return TRUE;
122 else
123 return FALSE;
124}
125
126/** prints variable bound assumption into certificate
127 *
128 * @return index of this bound in the certificate file
129 */
130static
132 SCIP_CERTIFICATE* certificate, /**< certificate information */
133 SCIP_VAR* var, /**< variable to print assumption for */
134 SCIP_RATIONAL* boundval, /**< value of the bound */
135 SCIP_BOUNDTYPE boundtype /**< is it the upper bound? */
136 )
137{
138 assert(certificate != NULL);
139 assert(SCIPcertificateIsEnabled(certificate));
140
141#ifndef NDEBUG
142 certificate->lastinfo->isbound = TRUE;
143 certificate->lastinfo->boundtype = boundtype;
144 certificate->lastinfo->varindex = SCIPvarGetCertificateIndex(var);
145 certificate->lastinfo->isglobal = FALSE;
146 certificate->lastinfo->certificateindex = certificate->indexcounter;
147 SCIPrationalSetRational(certificate->lastinfo->boundval, boundval);
148#endif
149
150 /** @todo it could be better to separate the printing from insertion of variable bound */
151 SCIPcertificatePrintProofMessage(certificate, "A%lld %c ", certificate->indexcounter, (boundtype == SCIP_BOUNDTYPE_LOWER) ? 'G' : 'L');
152
153 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, boundval) );
154 SCIPcertificatePrintProofMessage(certificate, " 1 %d 1 { asm } -1\n", SCIPvarGetCertificateIndex(var));
155 certificate->indexcounter++;
156
157 return certificate->indexcounter - 1;
158}
159
160/** free nodedata of corresponding node */
161static
163 SCIP_CERTIFICATE* certificate, /**< certificate information */
164 SCIP_NODE* node /**< focus node */
165 )
166{
168
169 assert(node != NULL);
170 assert(certificate != NULL);
171 assert(SCIPcertificateIsEnabled(certificate));
172
173 assert(SCIPhashmapExists(certificate->nodedatahash, node));
175 SCIPrationalFreeBlock(certificate->blkmem, &nodedata->derbound_left);
176 SCIPrationalFreeBlock(certificate->blkmem, &nodedata->derbound_right);
177 SCIPrationalFreeBlock(certificate->blkmem, &nodedata->derbound_self);
178 BMSfreeBlockMemory(certificate->blkmem, &nodedata);
179 SCIP_CALL( SCIPhashmapRemove(certificate->nodedatahash, node) );
180
181 return SCIP_OKAY;
182}
183
184/** prints dual bound to proof section and increments indexcounter */
185static
187 SCIP_CERTIFICATE* certificate, /**< certificate data structure */
188 const char* linename, /**< name of the unsplitting line */
189 SCIP_RATIONAL* lowerbound, /**< pointer to lower bound on the objective, NULL indicating infeasibility */
190 int len, /**< number of dual multipiers */
191 SCIP_Longint* ind, /**< index array */
192 SCIP_RATIONAL** val /**< array of dual multipliers */
193 )
194{
195 /* check whether certificate output should be created */
196 if( !SCIPcertificateIsEnabled(certificate) )
197 return SCIP_OKAY;
198
199 certificate->indexcounter++;
200 certificate->lastinfo->isbound = FALSE;
201
202 if( linename == NULL )
203 {
204 SCIPcertificatePrintProofMessage(certificate, "DualBound_%d ", certificate->indexcounter - 1);
205 }
206 else
207 {
208 SCIPcertificatePrintProofMessage(certificate, "%s ", linename);
209 }
210
211 if( SCIPrationalIsInfinity(lowerbound) )
212 {
213 SCIPcertificatePrintProofMessage(certificate, "G 1 0");
214 }
215 else
216 {
217 SCIPcertificatePrintProofMessage(certificate, "G ");
218 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, lowerbound) );
219 SCIPcertificatePrintProofMessage(certificate, " ");
220 SCIPcertificatePrintProofMessage(certificate, "OBJ");
221 }
222
223 if( val == NULL )
224 {
225 SCIPcertificatePrintProofMessage(certificate, " { lin ... } -1\n");
226 }
227 else
228 {
229 int i;
230
231 SCIPcertificatePrintProofMessage(certificate, " { lin %d", len);
232
233 for( i = 0; i < len; i++ )
234 {
235 /** @todo perform line breaking before exceeding maximum line length */
236 assert(!SCIPrationalIsAbsInfinity(val[i]));
237 SCIPcertificatePrintProofMessage(certificate, " %d ", ind[i]);
238 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, val[i]) );
239 }
240 SCIPcertificatePrintProofMessage(certificate, " } -1\n");
241 }
242
243 /* print rounding derivation */
244 if( !SCIPrationalIsNegInfinity(lowerbound) && certificate->objintegral && !SCIPrationalIsIntegral(lowerbound) )
245 {
246 certificate->indexcounter++;
247 certificate->lastinfo->isbound = FALSE;
248
249 SCIPcertificatePrintProofMessage(certificate, "R%d G ", certificate->indexcounter - 1);
250 SCIPrationalRoundInteger(lowerbound, lowerbound, SCIP_R_ROUND_UPWARDS);
251
252 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, lowerbound) );
253
254 SCIPcertificatePrintProofMessage(certificate, " ");
255 SCIPcertificatePrintProofMessage(certificate, "OBJ");
256 SCIPcertificatePrintProofMessage(certificate, " { rnd 1 %d 1 } -1\n", certificate->indexcounter - 2);
257 }
258
259 return SCIP_OKAY;
260}
261
262/** prints the best solution found */
263static
265 SCIP* scip, /**< SCIP data structure */
266 SCIP_Bool isorigfile, /**< should the original solution be printed or in transformed space */
267 SCIP_CERTIFICATE* certificate, /**< certificate information */
268 SCIP_SOL* sol /**< solution to be printed */
269 )
270{
271 SCIP_VAR** vars;
272 SCIP_RATIONAL** vals;
273 int nvars;
274 int nnonz;
275 int i;
276
277 /* check if certificate output should be created */
278 if( certificate->origfile == NULL )
279 return SCIP_OKAY;
280
281 assert(scip != NULL);
282
283 if( sol == NULL )
284 {
285 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "SOL 0\n");
286 return SCIP_OKAY;
287 }
288 else if( !SCIPsolIsExact(sol) )
289 {
291 }
292
293 /* get variables and number of the transformed problem */
294 if( isorigfile )
295 {
296 SCIP_CALL( SCIPgetOrigVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
297 }
298 else
299 {
300 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
301 }
302
304
305 /* get number of non-zero coefficient in the solution */
306 nnonz = 0;
307 for( i = 0; i < nvars; i++)
308 {
309 SCIPsolGetValExact(vals[i], sol, scip->set, scip->stat, vars[i]);
310 if( !SCIPrationalIsZero(vals[i]) )
311 nnonz++;
312 }
313
314 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "SOL 1\nbest %d", nnonz);
315
316 for( i = 0; i < nvars; i++ )
317 {
318 if( !SCIPrationalIsZero(vals[i]) )
319 {
320 /* print the solution into certificate */
321 SCIPcertificatePrintProblemMessage(certificate, isorigfile, " %d ", SCIPvarGetCertificateIndex(vars[i]));
322 SCIP_CALL( SCIPcertificatePrintProblemRational(certificate, isorigfile, vals[i]) );
323 }
324 }
325 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "\n");
326
328
329 return SCIP_OKAY;
330}
331
332/** updates the current derived bound of the node with newbound, if newbound is better */
334 SCIP_CERTIFICATE* certificate, /**< certificate information */
335 SCIP_NODE* node, /**< node data structure */
336 SCIP_Longint fileindex, /**< index of new bound's proof */
337 SCIP_RATIONAL* newbound /**< value of new bound */
338 )
339{
341
342 if( !SCIPcertificateIsEnabled(certificate) )
343 return SCIP_OKAY;
344
345 assert(SCIPhashmapExists(certificate->nodedatahash, node));
347
348 /* do nothing if newbound is not better than the current bound */
349 if( SCIPrationalIsLT(newbound, nodedata->derbound_self) )
350 return SCIP_OKAY;
351
352 nodedata->inheritedbound = FALSE;
353 nodedata->derindex_self = fileindex;
354 SCIPrationalSetRational(nodedata->derbound_self, newbound);
355
356 return SCIP_OKAY;
357}
358
359/** creates certificate data structure */
361 SCIP_CERTIFICATE** certificate, /**< pointer to store the certificate information */
362 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
363 )
364{
365 SCIP_ALLOC( BMSallocMemory(certificate) );
366
367 (*certificate)->messagehdlr = messagehdlr;
368 (*certificate)->lastinfo = NULL;
369 (*certificate)->blkmem = NULL;
370 (*certificate)->indexcounter = 0;
371 (*certificate)->indexcounter_ori = 0;
372 (*certificate)->conscounter = 0;
373 (*certificate)->origfile = NULL;
374 (*certificate)->transfile = NULL;
375 (*certificate)->origfilename = NULL;
376 (*certificate)->derivationfile = NULL;
377 (*certificate)->derivationfilename = NULL;
378 (*certificate)->filesize = 0.0;
379 (*certificate)->maxfilesize = SCIP_REAL_MAX;
380 (*certificate)->rowdatahash = NULL;
381 (*certificate)->naggrinfos = 0;
382 (*certificate)->nmirinfos = 0;
383 (*certificate)->aggrinfosize = 0;
384 (*certificate)->mirinfosize = 0;
385 (*certificate)->nodedatahash = NULL;
386 (*certificate)->rootbound = NULL;
387 (*certificate)->finalbound = NULL;
388 (*certificate)->derindex_root = -1;
389 (*certificate)->rootinfeas = FALSE;
390 (*certificate)->objintegral = FALSE;
391 (*certificate)->workingmirinfo = FALSE;
392 (*certificate)->workingaggrinfo = FALSE;
393 (*certificate)->vals = NULL;
394 (*certificate)->valssize = 0;
395 (*certificate)->aggrinfo = NULL;
396 (*certificate)->mirinfo = NULL;
397 (*certificate)->transfile_initialized = FALSE;
398
399 return SCIP_OKAY;
400}
401
402/** frees certificate data structure */
404 SCIP_CERTIFICATE** certificate /**< pointer to store the certificate information */
405 )
406{
407 assert(certificate != NULL);
408 assert(*certificate != NULL);
409 assert((*certificate)->origfile == NULL);
410 assert((*certificate)->transfile == NULL);
411 assert((*certificate)->derivationfile == NULL);
412
413 BMSfreeMemory(certificate);
414}
415
416/* @todo replace scip pointer by set->scip */
417/** initializes certificate information and creates files for certificate output */
419 SCIP* scip, /**< scip data structure */
420 SCIP_CERTIFICATE* certificate, /**< certificate information */
421 BMS_BLKMEM* blkmem, /**< block memory */
422 SCIP_SET* set, /**< global SCIP settings */
423 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
424 )
425{
426 int filenamelen;
427 int bufferlen;
428 int nvars;
429 int nintvars;
430 int nbinvars;
431 int nboundconss;
432 int ncertcons;
433 int ntransvars;
434 int j;
435 char* name = NULL;
436 SCIP_VAR** vars;
437 SCIP_VAR** transvars;
438 SCIP_CONS** conss;
439 SCIP_RATIONAL* lb;
440 SCIP_RATIONAL* ub;
441
442 assert(certificate != NULL);
443 assert(set != NULL);
444 assert(set->certificate_filename != NULL);
445 assert(certificate->derivationfile == NULL);
446 assert(certificate->nodedatahash == NULL);
447 assert(certificate->rowdatahash == NULL);
448
449 if( !(set->exact_enable) || (set->certificate_filename[0] == '-' && set->certificate_filename[1] == '\0') )
450 return SCIP_OKAY;
451
452 filenamelen = (int) strlen(set->certificate_filename);
453 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, filenamelen + 1) );
454 BMScopyMemoryArray(name, set->certificate_filename, filenamelen);
455 name[filenamelen] = '\0';
456
457 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_NORMAL,
458 "storing certificate information in file <%s>\n", set->certificate_filename);
459
460 certificate->transfile = SCIPfopen(set->certificate_filename, "wT");
461 certificate->maxfilesize = set->certificate_maxfilesize;
462
463 bufferlen = (int) strlen(name); /*lint !e668*/
464 SCIP_ALLOC( BMSallocMemoryArray(&certificate->derivationfilename, filenamelen+5) );
465 SCIP_ALLOC( BMSallocMemoryArray(&certificate->origfilename, filenamelen+5) );
466 BMScopyMemoryArray(certificate->derivationfilename, name, bufferlen);
467 BMScopyMemoryArray(certificate->origfilename, name, bufferlen);
468 certificate->derivationfilename[bufferlen] = '_';
469 certificate->derivationfilename[bufferlen+1] = 'd';
470 certificate->derivationfilename[bufferlen+2] = 'e';
471 certificate->derivationfilename[bufferlen+3] = 'r';
472 certificate->origfilename[bufferlen] = '_';
473 certificate->origfilename[bufferlen+1] = 'o';
474 certificate->origfilename[bufferlen+2] = 'r';
475 certificate->origfilename[bufferlen+3] = 'i';
476 certificate->derivationfilename[bufferlen+4] = '\0';
477 certificate->origfilename[bufferlen+4] = '\0';
478 certificate->derivationfile = SCIPfopen(certificate->derivationfilename, "wT");
479 certificate->origfile = SCIPfopen(certificate->origfilename, "wT");
480
481 if( certificate->transfile == NULL || certificate->origfile == NULL || certificate->derivationfile == NULL )
482 {
483 SCIPerrorMessage("error creating file <%s> and auxiliary certificate files\n", set->certificate_filename);
484 SCIPprintSysError(set->certificate_filename);
486 }
487
488 /* initialisation of hashmaps and hashtables */
497
498 certificate->blkmem = blkmem;
500
501 SCIP_CALL( SCIPgetOrigVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
502 SCIP_CALL( SCIPgetVarsData(scip, &transvars, &ntransvars, NULL, NULL, NULL, NULL) );
503 nboundconss = 0;
504 for( j = 0 ; j < nvars ; j++ )
505 {
506 lb = SCIPvarGetLbGlobalExact(vars[j]);
507 ub = SCIPvarGetUbGlobalExact(vars[j]);
509 nboundconss++;
511 nboundconss++;
512 }
513
514 /* print the Version Header into certificate */
516
517 /* print the Variable Header into certificate */
518 SCIPcertificatePrintVarHeader(certificate, TRUE, nvars);
519 for( j = 0; j < nvars; j++ )
520 {
521 const char* varname;
522
523 varname = SCIPvarGetName(vars[j]);
524 SCIPvarSetCertificateIndex(vars[j], j);
525 if( strstr(varname, " ") != NULL || strstr(varname, "\t") != NULL || strstr(varname, "\n") != NULL
526 || strstr(varname, "\v") != NULL || strstr(varname, "\f") != NULL || strstr(varname, "\r") != NULL )
527 {
528 SCIPerrorMessage("Variable name <%s> cannot be printed to certificate file because it contains whitespace.\n",
529 varname);
530 return SCIP_ERROR;
531 }
532
533 SCIPcertificatePrintProblemMessage(certificate, TRUE, "%s\n", varname);
534 }
535
536 /* print the Integer Variable Header into certificate */
537 SCIPcertificatePrintIntHeader(certificate, TRUE, nintvars + nbinvars);
538 for( j = 0; j < nvars; j++ )
539 {
541 {
543 }
544 }
545
546 {
547 SCIP_RATIONAL** objcoefs;
549
550 for( j = 0; j < nvars; j++)
551 SCIPrationalSetRational(objcoefs[j], SCIPvarGetObjExact(vars[j]));
552
553 /* print the objective function into certificate header */
554 SCIP_CALL( SCIPcertificateSetAndPrintObjective(certificate, TRUE, blkmem, objcoefs, nvars) );
555
556 SCIPrationalFreeBufferArray(SCIPbuffer(scip), &objcoefs, nvars);
557 }
558
559 conss = SCIPgetOrigConss(scip);
560 ncertcons = 0;
561 for( j = 0; j < SCIPgetNOrigConss(scip); j++ )
562 {
563 SCIP_CONS* cons;
564 SCIP_CONSHDLR* conshdlr;
565
566 cons = conss[j];
567 conshdlr = SCIPconsGetHdlr(cons);
568
569 if( strcmp(SCIPconshdlrGetName(conshdlr), "exactlinear") == 0 )
570 {
571 lb = SCIPgetLhsExactLinear(scip, cons);
572 ub = SCIPgetRhsExactLinear(scip, cons);
573
575 ncertcons += 2;
576 else
577 ncertcons += 1;
578 }
579 else
580 {
581 SCIPerrorMessage("Cannot print certificate for non-exact constraints \n");
582 SCIPABORT();
583 return SCIP_ERROR;
584 }
585 }
586
587 SCIPcertificatePrintConsHeader(certificate, TRUE, ncertcons, nboundconss);
588
589 for( j = 0; j < SCIPgetNOrigConss(scip); j++ )
590 {
591 SCIP_CONS* cons;
592 cons = conss[j];
594 }
595
596 for( j = 0; j < nvars; j++ )
597 {
599 {
601 }
603 {
604 SCIP_CALL( SCIPcertificatePrintBoundCons(certificate, TRUE, NULL, vars[j], SCIPvarGetUbGlobalExact(vars[j]), TRUE) );
605 }
606 }
607
608 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &certificate->rootbound) );
609 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &certificate->finalbound) );
610 certificate->valssize = SCIPgetNVars(scip) + SCIPgetNConss(scip);
611 SCIP_CALL( SCIPrationalCreateBlockArray(SCIPblkmem(scip), &(certificate->vals), certificate->valssize) );
612
613 return SCIP_OKAY;
614}
615
616/** initializes certificate information and creates files for certificate output */
618 SCIP* scip /**< scip data structure */
619 )
620{
621 int nvars;
622 int nintvars;
623 int nbinvars;
624 int nboundconss;
625 int ncertcons;
626 int j;
627 SCIP_VAR** vars;
628 SCIP_CONS** conss;
629 SCIP_RATIONAL* lb;
630 SCIP_RATIONAL* ub;
631 SCIP_CERTIFICATE* certificate;
632 BMS_BLKMEM* blkmem;
633 SCIP_Bool cutoff;
634
635 assert(scip != NULL);
636 assert(scip->set->certificate_filename != NULL);
637
638 certificate = SCIPgetCertificate(scip);
639 blkmem = SCIPblkmem(scip);
640 cutoff = FALSE;
641
642 assert(certificate != NULL);
643
644 if( certificate->transfile_initialized )
645 return SCIP_OKAY;
646
647 /* the transfile is constructed using the (exact) LP, so make sure this is constructed here */
649 {
650 SCIP_CALL( SCIPconstructLP(scip, &cutoff) );
651 }
652
653 if( certificate->transfile == NULL || certificate->origfile == NULL || certificate->derivationfile == NULL )
654 {
655 SCIPerrorMessage("error creating file <%s> and auxiliary certificate files\n", scip->set->certificate_filename);
656 SCIPprintSysError(scip->set->certificate_filename);
658 }
659
660 certificate->transfile_initialized = TRUE;
661 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
662 nboundconss = 0;
663 for( j = 0 ; j < nvars ; j++ )
664 {
665 lb = SCIPvarGetLbGlobalExact(vars[j]);
666 ub = SCIPvarGetUbGlobalExact(vars[j]);
668 nboundconss++;
670 nboundconss++;
671 }
672
673 /* print the Version Header into certificate */
675
676 /* print the Variable Header into certificate */
677 SCIPcertificatePrintVarHeader(certificate, FALSE, nvars);
678 for( j = 0; j < nvars; j++ )
679 {
680 const char* varname;
681
682 varname = SCIPvarGetName(vars[j]);
683 SCIPvarSetCertificateIndex(vars[j], j);
684 if( strstr(varname, " ") != NULL || strstr(varname, "\t") != NULL || strstr(varname, "\n") != NULL
685 || strstr(varname, "\v") != NULL || strstr(varname, "\f") != NULL || strstr(varname, "\r") != NULL )
686 {
687 SCIPerrorMessage("Variable name <%s> cannot be printed to certificate file because it contains whitespace.\n",
688 varname);
689 return SCIP_ERROR;
690 }
691
692 SCIPcertificatePrintProblemMessage(certificate, FALSE, "%s\n", varname);
693 }
694
695 /* print the Integer Variable Header into certificate */
696 SCIPcertificatePrintIntHeader(certificate, FALSE, nintvars + nbinvars);
697 for( j = 0; j < nvars; j++ )
698 {
700 {
702 }
703 }
704
705 {
706 SCIP_RATIONAL** objcoefs;
708
709 for( j = 0; j < nvars; j++)
710 SCIPrationalSetRational(objcoefs[j], SCIPvarGetObjExact(vars[j]));
711
712 /* print the objective function into certificate header */
713 SCIP_CALL( SCIPcertificateSetAndPrintObjective(certificate, FALSE, blkmem, objcoefs, nvars) );
714
715 SCIPrationalFreeBufferArray(SCIPbuffer(scip), &objcoefs, nvars);
716 }
717
718 conss = SCIPgetConss(scip);
719 ncertcons = 0;
720 for( j = 0; j < SCIPgetNConss(scip); j++ )
721 {
722 SCIP_CONS* cons;
723 SCIP_CONSHDLR* conshdlr;
724
725 cons = conss[j];
726 conshdlr = SCIPconsGetHdlr(cons);
727
728 SCIPdebug(SCIPprintCons(scip, conss[j], NULL));
729
730 if( strcmp(SCIPconshdlrGetName(conshdlr), "exactlinear") == 0 )
731 {
732 lb = SCIPgetLhsExactLinear(scip, cons);
733 ub = SCIPgetRhsExactLinear(scip, cons);
734
736 {
737 SCIPdebugMessage("constraint is a ranged constraint \n");
738 ncertcons += 2;
739 }
740 else
741 {
742 SCIPdebugMessage("constraint only has one side \n");
743 ncertcons += 1;
744 }
745 }
746 else
747 {
748 SCIPerrorMessage("Cannot print certificate for non-exact constraints \n");
749 SCIPABORT();
750 return SCIP_ERROR;
751 }
752 }
753
754 SCIPcertificatePrintConsHeader(certificate, FALSE, ncertcons, nboundconss);
755
756 for( j = 0; j < SCIPgetNConss(scip); j++ )
757 {
758 SCIP_CONS* cons;
759 cons = conss[j];
761 }
762
763 for( j = 0; j < nvars; j++ )
764 {
766 {
768 SCIPvarSetLbCertificateIndexGlobal(vars[j], certificate->indexcounter - 1);
769 }
771 {
773 SCIPvarSetUbCertificateIndexGlobal(vars[j], certificate->indexcounter - 1);
774 }
775 }
776
777 return SCIP_OKAY;
778}
779
780/** concatenates the certificate and the _der file and deletes the _der file */
781static
783 SCIP_CERTIFICATE* certificate /**< the certificate pointer */
784 )
785{
786 SCIP_FILE* derivationfile;
787 char buffer[SCIP_MAXSTRLEN];
788 size_t size;
789
790 derivationfile = SCIPfopen(certificate->derivationfilename, "r");
791
792 /* append the derivation file to the problem file */
793 while( 0 != (size = SCIPfread(buffer, sizeof(char), SCIP_MAXSTRLEN, derivationfile)) )
794 (void) SCIPfwrite(buffer, sizeof(char), size, certificate->transfile);
795
796 SCIPfclose(derivationfile);
797
798 /* delete the derivation file */
799 (void) remove(certificate->derivationfilename);
800}
801
802/** closes the certificate output files */
804 SCIP* scip /**< scip data structure */
805 )
806{
807 assert(scip != NULL);
808
811 SCIP_SET* set = scip->set;
812
813 if( !SCIPcertificateIsEnabled(certificate) )
814 return SCIP_OKAY;
815
816 assert(certificate != NULL);
817
818 if( certificate->origfile != NULL )
819 {
820 SCIP_Bool printingaborted = checkAndUpdateFilesize(certificate, 0) ? FALSE : TRUE;
821
822 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_NORMAL,
823 "closing certificate file (wrote approx. %.1f MB%s)\n", certificate->filesize,
824 printingaborted ? ", aborted printing after reaching max. file size" : "");
825
826 if( printingaborted )
827 {
828 (void) SCIPfprintf(certificate->origfile, "\n# ... aborted printing: max. file size reached.\n");
829 (void) SCIPfprintf(certificate->transfile, "\n# ... aborted printing: max. file size reached.\n");
830 (void) SCIPfprintf(certificate->derivationfile, "\n# ... aborted printing: max. file size reached.\n");
831 }
832
833 if( certificate->derivationfile != NULL )
834 {
835 SCIPfclose(certificate->derivationfile);
836 certificate->derivationfile = NULL;
837 concatenateCertificate(certificate);
838 /* if the file is empty (e.g. because we detected infeasibility in presolving) we delete it */
839 if( certificate->indexcounter == 0 )
840 {
841 SCIPdebugMessage("derivation file is empty; deleting it");
842 (void) remove(set->certificate_filename);
843 }
844 }
845 SCIPfclose(certificate->origfile);
846 SCIPfclose(certificate->transfile);
847 certificate->origfile = NULL;
848 certificate->transfile = NULL;
849
851 BMSfreeMemoryArray(&certificate->origfilename);
852
853 if( certificate->lastinfo != NULL )
854 {
855 SCIPrationalFreeBlock(certificate->blkmem, &certificate->lastinfo->boundval);
856 BMSfreeBlockMemory(certificate->blkmem, &certificate->lastinfo);
857 }
858
859 if( certificate->rowdatahash)
860 SCIPhashmapFree(&certificate->rowdatahash);
861
862 if( certificate->nodedatahash )
863 {
864 assert(SCIPhashmapIsEmpty(certificate->nodedatahash));
865 SCIPhashmapFree(&certificate->nodedatahash);
866 }
867 if( certificate->aggrinfohash )
868 {
870 }
871 if( certificate->mirinfohash )
872 {
874 }
875
876 SCIPrationalFreeBlock(certificate->blkmem, &certificate->rootbound);
877 SCIPrationalFreeBlock(certificate->blkmem, &certificate->finalbound);
878 SCIPrationalFreeBlockArray(certificate->blkmem, &certificate->vals, certificate->valssize);
879 }
880
881 return SCIP_OKAY;
882}
883
884/** returns certificate data structure */
886 SCIP* scip /**< SCIP data structure */
887 )
888{
889 assert(scip != NULL);
890 assert(scip->stat != NULL);
891
892 return scip->stat->certificate;
893}
894
895/** returns whether the certificate output is activated */
897 SCIP_CERTIFICATE* certificate /**< certificate information */
898 )
899{
900 if( certificate != NULL && certificate->transfile != NULL && certificate->origfile != NULL && certificate->derivationfile != NULL )
901 return TRUE;
902 return FALSE;
903}
904
905/** returns current certificate file size in MB */
907 SCIP_CERTIFICATE* certificate /**< certificate information */
908 )
909{
910 if( !SCIPcertificateIsEnabled(certificate) )
911 return 0.0;
912 else
913 return certificate->filesize;
914}
915
916/** returns current certificate index (return -1 if certificate not active) */
918 SCIP_CERTIFICATE* certificate /**< certificate information */
919 )
920{
921 if( !SCIPcertificateIsEnabled(certificate) )
922 return -1;
923 else
924 return certificate->indexcounter;
925}
926
927#ifndef NDEBUG
928/** checks if information is consistent with printed certificate line */
930 SCIP_CERTIFICATE* certificate, /**< certificate information */
931 SCIP_VAR* var, /**< variable that gets changed */
932 SCIP_BOUNDTYPE boundtype, /**< lb or ub changed? */
933 SCIP_Real newbound, /**< new bound */
934 SCIP_Bool needsglobal /**< if the bound needs to be global */
935 )
936{
937 SCIP_Bool consistent;
938
939 if( !SCIPcertificateIsEnabled(certificate) )
940 return TRUE;
941
942 assert(certificate != NULL);
943
944 consistent = certificate->lastinfo->isbound;
945 consistent = consistent && certificate->lastinfo->varindex == SCIPvarGetCertificateIndex(var); /*lint !e1785*/
946 if( boundtype == SCIP_BOUNDTYPE_LOWER )
947 {
948 consistent = consistent && certificate->lastinfo->boundtype == SCIP_BOUNDTYPE_LOWER; /*lint !e1785*/
949 consistent = consistent && SCIPrationalRoundReal(certificate->lastinfo->boundval, SCIP_R_ROUND_DOWNWARDS) >= newbound; /*lint !e1785*/
950 }
951 else
952 {
953 consistent = consistent && certificate->lastinfo->boundtype == SCIP_BOUNDTYPE_UPPER; /*lint !e1785*/
954 consistent = consistent && SCIPrationalRoundReal(certificate->lastinfo->boundval, SCIP_R_ROUND_UPWARDS) <= newbound; /*lint !e1785*/
955 }
956 consistent = consistent && (!needsglobal || certificate->lastinfo->isglobal); /*lint !e1785*/
957 consistent = consistent && certificate->lastinfo->certificateindex == certificate->indexcounter - 1; /*lint !e1785*/
958
959 return consistent;
960}
961#endif
962
963/** sets the objective function used when printing dual bounds */
965 SCIP_CERTIFICATE* certificate, /**< certificate information */
966 SCIP_Bool isorigfile, /**< should the line be printed to the origfile or the transfile */
967 BMS_BLKMEM* blkmem, /**< block memory */
968 SCIP_RATIONAL** coefs, /**< objective function coefficients */
969 int nvars /**< number of variables */
970 )
971{
972 char obj[SCIP_MAXSTRLEN - 2];
973 int nnonz;
974 int i;
975
976 assert(coefs != NULL);
977
978 /* check whether certificate output should be created */
979 if( !SCIPcertificateIsEnabled(certificate) )
980 return SCIP_OKAY;
981
982 /* create a hash table for the variable bounds (we work on the tranformed problem) */
983 if( isorigfile )
984 {
985 /* create working memory for bound struct */
986 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &certificate->lastinfo) );
987 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &certificate->lastinfo->boundval) );
988 }
989
990 nnonz = 0;
991 for( i = 0; i < nvars; i++ )
992 {
993 if( !SCIPrationalIsZero(coefs[i]) )
994 nnonz++;
995 }
996
997 (void) SCIPsnprintf(obj, SCIP_MAXSTRLEN - 2, "OBJ min\n %d ", nnonz);
998
999 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "%s ", obj);
1000
1001 for( i = 0; i < nvars; i++ )
1002 {
1003 if( !SCIPrationalIsZero(coefs[i]) )
1004 {
1005 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "%s%d ", (i > 0 ? " " : ""), i );
1006 SCIP_CALL( SCIPcertificatePrintProblemRational(certificate, isorigfile, coefs[i]) );
1007 }
1008 }
1009
1010 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "\n");
1011
1012 return SCIP_OKAY;
1013}
1014
1015/** prints the last part of the certificate header (RTP range/sol, ...) */
1017 SCIP* scip, /**< SCIP data structure */
1018 SCIP_Bool isorigfile, /**< should the line be printed to the origfile or the transfile */
1019 SCIP_SET* set, /**< general SCIP settings */
1020 SCIP_CERTIFICATE* certificate /**< certificate information */
1021 )
1022{
1023 SCIP_RATIONAL* primalbound;
1024 SCIP_RATIONAL* dualbound;
1025 SCIP_SOL* bestsol;
1026
1027 assert(scip != NULL);
1028
1029 /* check whether certificate output should be created */
1030 if( !SCIPcertificateIsEnabled(certificate) )
1031 return SCIP_OKAY;
1032
1033 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &primalbound) );
1034 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &dualbound) );
1035
1036 /* check status first: OPTIMAL / INFEAS / NOT OPTIMAL */
1037 if( SCIPisInRestart(scip) )
1038 return SCIP_ERROR;
1039
1041 {
1042 bestsol = SCIPgetBestSol(scip);
1043
1044 if( !SCIPsolIsExact(bestsol) )
1045 {
1046 SCIP_CALL( SCIPmakeSolExact(scip, bestsol) );
1047 }
1048
1049 if( isorigfile )
1050 {
1052 SCIPgetPrimalboundExact(scip, primalbound);
1053 }
1054 else
1055 {
1056 SCIPgetUpperboundExact(scip, primalbound);
1057 }
1058
1059 assert(!SCIPrationalIsAbsInfinity(primalbound));
1060
1061 /* for the orig file we only print the primal bound, since the derivation happens in the transformed problem */
1062 if( isorigfile )
1063 {
1064 SCIPrationalSetNegInfinity(dualbound);
1065 /* print RTP range (same when optimal solution found) */
1066 SCIP_CALL( SCIPcertificatePrintRtpRange(certificate, isorigfile, dualbound, primalbound) );
1067 }
1068 else
1069 {
1070 SCIP_CALL( SCIPcertificatePrintRtpRange(certificate, isorigfile, primalbound, primalbound) );
1071 }
1072
1073 /* print optimal solution into certificate */
1074 SCIP_CALL( certificatePrintSol(scip, isorigfile, certificate, bestsol) );
1075 }
1077 {
1078 if( isorigfile )
1079 {
1080 SCIPrationalSetNegInfinity(dualbound);
1081 SCIPrationalSetInfinity(primalbound);
1082 SCIP_CALL( SCIPcertificatePrintRtpRange(certificate, isorigfile, dualbound, primalbound) );
1083 }
1084 else
1085 {
1086 SCIPcertificatePrintRtpInfeas(certificate, isorigfile);
1087 }
1088
1089 SCIP_CALL( certificatePrintSol(scip, isorigfile, certificate, NULL) );
1090 }
1091 else
1092 {
1093 /* two cases to distinguish: a primal bound has been found or not */
1095 {
1096 bestsol = SCIPgetBestSol(scip);
1097 if( isorigfile )
1098 {
1100 SCIPgetPrimalboundExact(scip, primalbound);
1101 }
1102 else
1103 {
1104 SCIPgetUpperboundExact(scip, primalbound);
1105 }
1106 }
1107 else
1108 {
1109 bestsol = NULL;
1110 SCIPrationalSetInfinity(primalbound);
1111 }
1112
1113 if( isorigfile )
1114 SCIPrationalSetNegInfinity(dualbound);
1115 else
1116 SCIPrationalSetRational(dualbound, certificate->finalbound);
1117
1118 SCIP_CALL( SCIPcertificatePrintRtpRange(certificate, isorigfile, dualbound, primalbound) );
1119 SCIP_CALL( certificatePrintSol(scip, isorigfile, certificate, bestsol) );
1120 }
1121
1122 SCIPcertificatePrintDerHeader(certificate, isorigfile);
1123
1124 SCIPrationalFreeBuffer(set->buffer, &dualbound);
1125 SCIPrationalFreeBuffer(set->buffer, &primalbound);
1126
1127 return SCIP_OKAY;
1128}
1129
1130/** prints the last part of the certificate header (RTP range/sol, ...) */
1132 SCIP* scip, /**< SCIP data structure */
1133 SCIP_CERTIFICATE* certificate /**< certificate information */
1134 )
1135{
1136 assert(scip != NULL);
1137
1138 if( !SCIPcertificateIsEnabled(certificate) )
1139 return SCIP_OKAY;
1140
1141 SCIPgetLowerboundExact(scip, certificate->finalbound);
1142
1143 return SCIP_OKAY;
1144}
1145
1146/** prints a string to the problem section of the certificate file */
1148 SCIP_CERTIFICATE* certificate, /**< certificate information */
1149 SCIP_Bool isorigfile, /**< should the line be printed to the origfile or the transfile */
1150 const char* formatstr, /**< format string like in printf() function */
1151 ... /**< format arguments line in printf() function */
1152 )
1153{
1154 va_list ap;
1155 char buffer[3 * SCIP_MAXSTRLEN];
1156
1157 /* check whether certificate output should be created */
1158 if( !SCIPcertificateIsEnabled(certificate) )
1159 return;
1160
1161 va_start(ap, formatstr);
1162 (void) vsnprintf(buffer, 3 * SCIP_MAXSTRLEN, formatstr, ap);
1163
1164 if( checkAndUpdateFilesize(certificate, strlen(buffer)) )
1165 {
1166 if( isorigfile )
1167 (void) SCIPfprintf(certificate->origfile, "%s", buffer);
1168 else
1169 (void) SCIPfprintf(certificate->transfile, "%s", buffer);
1170 }
1171 va_end(ap);
1172}
1173
1174/** prints a string to the proof section of the certificate file */
1176 SCIP_CERTIFICATE* certificate, /**< certificate information */
1177 const char* formatstr, /**< format string like in printf() function */
1178 ... /**< format arguments line in printf() function */
1179 )
1180{
1181 va_list ap;
1182 char buffer[3 * SCIP_MAXSTRLEN];
1183
1184 /* check whether certificate output should be created */
1185 if( !SCIPcertificateIsEnabled(certificate) )
1186 return;
1187
1188 va_start(ap, formatstr);
1189 (void) vsnprintf(buffer, 3 * SCIP_MAXSTRLEN, formatstr, ap);
1190
1191 if( checkAndUpdateFilesize(certificate, strlen(buffer)) )
1192 (void) SCIPfprintf(certificate->derivationfile, "%s", buffer);
1193
1194 va_end(ap);
1195}
1196
1197
1198/** prints a rational number to the problem section of the certificate file */
1200 SCIP_CERTIFICATE* certificate, /**< certificate information */
1201 SCIP_Bool isorigfile, /**< should the line be printed to the origfile or the transfile */
1202 SCIP_RATIONAL* val /**< rational number to print */
1203 )
1204{
1205 int len = SCIPrationalStrLen(val) + 1;
1206 char* buffer = NULL;
1207
1208 /* check whether certificate output should be created */
1209 if( !SCIPcertificateIsEnabled(certificate) )
1210 return SCIP_OKAY;
1211
1212 SCIP_ALLOC( BMSallocMemoryArray(&buffer, len) );
1213 (void) SCIPrationalToString(val, buffer, len);
1214 if( checkAndUpdateFilesize(certificate, strlen(buffer)) )
1215 {
1216 if( isorigfile )
1217 (void) SCIPfputs(buffer, certificate->origfile);
1218 else
1219 (void) SCIPfputs(buffer, certificate->transfile);
1220 }
1221 BMSfreeMemoryArray(&buffer);
1222
1223 return SCIP_OKAY;
1224}
1225
1226
1227/** prints a rational number to the proof section of the certificate file */
1229 SCIP_CERTIFICATE* certificate, /**< certificate information */
1230 SCIP_RATIONAL* val /**< rational number to print */
1231 )
1232{
1233 int len = SCIPrationalStrLen(val) + 1;
1234 char* buffer = NULL;
1235
1236 /* check whether certificate output should be created */
1237 if( !SCIPcertificateIsEnabled(certificate) )
1238 return SCIP_OKAY;;
1239
1240 SCIP_ALLOC( BMSallocMemoryArray(&buffer, len) );
1241 (void) SCIPrationalToString(val, buffer, len);
1242
1243 if( checkAndUpdateFilesize(certificate, strlen(buffer)) )
1244 (void) SCIPfputs(buffer, certificate->derivationfile);
1245
1246 BMSfreeMemoryArray(&buffer);
1247
1248 return SCIP_OKAY;
1249}
1250
1251/** prints a comment to the problem section of the certificate file */
1253 SCIP_CERTIFICATE* certificate, /**< certificate information */
1254 SCIP_Bool isorigfile, /**< should the line be printed to the origfile or the transfile */
1255 const char* formatstr, /**< format string like in printf() function */
1256 ... /**< format arguments line in printf() function */
1257 )
1258{
1259 va_list ap;
1260 char buffer[3 * SCIP_MAXSTRLEN];
1261
1262 /* check whether certificate output should be created */
1263 if( !SCIPcertificateIsEnabled(certificate) )
1264 return;
1265
1266 (void) SCIPfprintf(certificate->origfile, "# ");
1267
1268 va_start(ap, formatstr);
1269 (void) vsnprintf(buffer, 3 * SCIP_MAXSTRLEN, formatstr, ap);
1270
1271 if( checkAndUpdateFilesize(certificate, 2 + strlen(buffer)) )
1272 {
1273 if( isorigfile )
1274 (void) SCIPfprintf(certificate->origfile, "%s", buffer);
1275 else
1276 (void) SCIPfprintf(certificate->transfile, "%s", buffer);
1277 }
1278 va_end(ap);
1279}
1280
1281/** prints a comment to the proof section of the certificate file */
1283 SCIP_CERTIFICATE* certificate, /**< certificate information */
1284 const char* formatstr, /**< format string like in printf() function */
1285 ... /**< format arguments line in printf() function */
1286 )
1287{
1288 va_list ap;
1289 char buffer[3 * SCIP_MAXSTRLEN];
1290
1291 /* check whether certificate output should be created */
1292 if( !SCIPcertificateIsEnabled(certificate) )
1293 return;
1294
1295 (void) SCIPfprintf(certificate->derivationfile, "# ");
1296
1297 va_start(ap, formatstr);
1298 (void) vsnprintf(buffer, 3 * SCIP_MAXSTRLEN, formatstr, ap);
1299
1300 if( checkAndUpdateFilesize(certificate, 2 + strlen(buffer)) )
1301 (void) SCIPfprintf(certificate->derivationfile, "%s", buffer);
1302
1303 va_end(ap);
1304}
1305
1306/** prints version header */
1308 SCIP_CERTIFICATE* certificate, /**< certificate information */
1309 SCIP_Bool isorigfile /**< should the line be printed to the origfile or the transfile */
1310 )
1311{
1312 /* check whether certificate output should be created */
1313 if( !SCIPcertificateIsEnabled(certificate) )
1314 return;
1315
1316 assert(certificate != NULL);
1317
1318 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "VER 1.0 \n");
1319}
1320
1321/** prints variable section header */
1323 SCIP_CERTIFICATE* certificate, /**< certificate information */
1324 SCIP_Bool isorigfile, /**< should the line be printed to the origfile or the transfile */
1325 int nvars /**< number of variables */
1326 )
1327{
1328 assert(nvars >= 0);
1329
1330 /* check whether certificate output should be created */
1331 if( !SCIPcertificateIsEnabled(certificate) )
1332 return;
1333
1334 assert(certificate != NULL);
1335
1336 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "VAR %d \n", nvars);
1337}
1338
1339/** prints integer section header */
1341 SCIP_CERTIFICATE* certificate, /**< certificate information */
1342 SCIP_Bool isorigfile, /**< should the line be printed to the origfile or the transfile */
1343 int nintvars /**< number of integer variables */
1344 )
1345{
1346 assert(nintvars >= 0);
1347
1348 /* check whether certificate output should be created */
1349 if( !SCIPcertificateIsEnabled(certificate) )
1350 return;
1351
1352 assert(certificate != NULL);
1353
1354 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "INT %d\n", nintvars);
1355}
1356
1357/** prints constraint section header */
1359 SCIP_CERTIFICATE* certificate, /**< certificate information */
1360 SCIP_Bool isorigfile, /**< should the line be printed to the origfile or the transfile */
1361 int nconss, /**< number of all constraints */
1362 int nboundconss /**< number of bound constraints */
1363 )
1364{
1365 assert(nconss >= 0);
1366
1367 /* check whether certificate output should be created */
1368 if( !SCIPcertificateIsEnabled(certificate) )
1369 return;
1370
1371 assert(certificate != NULL);
1372
1373 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "CON %d %d\n", nconss + nboundconss, nboundconss);
1374}
1375
1376/** prints derivation section header */
1378 SCIP_CERTIFICATE* certificate, /**< certificate information */
1379 SCIP_Bool isorigfile /**< should the line be printed to the origfile or the transfile */
1380 )
1381{
1382 SCIP_Longint nders;
1383
1384 /* check whether certificate output should be created */
1385 if( !SCIPcertificateIsEnabled(certificate) )
1386 return;
1387
1388 assert(certificate != NULL);
1389
1390 if( !isorigfile )
1391 nders = certificate->indexcounter - certificate->conscounter;
1392 else
1393 nders = 0;
1394
1395 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "DER %d\n", nders);
1396}
1397
1398/** prints constraint */
1400 SCIP_CERTIFICATE* certificate, /**< certificate information */
1401 SCIP_Bool isorigfile, /**< should the line be printed to the origfile or the transfile */
1402 const char* consname, /**< name of the constraint */
1403 const char sense, /**< sense of the constraint, i.e., G, L, or E */
1404 SCIP_RATIONAL* side, /**< left/right-hand side */
1405 int len, /**< number of nonzeros */
1406 int* ind, /**< index array */
1407 SCIP_RATIONAL** val /**< coefficient array */
1408 )
1409{
1410 SCIP_Longint index;
1411 int i;
1412
1413 /* check whether certificate output should be created */
1414 if( !SCIPcertificateIsEnabled(certificate) )
1415 return SCIP_OKAY;
1416
1417 index = isorigfile ? certificate->indexcounter_ori : certificate->indexcounter;
1418
1419 if( consname == NULL )
1420 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "C%d %c ", index, sense);
1421 else
1422 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "%s %c ", consname, sense);
1423
1424 SCIP_CALL( SCIPcertificatePrintProblemRational(certificate, isorigfile, side) );
1425
1426 SCIPcertificatePrintProblemMessage(certificate, isorigfile, " %d", len);
1427
1428 for( i = 0; i < len; i++ )
1429 {
1430 /** @todo perform line breaking before exceeding maximum line length */
1431 SCIPcertificatePrintProblemMessage(certificate, isorigfile, " %d ", ind[i]);
1432 SCIP_CALL( SCIPcertificatePrintProblemRational(certificate, isorigfile, val[i]) );
1433 }
1434 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "\n");
1435
1436 if( isorigfile )
1437 certificate->indexcounter_ori++;
1438 else
1439 {
1440 certificate->indexcounter++;
1441 certificate->lastinfo->isbound = FALSE;
1442 }
1443
1444 if( !isorigfile )
1445 {
1446 certificate->conscounter++;
1447 }
1448
1449 return SCIP_OKAY;
1450}
1451
1452/** prints a line for an exact row to the certificate (without derivation)
1453 *
1454 * @param alternativerhs is used instead of the real rhs of the row (infinity if real rhs should be used).
1455 * This is necessary for integer cut where the rhs was rounded down from the original rhs
1456 */
1457static
1459 SCIP_SET* set, /**< global SCIP settings */
1460 SCIP_CERTIFICATE* certificate, /**< certificate structure */
1461 SCIP_ROWEXACT* rowexact, /**< exact SCIP row */
1462 SCIP_Real alternativerhs /**< rhs to be used instead or rowexact->rhs (infinity to disable this) */
1463 )
1464{
1465 SCIP_ROW* row;
1466 SCIP_RATIONAL* rhs;
1467 int i;
1468
1469 /* check whether certificate output should be created */
1470 if( !SCIPcertificateIsEnabled(certificate) )
1471 return SCIP_OKAY;
1472
1473 assert(rowexact != NULL);
1474
1475 row = SCIProwExactGetRow(rowexact);
1476 assert(SCIProwGetNNonz(row) == SCIProwExactGetNNonz(rowexact));
1477
1478 SCIPcertificatePrintProofMessage(certificate, "L%d_%s %c ", certificate->indexcounter, row->name, 'L');
1479
1480 /* if we rounded the rhs in cut tightening we need to first verify the cut without it */
1481 if( SCIPsetIsInfinity(set, alternativerhs) )
1482 {
1483 rhs = SCIProwExactGetRhs(rowexact);
1484 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, rhs) );
1485 }
1486 else
1487 {
1488 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &rhs) );
1489 SCIPrationalSetReal(rhs, alternativerhs);
1490 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, rhs) );
1491 SCIPrationalFreeBuffer(set->buffer, &rhs);
1492 }
1493
1494 SCIPcertificatePrintProofMessage(certificate, " %d", SCIProwGetNNonz(row));
1495
1496 for( i = 0; i < SCIProwGetNNonz(row); i++ )
1497 {
1498 SCIP_RATIONAL* val;
1499 int varindex;
1500 /** @todo perform line breaking before exceeding maximum line length */
1501 assert(rowexact->cols[i]->fpcol->var->index == rowexact->fprow->cols[i]->var->index);
1502
1504 val = SCIProwExactGetVals(rowexact)[i];
1505
1506 SCIPcertificatePrintProofMessage(certificate, " %d ", varindex);
1507 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, val) );
1508 }
1509 certificate->indexcounter++;
1510 certificate->lastinfo->isbound = FALSE;
1511
1512 return SCIP_OKAY;
1513}
1514
1515/** prints mir split for the specified aggrrow */
1516static
1518 SCIP_SET* set, /**< SCIP settings */
1519 SCIP_PROB* prob, /**< SCIP problem data */
1520 SCIP_CERTIFICATE* certificate, /**< certificate information */
1521 SCIP_ROW* row /**< row that split should be printed for */
1522 )
1523{
1524 SCIP_MIRINFO* mirinfo;
1525 SCIP_RATIONAL* val;
1526 SCIP_VAR** vars;
1527 int i, j;
1528 SCIP_Real slackrhs;
1529 std::map<int, SCIP_Real> coefs;
1530
1531 assert(SCIPcertificateIsEnabled(certificate));
1532 assert(SCIPhashmapExists(certificate->mirinfohash, (void*) row));
1533
1534 mirinfo = (SCIP_MIRINFO*) SCIPhashmapGetImage(certificate->mirinfohash, (void*) row);
1535
1536 vars = SCIPprobGetVars(prob);
1537 slackrhs = 0;
1538
1539 SCIPrationalDebugMessage("printing split disjunction <= %q \\/ >= %q+1 \n", mirinfo->rhs, mirinfo->rhs);
1540
1541 for( i = 0; i < mirinfo->nsplitvars; ++i )
1542 {
1543 if( mirinfo->splitcoefficients[i] == 0 )
1544 continue;
1545 coefs[SCIPvarGetCertificateIndex(vars[mirinfo->varinds[i]])] += mirinfo->splitcoefficients[i];
1546 SCIPdebugMessage("+%g%s", mirinfo->splitcoefficients[i], SCIPvarGetName(vars[mirinfo->varinds[i]]));
1547 }
1548 for( i = 0; i < mirinfo->nslacks; ++i )
1549 {
1550 SCIP_ROW* slackrow = mirinfo->slackrows[i];
1551 SCIP_Real slackval = mirinfo->slackcoefficients[i];
1552
1553 if( slackval == 0 )
1554 continue;
1555
1556 for( j = 0; j < SCIProwGetNNonz(slackrow); ++j)
1557 {
1558 SCIP_VAR* var = SCIPcolGetVar(SCIProwGetCols(slackrow)[j]);
1559 int varidx = SCIPvarGetCertificateIndex(var);
1560 SCIP_Real rowcoef = SCIProwGetVals(slackrow)[j];
1561
1562 assert(SCIPrealIsExactlyIntegral(rowcoef * slackval));
1563 assert(SCIPvarIsBinary(var) || SCIPvarIsIntegral(var));
1564 coefs[varidx] += rowcoef * slackval;
1565 assert(SCIPrealIsExactlyIntegral(coefs[varidx]));
1566 }
1567 if( mirinfo->slacksign[i] == 1 )
1568 {
1569 assert(SCIPrealIsExactlyIntegral(SCIProwGetRhs(slackrow) - SCIProwGetConstant(slackrow)));
1570 slackrhs += (SCIProwGetRhs(slackrow) - SCIProwGetConstant(slackrow)) * slackval;
1571
1572 assert(SCIPrealIsExactlyIntegral(slackrhs));
1573 SCIPdebugMessage("+%gsrhs_%s", mirinfo->slackcoefficients[i], SCIProwGetName(mirinfo->slackrows[i]));
1574 }
1575 else
1576 {
1577 assert(SCIPrealIsExactlyIntegral(SCIProwGetLhs(slackrow) - SCIProwGetConstant(slackrow)));
1578 slackrhs += (SCIProwGetLhs(slackrow) - SCIProwGetConstant(slackrow)) * slackval;
1579
1580 assert(SCIPrealIsExactlyIntegral(slackrhs));
1581 SCIPdebugMessage("+%gslhs_%s", mirinfo->slackcoefficients[i], SCIProwGetName(mirinfo->slackrows[i]));
1582 }
1583 }
1584
1585 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &val) );
1586
1587 /* transform the split back into original variable space -> undo the bound transformations */
1588 SCIPcertificatePrintProofMessage(certificate, "A%d_split %c ", certificate->indexcounter, 'L');
1589
1590 /* add rhs change from integer slacks and print rhs */
1591 SCIPrationalAddReal(val, mirinfo->rhs, slackrhs);
1592 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, val) );
1593
1594 SCIPcertificatePrintProofMessage(certificate, " %d", coefs.size());
1595
1596 for( const auto & coef : coefs )
1597 {
1598 /** @todo perform line breaking before exceeding maximum line length */
1599 int varindex = coef.first;
1600 SCIPrationalSetReal(val, coef.second);
1601
1602 assert(SCIPrationalIsIntegral(val));
1603
1604 SCIPcertificatePrintProofMessage(certificate, " %d ", varindex);
1605 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, val) );
1606 }
1607
1608 SCIPcertificatePrintProofMessage(certificate, " { asm } -1 \n");
1609
1610 certificate->indexcounter++;
1611 certificate->lastinfo->isbound = FALSE;
1612
1613 SCIPcertificatePrintProofMessage(certificate, "A%d_split %c ", certificate->indexcounter, 'G');
1614
1615 SCIPrationalAddReal(val, mirinfo->rhs, slackrhs + 1.0);
1616 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, val) );
1617
1618 SCIPcertificatePrintProofMessage(certificate, " %d", coefs.size());
1619
1620 for( const auto & coef : coefs )
1621 {
1622 /** @todo perform line breaking before exceeding maximum line length */
1623 int varindex = coef.first;
1624 SCIPrationalSetReal(val, coef.second);
1625
1626 assert(SCIPrationalIsIntegral(val));
1627
1628 SCIPcertificatePrintProofMessage(certificate, " %d ", varindex);
1629 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, val) );
1630 }
1631
1632 SCIPcertificatePrintProofMessage(certificate, " { asm } -1 \n");
1633
1634 certificate->indexcounter++;
1635 certificate->lastinfo->isbound = FALSE;
1636
1637 SCIPrationalFreeBuffer(set->buffer, &val);
1638
1639 return SCIP_OKAY;
1640}
1641
1642#ifdef SCIP_DISABLED_CODE
1643/** prints all local bounds that differ from their global bounds as the bounds to take into account */
1644static
1645SCIP_RETCODE certificatePrintIncompleteDerStart(
1646 SCIP_CERTIFICATE* certificate, /**< SCIP certificate */
1647 SCIP_ROW** rows, /**< rows to be considered */
1648 int nrows, /**< number of rows to be considered */
1649 SCIP_PROB* prob, /**< SCIP problem data */
1650 SCIP_Bool local /**< TRUE if the cut is only valid locally */
1651 )
1652{
1653 SCIP_VAR** vars;
1654 int nvars;
1655 int i;
1656
1657 assert(!SCIPcertificateIsEnabled(certificate));
1658
1659 vars = SCIPprobGetVars(prob);
1660 nvars = SCIPprobGetNVars(prob);
1661
1662 SCIPcertificatePrintProofMessage(certificate, " { lin incomplete ");
1663
1664 /* add non-global bounds */
1665 for( i = 0; i < nvars; i++ )
1666 {
1667 SCIP_VAR* var = vars[i];
1668 SCIP_Longint index;
1669
1671 if( index != -1 )
1672 {
1673 assert(index <= certificate->indexcounter);
1674 SCIPcertificatePrintProofMessage(certificate, " %d ", index);
1675 }
1677 if( index != -1 )
1678 {
1679 assert(index <= certificate->indexcounter);
1680 SCIPcertificatePrintProofMessage(certificate, " %d ", index);
1681 }
1682 }
1683
1684 /* add non-default rows */
1685 for( i = 0; i < nrows; ++i )
1686 {
1687 SCIP_ROWEXACT* rowexact = SCIProwGetRowExact(rows[i]);
1688 SCIP_Longint key;
1689
1690 if( !local && SCIProwIsLocal(rows[i]) )
1691 continue;
1692
1693 if( !SCIPhashmapExists(certificate->rowdatahash, (void*) rowexact) )
1694 continue;
1695
1696 assert(rowexact != NULL);
1697 assert(SCIPhashmapExists(certificate->rowdatahash, (void*) rowexact));
1698 key = SCIPhashmapGetImageLong(certificate->rowdatahash, (void*) rowexact);
1699 SCIPcertificatePrintProofMessage(certificate, " %d ", key);
1700 /* for a ranged row, we need both sides to be safe */
1701 if( !SCIPrationalIsAbsInfinity(rowexact->lhs) && !SCIPrationalIsAbsInfinity(rowexact->rhs) && !SCIPrationalIsEQ(rowexact->lhs, rowexact->rhs) )
1702 {
1703 SCIPcertificatePrintProofMessage(certificate, " %d ", key + 1);
1704 }
1705 }
1706
1707 return SCIP_OKAY;
1708}
1709#endif
1710
1711/** prints all local bounds that differ from their global bounds as the bounds to take into account */
1712static
1714 SCIP_CERTIFICATE* certificate, /**< SCIP certificate */
1715 SCIP_PROB* prob, /**< SCIP problem data */
1716 SCIP_Bool local /**< TRUE if the cut is only valid locally */
1717 )
1718{
1719 SCIP_VAR** vars;
1720 int nvars;
1721 int i;
1722 int nboundentries;
1723
1724 assert(SCIPcertificateIsEnabled(certificate));
1725
1726 nboundentries = 0;
1727
1728 vars = SCIPprobGetVars(prob);
1729 nvars = SCIPprobGetNVars(prob);
1730
1731 /* count the number of needed entries */
1732 for( i = 0; i < nvars && local; i++ )
1733 {
1734 SCIP_VAR* var = vars[i];
1736 nboundentries++;
1738 nboundentries++;
1739
1740 assert(!SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb) == (var->glbdom.lb != var->locdom.lb));
1741 assert(!SCIPrationalIsEQ(var->exactdata->glbdom.ub, var->exactdata->locdom.ub) == (var->glbdom.ub != var->locdom.ub));
1742 }
1743
1744 SCIPcertificatePrintProofMessage(certificate, " { lin weak { %d", nboundentries);
1745
1746 for( i = 0; i < nvars && nboundentries > 0; i++ )
1747 {
1748 SCIP_VAR* var = vars[i];
1749
1751 {
1752 SCIP_Longint index;
1753 SCIP_RATIONAL* boundval;
1754
1756 boundval = SCIPvarGetLbLocalExact(var);
1757 SCIPcertificatePrintProofMessage(certificate, " L %d %d ", SCIPvarGetCertificateIndex(var), index);
1758 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, boundval) );
1759 }
1761 {
1762 SCIP_Longint index;
1763 SCIP_RATIONAL* boundval;
1764
1766 boundval = SCIPvarGetUbLocalExact(var);
1767 SCIPcertificatePrintProofMessage(certificate, " U %d %d ", SCIPvarGetCertificateIndex(var), index);
1768 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, boundval) );
1769 }
1770 }
1771
1772 SCIPcertificatePrintProofMessage(certificate, " } ");
1773
1774 return SCIP_OKAY;
1775}
1776
1777/** prints verification of row as a MIR cut (viewed as a split cut) */
1779 SCIP_SET* set, /**< SCIP settings */
1780 SCIP_LP* lp, /**< SCIP lp data structure */
1781 SCIP_CERTIFICATE* certificate, /**< certificate information */
1782 SCIP_PROB* prob, /**< SCIP problem data */
1783 SCIP_ROW* row, /**< the row to be printed */
1784 const char sense /**< sense of the constraint, i.e., G, L, or E */
1785 )
1786{
1787 SCIP_ROWEXACT* rowexact;
1788 SCIP_RATIONAL* tmpval;
1789 SCIP_RATIONAL* value;
1790 SCIP_RATIONAL* oneminusf0;
1791 SCIP_AGGREGATIONINFO* aggrinfo;
1792 SCIP_Longint leftdisjunctionindex;
1793 SCIP_Longint rightdisjunctionindex;
1794 SCIP_MIRINFO* mirinfo;
1795 int i;
1796
1797 /* check whether certificate output should be created */
1798 if( !SCIPcertificateIsEnabled(certificate) )
1799 return SCIP_OKAY;
1800
1801 assert(row != NULL);
1802 assert(sense == 'L'); /* for now only this case is needed */
1803 assert(SCIPhashmapExists(certificate->aggrinfohash, (void*) row));
1804
1805 rowexact = SCIProwGetRowExact(row);
1806
1807 /* only do something if row does not already exist*/
1808 if( SCIPhashmapExists(certificate->rowdatahash, (void*) rowexact) )
1809 return SCIP_OKAY;
1810
1811 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
1812 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oneminusf0) );
1813 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &value) );
1814
1815 SCIPdebugMessage("Printing MIR-certifiaction for row ");
1816 SCIPdebug(SCIProwExactPrint(rowexact, set->scip->messagehdlr, NULL));
1817
1818 /* get aggregation info and print aggregation row to certificate */
1819 aggrinfo = (SCIP_AGGREGATIONINFO*) SCIPhashmapGetImage(certificate->aggrinfohash, (void*) row);
1820 mirinfo = (SCIP_MIRINFO*) SCIPhashmapGetImage(certificate->mirinfohash, (void*) row);
1821
1822 /* compute the correct split from the aggregation row, and print the two assumptions (\xi \le \lfloor \beta \rfloor), and (\xi \ge \lfloor \beta + 1 \rfloor) */
1823 SCIP_CALL( certificatePrintMirSplit(set, prob, certificate, row) );
1824
1825 leftdisjunctionindex = certificate->indexcounter - 2;
1826 rightdisjunctionindex = certificate->indexcounter - 1;
1827
1828 /* if this aggregation depends on another no yet certified MIR cut, we need to print that first */
1829 for( i = 0; i < aggrinfo->naggrrows; i++ )
1830 {
1831 SCIP_ROWEXACT* aggrrow;
1832 aggrrow = SCIProwGetRowExact(aggrinfo->aggrrows[i]);
1833 assert(aggrrow != NULL);
1834 if( !SCIPhashmapExists(certificate->rowdatahash, (void*) aggrrow) )
1835 {
1836 SCIP_CALL( SCIPcertificatePrintMirCut(set, lp, certificate, prob, aggrinfo->aggrrows[i], 'L') );
1837 }
1838 }
1839
1840 /* print possibly missing derivations to the certifiacte */
1841 for( i = 0; i < aggrinfo->nnegslackrows; i++ )
1842 {
1843 SCIP_ROWEXACT* slackrow;
1844 slackrow = SCIProwGetRowExact(aggrinfo->negslackrows[i]);
1845
1846 if( !SCIPhashmapExists(certificate->rowdatahash, (void*) slackrow) )
1847 {
1848 SCIP_CALL( SCIPcertificatePrintMirCut(set, lp, certificate, prob, aggrinfo->negslackrows[i], 'L') );
1849 }
1850 }
1851
1852 /* print possibly missing derivations to the certifiacte */
1853 for( i = 0; i < mirinfo->nslacks; i++ )
1854 {
1855 SCIP_ROWEXACT* slackrow;
1856 slackrow = SCIProwGetRowExact(mirinfo->slackrows[i]);
1857
1858 if( !SCIPhashmapExists(certificate->rowdatahash, (void*) slackrow) )
1859 {
1860 SCIP_CALL( SCIPcertificatePrintMirCut(set, lp, certificate, prob, mirinfo->slackrows[i], 'L') );
1861 }
1862 }
1863
1864 /* print the mir cut with proof 1 * (\xi \le \lfloor \beta \rfloor) - (1/1-f)(\nu \ge 0) */
1865 /* we dont need the \nu \ge 0 part since it will be taken care of by the vipr completion part */
1866 assert(rowexact != NULL);
1867 {
1868 SCIP_CALL( certificatePrintRow(set, certificate, rowexact, mirinfo->unroundedrhs) );
1869
1870 /* calculate 1-f0 */
1871 SCIPrationalSetReal(oneminusf0, 1.0);
1872 SCIPrationalDiff(oneminusf0, oneminusf0, mirinfo->frac);
1873
1874 SCIP_CALL( certificatePrintWeakDerStart(certificate, prob, SCIProwIsLocal(row)) );
1875
1876 /* 1 * (\xi \le \lfloor \beta \rfloor) we also have to add the correct multipliers for the negative slacks that were used here */
1877 SCIPcertificatePrintProofMessage(certificate, "%d %d ", 1 + aggrinfo->nnegslackrows + mirinfo->nslacks, leftdisjunctionindex);
1878 /* multiply with scaling parameter that was used during cut computation */
1879 SCIPrationalSetReal(tmpval, mirinfo->scale);
1880 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, tmpval) );
1881
1882 SCIPdebugMessage("Verifying left part of split disjunction, multipliers 1 and 1/%g \n", SCIPrationalGetReal(oneminusf0));
1883
1884 SCIPdebugMessage("Correcting for negative continous slacks ( needed for v >= 0 part ) \n");
1885 for( i = 0; i < aggrinfo->nnegslackrows; i++ )
1886 {
1887 SCIP_Longint key;
1888 SCIP_ROWEXACT* slackrow;
1889 slackrow = SCIProwGetRowExact(aggrinfo->negslackrows[i]);
1890
1891 SCIPdebugMessage("adding (weight/(1-f0)) %g times row: ", aggrinfo->substfactor[i]);
1892 SCIPdebug(SCIProwExactPrint(slackrow, set->scip->messagehdlr, NULL));
1893 assert(slackrow != NULL);
1894 assert(SCIPhashmapExists(certificate->rowdatahash, (void*) slackrow));
1895 SCIPrationalSetReal(tmpval, aggrinfo->substfactor[i]);
1896
1897 key = SCIPcertificateGetRowIndex(certificate, slackrow, SCIPrationalIsPositive(tmpval));
1898
1899 SCIPcertificatePrintProofMessage(certificate, " %d ", key);
1900 SCIPrationalMultReal(tmpval, tmpval, mirinfo->scale);
1901 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, tmpval) );
1902 }
1903
1904 SCIPdebugMessage("Correcting for integer slacks ( needed for v >= 0 part ) \n");
1905 for( i = 0; i < mirinfo->nslacks; i++ )
1906 {
1907 SCIP_Longint key;
1908 SCIP_ROWEXACT* slackrow;
1909 slackrow = SCIProwGetRowExact(mirinfo->slackrows[i]);
1910 SCIP_Longint upar;
1911
1912 assert(slackrow != NULL);
1913 assert(SCIPhashmapExists(certificate->rowdatahash, (void*) slackrow));
1914 if( mirinfo->slackroundeddown[i] )
1915 SCIPrationalSetReal(tmpval, 0);
1916 else
1917 {
1918 /* value = weight * scale * sign -> compute (1 - fr)/(1-f0) where fr is the fractionality of value */
1919 SCIPrationalSetReal(tmpval, mirinfo->slackweight[i]);
1920 SCIPrationalMultReal(tmpval, tmpval, mirinfo->slackscale[i]);
1921 SCIPrationalMultReal(tmpval, tmpval, mirinfo->slacksign[i]);
1922 (void) SCIPrationalRoundLong(&upar, tmpval, SCIP_R_ROUND_UPWARDS);
1923 SCIPrationalDiffReal(tmpval, tmpval, upar);
1924 SCIPrationalNegate(tmpval, tmpval);
1925 SCIPrationalMultReal(tmpval, tmpval, mirinfo->slacksign[i]);
1926 SCIPrationalDiv(tmpval, tmpval, oneminusf0);
1927 SCIPrationalDebugMessage("tmpval 1 %g \n", SCIPrationalGetReal(tmpval));
1928 SCIPrationalSetReal(tmpval, mirinfo->slackusedcoef[i]);;
1929 SCIPrationalDiffReal(tmpval, tmpval, mirinfo->slackcoefficients[i]);
1930 SCIPrationalDebugMessage("tmpval 2 %g (slacksign %d, splitcoef %g, cutval %g) \n", SCIPrationalGetReal(tmpval), mirinfo->slacksign[i], mirinfo->slackcoefficients[i], mirinfo->slackusedcoef[i]);
1931 }
1932
1933 key = SCIPcertificateGetRowIndex(certificate, slackrow, SCIPrationalIsPositive(tmpval));
1934
1935 SCIPcertificatePrintProofMessage(certificate, " %d ", key);
1936 SCIPrationalMultReal(tmpval, tmpval, mirinfo->scale);
1937 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, tmpval) );
1938 }
1939
1940 SCIPcertificatePrintProofMessage(certificate, " } -1 \n");
1941
1942 SCIPdebugMessage("Verifying right part of split disjunction, multipliers -f/(1-f) and 1/1-f \n");
1943
1944 /* print the mir cut with proof (-f/1-f) * (\xi \ge \lfloor \beta + 1 \rfloor) + (1/1-f)(\xi - \nu \le \beta) */
1945 SCIP_CALL( certificatePrintRow(set, certificate, rowexact, mirinfo->unroundedrhs) );
1946
1947 SCIP_CALL( certificatePrintWeakDerStart(certificate, prob, SCIProwIsLocal(row)) );
1948 SCIPcertificatePrintProofMessage(certificate, " %d ", 1 + aggrinfo->naggrrows + aggrinfo->nnegslackrows + mirinfo->nslacks);
1949
1950 /* (-f/1-f) * (\xi \ge \lfloor \beta + 1 \rfloor) */
1951 SCIPcertificatePrintProofMessage(certificate, "%d ", rightdisjunctionindex);
1952 SCIPrationalSetRational(tmpval, mirinfo->frac);
1953 SCIPrationalNegate(tmpval, tmpval); /* -f */
1954 SCIPrationalDiv(tmpval, tmpval, oneminusf0); /* -f/(1-f) */
1955 /* multiply with scaling factor that was used in cut derivation */
1956 SCIPrationalMultReal(tmpval, tmpval, mirinfo->scale);
1957 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, tmpval) );
1958
1959 SCIPrationalDivReal(tmpval, tmpval, mirinfo->scale);
1960
1961 SCIPdebugMessage("Correcting for negative continous slacks \n");
1962 /* we also have to add the correct multipliers for the negative continuous slacks that were used here */
1963 for( i = 0; i < aggrinfo->nnegslackrows; i++ )
1964 {
1965 SCIP_Longint key;
1966 SCIP_ROWEXACT* slackrow;
1967 slackrow = SCIProwGetRowExact(aggrinfo->negslackrows[i]);
1968
1969 SCIPrationalSetReal(value, -aggrinfo->negslackweights[i]);
1970 SCIPrationalDiv(value, value, oneminusf0);
1971 SCIPrationalAddReal(value, value, aggrinfo->substfactor[i]);
1972 SCIPrationalDebugMessage("adding %q times row (negative continous slacks) (%g aggweight %g substfactor): ", value, -aggrinfo->negslackweights[i] / SCIPrationalGetReal(oneminusf0), aggrinfo->substfactor[i]);
1973 SCIPdebug(SCIProwExactPrint(slackrow, set->scip->messagehdlr, NULL));
1974
1975 assert(slackrow != NULL);
1976 assert(SCIPhashmapExists(certificate->rowdatahash, (void*) slackrow));
1977
1978 key = SCIPcertificateGetRowIndex(certificate, slackrow, SCIPrationalIsPositive(value));
1979
1980 SCIPcertificatePrintProofMessage(certificate, " %d ", key);
1981 SCIPrationalMultReal(value, value, mirinfo->scale);
1982 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, value) );
1983 }
1984
1985 SCIPdebugMessage("Correcting for %d integer slacks \n", mirinfo->nrounddownslacks);
1986 /* we also have to add the correct multipliers for the integer slacks that were used here */
1987 for( i = 0; i < mirinfo->nslacks; i++ )
1988 {
1989 SCIP_Longint key;
1990 SCIP_ROWEXACT* slackrow;
1991 slackrow = SCIProwGetRowExact(mirinfo->slackrows[i]);
1992
1993 if( mirinfo->slackroundeddown[i] )
1994 {
1995 SCIPdebugMessage("Rounded down intger slack on row %s \n", mirinfo->slackrows[i]->name);
1996 SCIPrationalSetReal(value, mirinfo->slackweight[i]);
1997 SCIPrationalMultReal(value, value, mirinfo->slackscale[i]);
1998 SCIPrationalMultReal(value, value, mirinfo->slacksign[i]);
1999 SCIPrationalDiffReal(value, value, mirinfo->slackcoefficients[i] * (-mirinfo->slacksign[i]));
2000 SCIPrationalMultReal(value, value, mirinfo->slacksign[i]);
2001 SCIPrationalDiv(value, value, oneminusf0);
2002 }
2003 else
2004 {
2005 SCIPdebugMessage("Rounded up intger slack on row %s \n", mirinfo->slackrows[i]->name);
2006 SCIPrationalSetReal(value, mirinfo->slackweight[i]);
2007 SCIPrationalMultReal(value, value, mirinfo->slackscale[i]);
2008 SCIPrationalMultReal(value, value, mirinfo->slacksign[i]);
2009 SCIPrationalDiffReal(value, value, (mirinfo->slackcoefficients[i] * -mirinfo->slacksign[i]) - 1); /* fr exactly */
2010 SCIPrationalDiff(value, value, mirinfo->frac); /* fr - f0 */
2011 SCIPrationalDiv(value, value, oneminusf0); /* (fr-f0) / (1-f0) */
2012 SCIPrationalAddReal(value, value, (mirinfo->slackcoefficients[i] * -mirinfo->slacksign[i]) - 1); /* (down(ar) + (fr-f0) / (1-f0) */
2013 SCIPrationalMultReal(value, value, mirinfo->slacksign[i]);
2014 SCIPrationalDebugMessage("Exact coefficient %q(%g), used coefficient %g\n", value, SCIPrationalGetReal(value), mirinfo->slackusedcoef[i]);
2015
2016 SCIPrationalAddReal(value, value, mirinfo->slackusedcoef[i]);
2017 }
2018
2019 SCIPrationalDebugMessage("adding %q(%g) times row: ", value, SCIPrationalGetReal(value));
2020 SCIPdebug(SCIProwExactPrint(slackrow, set->scip->messagehdlr, NULL));
2021
2022 assert(slackrow != NULL);
2023 assert(SCIPhashmapExists(certificate->rowdatahash, (void*) slackrow));
2024
2025 key = SCIPcertificateGetRowIndex(certificate, slackrow, SCIPrationalIsPositive(value));
2026
2027 SCIPcertificatePrintProofMessage(certificate, " %d ", key);
2028 SCIPrationalMultReal(value, value, mirinfo->scale);
2029 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, value) );
2030 }
2031
2032 SCIPdebugMessage("Adding %d aggregation rows \n", aggrinfo->naggrrows);
2033 /* we also have to add the correct multipliers for the aggregation rows that were used here */
2034 for( i = 0; i < aggrinfo->naggrrows; i++ )
2035 {
2036 SCIP_Longint key;
2037 SCIP_ROWEXACT* aggrrow;
2038 aggrrow = SCIProwGetRowExact(aggrinfo->aggrrows[i]);
2039
2040 SCIPrationalSetReal(value, aggrinfo->weights[i]);
2041 SCIPrationalDiv(value, value, oneminusf0);
2042
2043 SCIPdebugMessage("adding (%g/%g) = %g times row: ", aggrinfo->weights[i], SCIPrationalGetReal(oneminusf0), SCIPrationalGetReal(value));
2044 SCIPdebug(SCIProwExactPrint(aggrrow, set->scip->messagehdlr, NULL));
2045
2046 assert(aggrrow != NULL);
2047 assert(SCIPhashmapExists(certificate->rowdatahash, (void*) aggrrow));
2048
2049 key = SCIPcertificateGetRowIndex(certificate, aggrrow, SCIPrationalIsPositive(value));
2050
2051 SCIPcertificatePrintProofMessage(certificate, " %d ", key);
2052 SCIPrationalMultReal(value, value, mirinfo->scale);
2053 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, value) );
2054 }
2055
2056 SCIPcertificatePrintProofMessage(certificate, " } -1\n");
2057 }
2058#ifdef SCIP_DISABLED_CODE
2059 /* this was an alternative piece of code to the block right above */
2060 {
2061 SCIP_CALL( certificatePrintRow(set, certificate, rowexact, mirinfo->unroundedrhs) );
2062 SCIP_CALL( certificatePrintIncompleteDerStart(certificate, SCIPlpGetRows(lp), SCIPlpGetNRows(lp), prob, SCIProwIsLocal(row)) );
2063 SCIPcertificatePrintProofMessage(certificate, " %d } -1\n", leftdisjunctionindex);
2064
2065 SCIP_CALL( certificatePrintRow(set, certificate, rowexact, mirinfo->unroundedrhs) );
2066 SCIP_CALL( certificatePrintIncompleteDerStart(certificate, SCIPlpGetRows(lp), SCIPlpGetNRows(lp), prob, SCIProwIsLocal(row)) );
2067 SCIPcertificatePrintProofMessage(certificate, " %d } -1\n", rightdisjunctionindex);
2068 }
2069#endif
2070
2071 /* print the unsplitting of the split disjunction */
2072 SCIP_CALL( certificatePrintRow(set, certificate, rowexact, mirinfo->unroundedrhs) );
2073 SCIPcertificatePrintProofMessage(certificate, " { uns %d %d %d %d } -1\n", certificate->indexcounter - 3, leftdisjunctionindex,
2074 certificate->indexcounter - 2, rightdisjunctionindex);
2075
2076 /* if we rounded the rhs we need to still certify that part */
2077 if( !SCIPsetIsInfinity(set, mirinfo->unroundedrhs) )
2078 {
2079 /* print the row with the rounded rhs */
2080 SCIP_CALL( certificatePrintRow(set, certificate, rowexact, SCIPsetInfinity(set)) );
2081 SCIPcertificatePrintProofMessage(certificate, " { rnd 1 %d 1 } -1\n", certificate->indexcounter - 2);
2082 }
2083 SCIP_CALL( SCIPhashmapInsertLong(certificate->rowdatahash, SCIProwGetRowExact(row), certificate->indexcounter - 1) );
2084
2085 SCIP_CALL( SCIPcertificateFreeAggrInfo(set, certificate, lp, aggrinfo, row) );
2086 SCIP_CALL( SCIPcertificateFreeMirInfo(set, certificate, lp, mirinfo, row) );
2087
2088 SCIPrationalFreeBuffer(set->buffer, &value);
2089 SCIPrationalFreeBuffer(set->buffer, &oneminusf0);
2090 SCIPrationalFreeBuffer(set->buffer, &tmpval);
2091
2092 return SCIP_OKAY;
2093}
2094
2095/** prints a variable bound to the problem section of the certificate file and returns line index */
2097 SCIP_CERTIFICATE* certificate, /**< certificate information */
2098 SCIP_Bool isorigfile, /**< should the line be printed to the origfile or the transfile */
2099 const char* boundname, /**< name of the bound constraint */
2100 SCIP_VAR* var, /**< variable to print the bound cons for */
2101 SCIP_RATIONAL* boundval, /**< value of the bound */
2102 SCIP_Bool isupper /**< is it the upper bound? */
2103 )
2104{
2105 /* check whether certificate output should be created */
2106 if( !SCIPcertificateIsEnabled(certificate) )
2107 return SCIP_OKAY;
2108
2109 if( !isorigfile )
2110 {
2111 certificate->indexcounter++;
2112 certificate->conscounter++;
2113
2114#ifndef NDEBUG
2115 certificate->lastinfo->isbound = TRUE;
2116 certificate->lastinfo->boundtype = isupper ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER;
2117 certificate->lastinfo->varindex = SCIPvarGetCertificateIndex(var);
2118 certificate->lastinfo->isglobal = TRUE;
2119 certificate->lastinfo->certificateindex = certificate->indexcounter - 1;
2120 SCIPrationalSetRational(certificate->lastinfo->boundval, boundval);
2121#endif
2122
2123 if( isupper )
2124 SCIPvarSetUbCertificateIndexGlobal(var, certificate->indexcounter - 1);
2125 else
2126 SCIPvarSetLbCertificateIndexGlobal(var, certificate->indexcounter - 1);
2127
2128 if( boundname == NULL )
2129 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "B%d %c ", certificate->indexcounter - 1, (isupper ? 'L' : 'G'));
2130 else
2131 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "%s %c ", boundname, (isupper ? 'L' : 'G'));
2132 }
2133 else
2134 {
2135 certificate->indexcounter_ori++;
2136 if( boundname == NULL )
2137 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "B%d %c ", certificate->indexcounter_ori - 1, (isupper ? 'L' : 'G'));
2138 else
2139 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "%s %c ", boundname, (isupper ? 'L' : 'G'));
2140 }
2141
2142 SCIP_CALL( SCIPcertificatePrintProblemRational(certificate, isorigfile, boundval) );
2143 SCIPcertificatePrintProblemMessage(certificate, isorigfile, " 1 %d 1\n", SCIPvarGetCertificateIndex(var));
2144
2145 return SCIP_OKAY;
2146}
2147
2148/** installs updated node data in parent node */
2150 SCIP_CERTIFICATE* certificate, /**< certificate information */
2151 SCIP_NODE* node, /**< node data structure */
2152 SCIP_Longint fileindex, /**< index of new bound */
2153 SCIP_RATIONAL* newbound /**< pointer to value of new bound, NULL if infeasible */
2154 )
2155{
2156 SCIP_CERTNODEDATA* nodedataparent;
2158
2159 assert(node != NULL);
2160 assert(fileindex >= 0);
2161
2162 if( !SCIPcertificateIsEnabled(certificate) )
2163 return SCIP_OKAY;
2164
2165 /* retrieve node data */
2166 assert(SCIPhashmapExists(certificate->nodedatahash, node));
2168
2169 if( newbound != NULL && SCIPrationalIsLT(newbound, nodedata->derbound_self) )
2170 return SCIP_OKAY;
2171
2172 /* if the node is the root node, then only update the index and bound */
2173 if( SCIPnodeGetParent(node) == NULL )
2174 {
2175 certificate->derindex_root = fileindex;
2176 if( newbound == NULL )
2177 certificate->rootinfeas = TRUE;
2178 else
2179 SCIPrationalSetRational(certificate->rootbound, newbound);
2180 return SCIP_OKAY;
2181 }
2182
2183 /* retrieve parent node data */
2184 assert(SCIPhashmapExists(certificate->nodedatahash, SCIPnodeGetParent(node)));
2185 nodedataparent = (SCIP_CERTNODEDATA*)SCIPhashmapGetImage(certificate->nodedatahash, SCIPnodeGetParent(node));
2186
2187 /* First we check whether the node is left/right child of its parent node; left/rightfilled tells us if a bound has
2188 * already been derived for this node. We only install the new bound if the node is not already marked as infeasible
2189 * and the new bound is better than the current bound if it is filled.
2190 */
2191 if( certificateIsLeftNode(certificate, node) )
2192 {
2193 if( newbound != NULL && !nodedataparent->leftinfeas && (!nodedataparent->leftfilled || SCIPrationalIsGT(newbound, nodedataparent->derbound_left)) )
2194 {
2195 nodedataparent->derindex_left = fileindex;
2196 SCIPrationalSetRational(nodedataparent->derbound_left, newbound);
2197 }
2198 if( newbound == NULL || SCIPrationalIsInfinity(newbound) )
2199 {
2200 nodedataparent->derindex_left = fileindex;
2201 nodedataparent->leftinfeas = TRUE;
2202 }
2203 nodedataparent->leftfilled = TRUE;
2204 }
2205 else
2206 {
2207 if( newbound != NULL && !nodedataparent->rightinfeas && (!nodedataparent->rightfilled || SCIPrationalIsGT(newbound, nodedataparent->derbound_right)) )
2208 {
2209 nodedataparent->derindex_right = fileindex;
2210 SCIPrationalSetRational(nodedataparent->derbound_right, newbound);
2211 }
2212 if( newbound == NULL || SCIPrationalIsInfinity(newbound) )
2213 {
2214 nodedataparent->rightinfeas = TRUE;
2215 nodedataparent->derindex_right = fileindex;
2216 }
2217 nodedataparent->rightfilled = TRUE;
2218 }
2219
2220 return SCIP_OKAY;
2221}
2222
2223/** prints a dual bound from an exact lp solution */
2225 SCIP_CERTIFICATE* certificate, /**< scip certificate struct */
2226 SCIP_LPEXACT* lpexact, /**< the exact lp */
2227 SCIP_SET* set, /**< scip settings */
2228 SCIP_NODE* node, /**< the current node */
2229 SCIP_PROB* prob, /**< problem data */
2230 SCIP_Bool usefarkas /**< should an infeasibility proof be printed? */
2231 )
2232{
2233 SCIP_RATIONAL** vals;
2234 SCIP_RATIONAL* val;
2235 SCIP_RATIONAL* lowerbound;
2236 SCIP_RATIONAL* farkasrhs;
2237 SCIP_RATIONAL* tmp;
2238 SCIP_Longint* ind = NULL;
2239 int len;
2240 int i;
2241 SCIP_Longint key;
2242
2243 /* check whether certificate output should be created */
2244 if( !SCIPcertificateIsEnabled(certificate) )
2245 return SCIP_OKAY;
2246
2247 SCIPdebugMessage("Printing dual bound from exact LP. Certificate index %lld \n", certificate->indexcounter);
2248
2249 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
2250 SCIPlpExactGetObjval(lpexact, set, tmp);
2251
2252 /* only print line if bound improved */
2253 if( !usefarkas && SCIPrationalIsLT(tmp, SCIPnodeGetLowerboundExact(node)) )
2254 {
2255 SCIPrationalFreeBuffer(set->buffer, &tmp);
2256 return SCIP_OKAY;
2257 }
2258
2259 /* init the flag objintegral if at root node */
2260 if( SCIPnodeGetParent(node) == NULL )
2261 certificate->objintegral = SCIPprobIsObjIntegral(prob);
2262
2263 assert(lpexact != NULL);
2264 assert(certificate->transfile != NULL);
2265
2266 /* if needed extend vals array */
2267 if( lpexact->ncols + lpexact->nrows > certificate->valssize )
2268 {
2269 SCIP_CALL( SCIPrationalReallocBlockArray(certificate->blkmem, &(certificate->vals), certificate->valssize, lpexact->nrows + lpexact->ncols + 50) );
2270 certificate->valssize = lpexact->ncols + lpexact->nrows + 50;
2271 }
2272
2273 vals = certificate->vals;
2274
2275 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &farkasrhs) );
2276
2277 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, (lpexact->nrows + lpexact->ncols)) );
2278
2279 len = 0;
2280 for( i = 0; i < lpexact->ncols; ++i )
2281 {
2282 SCIP_COLEXACT* col = lpexact->cols[i];
2283 SCIP_VAR* var = SCIPcolExactGetVar(col);
2284
2285 if( usefarkas )
2286 val = col->farkascoef;
2287 else
2288 val = col->redcost;
2289
2290 assert(!SCIPrationalIsAbsInfinity(val));
2291
2292 if( !SCIPrationalIsZero(val) )
2293 {
2294 if( usefarkas )
2295 SCIPrationalNegate(vals[len], val);
2296 else
2297 SCIPrationalSetRational(vals[len], val);
2298
2300
2301 SCIPrationalDebugMessage("Column %d for var %s has index %l and farkas coef %q \n", col->index, col->var->name, ind[len], val);
2302
2303 /* update farkasrhs */
2304 if( usefarkas )
2305 {
2307 SCIPrationalAddProd(farkasrhs, vals[len], val);
2308 }
2309 len++;
2310 }
2311 }
2312
2313 for( i = 0; i < lpexact->nrows; ++i )
2314 {
2315 SCIP_ROWEXACT* row;
2316 row = lpexact->rows[i];
2317 val = usefarkas ? row->dualfarkas : row->dualsol;
2318 assert(!SCIPrationalIsAbsInfinity(val));
2319
2320 if( !SCIPrationalIsZero(val) )
2321 {
2322 SCIPrationalSetRational(vals[len], val);
2323 key = SCIPhashmapGetImageLong(certificate->rowdatahash, (void*) row);
2324
2326 {
2327 SCIP_CALL( SCIPcertificatePrintMirCut(set, lpexact->fplp, certificate, prob, SCIProwExactGetRow(row), 'L') );
2328 key = SCIPhashmapGetImageLong(certificate->rowdatahash, (void*) row);
2329 }
2330 else if( key == SCIP_LONGINT_MAX && SCIProwExactGetNNonz(row) == 1 )
2331 {
2334 }
2335
2336 assert(key != SCIP_LONGINT_MAX);
2337
2338 ind[len] = key;
2339 /* if we have a ranged row, and the dual corresponds to the upper bound,
2340 * the index for the rhs-constraint is one larger in the certificate */
2341 if( !SCIPrationalIsEQ(row->lhs, row->rhs) && !SCIPrationalIsAbsInfinity(row->lhs) && SCIPrationalIsNegative(val) )
2342 ind[len] += 1;
2343
2344 SCIPrationalDebugMessage("Row (index %d, %s has index %l and farkas coef %q ", row->index, row->fprow->name, ind[len], val);
2345 SCIPdebug(SCIProwExactPrint(row, set->scip->messagehdlr, NULL) );
2346
2347 /* update farkasrhs */
2348 if( usefarkas )
2349 {
2350 val = SCIPrationalIsPositive(vals[len]) ? row->lhs : row->rhs;
2351 SCIPrationalAddProd(farkasrhs, vals[len], val);
2352 SCIPrationalDiffProd(farkasrhs, vals[len], row->constant);
2353 }
2354
2355 len++;
2356 }
2357 }
2358
2359 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &lowerbound) );
2360 if( usefarkas )
2361 {
2362 SCIPrationalSetInfinity(lowerbound);
2363 }
2364 else
2365 {
2366 /* vipr does not accept infinity, so in case of objlimit, get the objval from the lpi */
2367 if( !SCIPrationalIsInfinity(lpexact->lpobjval) )
2368 SCIPrationalSetRational(lowerbound, lpexact->lpobjval);
2369 else
2370 {
2371 SCIP_CALL( SCIPlpiExactGetObjval(lpexact->lpiexact, lowerbound) );
2372 }
2373 }
2374
2375 SCIP_CALL( certificatePrintDualbound(certificate, NULL, lowerbound, len, ind, vals) );
2376 SCIP_CALL( SCIPcertificateUpdateParentData(certificate, node, certificate->indexcounter - 1, lowerbound) );
2377 SCIP_CALL( SCIPcertificateUpdateBoundData(certificate, node, certificate->indexcounter - 1, lowerbound) );
2378
2379 SCIPrationalFreeBuffer(set->buffer, &lowerbound);
2381 SCIPrationalFreeBuffer(set->buffer, &farkasrhs);
2382 SCIPrationalFreeBuffer(set->buffer, &tmp);
2383
2384 return SCIP_OKAY;
2385}
2386
2387/** prints a dual bound from the pseudo solution
2388 *
2389 * in case of a bound change (branching), this happens before the bound change is processed;
2390 * therefore we add the option to give on varindex, boundchgindex pair to pass directly to the method
2391 */
2393 SCIP_CERTIFICATE* certificate, /**< scip certificate struct */
2394 SCIP_LPEXACT* lpexact, /**< the exact lp */
2395 SCIP_NODE* node, /**< current node */
2396 SCIP_SET* set, /**< scip settings */
2397 SCIP_PROB* prob, /**< problem data */
2398 SCIP_Bool lowerchanged, /**< do the modified indices address a change in lb or ub? */
2399 int modifiedvarindex, /**< index of modified variable, or -1 */
2400 SCIP_Longint boundchangeindex, /**< index of unprocessed bound change in the certificate, or -1 */
2401 SCIP_Real psval /**< the pseudo obj value (or inf to use exact lp value) */
2402 )
2403{
2404 SCIP_VAR** vars;
2405 SCIP_RATIONAL* pseudoobjval;
2406 SCIP_RATIONAL** bounds;
2407 SCIP_Longint* dualind = NULL;
2408 int nvars;
2409 int duallen;
2410 int i;
2411 int nnonzeros;
2412
2413 assert(certificate != NULL);
2414 assert(prob != NULL);
2415 assert(set != NULL);
2416 assert((modifiedvarindex >= 0 && boundchangeindex >= 0) || (modifiedvarindex == -1 && boundchangeindex == -1) );
2417
2418 /* check whether certificate output should be created */
2419 if( !SCIPcertificateIsEnabled(certificate) )
2420 return SCIP_OKAY;
2421
2422 /* only print if bound is finite and improving */
2423 if( SCIPsetIsInfinity(set, -psval) || psval < SCIPnodeGetLowerbound(node) )
2424 return SCIP_OKAY;
2425
2426 /* if at root node set, objintegral flag */
2427 if( SCIPnodeGetParent(node) == NULL )
2428 certificate->objintegral = SCIPprobIsObjIntegral(prob);
2429
2430 vars = SCIPprobGetVars(prob);
2431 nvars = SCIPprobGetNVars(prob);
2432 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &pseudoobjval) );
2433
2434 /* infinity means we use the exact lp value */
2435 if( SCIPsetIsInfinity(set, psval) )
2436 SCIPlpExactGetPseudoObjval(lpexact, set, pseudoobjval);
2437 else
2438 SCIPrationalSetReal(pseudoobjval, psval);
2439 duallen = SCIPprobGetNObjVars(prob, set);
2440 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &bounds, duallen) );
2441 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualind, duallen) );
2442 /* computes pseudo objective value (with bound change if necessary) */
2443 /*lint --e{838}*/
2444
2445 nnonzeros = 0;
2446 for( i = 0; i < nvars; i++ )
2447 {
2448 SCIP_RATIONAL* obj = SCIPvarGetObjExact(vars[i]);
2449 if( !SCIPrationalIsZero(obj) )
2450 {
2451 SCIPrationalSetRational(bounds[nnonzeros], obj);
2452
2453 assert(!SCIPrationalIsAbsInfinity(bounds[nnonzeros]));
2454
2455 /* retrieve the line in the certificate of the bound */
2456 if( SCIPrationalIsPositive(obj) )
2457 {
2458 dualind[nnonzeros] = SCIPvarGetLbCertificateIndexLocal(vars[i]);
2459 if( lowerchanged && modifiedvarindex == SCIPvarGetCertificateIndex(vars[i]) )
2460 dualind[nnonzeros] = boundchangeindex;
2461 }
2462 else
2463 {
2464 dualind[nnonzeros] = SCIPvarGetUbCertificateIndexLocal(vars[i]);
2465 if( !lowerchanged && modifiedvarindex == SCIPvarGetCertificateIndex(vars[i]) )
2466 dualind[nnonzeros] = boundchangeindex;
2467 }
2468
2469 nnonzeros++;
2470 }
2471 }
2472 assert(nnonzeros == duallen);
2473
2474 /* print pseudo solution into certificate file */
2475 SCIP_CALL( certificatePrintDualbound(certificate, NULL, pseudoobjval, duallen, dualind, bounds) );
2476
2477 SCIP_CALL( SCIPcertificateUpdateParentData(certificate, node, certificate->indexcounter - 1,
2478 pseudoobjval) );
2479
2480 SCIP_CALL( SCIPcertificateUpdateBoundData(certificate, node, certificate->indexcounter - 1, pseudoobjval) );
2481
2482 SCIPsetFreeBufferArray(set, &dualind);
2483 SCIPrationalFreeBufferArray(set->buffer, &bounds, nnonzeros);
2484 SCIPrationalFreeBuffer(set->buffer, &pseudoobjval);
2485
2486 return SCIP_OKAY;
2487}
2488
2489/** prints the bound that a node inherits from its parent to the certificate */
2491 SCIP_SET* set, /**< general SCIP settings */
2492 SCIP_CERTIFICATE* certificate, /**< certificate data structure */
2493 SCIP_NODE* node /**< node data */
2494 )
2495{
2497 SCIP_RATIONAL* lowerbound;
2498
2499 assert(node != NULL);
2500
2501 /* check whether certificate output should be created */
2502 if( !SCIPcertificateIsEnabled(certificate) )
2503 return SCIP_OKAY;
2504
2505 /* certificate is disabled on probing nodes */
2507 return SCIP_OKAY;
2508
2509 /* get the current node data */
2510 assert(SCIPhashmapExists(certificate->nodedatahash, node));
2512
2513 if( nodedata->inheritedbound && nodedata->assumptionindex_self != - 1 )
2514 {
2515 SCIP_Longint ind[1];
2516 SCIP_RATIONAL* val;
2517
2518 ind[0] = nodedata->derindex_self;
2519
2520 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &lowerbound) );
2521 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &val) );
2522
2523 SCIPrationalSetRational(lowerbound, nodedata->derbound_self);
2524 SCIPrationalSetFraction(val, 1LL, 1LL);
2525
2526 SCIP_CALL( certificatePrintDualbound(certificate, NULL, lowerbound, 1, ind, &val) );
2527 SCIP_CALL( SCIPcertificateUpdateParentData(certificate, node, certificate->indexcounter - 1, lowerbound) );
2528
2529 SCIPrationalFreeBuffer(set->buffer, &lowerbound);
2530 SCIPrationalFreeBuffer(set->buffer, &val);
2531 }
2532
2533 return SCIP_OKAY;
2534}
2535
2536/** returns the index for a row in the certificate
2537 *
2538 * @todo let this method return LONG_MAX if row is not in the hashmap; add method to check existence, and to insert an
2539 * element, and use these throughout the SCIP core
2540 */
2542 SCIP_CERTIFICATE* certificate, /**< certificate data structure */
2543 SCIP_ROWEXACT* row, /**< row to consider */
2544 SCIP_Bool rhs /**< whether we want the index for the rhs or the lhs */
2545 )
2546{
2547 SCIP_Longint ret = SCIPhashmapGetImageLong(certificate->rowdatahash, row);
2548 assert( ret != SCIP_LONGINT_MAX );
2549 /* for ranged rows, the key always corresponds to the >= part of the row;
2550 therefore we need to increase it by one to get the correct key */
2551 if( !SCIPrationalIsAbsInfinity(row->rhs) && !SCIPrationalIsAbsInfinity(row->lhs) && !SCIPrationalIsEQ(row->lhs, row->rhs) && rhs)
2552 ret += 1;
2553 return ret;
2554}
2555
2556/** updates the parent certificate node data when branching */
2558 SCIP_SET* set, /**< general SCIP settings */
2559 SCIP_CERTIFICATE* certificate, /**< certificate information */
2560 SCIP_STAT* stat, /**< dynamic problem statistics */
2561 SCIP_LP* lp, /**< LP informations */
2562 SCIP_NODE* node, /**< node data */
2563 SCIP_VAR* branchvar, /**< the variable that gets branched on */
2564 SCIP_BOUNDTYPE boundtype, /**< the bounding type */
2565 SCIP_Real newbound /**< the new bound */
2566 )
2567{
2568 SCIP_CERTNODEDATA* nodedataparent;
2570 SCIP_RATIONAL* branchbound;
2571
2572 assert(node != NULL);
2573 assert(stat != NULL);
2574
2575 /* check whether certificate output should be created */
2576 if( !SCIPcertificateIsEnabled(certificate) )
2577 return SCIP_OKAY;
2578
2579 /* certificate is disabled on probing nodes */
2581 return SCIP_OKAY;
2582
2583 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &branchbound) );
2584 SCIPrationalSetReal(branchbound, newbound);
2585
2586 assert(SCIPrationalIsIntegral(branchbound));
2587
2589
2590 if( branchvar != NULL )
2591 {
2592 nodedata->assumptionindex_self = printBoundAssumption(certificate, branchvar,
2593 branchbound, boundtype);
2594 }
2595
2596 if( SCIPnodeGetParent(node) != NULL && certificate->transfile != NULL )
2597 {
2598 nodedataparent = (SCIP_CERTNODEDATA*)SCIPhashmapGetImage(certificate->nodedatahash, SCIPnodeGetParent(node));
2599
2600 if( branchvar != NULL )
2601 {
2602 if( boundtype == SCIP_BOUNDTYPE_UPPER )
2603 nodedataparent->assumptionindex_right = nodedata->assumptionindex_self;
2604 if( boundtype == SCIP_BOUNDTYPE_LOWER )
2605 nodedataparent->assumptionindex_left = nodedata->assumptionindex_self;
2606 }
2607 }
2608
2609 SCIPrationalFreeBuffer(set->buffer, &branchbound);
2610
2611 return SCIP_OKAY;
2612}
2613
2614/** create a new node data structure for the current node */
2616 SCIP_CERTIFICATE* certificate, /**< SCIP certificate */
2617 SCIP_STAT* stat, /**< problem statistics */
2618 SCIP_NODE* node /**< new node, that was created */
2619 )
2620{
2622
2623 assert(stat != NULL );
2624 assert(node != NULL );
2625
2626 /* check whether certificate output should be created */
2627 if( !SCIPcertificateIsEnabled(certificate) )
2628 return SCIP_OKAY;
2629
2630 /* certificate is disabled on probing nodes */
2632 return SCIP_OKAY;
2633
2634 SCIP_ALLOC( BMSallocBlockMemory(certificate->blkmem, &nodedata) );
2635
2636 nodedata->derindex_left = -1;
2637 nodedata->derindex_right = -1;
2638 nodedata->assumptionindex_left = -1;
2639 nodedata->assumptionindex_right = -1;
2640 SCIP_CALL( SCIPrationalCreateString(certificate->blkmem, &nodedata->derbound_left, "-inf") );
2641 SCIP_CALL( SCIPrationalCreateString(certificate->blkmem, &nodedata->derbound_right, "-inf") );
2642 SCIP_CALL( SCIPrationalCreateString(certificate->blkmem, &nodedata->derbound_self, "-inf") );
2643 nodedata->assumptionindex_self = -1;
2644 nodedata->leftinfeas = FALSE;
2645 nodedata->leftfilled = FALSE;
2646 nodedata->rightinfeas = FALSE;
2647 nodedata->rightfilled = FALSE;
2648 nodedata->inheritedbound = TRUE;
2649 nodedata->derindex_self = -1;
2650 if( SCIPnodeGetParent(node) != NULL )
2651 {
2652 SCIP_NODE* parent = SCIPnodeGetParent(node);
2653 SCIP_CERTNODEDATA* parentdata;
2654 assert(SCIPhashmapExists(certificate->nodedatahash, parent));
2655 parentdata = (SCIP_CERTNODEDATA*) SCIPhashmapGetImage(certificate->nodedatahash, (void*) parent);
2656 assert(parentdata != NULL);
2657
2658 nodedata->derindex_self = parentdata->derindex_self;
2659 SCIPrationalSetRational(nodedata->derbound_self, parentdata->derbound_self);
2660 }
2661
2662 /* link the node to its nodedata in the corresponding hashmap */
2663 SCIP_CALL( SCIPhashmapSetImage(certificate->nodedatahash, node, (void*)nodedata) );
2664
2665 return SCIP_OKAY;
2666}
2667
2668/** prints cutoff bound for objective value **/
2670 SCIP* scip, /**< SCIP data structure */
2671 SCIP_CERTIFICATE* certificate, /**< SCIP certificate */
2672 SCIP_RATIONAL* bound, /**< the bound */
2673 SCIP_Longint* certificateline /**< save the line index */
2674 )
2675{
2676 SCIP_RATIONAL* newbound;
2677
2678 /* check whether certificate output should be created */
2679 if( !SCIPcertificateIsEnabled(certificate) )
2680 return SCIP_OKAY;
2681
2685 else
2686 SCIPrationalSetRational(newbound, bound);
2687
2688 SCIPcertificatePrintProofMessage(certificate, "O%d L ", certificate->indexcounter);
2689 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, newbound) );
2690 SCIPcertificatePrintProofMessage(certificate, " OBJ { sol } -1\n");
2691
2692 certificate->indexcounter++;
2693 *certificateline = certificate->indexcounter - 1;
2695
2696 return SCIP_OKAY;
2697}
2698
2699/** create a new node data structure for the current node */
2701 SCIP_SET* set, /**< general SCIP settings */
2702 SCIP_PROB* prob, /**< SCIP problem data */
2703 SCIP_CERTIFICATE* certificate, /**< SCIP certificate */
2704 SCIP_AGGRROW* aggrrow, /**< agrrrow that results from the aggregation */
2705 SCIP_ROW** aggrrows, /**< array of rows used fo the aggregation */
2706 SCIP_Real* weights, /**< array of weights */
2707 int naggrrows, /**< length of the arrays */
2708 SCIP_Bool local, /**< true if local bound information can be used */
2709 SCIP_Longint* certificateline /**< pointer to store the certificate line index or NULL */
2710 )
2711{
2712 int i;
2713 SCIP_RATIONAL* tmpval;
2714 SCIP_ROWEXACT* rowexact;
2715 SCIP_VAR** vars;
2716
2717 /* check whether certificate output should be created */
2718 if( !SCIPcertificateIsEnabled(certificate) )
2719 return SCIP_OKAY;
2720
2721 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
2722 vars = SCIPprobGetVars(prob);
2723
2724 SCIPdebugMessage("printing certificate for aggrrow: ");
2725 SCIPdebug(SCIPaggrRowPrint(set->scip, aggrrow, NULL));
2726
2727 SCIPcertificatePrintProofMessage(certificate, "AggrRow_%d %c ", certificate->indexcounter, 'L');
2728
2729 SCIPrationalSetReal(tmpval, SCIPaggrRowGetRhs(aggrrow));
2730
2731 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, tmpval) );
2732
2733 SCIPcertificatePrintProofMessage(certificate, " %d", SCIPaggrRowGetNNz(aggrrow));
2734
2735 for( i = 0; i < SCIPaggrRowGetNNz(aggrrow); i++ )
2736 {
2737 int varindex;
2738
2739 /** @todo perform line breaking before exceeding maximum line length */
2740 varindex = SCIPvarGetCertificateIndex(vars[SCIPaggrRowGetInds(aggrrow)[i]]);
2742
2743 SCIPcertificatePrintProofMessage(certificate, " %d ", varindex);
2744 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, tmpval) );
2745 }
2746
2747 SCIP_CALL( certificatePrintWeakDerStart(certificate, prob, local) );
2748 SCIPcertificatePrintProofMessage(certificate, " %d", naggrrows);
2749 for( i = 0; i < naggrrows; i++ )
2750 {
2751 SCIP_Longint key;
2752 rowexact = SCIProwGetRowExact(aggrrows[i]);
2753
2754 SCIPdebugMessage("adding %g times row: ", weights[i]);
2755 SCIPdebug(SCIProwExactPrint(rowexact, set->scip->messagehdlr, NULL));
2756 SCIPrationalSetReal(tmpval, weights[i]);
2757
2758 assert(rowexact != NULL);
2759 assert(SCIPhashmapExists(certificate->rowdatahash, (void*) rowexact));
2760
2761 key = SCIPcertificateGetRowIndex(certificate, rowexact, SCIPrationalIsPositive(tmpval));
2762
2763 SCIPcertificatePrintProofMessage(certificate, " %d ", key);
2764 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, tmpval) );
2765 }
2766
2767 SCIPcertificatePrintProofMessage(certificate, " } -1\n");
2768
2769 if( certificateline != NULL )
2770 *certificateline = certificate->indexcounter;
2771 certificate->indexcounter++;
2772 certificate->lastinfo->isbound = FALSE;
2773
2774 SCIPrationalFreeBuffer(set->buffer, &tmpval);
2775
2776 return SCIP_OKAY;
2777}
2778
2779/** free all aggregation information */
2781 SCIP* scip /**< global SCIP data structure */
2782 )
2783{
2784 SCIP_Longint i;
2785 SCIP_CERTIFICATE* certificate;
2786
2787 certificate = SCIPgetCertificate(scip);
2788
2789 /* check whether certificate output should be created */
2790 if( !SCIPcertificateIsEnabled(certificate) )
2791 return SCIP_OKAY;
2792
2793 if( certificate == NULL || certificate->aggrinfo == NULL )
2794 return SCIP_OKAY;
2795
2796 assert(certificate != NULL);
2797
2798 for( i = certificate->naggrinfos - 1; i >= 0; i-- )
2799 {
2800 SCIP_CALL( SCIPcertificateFreeAggrInfo(scip->set, certificate, scip->lp, certificate->aggrinfo[i], NULL) );
2801 }
2802
2803 BMSfreeBlockMemoryArray(certificate->blkmem, &certificate->aggrinfo, certificate->aggrinfosize);
2805 SCIPhashmapFree(&certificate->aggrinfohash);
2806 certificate->naggrinfos = 0;
2807 certificate->aggrinfohash = NULL;
2808
2809 return SCIP_OKAY;
2810}
2811
2812/** free all mir information */
2814 SCIP* scip /**< global SCIP data structure */
2815 )
2816{
2817 int i, j;
2818 SCIP_CERTIFICATE* certificate;
2819
2820 certificate = SCIPgetCertificate(scip);
2821
2822 /* check whether certificate output should be created */
2823 if( !SCIPcertificateIsEnabled(certificate) )
2824 return SCIP_OKAY;
2825
2826 if( certificate == NULL || certificate->mirinfo == NULL )
2827 return SCIP_OKAY;
2828
2829 assert(certificate != NULL);
2830
2831 for( i = 0; i < certificate->nmirinfos; i++ )
2832 {
2833 for( j = 0; j < certificate->mirinfo[i]->nslacks; ++j )
2834 {
2835 SCIP_CALL( SCIPreleaseRow(scip, &(certificate->mirinfo[i]->slackrows[j])) );
2836 }
2837 SCIPrationalFreeBlock(certificate->blkmem, &certificate->mirinfo[i]->frac);
2838 SCIPrationalFreeBlock(certificate->blkmem, &certificate->mirinfo[i]->rhs);
2839 BMSfreeBlockMemoryArray(certificate->blkmem, &(certificate->mirinfo[i]->varinds), certificate->mirinfo[i]->nsplitvars);
2840 BMSfreeBlockMemoryArray(certificate->blkmem, &(certificate->mirinfo[i]->splitcoefficients), certificate->mirinfo[i]->nsplitvars);
2841 BMSfreeBlockMemoryArray(certificate->blkmem, &(certificate->mirinfo[i]->upperused), certificate->mirinfo[i]->nsplitvars);
2842 BMSfreeBlockMemoryArray(certificate->blkmem, &(certificate->mirinfo[i]->localbdused), certificate->mirinfo[i]->nsplitvars);
2843 BMSfreeBlockMemoryArray(certificate->blkmem, &(certificate->mirinfo[i]->slackrows), certificate->mirinfo[i]->nslacks);
2844 BMSfreeBlockMemoryArray(certificate->blkmem, &(certificate->mirinfo[i]->slacksign), certificate->mirinfo[i]->nslacks);
2845 BMSfreeBlockMemoryArray(certificate->blkmem, &(certificate->mirinfo[i]->slackcoefficients), certificate->mirinfo[i]->nslacks);
2846 BMSfreeBlockMemoryArray(certificate->blkmem, &(certificate->mirinfo[i]->slackweight), certificate->mirinfo[i]->nslacks);
2847 BMSfreeBlockMemoryArray(certificate->blkmem, &(certificate->mirinfo[i]->slackroundeddown), certificate->mirinfo[i]->nslacks);
2848 BMSfreeBlockMemoryArray(certificate->blkmem, &(certificate->mirinfo[i]->slackscale), certificate->mirinfo[i]->nslacks);
2849 BMSfreeBlockMemoryArray(certificate->blkmem, &(certificate->mirinfo[i]->slackusedcoef), certificate->mirinfo[i]->nslacks);
2850 BMSfreeBlockMemory(certificate->blkmem, &certificate->mirinfo[i]);
2851 }
2852
2853 certificate->nmirinfos = 0;
2854 BMSfreeBlockMemoryArray(certificate->blkmem, &certificate->mirinfo, certificate->mirinfosize);
2856 SCIPhashmapFree(&certificate->mirinfohash);
2857
2858 return SCIP_OKAY;
2859}
2860
2861/** free aggregation information for row */
2863 SCIP_SET* set, /**< general SCIP settings */
2864 SCIP_CERTIFICATE* certificate, /**< SCIP certificate structure */
2865 SCIP_LP* lp, /**< SCIP lp data structure */
2866 SCIP_AGGREGATIONINFO* aggrinfo, /**< SCIP aggregation info */
2867 SCIP_ROW* row /**< row that should be freed, or NULL if not needed */
2868 )
2869{
2870 SCIP_Longint arraypos;
2871 int i;
2872
2873 /* check whether certificate output should be created */
2874 if( !SCIPcertificateIsEnabled(certificate) )
2875 return SCIP_OKAY;
2876
2877 /* remove the (no longer needed aggrinfo), move last element to now freed spot */
2878 arraypos = aggrinfo->arpos;
2879
2880 if( row != NULL )
2881 {
2882 SCIP_CALL( SCIPhashmapRemove(certificate->aggrinfohash, (void*) row) );
2883 }
2884
2885 for( i = 0; i < aggrinfo->naggrrows; i++ )
2886 {
2887 SCIP_CALL( SCIProwRelease(&(aggrinfo->aggrrows[i]), certificate->blkmem, set, lp) );
2888 }
2889 for( i = 0; i < aggrinfo->nnegslackrows; i++ )
2890 {
2891 SCIP_CALL( SCIProwRelease(&(aggrinfo->negslackrows[i]), certificate->blkmem, set, lp) );
2892 }
2893
2894 BMSfreeBlockMemoryArray(certificate->blkmem, &(aggrinfo->substfactor), aggrinfo->nnegslackrows);
2895 BMSfreeBlockMemoryArray(certificate->blkmem, &(aggrinfo->negslackweights), aggrinfo->nnegslackrows);
2896 BMSfreeBlockMemoryArray(certificate->blkmem, &(aggrinfo->negslackrows), aggrinfo->nnegslackrows);
2897 BMSfreeBlockMemoryArray(certificate->blkmem, &(aggrinfo->weights), aggrinfo->naggrrows);
2898 BMSfreeBlockMemoryArray(certificate->blkmem, &(aggrinfo->aggrrows), aggrinfo->naggrrows);
2899 SCIPaggrRowFree(set->scip, &(aggrinfo->aggrrow));
2900 BMSfreeBlockMemory(certificate->blkmem, &aggrinfo);
2901 if( arraypos != certificate->naggrinfos - 1 )
2902 {
2903 certificate->aggrinfo[arraypos] = certificate->aggrinfo[certificate->naggrinfos - 1];
2904 certificate->aggrinfo[arraypos]->arpos = arraypos;
2905 }
2906 certificate->naggrinfos--;
2907
2908 return SCIP_OKAY;
2909}
2910
2911/** free mir information for row */
2913 SCIP_SET* set, /**< general SCIP settings */
2914 SCIP_CERTIFICATE* certificate, /**< SCIP certificate structure */
2915 SCIP_LP* lp, /**< SCIP lp data structure */
2916 SCIP_MIRINFO* mirinfo, /**< SCIP mir info */
2917 SCIP_ROW* row /**< row that should be freed, or NULL if not needed */
2918 )
2919{
2920 SCIP_Longint arraypos;
2921 int i;
2922
2923 /* check whether certificate output should be created */
2924 if( !SCIPcertificateIsEnabled(certificate) )
2925 return SCIP_OKAY;
2926
2927 /* remove the mirinfo, move last element to the now freed up one */
2928 arraypos = mirinfo->arpos;
2929 SCIP_CALL( SCIPhashmapRemove(certificate->mirinfohash, (void*) row) );
2930 for( i = 0; i < mirinfo->nslacks; ++i)
2931 {
2932 SCIP_CALL( SCIProwRelease(&(mirinfo->slackrows[i]), certificate->blkmem, set, lp) );
2933 }
2934
2935 SCIPrationalFreeBlock(certificate->blkmem, &(mirinfo->rhs));
2936 SCIPrationalFreeBlock(certificate->blkmem, &(mirinfo->frac));
2937 BMSfreeBlockMemoryArray(certificate->blkmem, &(mirinfo->splitcoefficients), mirinfo->nsplitvars);
2938 BMSfreeBlockMemoryArray(certificate->blkmem, &(mirinfo->varinds), mirinfo->nsplitvars);
2939 BMSfreeBlockMemoryArray(certificate->blkmem, &(mirinfo->upperused), mirinfo->nsplitvars);
2940 BMSfreeBlockMemoryArray(certificate->blkmem, &(mirinfo->localbdused), mirinfo->nsplitvars);
2941
2942 BMSfreeBlockMemoryArray(certificate->blkmem, &(mirinfo->slackrows), mirinfo->nslacks);
2943 BMSfreeBlockMemoryArray(certificate->blkmem, &(mirinfo->slacksign), mirinfo->nslacks);
2944 BMSfreeBlockMemoryArray(certificate->blkmem, &(mirinfo->slackcoefficients), mirinfo->nslacks);
2945 BMSfreeBlockMemoryArray(certificate->blkmem, &(mirinfo->slackweight), mirinfo->nslacks);
2946 BMSfreeBlockMemoryArray(certificate->blkmem, &(mirinfo->slackscale), mirinfo->nslacks);
2947 BMSfreeBlockMemoryArray(certificate->blkmem, &(mirinfo->slackusedcoef), mirinfo->nslacks);
2948 BMSfreeBlockMemoryArray(certificate->blkmem, &(mirinfo->slackroundeddown), mirinfo->nslacks);
2949
2950 BMSfreeBlockMemory(certificate->blkmem, &mirinfo);
2951 if( arraypos != certificate->nmirinfos - 1 )
2952 {
2953 certificate->mirinfo[arraypos] = certificate->mirinfo[certificate->nmirinfos - 1];
2954 certificate->mirinfo[arraypos]->arpos = arraypos;
2955 }
2956 certificate->nmirinfos--;
2957
2958 return SCIP_OKAY;
2959}
2960
2961/** free information that is possibly still stored about this row in the certificate structure */
2963 SCIP* scip, /**< SCIP data structure */
2964 SCIP_ROW* row /**< a SCIP row */
2965 )
2966{
2967 SCIP_CERTIFICATE* certificate;
2968 SCIP_AGGREGATIONINFO* aggrinfo;
2969 SCIP_MIRINFO* mirinfo;
2970
2972 return SCIP_OKAY;
2973
2974 certificate = SCIPgetCertificate(scip);
2975
2976 /* only do something if row does not already exist*/
2977 if( SCIPhashmapExists(certificate->rowdatahash, (void*) SCIProwGetRowExact(row)) )
2978 {
2979 SCIP_CALL( SCIPhashmapRemove(certificate->rowdatahash, (void*) SCIProwGetRowExact(row)) );
2980 return SCIP_OKAY;
2981 }
2982
2983 if( certificate->workingaggrinfo || certificate->workingmirinfo )
2984 return SCIP_OKAY;
2985
2986 SCIPdebugMessage("Removing information stored in certificate for row \n");
2987
2988 if( (certificate->aggrinfohash != NULL) && SCIPhashmapExists(certificate->aggrinfohash, (void*) row) )
2989 {
2990 aggrinfo = (SCIP_AGGREGATIONINFO*) SCIPhashmapGetImage(certificate->aggrinfohash, (void*) row);
2991 SCIP_CALL( SCIPcertificateFreeAggrInfo(scip->set, certificate, scip->lp, aggrinfo, row) );
2992 }
2993
2994 if( (certificate->mirinfohash != NULL) && SCIPhashmapExists(certificate->mirinfohash, (void*) row) )
2995 {
2996 mirinfo = (SCIP_MIRINFO*) SCIPhashmapGetImage(certificate->mirinfohash, (void*) row);
2997 SCIP_CALL( SCIPcertificateFreeMirInfo(scip->set, certificate, scip->lp, mirinfo, row) );
2998 }
2999
3000 return SCIP_OKAY;
3001}
3002
3003/** create a new node data structure for the current node */
3005 SCIP* scip, /**< SCIP data structure */
3006 SCIP_AGGRROW* aggrrow, /**< agrrrow that results from the aggregation */
3007 SCIP_ROW** aggrrows, /**< array of rows used fo the aggregation */
3008 SCIP_Real* weights, /**< array of weights */
3009 int naggrrows, /**< length of the arrays */
3010 SCIP_ROW** negslackrows, /**< array of rows that are added implicitly with negative slack */
3011 SCIP_Real* negslackweights, /**< array of negative slack weights */
3012 int nnegslackrows /**< length of the negative slack array */
3013 )
3014{
3015 int i;
3016 SCIP_AGGREGATIONINFO* info = NULL;
3017 SCIP_CERTIFICATE* certificate;
3018
3019 assert(scip != NULL );
3020
3021 certificate = SCIPgetCertificate(scip);
3022
3023 /* check whether certificate output should be created */
3024 if( !SCIPcertificateIsEnabled(certificate) )
3025 return SCIP_OKAY;
3026
3027 assert(certificate != NULL);
3028
3030
3031 SCIPdebugMessage("adding aggrinfo, with %d rows to certficate \n", naggrrows);
3032
3033 SCIP_CALL( SCIPaggrRowCopy(scip, &(info->aggrrow), aggrrow) );
3034
3035 info->naggrrows = naggrrows;
3036 info->nnegslackrows = nnegslackrows;
3037 info->fileindex = certificate->indexcounter - 1;
3038
3039 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(info->aggrrows), naggrrows) );
3040 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(info->weights), naggrrows) );
3041 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(info->negslackrows), nnegslackrows) );
3042 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(info->negslackweights), nnegslackrows) );
3043 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(info->substfactor), nnegslackrows) );
3044 for( i = 0; i < naggrrows; i++ )
3045 {
3046 SCIPdebugMessage("adding row %s with weight %g to aggrinfo \n", SCIProwGetName(aggrrows[i]), weights[i]);
3047 info->aggrrows[i] = aggrrows[i];
3048 info->weights[i] = weights[i];
3049 SCIProwCapture(aggrrows[i]);
3050 }
3051 for( i = 0; i < nnegslackrows; i++ )
3052 {
3053 SCIPdebugMessage("adding (implicitly) row %s with negative slack multiplier %g to aggrinfo \n", SCIProwGetName(negslackrows[i]), negslackweights[i]);
3054 info->negslackrows[i] = negslackrows[i];
3055 info->negslackweights[i] = negslackweights[i];
3056 SCIProwCapture(negslackrows[i]);
3057 }
3058
3059 /* link the node to its nodedata in the corresponding hashmap */
3060 if( certificate->aggrinfosize == certificate->naggrinfos )
3061 {
3062 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &certificate->aggrinfo, certificate->aggrinfosize, certificate->aggrinfosize + 100) );
3063 certificate->aggrinfosize += 100;
3064 }
3065 certificate->aggrinfo[certificate->naggrinfos] = info;
3066 info->arpos = certificate->naggrinfos;
3067 certificate->naggrinfos++;
3068 certificate->workingaggrinfo = TRUE;
3069
3070 return SCIP_OKAY;
3071}
3072
3073/** create a new split info structure for the current cut */
3075 SCIP* scip /**< SCIP data structure */
3076 )
3077{
3078 SCIP_MIRINFO* mirinfo;
3079 SCIP_CERTIFICATE* certificate;
3080
3081 assert(scip != NULL );
3082
3083 certificate = SCIPgetCertificate(scip);
3084
3085 /* check whether certificate output should be created */
3086 if( !SCIPcertificateIsEnabled(certificate) )
3087 return SCIP_OKAY;
3088
3089 if( certificate->mirinfosize == certificate->nmirinfos )
3090 {
3091 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &certificate->mirinfo, certificate->mirinfosize, certificate->mirinfosize + 100) );
3092 certificate->mirinfosize += 100;
3093 }
3094
3095 SCIP_CALL( SCIPallocBlockMemory(scip, &(certificate->mirinfo[certificate->nmirinfos])) );
3096
3097 mirinfo = certificate->mirinfo[certificate->nmirinfos];
3098
3099 SCIPdebugMessage("adding mirinfo, with to certficate \n");
3100
3103 mirinfo->nlocalvars = 0;
3104 mirinfo->nslacks = 0;
3105 mirinfo->nrounddownslacks = 0;
3106 mirinfo->nsplitvars = SCIPgetNVars(scip);
3107 mirinfo->arpos = certificate->nmirinfos;
3108 mirinfo->scale = 1.0;
3109 mirinfo->unroundedrhs = SCIPinfinity(scip);
3110
3121 mirinfo->varinds = NULL;
3122
3123 certificate->nmirinfos++;
3124 certificate->workingmirinfo = TRUE;
3125
3126 return SCIP_OKAY;
3127}
3128
3129/** prints unsplitting information to proof section */
3131 SCIP_SET* set, /**< general SCIP settings */
3132 SCIP_CERTIFICATE* certificate, /**< certificate data structure */
3133 SCIP_NODE* node /**< node data */
3134 )
3135{
3137 SCIP_RATIONAL* lowerbound;
3138 SCIP_Bool infeas;
3139
3140 assert(node != NULL);
3141
3142 /* check whether certificate output should be created */
3143 if( !SCIPcertificateIsEnabled(certificate) )
3144 return SCIP_OKAY;
3145
3146 /* certificate is disabled on probing nodes */
3148 return SCIP_OKAY;
3149
3150 /* get the current node data */
3151 assert(SCIPhashmapExists(certificate->nodedatahash, node));
3153 (void) SCIPrationalCreateBuffer(set->buffer, &lowerbound);
3154 infeas = FALSE;
3155
3156 assert(nodedata != NULL);
3157
3158 if( nodedata->leftfilled && nodedata->rightfilled )
3159 {
3160 if( nodedata->leftinfeas && nodedata->rightinfeas )
3161 {
3162 infeas = TRUE;
3163 SCIPrationalSetInfinity(lowerbound);
3164 }
3165 else if( nodedata->leftinfeas )
3166 SCIPrationalSetRational(lowerbound, nodedata->derbound_right);
3167 else if( nodedata->rightinfeas )
3168 SCIPrationalSetRational(lowerbound, nodedata->derbound_left);
3169 else
3170 SCIPrationalMin(lowerbound, nodedata->derbound_left, nodedata->derbound_right);
3171
3172 if( SCIPrationalIsInfinity(nodedata->derbound_left) && SCIPrationalIsInfinity(nodedata->derbound_right) )
3173 infeas = TRUE;
3174
3175 certificate->indexcounter++;
3176 certificate->lastinfo->isbound = FALSE;
3177
3178 SCIPcertificatePrintProofMessage(certificate, "UnsplitNode%d_%d ", SCIPnodeGetNumber(node), certificate->indexcounter - 1);
3179
3180 if( infeas )
3181 {
3182 SCIPcertificatePrintProofMessage(certificate, "G 1 0");
3183 }
3184 else
3185 {
3186 SCIPcertificatePrintProofMessage(certificate, "G ");
3187 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, lowerbound) );
3188 SCIPcertificatePrintProofMessage(certificate, " ");
3189 SCIPcertificatePrintProofMessage(certificate, "OBJ");
3190 }
3191
3192 assert(nodedata->derindex_right < certificate->indexcounter - 1);
3193 assert(nodedata->derindex_left < certificate->indexcounter - 1);
3194 assert(SCIPrationalIsGE(lowerbound, SCIPnodeGetLowerboundExact(node)));
3195 assert(SCIPrationalIsGEReal(lowerbound, SCIPnodeGetLowerbound(node)));
3196
3197 SCIPcertificatePrintProofMessage(certificate, " { uns %d %d %d %d } -1\n", nodedata->derindex_left, nodedata->assumptionindex_left,
3198 nodedata->derindex_right, nodedata->assumptionindex_right);
3199
3200 SCIP_CALL( SCIPcertificateUpdateParentData(certificate, node, certificate->indexcounter - 1, lowerbound) );
3201 }
3202 else
3203 {
3204 SCIPdebugMessage("Node %lld is a leaf! \n", SCIPnodeGetNumber(node));
3205 /* if a leaf has an inherited bound, we need to print a bound for it and update the parent data
3206 don't do it if we interrupted the solve, e.g. due to timeout */
3207 if( nodedata->inheritedbound && nodedata->assumptionindex_self != - 1 )
3208 {
3209 SCIP_Longint ind[1];
3210 SCIP_RATIONAL* val;
3211
3212 ind[0] = nodedata->derindex_self;
3213
3214 (void) SCIPrationalCreateBuffer(set->buffer, &val);
3215
3216 SCIPrationalSetRational(lowerbound, nodedata->derbound_self);
3217 SCIPrationalSetFraction(val, 1LL, 1LL);
3218
3219 SCIP_CALL( certificatePrintDualbound(certificate, NULL, lowerbound, 1, ind, &val) );
3220 SCIP_CALL( SCIPcertificateUpdateParentData(certificate, node, certificate->indexcounter - 1, lowerbound) );
3221
3222 SCIPrationalFreeBuffer(set->buffer, &val);
3223 }
3224 }
3225
3226 SCIP_CALL( certificateFreeNodeData(certificate, node) );
3227
3228 SCIPrationalFreeBuffer(set->buffer, &lowerbound);
3229
3230 return SCIP_OKAY;
3231}
3232
3233/** prints RTP section with lowerbound and upperbound range */
3235 SCIP_CERTIFICATE* certificate, /**< certificate data structure */
3236 SCIP_Bool isorigfile, /**< should the original solution be printed or in transformed space */
3237 SCIP_RATIONAL* lowerbound, /**< pointer to lower bound on the objective */
3238 SCIP_RATIONAL* upperbound /**< pointer to upper bound on the objective */
3239 )
3240{
3241 /* check whether certificate output should be created */
3242 if( !SCIPcertificateIsEnabled(certificate) )
3243 return SCIP_OKAY;
3244
3245 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "RTP range ");
3246 if( SCIPrationalIsNegInfinity(lowerbound) )
3247 {
3248 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "-inf");
3249 }
3250 else
3251 {
3252 SCIP_CALL( SCIPcertificatePrintProblemRational(certificate, isorigfile, lowerbound) );
3253 }
3254
3255 SCIPcertificatePrintProblemMessage(certificate, isorigfile, " ");
3256 if( SCIPrationalIsInfinity(upperbound) )
3257 {
3258 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "inf");
3259 }
3260 else
3261 {
3262 SCIP_CALL( SCIPcertificatePrintProblemRational(certificate, isorigfile, upperbound) );
3263 }
3264 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "\n");
3265
3266 return SCIP_OKAY;
3267 }
3268
3269/** prints RTP section for infeasibility */
3271 SCIP_CERTIFICATE* certificate, /**< certificate data structure */
3272 SCIP_Bool isorigfile /**< should the original solution be printed or in transformed space */
3273 )
3274{
3275 /* check whether certificate output should be created */
3276 if( !SCIPcertificateIsEnabled(certificate) )
3277 return;
3278
3279 SCIPcertificatePrintProblemMessage(certificate, isorigfile, "RTP infeas\n");
3280 }
3281
3282/** sets the last bound index for the certificate */
3284 SCIP_CERTIFICATE* certificate, /**< certificate data structure */
3285 SCIP_Longint index /**< index of new bound */
3286 )
3287{
3288 assert(index >= 0);
3289
3290 if( SCIPcertificateIsEnabled(certificate) )
3291 certificate->lastboundindex = index;
3292
3293 return SCIP_OKAY;
3294}
3295
3296/** returns the last bound index for the certificate */
3298 SCIP_CERTIFICATE* certificate /**< certificate data structure */
3299 )
3300{
3301 return SCIPcertificateIsEnabled(certificate) ? certificate->lastboundindex : -1;
3302}
3303
3304/** prints a proof that boundchange is leads to infeasibility */
3306 SCIP* scip, /**< SCIP data structure */
3307 SCIP_CERTIFICATE* certificate, /**< certificate data structure */
3308 SCIP_VAR* var, /**< variable */
3309 SCIP_RATIONAL* lb, /**< lower bound */
3310 SCIP_RATIONAL* ub, /**< upper bound */
3311 SCIP_Longint lbindex, /**< index of the lower bound */
3312 SCIP_Longint ubindex /**< index of the upper bound */
3313 )
3314{
3315 SCIP_RATIONAL* lowerbound;
3316
3317 if( !SCIPisCertified(scip) )
3318 return SCIP_OKAY;
3319
3320 assert(certificate != NULL);
3321
3322 switch( var->varstatus )
3323 {
3327 SCIPABORT();
3328 return SCIP_ERROR;
3330 if( lb != NULL )
3331 {
3332 SCIPrationalMultReal(lb, lb, -1);
3333 SCIPrationalAddReal(lb, lb, 1.0);
3334 }
3335 if( ub != NULL )
3336 {
3337 SCIPrationalMultReal(ub, ub, -1);
3338 SCIPrationalAddReal(ub, ub, 1.0);
3339 }
3340 assert( SCIPvarGetNegationConstant(var) == 1 );
3341 SCIP_CALL( SCIPcertificatePrintCutoffConflictingBounds(scip, certificate, var->negatedvar, ub, lb, ubindex, lbindex) );
3342 if( lb != NULL )
3343 {
3344 SCIPrationalAddReal(lb, lb, -1.0);
3345 SCIPrationalMultReal(lb, lb, -1);
3346 }
3347 if( ub != NULL )
3348 {
3349 SCIPrationalAddReal(ub, ub, -1.0);
3350 SCIPrationalMultReal(ub, ub, -1);
3351 }
3352 return SCIP_OKAY;
3354 {
3355 if( lb != NULL )
3357 if( ub != NULL )
3359
3362 SCIP_CALL( SCIPcertificatePrintCutoffConflictingBounds(scip, certificate, var->data.aggregate.var, swapBounds ? ub : lb, swapBounds ? lb : ub, swapBounds ? ubindex : lbindex, swapBounds ? lbindex : ubindex) );
3363 if( lb != NULL )
3365 if( ub != NULL )
3367 }
3368 return SCIP_OKAY;
3370 break;
3371 default:
3372 SCIPABORT();
3373 return SCIP_ERROR;
3374 }
3375
3376 if( lb == NULL )
3377 {
3378 lb = SCIPvarGetLbLocalExact(var);
3379 lbindex = SCIPvarGetLbCertificateIndexLocal(var);
3380 }
3381 if( ub == NULL )
3382 {
3383 ub = SCIPvarGetUbLocalExact(var);
3384 ubindex = SCIPvarGetUbCertificateIndexLocal(var);
3385 }
3386 assert( SCIPrationalIsGT(lb, ub) );
3388
3389 SCIPcertificatePrintProofMessage(certificate, "BoundConflict%d ", certificate->indexcounter);
3390 SCIPcertificatePrintProofMessage(certificate, "G ");
3391 SCIPrationalDiff(lowerbound, lb, ub);
3392 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, lowerbound) );
3393 SCIPcertificatePrintProofMessage(certificate, " 0 { lin 2 %d 1 %d -1 } -1\n", lbindex, ubindex);
3394
3395 SCIPrationalFreeBuffer(SCIPbuffer(scip), &lowerbound);
3396
3398 certificate->indexcounter++;
3399
3400 return SCIP_OKAY;
3401}
3402
3403/** prints a proof for a new global bound */
3405 SCIP* scip, /**< SCIP data structure */
3406 SCIP_CERTIFICATE* certificate, /**< SCIP certificate */
3407 SCIP_VAR* var, /**< variable */
3408 SCIP_BOUNDTYPE boundtype, /**< Whether we have an upper bound or a lower bound */
3409 SCIP_RATIONAL* value, /**< value of the bound */
3410 SCIP_Longint certificateindex /**< index in the certificate */
3411 )
3412{
3413 SCIP_RETCODE res;
3414
3415 if( !SCIPisCertified(scip) )
3416 return SCIP_OKAY;
3417
3418 assert(certificate != NULL);
3419
3420 switch( var->varstatus )
3421 {
3425 SCIPABORT();
3426 return SCIP_ERROR;
3428 SCIPrationalMultReal(value, value, -1);
3429 assert( SCIPvarGetNegationConstant(var) == 1 );
3430 SCIPrationalAddReal(value, value, 1.0);
3431 res = SCIPcertificatePrintGlobalBound(scip, certificate, var->negatedvar, boundtype == SCIP_BOUNDTYPE_UPPER ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, value, certificateindex);
3432 SCIPrationalAddReal(value, value, -1.0);
3433 SCIPrationalMultReal(value, value, -1);
3434 return res;
3435 break;
3437 SCIPrationalDiv(value, value, var->exactdata->aggregate.scalar);
3440 SCIPrationalMult(value, value, var->exactdata->aggregate.scalar);
3441 return res;
3442 break;
3444 break;
3445 default:
3446 SCIPABORT();
3447 return SCIP_ERROR;
3448 }
3449
3450#ifndef NDEBUG
3451 certificate->lastinfo->isbound = TRUE;
3452 certificate->lastinfo->boundtype = boundtype;
3453 certificate->lastinfo->varindex = SCIPvarGetCertificateIndex(var);
3454 certificate->lastinfo->isglobal = TRUE;
3455 certificate->lastinfo->certificateindex = certificate->indexcounter;
3456 SCIPrationalSetRational(certificate->lastinfo->boundval, value);
3457#endif
3458
3459 SCIPcertificatePrintProofMessage(certificate, "GlobalBound_%d %c ", certificate->indexcounter,
3460 boundtype == SCIP_BOUNDTYPE_UPPER ? 'L' : 'G');
3461 SCIP_CALL( SCIPcertificatePrintProofRational(certificate, value) );
3462 SCIPcertificatePrintProofMessage(certificate, " 1 %d 1 ", SCIPvarGetCertificateIndex(var));
3463 SCIPcertificatePrintProofMessage(certificate, "{ lin 1 %d 1 } -1 global\n", certificateindex);
3464
3465 certificate->indexcounter++;
3466 return SCIP_OKAY;
3467}
3468
3469/* prints information for constraint to certificate file */
3471 SCIP* scip, /**< SCIP data structure */
3472 SCIP_CONS* cons /**< constraint */
3473 )
3474{
3475 SCIP_CERTIFICATE* certificate;
3476 SCIP_ROWEXACT* row;
3477 SCIP_RATIONAL* correctedside;
3478 int* varsindex = NULL;
3479 int i;
3480 SCIP_Longint image;
3481 SCIP_RATIONAL* lhs;
3482 SCIP_RATIONAL* rhs;
3483
3484 /*lint --e{715}*/
3485 assert(scip != NULL);
3486 assert(cons != NULL);
3487
3488 /* print constraint into certificate output */
3489 if( !SCIPisCertified(scip) )
3490 return SCIP_OKAY;
3491 certificate = SCIPgetCertificate(scip);
3492 row = SCIPgetRowExactExactLinear(scip, cons);
3493
3494 lhs = SCIProwExactGetLhs(row);
3495 rhs = SCIProwExactGetRhs(row);
3496
3497 assert(row != NULL);
3498
3499 image = SCIPhashmapGetImageLong(certificate->rowdatahash, row);
3500 /* add row to hashmap */
3501 if( image != SCIP_LONGINT_MAX )
3502 {
3503 SCIPmessageFPrintWarning(scip->messagehdlr, "%lu \n", (size_t) SCIPhashmapGetImage(certificate->rowdatahash, row));
3504 SCIPerrorMessage("Duplicate row in certificate row hashmap\n");
3505 SCIPABORT();
3506 return SCIP_ERROR;
3507 }
3508 else
3509 {
3510 SCIP_CALL( SCIPhashmapInsertLong(certificate->rowdatahash, row, certificate->indexcounter) );
3511 SCIP_CALL( SCIPhashmapInsertLong(certificate->rowdatahash, cons, certificate->indexcounter) );
3512 assert(SCIPhashmapExists(certificate->rowdatahash, row));
3513 assert(SCIPhashmapExists(certificate->rowdatahash, cons));
3514 }
3515
3517 for( i = 0; i < SCIProwExactGetNNonz(row); ++i )
3519
3521
3522 /* print constraint */
3523 if( SCIPrationalIsEQ(lhs, rhs) )
3524 {
3525 assert(!SCIPrationalIsAbsInfinity(lhs));
3527 SCIP_CALL( SCIPcertificatePrintCons(certificate, FALSE, NULL, 'E', correctedside, SCIProwExactGetNNonz(row), varsindex, SCIProwExactGetVals(row)) );
3528 }
3529 else
3530 {
3531 if( !SCIPrationalIsNegInfinity(lhs) )
3532 {
3534 SCIP_CALL( SCIPcertificatePrintCons(certificate, FALSE, NULL, 'G', correctedside, SCIProwExactGetNNonz(row), varsindex, SCIProwExactGetVals(row)) );
3535 }
3536 if( !SCIPrationalIsInfinity(rhs) )
3537 {
3539 SCIP_CALL( SCIPcertificatePrintCons(certificate, FALSE, NULL, 'L', correctedside, SCIProwExactGetNNonz(row), varsindex, SCIProwExactGetVals(row)) );
3540 }
3541 }
3542
3543 SCIPrationalFreeBuffer(SCIPbuffer(scip), &correctedside);
3544 SCIPfreeBufferArray(scip, &varsindex);
3545
3546 return SCIP_OKAY;
3547}
3548
3549/** returns the index of the given constraint in the certificate */
3551 SCIP_CERTIFICATE* certificate, /**< certificate data structure */
3552 SCIP_CONS* cons, /**< constraint */
3553 SCIP_RATIONAL* lhs, /**< lhs of the constraint */
3554 SCIP_RATIONAL* rhs, /**< rhs of the constraint */
3555 SCIP_Bool useRhs /**< whether to return the index of the rhs or lhs */
3556 )
3557{
3558 SCIP_Longint ret;
3559
3560 ret = SCIPhashmapGetImageLong(certificate->rowdatahash, cons);
3561
3562 assert( ret != SCIP_LONGINT_MAX );
3563 if( !SCIPrationalIsAbsInfinity(rhs) && !SCIPrationalIsAbsInfinity(lhs) && !SCIPrationalIsEQ(lhs, rhs) && useRhs)
3564 ret += 1;
3565
3566 assert(ret >= 0);
3567
3568 return ret;
3569}
static long bound
SCIP_RETCODE SCIPcertificatePrintInheritedBound(SCIP_SET *set, SCIP_CERTIFICATE *certificate, SCIP_NODE *node)
SCIP_RETCODE SCIPcertificatePrintAggrrow(SCIP_SET *set, SCIP_PROB *prob, SCIP_CERTIFICATE *certificate, SCIP_AGGRROW *aggrrow, SCIP_ROW **aggrrows, SCIP_Real *weights, int naggrrows, SCIP_Bool local, SCIP_Longint *certificateline)
#define SCIP_MB_TO_CHAR_RATE
Definition: certificate.cpp:78
SCIP_RETCODE SCIPcertificatePrintDualboundPseudo(SCIP_CERTIFICATE *certificate, SCIP_LPEXACT *lpexact, SCIP_NODE *node, SCIP_SET *set, SCIP_PROB *prob, SCIP_Bool lowerchanged, int modifiedvarindex, SCIP_Longint boundchangeindex, SCIP_Real psval)
SCIP_RETCODE SCIPcertificatePrintResult(SCIP *scip, SCIP_Bool isorigfile, SCIP_SET *set, SCIP_CERTIFICATE *certificate)
#define SCIP_HASHSIZE_CERTIFICATE
Definition: certificate.cpp:77
SCIP_RETCODE SCIPconsPrintCertificateExactLinear(SCIP *scip, SCIP_CONS *cons)
void SCIPcertificateFree(SCIP_CERTIFICATE **certificate)
static SCIP_RETCODE certificatePrintWeakDerStart(SCIP_CERTIFICATE *certificate, SCIP_PROB *prob, SCIP_Bool local)
SCIP_CERTIFICATE * SCIPgetCertificate(SCIP *scip)
static SCIP_RETCODE certificatePrintSol(SCIP *scip, SCIP_Bool isorigfile, SCIP_CERTIFICATE *certificate, SCIP_SOL *sol)
SCIP_RETCODE SCIPcertificateNewNodeData(SCIP_CERTIFICATE *certificate, SCIP_STAT *stat, SCIP_NODE *node)
SCIP_RETCODE SCIPcertificateClearMirinfo(SCIP *scip)
SCIP_Longint SCIPcertificateGetRowIndex(SCIP_CERTIFICATE *certificate, SCIP_ROWEXACT *row, SCIP_Bool rhs)
static SCIP_RETCODE certificateFreeNodeData(SCIP_CERTIFICATE *certificate, SCIP_NODE *node)
SCIP_RETCODE SCIPcertificatePrintMirCut(SCIP_SET *set, SCIP_LP *lp, SCIP_CERTIFICATE *certificate, SCIP_PROB *prob, SCIP_ROW *row, const char sense)
SCIP_RETCODE SCIPcertificateUpdateParentData(SCIP_CERTIFICATE *certificate, SCIP_NODE *node, SCIP_Longint fileindex, SCIP_RATIONAL *newbound)
SCIP_RETCODE SCIPcertificateInitTransFile(SCIP *scip)
SCIP_RETCODE SCIPcertificateSetLastBoundIndex(SCIP_CERTIFICATE *certificate, SCIP_Longint index)
static void concatenateCertificate(SCIP_CERTIFICATE *certificate)
static SCIP_RETCODE certificatePrintDualbound(SCIP_CERTIFICATE *certificate, const char *linename, SCIP_RATIONAL *lowerbound, int len, SCIP_Longint *ind, SCIP_RATIONAL **val)
SCIP_RETCODE SCIPcertificateFreeMirInfo(SCIP_SET *set, SCIP_CERTIFICATE *certificate, SCIP_LP *lp, SCIP_MIRINFO *mirinfo, SCIP_ROW *row)
void SCIPcertificatePrintRtpInfeas(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile)
void SCIPcertificatePrintVersionHeader(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile)
void SCIPcertificatePrintDerHeader(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile)
static SCIP_RETCODE certificatePrintMirSplit(SCIP_SET *set, SCIP_PROB *prob, SCIP_CERTIFICATE *certificate, SCIP_ROW *row)
SCIP_RETCODE SCIPcertificateUpdateBoundData(SCIP_CERTIFICATE *certificate, SCIP_NODE *node, SCIP_Longint fileindex, SCIP_RATIONAL *newbound)
SCIP_RETCODE SCIPcertificateSaveFinalbound(SCIP *scip, SCIP_CERTIFICATE *certificate)
SCIP_RETCODE SCIPcertificatePrintDualboundExactLP(SCIP_CERTIFICATE *certificate, SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_NODE *node, SCIP_PROB *prob, SCIP_Bool usefarkas)
SCIP_RETCODE SCIPcertificatePrintGlobalBound(SCIP *scip, SCIP_CERTIFICATE *certificate, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_RATIONAL *value, SCIP_Longint certificateindex)
static SCIP_Longint printBoundAssumption(SCIP_CERTIFICATE *certificate, SCIP_VAR *var, SCIP_RATIONAL *boundval, SCIP_BOUNDTYPE boundtype)
SCIP_Longint SCIPcertificateGetLastBoundIndex(SCIP_CERTIFICATE *certificate)
SCIP_RETCODE SCIPcertificatePrintProofRational(SCIP_CERTIFICATE *certificate, SCIP_RATIONAL *val)
SCIP_Bool SCIPcertificateIsEnabled(SCIP_CERTIFICATE *certificate)
static SCIP_Bool certificateIsLeftNode(SCIP_CERTIFICATE *certificate, SCIP_NODE *node)
Definition: certificate.cpp:96
SCIP_RETCODE SCIPcertificatePrintCutoffBound(SCIP *scip, SCIP_CERTIFICATE *certificate, SCIP_RATIONAL *bound, SCIP_Longint *certificateline)
SCIP_Longint SCIPcertificateGetConsIndex(SCIP_CERTIFICATE *certificate, SCIP_CONS *cons, SCIP_RATIONAL *lhs, SCIP_RATIONAL *rhs, SCIP_Bool useRhs)
void SCIPcertificatePrintConsHeader(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile, int nconss, int nboundconss)
SCIP_RETCODE SCIPcertificateClearAggrinfo(SCIP *scip)
void SCIPcertificatePrintIntHeader(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile, int nintvars)
SCIP_RETCODE SCIPcertificateExit(SCIP *scip)
SCIP_Longint SCIPcertificateGetCurrentIndex(SCIP_CERTIFICATE *certificate)
SCIP_RETCODE SCIPcertificatePrintUnsplitting(SCIP_SET *set, SCIP_CERTIFICATE *certificate, SCIP_NODE *node)
SCIP_RETCODE SCIPcertificateInit(SCIP *scip, SCIP_CERTIFICATE *certificate, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr)
SCIP_Bool SCIPcertificateEnsureLastBoundInfoConsistent(SCIP_CERTIFICATE *certificate, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real newbound, SCIP_Bool needsglobal)
SCIP_RETCODE SCIPcertificateFreeRowInfo(SCIP *scip, SCIP_ROW *row)
SCIP_RETCODE SCIPcertificateFreeAggrInfo(SCIP_SET *set, SCIP_CERTIFICATE *certificate, SCIP_LP *lp, SCIP_AGGREGATIONINFO *aggrinfo, SCIP_ROW *row)
SCIP_RETCODE SCIPcertificateSetAndPrintObjective(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile, BMS_BLKMEM *blkmem, SCIP_RATIONAL **coefs, int nvars)
SCIP_RETCODE SCIPcertificatePrintCutoffConflictingBounds(SCIP *scip, SCIP_CERTIFICATE *certificate, SCIP_VAR *var, SCIP_RATIONAL *lb, SCIP_RATIONAL *ub, SCIP_Longint lbindex, SCIP_Longint ubindex)
SCIP_RETCODE SCIPcertificatePrintBoundCons(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile, const char *boundname, SCIP_VAR *var, SCIP_RATIONAL *boundval, SCIP_Bool isupper)
SCIP_RETCODE SCIPcertificateCreate(SCIP_CERTIFICATE **certificate, SCIP_MESSAGEHDLR *messagehdlr)
SCIP_Real SCIPcertificateGetFilesize(SCIP_CERTIFICATE *certificate)
SCIP_RETCODE SCIPcertificatePrintCons(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile, const char *consname, const char sense, SCIP_RATIONAL *side, int len, int *ind, SCIP_RATIONAL **val)
void SCIPcertificatePrintProofMessage(SCIP_CERTIFICATE *certificate, const char *formatstr,...)
static SCIP_RETCODE certificatePrintRow(SCIP_SET *set, SCIP_CERTIFICATE *certificate, SCIP_ROWEXACT *rowexact, SCIP_Real alternativerhs)
SCIP_RETCODE SCIPcertificatePrintRtpRange(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile, SCIP_RATIONAL *lowerbound, SCIP_RATIONAL *upperbound)
void SCIPcertificatePrintProblemComment(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile, const char *formatstr,...)
SCIP_RETCODE SCIPcertificateUpdateBranchingData(SCIP_SET *set, SCIP_CERTIFICATE *certificate, SCIP_STAT *stat, SCIP_LP *lp, SCIP_NODE *node, SCIP_VAR *branchvar, SCIP_BOUNDTYPE boundtype, SCIP_Real newbound)
SCIP_RETCODE SCIPcertificateNewAggrInfo(SCIP *scip, SCIP_AGGRROW *aggrrow, SCIP_ROW **aggrrows, SCIP_Real *weights, int naggrrows, SCIP_ROW **negslackrows, SCIP_Real *negslackweights, int nnegslackrows)
void SCIPcertificatePrintProofComment(SCIP_CERTIFICATE *certificate, const char *formatstr,...)
SCIP_RETCODE SCIPcertificateNewMirInfo(SCIP *scip)
void SCIPcertificatePrintProblemMessage(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile, const char *formatstr,...)
SCIP_RETCODE SCIPcertificatePrintProblemRational(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile, SCIP_RATIONAL *val)
void SCIPcertificatePrintVarHeader(SCIP_CERTIFICATE *certificate, SCIP_Bool isorigfile, int nvars)
static SCIP_Bool checkAndUpdateFilesize(SCIP_CERTIFICATE *certificate, SCIP_Real nchars)
Definition: certificate.cpp:82
methods for certificate output
Constraint handler for linear constraints in their most general form, .
methods for the aggregation rows
common defines and data types used in all packages of SCIP
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_REAL_MAX
Definition: def.h:158
#define SCIP_Bool
Definition: def.h:91
#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 SCIPABORT()
Definition: def.h:327
#define SCIP_LONGINT_MAX
Definition: def.h:142
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:153
size_t SCIPfwrite(const void *ptr, size_t size, size_t nmemb, SCIP_FILE *stream)
Definition: fileio.c:168
int SCIPfprintf(SCIP_FILE *stream, const char *format,...)
Definition: fileio.c:173
size_t SCIPfread(void *ptr, size_t size, size_t nmemb, SCIP_FILE *stream)
Definition: fileio.c:163
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:232
int SCIPfputs(const char *s, SCIP_FILE *stream)
Definition: fileio.c:190
static const NodeData nodedata[]
Definition: gastrans.c:83
SCIP_RATIONAL * SCIPgetLhsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RATIONAL * SCIPgetRhsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcertifyConsOrigExactLinear(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons)
SCIP_ROWEXACT * SCIPgetRowExactExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip_general.c:562
SCIP_RETCODE SCIPgetOrigVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2753
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2115
int SCIPgetNOrigConss(SCIP *scip)
Definition: scip_prob.c:3712
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3666
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3620
SCIP_CONS ** SCIPgetOrigConss(SCIP *scip)
Definition: scip_prob.c:3739
SCIP_Bool SCIPisObjIntegral(SCIP *scip)
Definition: scip_prob.c:1801
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3095
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapSetImage(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3366
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3061
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3466
SCIP_Bool SCIPhashmapIsEmpty(SCIP_HASHMAP *hashmap)
Definition: misc.c:3566
SCIP_RETCODE SCIPhashmapInsertLong(SCIP_HASHMAP *hashmap, void *origin, SCIP_Longint image)
Definition: misc.c:3215
SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
Definition: misc.c:3676
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3482
SCIP_Longint SCIPhashmapGetImageLong(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3324
SCIP_RETCODE SCIPlpiExactGetObjval(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *objval)
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:88
SCIP_Bool SCIPrealIsExactlyIntegral(SCIP_Real val)
Definition: misc.c:9604
SCIP_Bool SCIPisCertified(SCIP *scip)
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17425
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4316
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8409
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2536
SCIP_RETCODE SCIPaggrRowCopy(SCIP *scip, SCIP_AGGRROW **aggrrow, SCIP_AGGRROW *source)
Definition: cuts.c:2758
SCIP_Real SCIPaggrRowGetRhs(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:4068
void SCIPaggrRowFree(SCIP *scip, SCIP_AGGRROW **aggrrow)
Definition: cuts.c:2700
int * SCIPaggrRowGetInds(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:4028
void SCIPaggrRowPrint(SCIP *scip, SCIP_AGGRROW *aggrrow, FILE *file)
Definition: cuts.c:2721
int SCIPaggrRowGetNNz(SCIP_AGGRROW *aggrrow)
Definition: cuts.c:4038
static INLINE SCIP_Real SCIPaggrRowGetValueSafely(SCIP_AGGRROW *aggrrow, int i)
Definition: cuts.h:287
SCIP_Bool SCIPisExact(SCIP *scip)
Definition: scip_exact.c:193
SCIP_RETCODE SCIPconstructLP(SCIP *scip, SCIP_Bool *cutoff)
Definition: scip_lp.c:130
SCIP_Bool SCIPisLPConstructed(SCIP *scip)
Definition: scip_lp.c:105
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
#define SCIPallocClearBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:97
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
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:8473
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:8503
SCIP_RATIONAL * SCIPnodeGetLowerboundExact(SCIP_NODE *node)
Definition: tree.c:8513
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:8483
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:8782
void SCIPrationalMin(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1342
SCIP_Bool SCIPrationalRoundLong(SCIP_Longint *res, SCIP_RATIONAL *src, SCIP_ROUNDMODE_RAT roundmode)
Definition: rational.cpp:2204
SCIP_RETCODE SCIPrationalCreateBlock(BMS_BLKMEM *blkmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:108
void SCIPrationalMult(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1066
void SCIPrationalSetInfinity(SCIP_RATIONAL *res)
Definition: rational.cpp:618
SCIP_Real SCIPrationalGetReal(SCIP_RATIONAL *rational)
Definition: rational.cpp:2085
SCIP_RETCODE SCIPrationalCreateString(BMS_BLKMEM *mem, SCIP_RATIONAL **rational, const char *desc)
Definition: rational.cpp:796
void SCIPrationalFreeBlock(BMS_BLKMEM *mem, SCIP_RATIONAL **rational)
Definition: rational.cpp:461
int SCIPrationalToString(SCIP_RATIONAL *rational, char *str, int strlen)
Definition: rational.cpp:1743
SCIP_RETCODE SCIPrationalCreateBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***rational, int size)
Definition: rational.cpp:196
#define SCIPrationalDebugMessage
Definition: rational.h:641
void SCIPrationalRoundInteger(SCIP_RATIONAL *res, SCIP_RATIONAL *src, SCIP_ROUNDMODE_RAT roundmode)
Definition: rational.cpp:2158
void SCIPrationalDiv(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1132
SCIP_Bool SCIPrationalIsAbsInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1680
SCIP_Bool SCIPrationalIsLT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1503
void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
Definition: rational.cpp:603
SCIP_Bool SCIPrationalIsGT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1474
void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:473
void SCIPrationalDiff(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:983
SCIP_Bool SCIPrationalIsPositive(SCIP_RATIONAL *rational)
Definition: rational.cpp:1640
SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:123
void SCIPrationalAddProd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1173
SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
Definition: rational.cpp:1624
void SCIPrationalSetRational(SCIP_RATIONAL *res, SCIP_RATIONAL *src)
Definition: rational.cpp:569
SCIP_Bool SCIPrationalIsGEReal(SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1606
SCIP_Bool SCIPrationalIsIntegral(SCIP_RATIONAL *rational)
Definition: rational.cpp:1691
SCIP_Bool SCIPrationalIsGE(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1512
void SCIPrationalSetNegInfinity(SCIP_RATIONAL *res)
Definition: rational.cpp:630
void SCIPrationalSetFraction(SCIP_RATIONAL *res, SCIP_Longint nom, SCIP_Longint denom)
Definition: rational.cpp:582
void SCIPrationalNegate(SCIP_RATIONAL *res, SCIP_RATIONAL *op)
Definition: rational.cpp:1297
SCIP_Bool SCIPrationalIsNegative(SCIP_RATIONAL *rational)
Definition: rational.cpp:1650
void SCIPrationalDiffReal(SCIP_RATIONAL *res, SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1009
SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1660
void SCIPrationalFreeBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***ratblockarray, int size)
Definition: rational.cpp:501
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
SCIP_Bool SCIPrationalIsNegInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1670
void SCIPrationalDivReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
Definition: rational.cpp:1147
SCIP_RETCODE SCIPrationalReallocBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***result, int oldlen, int newlen)
Definition: rational.cpp:344
SCIP_Bool SCIPrationalIsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1404
void SCIPrationalDiffProd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1239
void SCIPrationalMultReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
Definition: rational.cpp:1097
void SCIPrationalFreeBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***ratbufarray, int size)
Definition: rational.cpp:518
void SCIPrationalAddReal(SCIP_RATIONAL *res, SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:961
int SCIPrationalStrLen(SCIP_RATIONAL *rational)
Definition: rational.cpp:1774
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
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:17795
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17745
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1508
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17652
SCIP_ROWEXACT * SCIProwGetRowExact(SCIP_ROW *row)
Definition: lp.c:17959
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17642
SCIP_ROWORIGINTYPE SCIProwGetOrigintype(SCIP_ROW *row)
Definition: lp.c:17825
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2981
SCIP_RETCODE SCIPmakeSolExact(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:3146
SCIP_RETCODE SCIPretransformSolExact(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:3245
SCIP_Bool SCIPsolIsExact(SCIP_SOL *sol)
Definition: sol.c:4150
SCIP_Bool SCIPisInRestart(SCIP *scip)
Definition: scip_solve.c:3709
SCIP_Bool SCIPisPrimalboundSol(SCIP *scip)
void SCIPgetUpperboundExact(SCIP *scip, SCIP_RATIONAL *result)
void SCIPgetPrimalboundExact(SCIP *scip, SCIP_RATIONAL *result)
void SCIPgetLowerboundExact(SCIP *scip, SCIP_RATIONAL *result)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip_tree.c:91
SCIP_Longint SCIPvarGetUbCertificateIndexLocal(SCIP_VAR *var)
Definition: var.c:25188
void SCIPvarSetLbCertificateIndexGlobal(SCIP_VAR *var, SCIP_Longint certidx)
Definition: var.c:25162
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:23889
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
SCIP_Longint SCIPvarGetUbCertificateIndexGlobal(SCIP_VAR *var)
Definition: var.c:25212
void SCIPvarSetCertificateIndex(SCIP_VAR *var, int certidx)
Definition: var.c:25109
int SCIPvarGetCertificateIndex(SCIP_VAR *var)
Definition: var.c:25098
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_Longint SCIPvarGetLbCertificateIndexGlobal(SCIP_VAR *var)
Definition: var.c:25200
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_RATIONAL * SCIPvarGetUbLocalExact(SCIP_VAR *var)
Definition: var.c:24278
void SCIPvarSetUbCertificateIndexGlobal(SCIP_VAR *var, SCIP_Longint certidx)
Definition: var.c:25122
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
SCIP_Longint SCIPvarGetLbCertificateIndexLocal(SCIP_VAR *var)
Definition: var.c:25176
SCIP_RATIONAL * SCIPvarGetLbGlobalExact(SCIP_VAR *var)
Definition: var.c:24130
SCIP_RATIONAL * SCIPvarGetLbLocalExact(SCIP_VAR *var)
Definition: var.c:24244
SCIP_RATIONAL * SCIPvarGetObjExact(SCIP_VAR *var)
Definition: var.c:23910
SCIP_RATIONAL * SCIPvarGetUbGlobalExact(SCIP_VAR *var)
Definition: var.c:24152
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
void SCIPprintSysError(const char *message)
Definition: misc.c:10719
void SCIProwCapture(SCIP_ROW *row)
Definition: lp.c:5554
SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
Definition: lp.c:18016
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:18026
SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:5567
internal methods for LP management
SCIP_COLEXACT ** SCIProwExactGetCols(SCIP_ROWEXACT *row)
Definition: lpexact.c:5026
SCIP_RATIONAL * SCIProwExactGetRhs(SCIP_ROWEXACT *row)
Definition: lpexact.c:6266
void SCIProwExactPrint(SCIP_ROWEXACT *row, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: lpexact.c:4953
SCIP_ROW * SCIProwExactGetRow(SCIP_ROWEXACT *row)
Definition: lpexact.c:5069
SCIP_RATIONAL * SCIProwExactGetConstant(SCIP_ROWEXACT *row)
Definition: lpexact.c:6277
SCIP_VAR * SCIPcolExactGetVar(SCIP_COLEXACT *col)
Definition: lpexact.c:6052
SCIP_RATIONAL * SCIProwExactGetLhs(SCIP_ROWEXACT *row)
Definition: lpexact.c:6255
void SCIPlpExactGetPseudoObjval(SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_RATIONAL *res)
Definition: lpexact.c:7438
SCIP_RATIONAL ** SCIProwExactGetVals(SCIP_ROWEXACT *row)
Definition: lpexact.c:5016
void SCIPlpExactGetObjval(SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_RATIONAL *res)
Definition: lpexact.c:7416
int SCIProwExactGetNNonz(SCIP_ROWEXACT *row)
Definition: lpexact.c:5006
internal methods for exact LP management
interface methods for specific exact LP solvers
memory allocation routines
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:123
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:147
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
#define BMSallocMemory(ptr)
Definition: memory.h:118
void SCIPmessageFPrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:451
void SCIPmessagePrintVerbInfo(SCIP_MESSAGEHDLR *messagehdlr, SCIP_VERBLEVEL verblevel, SCIP_VERBLEVEL msgverblevel, const char *formatstr,...)
Definition: message.c:678
internal miscellaneous methods
int SCIPprobGetNObjVars(SCIP_PROB *prob, SCIP_SET *set)
Definition: prob.c:2423
SCIP_Bool SCIPprobIsObjIntegral(SCIP_PROB *prob)
Definition: prob.c:2813
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2868
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2913
internal methods for storing and manipulating the main problem
public methods for managing constraints
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:43
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugMessage
Definition: pub_message.h:96
public data structures and miscellaneous methods
public methods for branch and bound tree
public methods for problem variables
public methods for certified solving
public methods for exact solving
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public solving methods
public methods for querying solving statistics
public methods for the branch-and-bound tree
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6380
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6515
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1782
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1775
void SCIPsolGetValExact(SCIP_RATIONAL *res, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:2039
internal methods for storing primal CIP solutions
SCIP_RATIONAL * scalar
Definition: struct_var.h:218
SCIP_RATIONAL * constant
Definition: struct_var.h:219
SCIP_VAR * var
Definition: struct_var.h:212
SCIP_RATIONAL * boundval
SCIP_Longint lastboundindex
SCIP_Longint indexcounter_ori
SCIP_FILE * derivationfile
SCIP_Longint indexcounter
SCIP_HASHMAP * nodedatahash
SCIP_Longint nmirinfos
SCIP_MIRINFO ** mirinfo
SCIP_Longint conscounter
SCIP_RATIONAL * rootbound
SCIP_CERTIFICATEBOUND * lastinfo
SCIP_HASHMAP * mirinfohash
SCIP_Longint naggrinfos
SCIP_Longint mirinfosize
SCIP_Longint aggrinfosize
SCIP_HASHMAP * rowdatahash
SCIP_Longint derindex_root
SCIP_AGGREGATIONINFO ** aggrinfo
SCIP_RATIONAL ** vals
SCIP_RATIONAL * finalbound
SCIP_Bool transfile_initialized
SCIP_HASHMAP * aggrinfohash
SCIP_Longint assumptionindex_left
unsigned int rightfilled
SCIP_Longint derindex_self
unsigned int rightinfeas
SCIP_RATIONAL * derbound_left
SCIP_RATIONAL * derbound_self
SCIP_RATIONAL * derbound_right
SCIP_Longint assumptionindex_right
SCIP_Longint derindex_left
SCIP_Longint derindex_right
SCIP_COL * fpcol
SCIP_RATIONAL * farkascoef
SCIP_RATIONAL * redcost
SCIP_VAR * var
SCIP_VAR * var
Definition: struct_lp.h:162
SCIP_RATIONAL * ub
Definition: struct_var.h:185
SCIP_RATIONAL * lb
Definition: struct_var.h:184
SCIP_Real lb
Definition: struct_var.h:176
SCIP_Real ub
Definition: struct_var.h:177
SCIP_COLEXACT ** cols
SCIP_LPIEXACT * lpiexact
SCIP_ROWEXACT ** rows
SCIP_LP * fplp
SCIP_RATIONAL * lpobjval
SCIP_Bool diving
Definition: struct_lp.h:386
SCIP_Real * slackscale
SCIP_Real * slackcoefficients
SCIP_RATIONAL * frac
SCIP_Longint arpos
SCIP_ROW ** slackrows
SCIP_Real * slackweight
SCIP_Bool * upperused
SCIP_Real * splitcoefficients
SCIP_RATIONAL * rhs
SCIP_Real * slackusedcoef
SCIP_Real unroundedrhs
SCIP_Bool * localbdused
SCIP_Bool * slackroundeddown
SCIP_ROW * fprow
SCIP_RATIONAL * dualfarkas
SCIP_RATIONAL * lhs
SCIP_COLEXACT ** cols
SCIP_RATIONAL * rhs
SCIP_RATIONAL * dualsol
char * name
Definition: struct_lp.h:229
SCIP_COL ** cols
Definition: struct_lp.h:230
SCIP_DOMEXACT glbdom
Definition: struct_var.h:251
SCIP_AGGREGATEEXACT aggregate
Definition: struct_var.h:253
SCIP_DOMEXACT locdom
Definition: struct_var.h:250
SCIP_AGGREGATE aggregate
Definition: struct_var.h:286
SCIP_VAR * negatedvar
Definition: struct_var.h:298
unsigned int varstatus
Definition: struct_var.h:338
SCIP_DOM glbdom
Definition: struct_var.h:279
char * name
Definition: struct_var.h:291
SCIP_VARDATAEXACT * exactdata
Definition: struct_var.h:290
SCIP_DOM locdom
Definition: struct_var.h:280
union SCIP_Var::@24 data
int index
Definition: struct_var.h:310
data structures for certificate output
data structures for exact LP management
SCIP main data structure.
datastructures for problem statistics
datastructures for problem variables
Definition: heur_padm.c:135
@ SCIP_ROWORIGINTYPE_SEPA
Definition: type_lp.h:76
@ 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_VERBLEVEL_NORMAL
Definition: type_message.h:60
@ SCIP_R_ROUND_UPWARDS
Definition: type_rational.h:58
@ SCIP_R_ROUND_DOWNWARDS
Definition: type_rational.h:57
@ SCIP_FILECREATEERROR
Definition: type_retcode.h:48
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_ERROR
Definition: type_retcode.h:43
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STATUS_OPTIMAL
Definition: type_stat.h:43
@ SCIP_STATUS_INFEASIBLE
Definition: type_stat.h:44
@ SCIP_NODETYPE_PROBINGNODE
Definition: type_tree.h:42
@ SCIP_VARTYPE_INTEGER
Definition: type_var.h:65
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:64
@ SCIP_VARSTATUS_ORIGINAL
Definition: type_var.h:51
@ SCIP_VARSTATUS_FIXED
Definition: type_var.h:54
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:53
@ SCIP_VARSTATUS_NEGATED
Definition: type_var.h:57
@ SCIP_VARSTATUS_AGGREGATED
Definition: type_var.h:55
@ SCIP_VARSTATUS_LOOSE
Definition: type_var.h:52
internal methods for problem variables