Scippy

SCIP

Solving Constraint Integer Programs

debug.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2024 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 debug.c
26 * @ingroup OTHER_CFILES
27 * @brief methods for debugging
28 * @author Tobias Achterberg
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
33#include <stdio.h>
34#include <string.h>
35#include <assert.h>
36#if defined(_WIN32) || defined(_WIN64)
37#else
38#include <strings.h> /*lint --e{766}*/
39#endif
40
41#include "scip/def.h"
43#include "scip/set.h"
44#include "scip/lp.h"
45#include "scip/var.h"
46#include "scip/prob.h"
47#include "scip/tree.h"
48#include "scip/scip.h"
49#include "scip/debug.h"
50#include "scip/pub_message.h"
51#include "scip/pub_misc.h"
52#include "scip/struct_scip.h"
53
54#ifdef WITH_DEBUG_SOLUTION
55
56#define SCIP_HASHSIZE_DEBUG 500 /**< minimum size of hash map for storing whether a solution is valid for the node */
57
58struct SCIP_DebugSolData
59{
60 char** solnames; /**< variable names in the solution */
61 SCIP_Real* solvals; /**< solution value array (only nonzero entries) */
62 int nsolvals; /**< number of entries in the debug solution */
63 int solsize; /**< size of the array entries */
64 SCIP_SOL* debugsol; /**< a debug solution */
65 SCIP_STAGE debugsolstage; /**< solving stage of debug solution */
66 SCIP_HASHMAP* solinnode; /**< maps nodes to bools, storing whether the solution is valid for the node */
67 SCIP_Bool falseptr; /**< pointer to value FALSE used for hashmap */
68 SCIP_Bool trueptr; /**< pointer to value TRUE used for hashmap */
69 SCIP_Bool solisachieved; /**< means if current best solution is better than the given debug solution */
70 SCIP_Real debugsolval; /**< objective value for debug solution */
71 SCIP_Bool debugsoldisabled; /**< flag indicating if debugging of solution was disabled or not */
72 SCIP_Bool warningprinted; /**< flag indicating if a warning was already printed */
73};
74
75
76/** creates debug solution data */
78 SCIP_DEBUGSOLDATA** debugsoldata /**< pointer to debug solution data */
79 )
80{
81 assert(debugsoldata != NULL);
82
83 SCIP_ALLOC( BMSallocMemory(debugsoldata) );
84
85 (*debugsoldata)->solnames = NULL;
86 (*debugsoldata)->solvals = NULL;
87 (*debugsoldata)->nsolvals = 0;
88 (*debugsoldata)->solsize = 0;
89 (*debugsoldata)->debugsol = NULL;
90 (*debugsoldata)->debugsolstage = SCIP_STAGE_INIT;
91 (*debugsoldata)->solinnode = NULL;
92 (*debugsoldata)->falseptr = FALSE;
93 (*debugsoldata)->trueptr = TRUE;
94 (*debugsoldata)->solisachieved = FALSE;
95 (*debugsoldata)->debugsolval = 0.0;
96 (*debugsoldata)->debugsoldisabled = TRUE;
97 (*debugsoldata)->warningprinted = FALSE;
98
99 return SCIP_OKAY;
100}
101
102#ifdef SCIP_MORE_DEBUG
103/** comparison method for sorting variables w.r.t. to their name */
104static
105SCIP_DECL_SORTPTRCOMP(sortVarsAfterNames)
106{
107 return strcmp(SCIPvarGetName((SCIP_VAR*)elem1), SCIPvarGetName((SCIP_VAR*)elem2));
108}
109#endif
110
111/* checks whether the parameter is specified */
112static
113SCIP_Bool debugSolutionAvailable(
114 SCIP_SET* set /**< global SCIP settings */
115 )
116{
117 SCIP_DEBUGSOLDATA* debugsoldata;
118
119 assert(set != NULL);
120
121 debugsoldata = SCIPsetGetDebugSolData(set);
122
123 /* check whether a debug solution is specified */
124 if( strcmp(set->misc_debugsol, "-") == 0 )
125 {
126 if( !debugsoldata->warningprinted )
127 {
128 SCIPmessagePrintWarning(SCIPgetMessagehdlr(set->scip), "SCIP is compiled with 'DEBUGSOL=true' but no debug solution is given:\n ");
129 SCIPmessagePrintWarning(SCIPgetMessagehdlr(set->scip), "*** Please set the parameter 'misc/debugsol' and reload the problem again to use the debugging-mechanism ***\n\n");
130 debugsoldata->warningprinted = TRUE;
131 }
132 return FALSE;
133 }
134 else
135 {
136 debugsoldata->warningprinted = FALSE;
137 return TRUE;
138 }
139}
140
141/** reads solution from given file into given arrays */
142static
143SCIP_RETCODE readSolfile(
144 SCIP_SET* set, /**< global SCIP settings */
145 const char* solfilename, /**< solution filename to read */
146 SCIP_SOL** debugsolptr,
147 SCIP_Real* debugsolvalptr,
148 SCIP_STAGE* debugsolstageptr,
149 char*** names, /**< pointer to store the array of variable names */
150 SCIP_Real** vals, /**< pointer to store the array of solution values */
151 int* nvals, /**< pointer to store the number of non-zero elements */
152 int* valssize /**< pointer to store the length of the variable names and solution values arrays */
153 )
154{
155 SCIP_VAR** vars;
156 SCIP_Real* solvalues;
157 SCIP_FILE* file;
158 SCIP_SOL* debugsol;
159 SCIP_Real debugsolval;
160 int nonvalues;
161 int nfound;
162 int i;
163 SCIP_Bool unknownvariablemessage;
164
165 assert(set != NULL);
166 assert(solfilename != NULL);
167 assert(names != NULL);
168 assert(*names == NULL);
169 assert(vals != NULL);
170 assert(*vals == NULL);
171 assert(nvals != NULL);
172 assert(valssize != NULL);
173
174 printf("***** debug: reading solution file <%s>\n", solfilename);
175
176 /* open solution file */
177 file = SCIPfopen(solfilename, "r");
178 if( file == NULL )
179 {
180 SCIPerrorMessage("cannot open solution file <%s> specified in scip/debug.h\n", solfilename);
181 SCIPprintSysError(solfilename);
182 return SCIP_NOFILE;
183 }
184
185 /* read data */
186 nonvalues = 0;
187 *valssize = 0;
188 unknownvariablemessage = FALSE;
189
190 while( !SCIPfeof(file) )
191 {
192 char buf[SCIP_MAXSTRLEN];
193 char name[SCIP_MAXSTRLEN];
194 char objstring[SCIP_MAXSTRLEN];
195 char valuestring[SCIP_MAXSTRLEN];
196 SCIP_VAR* var;
197 SCIP_Real val;
198 int nread;
199
200 if( SCIPfgets(buf, SCIP_MAXSTRLEN, file) == NULL )
201 {
202 if( SCIPfeof(file) )
203 break;
204 else
205 return SCIP_READERROR;
206 }
207
208 /* there are some lines which may preceed the solution information */
209 if( SCIPstrncasecmp(buf, "solution status:", 16) == 0 || SCIPstrncasecmp(buf, "objective value:", 16) == 0 ||
210 SCIPstrncasecmp(buf, "Log started", 11) == 0 || SCIPstrncasecmp(buf, "Variable Name", 13) == 0 ||
211 SCIPstrncasecmp(buf, "All other variables", 19) == 0 || strspn(buf, " \n\r\t\f") == strlen(buf) ||
212 SCIPstrncasecmp(buf, "NAME", 4) == 0 || SCIPstrncasecmp(buf, "ENDATA", 6) == 0 || /* allow parsing of SOL-format on the MIPLIB 2003 pages */
213 SCIPstrncasecmp(buf, "=obj=", 5) == 0 ) /* avoid "unknown variable" warning when reading MIPLIB SOL files */
214 {
215 ++nonvalues;
216 continue;
217 }
218
219 /* cppcheck-suppress invalidscanf */
220 nread = sscanf(buf, "%s %s %s\n", name, valuestring, objstring);
221 if( nread < 2 )
222 {
223 printf("invalid input line %d in solution file <%s>: <%s>\n", *nvals + nonvalues, solfilename, name);
224 SCIPfclose(file);
225 return SCIP_READERROR;
226 }
227
228 /* find the variable */
229 var = SCIPfindVar(set->scip, name);
230 if( var == NULL )
231 {
232 if( !unknownvariablemessage )
233 {
234 SCIPverbMessage(set->scip, SCIP_VERBLEVEL_NORMAL, NULL, "unknown variable <%s> in line %d of solution file <%s>\n",
235 name, *nvals + nonvalues, solfilename);
236 SCIPverbMessage(set->scip, SCIP_VERBLEVEL_NORMAL, NULL, " (further unknown variables are ignored)\n");
237 unknownvariablemessage = TRUE;
238 }
239 continue;
240 }
241
242 /* cast the value, check first for inv(alid) or inf(inite) ones that need special treatment */
243 if( SCIPstrncasecmp(valuestring, "inv", 3) == 0 )
244 continue;
245 else if( SCIPstrncasecmp(valuestring, "+inf", 4) == 0 || SCIPstrncasecmp(valuestring, "inf", 3) == 0 )
246 val = SCIPsetInfinity(set);
247 else if( SCIPstrncasecmp(valuestring, "-inf", 4) == 0 )
248 val = -SCIPsetInfinity(set);
249 else
250 {
251 /* cppcheck-suppress invalidscanf */
252 nread = sscanf(valuestring, "%lf", &val);
253 if( nread != 1 )
254 {
255 SCIPerrorMessage("Invalid solution value <%s> for variable <%s> in line %d of solution file <%s>.\n",
256 valuestring, name, *nvals + nonvalues, solfilename);
257 SCIPfclose(file);
258 return SCIP_READERROR;
259 }
260 }
261
262 /* allocate memory */
263 if( *nvals >= *valssize )
264 {
265 *valssize = MAX(2 * *valssize, (*nvals)+1);
266 SCIP_ALLOC( BMSreallocMemoryArray(names, *valssize) );
267 SCIP_ALLOC( BMSreallocMemoryArray(vals, *valssize) );
268 }
269 assert(*nvals < *valssize);
270
271 /* store solution value in sorted list */
272 for( i = *nvals; i > 0 && strcmp(name, (*names)[i-1]) < 0; --i )
273 {
274 (*names)[i] = (*names)[i-1];
275 (*vals)[i] = (*vals)[i-1];
276 }
277 SCIP_ALLOC( BMSduplicateMemoryArray(&(*names)[i], name, strlen(name)+1) );
278 SCIPdebugMsg(set->scip, "found variable <%s>: value <%g>\n", (*names)[i], val);
279 (*vals)[i] = val;
280 (*nvals)++;
281 }
282
283 /* get memory for SCIP solution */
284 SCIP_ALLOC( BMSallocMemoryArray(&vars, *valssize) );
285 SCIP_ALLOC( BMSallocMemoryArray(&solvalues, *valssize) );
286
287 debugsolval = 0.0;
288 nfound = 0;
289
290 /* get solution value */
291 for( i = 0; i < *nvals; ++i)
292 {
293 SCIP_VAR* var;
294 var = SCIPfindVar(set->scip, (*names)[i]);
295 if( var != NULL )
296 {
297 vars[nfound] = var;
298 solvalues[nfound] = (*vals)[i];
299 ++nfound;
300 debugsolval += (*vals)[i] * SCIPvarGetObj(var);
301 }
302 }
303 SCIPdebugMsg(set->scip, "Debug Solution value is %g.\n", debugsolval);
304
305#ifdef SCIP_MORE_DEBUG
306 SCIPsortPtrReal((void**)vars, solvalues, sortVarsAfterNames, nfound);
307
308 for( i = 0; i < nfound - 1; ++i)
309 {
310 assert(strcmp(SCIPvarGetName(vars[i]), SCIPvarGetName(vars[i + 1])) != 0);
311 }
312#endif
313
314 if( debugsolptr != NULL )
315 {
316 /* create SCIP solution */
317 SCIP_CALL( SCIPcreateOrigSol(set->scip, &debugsol, NULL) );
318 *debugsolstageptr = SCIPgetStage(set->scip);
319
320 /* set SCIP solution values */
321 SCIP_CALL( SCIPsetSolVals(set->scip, debugsol, nfound, vars, solvalues ) );
322 }
323
324 BMSfreeMemoryArray(&vars);
325 BMSfreeMemoryArray(&solvalues);
326
327 if( debugsolptr != NULL )
328 *debugsolptr = debugsol;
329
330 if( debugsolvalptr != NULL )
331 *debugsolvalptr = debugsolval;
332
333 /* close file */
334 SCIPfclose(file);
335
336 printf("***** debug: read %d non-zero entries (%d variables found)\n", *nvals, nfound);
337
338 return SCIP_OKAY;
339}
340
341/** reads feasible solution to check from file */
342static
343SCIP_RETCODE readSolution(
344 SCIP_SET* set /**< global SCIP settings */
345 )
346{
347 SCIP_DEBUGSOLDATA* debugsoldata;
348
349 assert(set != NULL);
350
351 debugsoldata = SCIPsetGetDebugSolData(set);
352
353 /* check whether a debug solution is available */
354 if( !debugSolutionAvailable(set) )
355 return SCIP_OKAY;
356
357 if( debugsoldata == NULL || debugsoldata->nsolvals > 0 )
358 return SCIP_OKAY;
359
360 SCIP_CALL( readSolfile(set, set->misc_debugsol, &debugsoldata->debugsol, &debugsoldata->debugsolval,
361 &debugsoldata->debugsolstage, &(debugsoldata->solnames), &(debugsoldata->solvals), &(debugsoldata->nsolvals),
362 &(debugsoldata->solsize)) );
363
364 return SCIP_OKAY;
365}
366
367/** gets value of given variable in debugging solution */
368static
369SCIP_RETCODE getSolutionValue(
370 SCIP_SET* set, /**< global SCIP settings */
371 SCIP_VAR* var, /**< variable to get solution value for */
372 SCIP_Real* val /**< pointer to store solution value */
373 )
374{
375 SCIP_VAR* solvar;
376 SCIP_DEBUGSOLDATA* debugsoldata;
377 SCIP_Real scalar;
378 SCIP_Real constant;
379 const char* name;
380 int left;
381 int right;
382 int middle;
383 int cmp;
384
385 assert(set != NULL);
386 assert(var != NULL);
387 assert(val != NULL);
388
389 /* check whether a debug solution is available */
390 if( !debugSolutionAvailable(set) )
391 return SCIP_OKAY;
392
393 debugsoldata = SCIPsetGetDebugSolData(set);
394 assert(debugsoldata != NULL);
395
396 /* allow retrieving solution values only if referring to the SCIP instance that is debugged */
397 if( !SCIPdebugSolIsEnabled(set->scip) )
398 {
399 *val = SCIP_UNKNOWN;
400 return SCIP_OKAY;
401 }
402
403 SCIP_CALL( readSolution(set) );
404 SCIPsetDebugMsg(set, "Now handling variable <%s>, which has status %d, is of type %d, and was deleted: %d, negated: %d, transformed: %d\n",
406
407 /* ignore deleted variables */
408 if( SCIPvarIsDeleted(var) )
409 {
410 SCIPsetDebugMsg(set, "**** unknown solution value for deleted variable <%s>\n", SCIPvarGetName(var));
411 *val = SCIP_UNKNOWN;
412 return SCIP_OKAY;
413 }
414
415 /* retransform variable onto original variable space */
416 solvar = var;
417 scalar = 1.0;
418 constant = 0.0;
419 if( SCIPvarIsNegated(solvar) )
420 {
421 scalar = -1.0;
422 constant = SCIPvarGetNegationConstant(solvar);
423 solvar = SCIPvarGetNegationVar(solvar);
424 }
425
426 if( SCIPvarIsTransformed(solvar) )
427 {
428 SCIP_CALL( SCIPvarGetOrigvarSum(&solvar, &scalar, &constant) );
429 if( solvar == NULL )
430 {
431 /* if no original counterpart, then maybe someone added a value for the transformed variable, so search for var (or its negation) */
432 SCIPsetDebugMsg(set, "variable <%s> has no original counterpart\n", SCIPvarGetName(var));
433 solvar = var;
434 scalar = 1.0;
435 constant = 0.0;
436 if( SCIPvarIsNegated(solvar) )
437 {
438 scalar = -1.0;
439 constant = SCIPvarGetNegationConstant(solvar);
440 solvar = SCIPvarGetNegationVar(solvar);
441 }
442 }
443 }
444
445 /* perform a binary search for the variable */
446 name = SCIPvarGetName(solvar);
447 left = 0;
448 right = debugsoldata->nsolvals-1;
449 while( left <= right )
450 {
451 middle = (left+right)/2;
452 cmp = strcmp(name, debugsoldata->solnames[middle]);
453 if( cmp < 0 )
454 right = middle-1;
455 else if( cmp > 0 )
456 left = middle+1;
457 else
458 {
459 *val = scalar * debugsoldata->solvals[middle] + constant;
460
462 {
463 SCIPmessagePrintWarning(SCIPgetMessagehdlr(set->scip), "invalid solution value %.15g for variable <%s>[%.15g,%.15g]\n",
465 }
466
467 return SCIP_OKAY;
468 }
469 }
470 *val = constant;
471
473 {
474 SCIPmessagePrintWarning(SCIPgetMessagehdlr(set->scip), "invalid solution value %.15g for variable <%s>[%.15g,%.15g]\n",
476 }
477
478 return SCIP_OKAY;
479}
480
481/** gets pointer to the debug solution */
482SCIP_RETCODE SCIPdebugGetSol(
483 SCIP* scip, /**< SCIP data structure */
484 SCIP_SOL** sol /**< buffer to store pointer to the debug solution */
485 )
486{
487 SCIP_DEBUGSOLDATA* debugsoldata;
488
489 debugsoldata = SCIPsetGetDebugSolData(scip->set);
490 assert(scip != NULL);
491 assert(sol != NULL);
492
493 *sol = NULL;
494
495 /* check whether a debug solution is available */
496 if( !debugSolutionAvailable(scip->set) )
497 return SCIP_OKAY;
498
499 SCIP_CALL( readSolution(scip->set) );
500
501 if( debugsoldata->debugsol == NULL )
502 return SCIP_ERROR;
503
504 *sol = debugsoldata->debugsol;
505
506 return SCIP_OKAY;
507}
508
509/** gets value for a variable in the debug solution
510 *
511 * if no value is stored for the variable, gives 0.0
512 */
514 SCIP* scip, /**< SCIP data structure */
515 SCIP_VAR* var, /**< variable for which to get the value */
516 SCIP_Real* val /**< buffer to store solution value */
517 )
518{
519 SCIP_CALL( getSolutionValue(scip->set, var, val) );
520
521 return SCIP_OKAY;
522}
523
524/** returns whether the debug solution is worse than the best known solution or if the debug solution was found */
525static
526SCIP_Bool debugSolIsAchieved(
527 SCIP_SET* set /**< global SCIP settings */
528 )
529{
530 SCIP_SOL* bestsol;
531 SCIP* scip;
532 SCIP_DEBUGSOLDATA* debugsoldata;
533
534 /* check whether a debug solution is available */
535 if( !debugSolutionAvailable(set) )
536 return SCIP_OKAY;
537
538 assert(set != NULL);
539 debugsoldata = SCIPsetGetDebugSolData(set);
540
541 assert(debugsoldata != NULL);
542
543 if( debugsoldata->solisachieved )
544 return TRUE;
545
546 assert(set != NULL);
547
548 scip = set->scip;
549 assert(scip != NULL);
550
551 bestsol = SCIPgetBestSol(scip);
552
553 if( bestsol != NULL )
554 {
555 SCIP_Real solvalue;
556
557 /* don't check solution while in problem creation stage */
559 return TRUE;
560
561 solvalue = SCIPgetSolOrigObj(scip, bestsol);
562
563 /* make sure a debug solution has been read, so we do not compare against the initial debugsolval == 0 */
564 SCIP_CALL( readSolution(set) );
565
566 if( (SCIPgetObjsense(scip) == SCIP_OBJSENSE_MINIMIZE && SCIPsetIsLE(set, solvalue, debugsoldata->debugsolval))
567 || (SCIPgetObjsense(scip) == SCIP_OBJSENSE_MAXIMIZE && SCIPsetIsGE(set, solvalue, debugsoldata->debugsolval)) )
568 debugsoldata->solisachieved = TRUE;
569 }
570
571 return debugsoldata->solisachieved;
572}
573
574/** returns whether the solution is contained in node's subproblem */
575static
576SCIP_RETCODE isSolutionInNode(
577 BMS_BLKMEM* blkmem, /**< block memory */
578 SCIP_SET* set, /**< global SCIP settings */
579 SCIP_NODE* node, /**< local node where this bound change was applied */
580 SCIP_Bool* solcontained /**< pointer to store whether the solution is contained in node's subproblem */
581 )
582{
583 SCIP_Bool* boolptr;
584 SCIP_DEBUGSOLDATA* debugsoldata;
585
586 assert(set != NULL);
587 assert(blkmem != NULL);
588 assert(node != NULL);
589 assert(solcontained != NULL);
590
591 /* check whether a debug solution is available */
592 if( !debugSolutionAvailable(set) )
593 return SCIP_OKAY;
594
595 debugsoldata = SCIPsetGetDebugSolData(set);
596 assert(debugsoldata != NULL);
597
598 if( debugsoldata ->debugsoldisabled )
599 {
600 *solcontained = FALSE;
601 return SCIP_OKAY;
602 }
603
604 /* generate the hashmap */
605 if( debugsoldata->solinnode == NULL )
606 {
607 SCIP_CALL( SCIPhashmapCreate(&debugsoldata->solinnode, blkmem, SCIP_HASHSIZE_DEBUG) );
608 }
609
610 /* check, whether we know already whether the solution is contained in the given node */
611 boolptr = (SCIP_Bool*)SCIPhashmapGetImage(debugsoldata->solinnode, (void*)node);
612 if( boolptr != NULL )
613 {
614 if( boolptr != &debugsoldata->falseptr && boolptr != &debugsoldata->trueptr )
615 {
616 SCIPerrorMessage("wrong value in node hashmap\n");
617 SCIPABORT();
618 return SCIP_ERROR;
619 }
620 *solcontained = *boolptr;
621 return SCIP_OKAY;
622 }
623
624 /* if the solution is not contained in the parent of the node, it cannot be contained in the current node */
625 *solcontained = TRUE;
626 if( node->parent != NULL )
627 {
628 SCIP_CALL( isSolutionInNode(blkmem, set, node->parent, solcontained) );
629 }
630
631 if( *solcontained )
632 {
633 /* check whether the bound changes at the current node remove the debugging solution from the subproblem */
634 if( node->domchg != NULL )
635 {
636 SCIP_DOMCHGBOUND* domchgbound;
637 SCIP_BOUNDCHG* boundchgs;
638 int i;
639
640 domchgbound = &node->domchg->domchgbound;
641 boundchgs = domchgbound->boundchgs;
642 for( i = 0; i < (int)domchgbound->nboundchgs && *solcontained; ++i )
643 {
644 SCIP_Real varsol;
645
646 /* get solution value of variable */
647 SCIP_CALL( getSolutionValue(set, boundchgs[i].var, &varsol) );
648
649 if( varsol != SCIP_UNKNOWN ) /*lint !e777*/
650 {
651 /* compare the bound change with the solution value */
652 if( SCIPboundchgGetBoundtype(&boundchgs[i]) == SCIP_BOUNDTYPE_LOWER )
653 *solcontained = SCIPsetIsFeasGE(set, varsol, boundchgs[i].newbound);
654 else
655 *solcontained = SCIPsetIsFeasLE(set, varsol, boundchgs[i].newbound);
656
657 if( !(*solcontained) && SCIPboundchgGetBoundchgtype(&boundchgs[i]) != SCIP_BOUNDCHGTYPE_BRANCHING )
658 {
659 SCIPerrorMessage("debugging solution was cut off in local node %p at depth %d by inference <%s>[%.15g] %s %.15g\n",
660 (void*) node, SCIPnodeGetDepth(node), SCIPvarGetName(boundchgs[i].var), varsol,
661 SCIPboundchgGetBoundtype(&boundchgs[i]) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", boundchgs[i].newbound);
662 SCIPABORT();
663 }
664 }
666 {
667 /* we branched on a variable were we don't know the solution: no debugging can be applied in this subtree */
668 *solcontained = FALSE;
669 }
670 }
671 }
672 if( *solcontained && SCIPnodeGetNAddedConss(node) > 0 )
673 {
674 int i;
675 int naddedcons = 0;
676 SCIP_CONS** addedcons;
677
679
680 SCIPnodeGetAddedConss(node, addedcons, &naddedcons, SCIPnodeGetNAddedConss(node));
681
682 for( i = 0; i < naddedcons && *solcontained; ++i )
683 {
684 SCIP_RESULT result = SCIP_FEASIBLE;
685 SCIP_CALL( SCIPcheckCons(set->scip, addedcons[i], debugsoldata->debugsol , TRUE, TRUE, FALSE, &result) );
686
687 if( result != SCIP_FEASIBLE )
688 *solcontained = FALSE;
689 }
690
691 SCIPsetFreeBufferArray(set, &addedcons);
692 }
693 }
694
695 /* remember the status of the current node */
696 SCIP_CALL( SCIPhashmapSetImage(debugsoldata->solinnode, (void*)node, *solcontained ? (void*)(&debugsoldata->trueptr) : (void*)(&debugsoldata->falseptr)) );
697
698 return SCIP_OKAY;
699}
700
701/** frees the debug solution */
704 )
705{
706 SCIP_DEBUGSOLDATA* debugsoldata;
707
708 debugsoldata = SCIPsetGetDebugSolData(set);
709 assert(debugsoldata != NULL);
710
711 if( debugsoldata->debugsol != NULL && ((SCIPgetStage(set->scip) > SCIP_STAGE_PROBLEM && debugsoldata->debugsolstage > SCIP_STAGE_PROBLEM)
712 || (SCIPgetStage(set->scip) <= SCIP_STAGE_PROBLEM && debugsoldata->debugsolstage <= SCIP_STAGE_PROBLEM)) )
713 {
714 SCIP_CALL( SCIPfreeSol(set->scip, &debugsoldata->debugsol) );
715 }
716
717 return SCIP_OKAY;
718}
719
720/** resets the data structure after restart */
723 )
724{
725 SCIP_DEBUGSOLDATA* debugsoldata;
726
727 assert(set != NULL);
728
729 debugsoldata = SCIPsetGetDebugSolData(set);
730 assert(debugsoldata != NULL);
731
732 if( debugsoldata->solinnode != NULL )
733 {
734 SCIP_CALL( SCIPhashmapRemoveAll(debugsoldata->solinnode) );
735 }
736
737 return SCIP_OKAY;
738}
739
740/** frees debugging data for the particular instance */
742 SCIP_SET* set /**< global SCIP settings */
743 )
744{
745 int s;
746
747 SCIP_DEBUGSOLDATA* debugsoldata;
748 assert(set != NULL);
749
750 debugsoldata = SCIPsetGetDebugSolData(set);
751 assert(debugsoldata != NULL);
752
753 for( s = debugsoldata->nsolvals - 1; s >= 0; --s )
754 BMSfreeMemoryArrayNull(&(debugsoldata->solnames[s]));
755
756 BMSfreeMemoryArrayNull(&debugsoldata->solnames);
757 BMSfreeMemoryArrayNull(&debugsoldata->solvals);
758
759 debugsoldata->nsolvals = 0;
760 debugsoldata->debugsolval= 0.0;
761 debugsoldata->solisachieved = FALSE;
762
763 if( debugsoldata->solinnode != NULL)
764 SCIPhashmapFree(&debugsoldata->solinnode);
765
766 /* free the debug solution */
768
769 return SCIP_OKAY;
770}
771
772/** frees all debugging data */
774 SCIP_SET* set /**< global SCIP settings */
775 )
776{
777 SCIP_DEBUGSOLDATA* debugsoldata;
778
779 assert(set != NULL);
780
781 debugsoldata = SCIPsetGetDebugSolData(set);
782 assert(debugsoldata != NULL);
783
785 BMSfreeMemoryNull(&debugsoldata);
786
787 set->debugsoldata = NULL;
788
789 return SCIP_OKAY;
790}
791
792/** checks for validity of the debugging solution in given constraints */
794 SCIP* scip, /**< SCIP data structure */
795 SCIP_CONS** conss, /**< constraints to check for validity */
796 int nconss /**< number of given constraints */
797 )
798{
799 SCIP_RESULT result;
800 int c;
801
802 SCIP_DEBUGSOLDATA* debugsoldata;
803 assert(scip->set != NULL);
804
805 /* check if we are in the original problem and not in a sub MIP */
807 return SCIP_OKAY;
808
809 /* check whether a debug solution is available */
810 if( !debugSolutionAvailable(scip->set) )
811 return SCIP_OKAY;
812
813 debugsoldata = SCIPsetGetDebugSolData(scip->set);
814
815 assert(conss != NULL || nconss == 0);
816 assert(debugsoldata->debugsol != NULL);
817
818 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug
819 * solution
820 */
821 if( debugSolIsAchieved(scip->set) )
822 return SCIP_OKAY;
823
824 result = SCIP_FEASIBLE;
825
826 /* checking each given constraint against the debugging solution */
827 for( c = nconss - 1; c >= 0; --c )
828 {
829 assert(conss[c] != NULL);
830
831 if( !SCIPconsIsActive(conss[c]) )
832 continue;
833
834 assert(SCIPconsGetActiveDepth(conss[c]) <= SCIPgetDepth(scip));
835
836 /* if the cons is only locally valid, check whether the debugging solution is contained in the local subproblem */
837 if( SCIPconsIsLocal(conss[c]) )
838 {
839 SCIP_Bool solcontained;
840
841 SCIP_CALL( isSolutionInNode(SCIPblkmem(scip), scip->set, SCIPgetCurrentNode(scip), &solcontained) );
842 if( !solcontained )
843 return SCIP_OKAY;
844 }
845
846 SCIP_CALL( SCIPcheckCons(scip, conss[c], debugsoldata->debugsol, TRUE, TRUE, TRUE, &result) );
847
848 SCIPdebugMsg(scip, " -> checking of constraint %s returned result <%d>\n", SCIPconsGetName(conss[c]), result);
849
850 if( result != SCIP_FEASIBLE )
851 {
852 SCIPerrorMessage("constraint %s violates the debugging solution\n", SCIPconsGetName(conss[c]));
853 SCIPABORT();
854 }
855 }
856
857 return SCIP_OKAY;
858}
859
860/** checks whether given row is valid for the debugging solution */
862 SCIP_SET* set, /**< global SCIP settings */
863 SCIP_ROW* row /**< row to check for validity */
864 )
865{
866 SCIP_COL** cols;
867 SCIP_Real* vals;
868 SCIP_Real lhs;
869 SCIP_Real rhs;
870 int nnonz;
871 int i;
872 SCIP_Real minactivity;
873 SCIP_Real maxactivity;
874 SCIP_Real solval;
875
876 assert(set != NULL);
877 assert(row != NULL);
878
879 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
880 if( !SCIPdebugSolIsEnabled(set->scip) )
881 return SCIP_OKAY;
882
883 /* check whether a debug solution is available */
884 if( !debugSolutionAvailable(set) )
885 return SCIP_OKAY;
886
887 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
888 if( debugSolIsAchieved(set) )
889 return SCIP_OKAY;
890
891 /* if the row is only locally valid, check whether the debugging solution is contained in the local subproblem */
892 if( SCIProwIsLocal(row) )
893 {
894 SCIP_Bool solcontained;
895
896 SCIP_CALL( isSolutionInNode(SCIPblkmem(set->scip), set, SCIPgetCurrentNode(set->scip), &solcontained) );
897 if( !solcontained )
898 return SCIP_OKAY;
899 }
900
901 cols = SCIProwGetCols(row);
902 vals = SCIProwGetVals(row);
903 nnonz = SCIProwGetNNonz(row);
904 lhs = SCIProwGetLhs(row);
905 rhs = SCIProwGetRhs(row);
906
907 /* calculate row's activity on debugging solution */
908 minactivity = SCIProwGetConstant(row);
909 maxactivity = minactivity;
910 for( i = 0; i < nnonz; ++i )
911 {
912 SCIP_VAR* var;
913
914 /* get solution value of variable in debugging solution */
915 var = SCIPcolGetVar(cols[i]);
916 SCIP_CALL( getSolutionValue(set, var, &solval) );
917
918 if( solval != SCIP_UNKNOWN ) /*lint !e777*/
919 {
920 minactivity += vals[i] * solval;
921 maxactivity += vals[i] * solval;
922 }
923 else if( vals[i] > 0.0 )
924 {
925 minactivity += vals[i] * SCIPvarGetLbGlobal(var);
926 maxactivity += vals[i] * SCIPvarGetUbGlobal(var);
927 }
928 else if( vals[i] < 0.0 )
929 {
930 minactivity += vals[i] * SCIPvarGetUbGlobal(var);
931 maxactivity += vals[i] * SCIPvarGetLbGlobal(var);
932 }
933 }
934 SCIPsetDebugMsg(set, "debugging solution on row <%s>: %g <= [%g,%g] <= %g\n",
935 SCIProwGetName(row), lhs, minactivity, maxactivity, rhs);
936
937 /* check row for violation, using absolute LP feasibility tolerance (as LP solver should do) */
938 if( maxactivity + SCIPgetLPFeastol(set->scip) < lhs || minactivity - SCIPgetLPFeastol(set->scip) > rhs )
939 {
940 printf("***** debug: row <%s> violates debugging solution (lhs=%.15g, rhs=%.15g, activity=[%.15g,%.15g], local=%u, lpfeastol=%g)\n",
941 SCIProwGetName(row), lhs, rhs, minactivity, maxactivity, SCIProwIsLocal(row), SCIPgetLPFeastol(set->scip));
943
944 /* output row with solution values */
945 printf("\n\n");
946 printf("***** debug: violated row <%s>:\n", SCIProwGetName(row));
947 printf(" %.15g <= %.15g", lhs, SCIProwGetConstant(row));
948 for( i = 0; i < nnonz; ++i )
949 {
950 /* get solution value of variable in debugging solution */
951 SCIP_CALL( getSolutionValue(set, SCIPcolGetVar(cols[i]), &solval) );
952 printf(" %+.15g<%s>[%.15g]", vals[i], SCIPvarGetName(SCIPcolGetVar(cols[i])), solval);
953 }
954 printf(" <= %.15g\n", rhs);
955
956 SCIPABORT();
957 }
958
959 return SCIP_OKAY;
960}
961
962/** checks whether given global lower bound is valid for the debugging solution */
964 SCIP* scip, /**< SCIP data structure */
965 SCIP_VAR* var, /**< problem variable */
966 SCIP_Real lb /**< lower bound */
967 )
968{
969 SCIP_Real varsol;
970
971 assert(scip != NULL);
972 assert(var != NULL);
973
974 /* check if we are in the original problem and not in a sub MIP */
976 return SCIP_OKAY;
977
978 /* check whether a debug solution is available */
979 if( !debugSolutionAvailable(scip->set) )
980 return SCIP_OKAY;
981
983 return SCIP_OKAY;
984
985 /* skip unused relaxation-only variables
986 * Relaxation-only variables are not part of any constraints or the original problem and thus there is no need to check their solution value.
987 * However, for relaxation-only variables that are still in use for the current solve round and for which a debug solution value has been set,
988 * checking against the debug solution value is helpful. If they not in use anymore, they will be captured only by the transformed problem
989 * and they may get fixed to some arbitrary value, e.g., in dual fixing.
990 * Thus, we skip checking bound changes on unused relaxation-only variables.
991 */
992 if( SCIPvarIsRelaxationOnly(var) && SCIPvarGetNUses(var) == 1 )
993 return SCIP_OKAY;
994
995 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
996 if( debugSolIsAchieved(scip->set) )
997 return SCIP_OKAY;
998
999 /* get solution value of variable */
1000 SCIP_CALL( getSolutionValue(scip->set, var, &varsol) );
1001 SCIPdebugMsg(scip, "debugging solution on lower bound of <%s>[%g] >= %g\n", SCIPvarGetName(var), varsol, lb);
1002
1003 /* check validity of debugging solution */
1004 if( varsol != SCIP_UNKNOWN && SCIPisFeasLT(scip, varsol, lb) ) /*lint !e777*/
1005 {
1006 SCIPerrorMessage("invalid global lower bound: <%s>[%.15g] >= %.15g\n", SCIPvarGetName(var), varsol, lb);
1007 SCIPABORT();
1008 }
1009
1010 return SCIP_OKAY;
1011}
1012
1013/** checks whether given global upper bound is valid for the debugging solution */
1015 SCIP* scip, /**< SCIP data structure */
1016 SCIP_VAR* var, /**< problem variable */
1017 SCIP_Real ub /**< upper bound */
1018 )
1019{
1020 SCIP_Real varsol;
1021
1022 assert(scip != NULL);
1023 assert(var != NULL);
1024
1025 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1027 return SCIP_OKAY;
1028
1029 /* check whether a debug solution is available */
1030 if( !debugSolutionAvailable(scip->set) )
1031 return SCIP_OKAY;
1032
1034 return SCIP_OKAY;
1035
1036 /* skip unused relaxation-only variables, see also comment in SCIPdebugCheckLbGlobal() */
1037 if( SCIPvarIsRelaxationOnly(var) && SCIPvarGetNUses(var) == 1 )
1038 return SCIP_OKAY;
1039
1040 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
1041 if( debugSolIsAchieved(scip->set) )
1042 return SCIP_OKAY;
1043
1044 /* get solution value of variable */
1045 SCIP_CALL( getSolutionValue(scip->set, var, &varsol) );
1046 SCIPdebugMsg(scip, "debugging solution on upper bound of <%s>[%g] <= %g\n", SCIPvarGetName(var), varsol, ub);
1047
1048 /* check validity of debugging solution */
1049 if( varsol != SCIP_UNKNOWN && SCIPisFeasGT(scip, varsol, ub) ) /*lint !e777*/
1050 {
1051 SCIPerrorMessage("invalid global upper bound: <%s>[%.15g] <= %.15g\n", SCIPvarGetName(var), varsol, ub);
1052 SCIPABORT();
1053 }
1054
1055 return SCIP_OKAY;
1056}
1057
1058/** checks whether given local bound implication is valid for the debugging solution */
1060 BMS_BLKMEM* blkmem, /**< block memory */
1061 SCIP_SET* set, /**< global SCIP settings */
1062 SCIP_NODE* node, /**< local node where this bound change was applied */
1063 SCIP_VAR* var, /**< problem variable */
1064 SCIP_Real newbound, /**< new value for bound */
1065 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
1066 )
1067{
1068 SCIP_Real varsol;
1069 SCIP_Bool solcontained;
1070
1071 assert(set != NULL);
1072 assert(blkmem != NULL);
1073 assert(node != NULL);
1074 assert(var != NULL);
1075
1076 /* in case we are in probing or diving we have to avoid checking the solution */
1077 if( SCIPlpDiving(set->scip->lp) || SCIPtreeProbing(set->scip->tree) )
1078 return SCIP_OKAY;
1079
1080 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1081 if( !SCIPdebugSolIsEnabled(set->scip) )
1082 return SCIP_OKAY;
1083
1084 /* check whether a debug solution is available */
1085 if( !debugSolutionAvailable(set) )
1086 return SCIP_OKAY;
1087
1088 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
1089 if( debugSolIsAchieved(set) )
1090 return SCIP_OKAY;
1091
1092 /* check whether the debugging solution is contained in the local subproblem */
1093 SCIP_CALL( isSolutionInNode(blkmem, set, node, &solcontained) );
1094 if( !solcontained )
1095 return SCIP_OKAY;
1096
1097 /* get solution value of variable */
1098 SCIP_CALL( getSolutionValue(set, var, &varsol) );
1099
1100 /* check validity of debugging solution */
1101 if( varsol != SCIP_UNKNOWN ) /*lint !e777*/
1102 {
1103 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLT(set, varsol, newbound) )
1104 {
1105 SCIPerrorMessage("invalid local lower bound implication: <%s>[%.15g] >= %.15g\n", SCIPvarGetName(var), varsol, newbound);
1106 SCIPABORT();
1107 }
1108 if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGT(set, varsol, newbound) )
1109 {
1110 SCIPerrorMessage("invalid local upper bound implication: <%s>[%.15g] <= %.15g\n", SCIPvarGetName(var), varsol, newbound);
1111 SCIPABORT();
1112 }
1113 }
1114
1115 return SCIP_OKAY;
1116}
1117
1118/** informs solution debugger, that the given node will be freed */
1120 BMS_BLKMEM* blkmem, /**< block memory */
1121 SCIP_SET* set, /**< global SCIP settings */
1122 SCIP_NODE* node /**< node that will be freed */
1123 )
1124{
1125 SCIP_DEBUGSOLDATA* debugsoldata;
1126
1127 assert(set != NULL);
1128 assert(blkmem != NULL);
1129 assert(node != NULL);
1130
1131 debugsoldata = SCIPsetGetDebugSolData(set);
1132 assert(debugsoldata != NULL);
1133
1134 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1135 if( !SCIPdebugSolIsEnabled(set->scip) )
1136 return SCIP_OKAY;
1137
1138 /* check whether a debug solution is available */
1139 if( !debugSolutionAvailable(set) )
1140 return SCIP_OKAY;
1141
1142 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
1143 if( debugSolIsAchieved(set) )
1144 return SCIP_OKAY;
1145
1146 /* check if a solution will be cutoff in tree */
1149 {
1150 SCIP_Bool solisinnode;
1151
1152 solisinnode = FALSE;
1153
1154 SCIP_CALL( isSolutionInNode(blkmem, set, node, &solisinnode) );
1155 /* wrong node will be cutoff */
1156 if( solisinnode )
1157 {
1158 SCIPerrorMessage("debugging solution was cut off in local node #%" SCIP_LONGINT_FORMAT " (%p) at depth %d\n",
1159 node->number, (void*) node, SCIPnodeGetDepth(node));
1160 SCIPABORT();
1161 }
1162 }
1163
1164 /* remove node from the hash map */
1165 if( debugsoldata->solinnode != NULL )
1166 {
1167 SCIP_CALL( SCIPhashmapRemove(debugsoldata->solinnode, (void*)node) );
1168 }
1169
1170 return SCIP_OKAY;
1171}
1172
1173/** checks whether global lower bound does not exceed debuging solution value */
1175 BMS_BLKMEM* blkmem, /**< block memory */
1176 SCIP_SET* set /**< global SCIP settings */
1177 )
1178{
1179 SCIP_DEBUGSOLDATA* debugsoldata;
1180 SCIP_Real treelowerbound;
1181
1182 assert(set != NULL);
1183 assert(blkmem != NULL);
1184
1185 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1186 if( !SCIPdebugSolIsEnabled(set->scip) )
1187 return SCIP_OKAY;
1188
1189 /* check whether a debug solution is available */
1190 if( !debugSolutionAvailable(set) )
1191 return SCIP_OKAY;
1192
1194 return SCIP_OKAY;
1195
1197 return SCIP_OKAY;
1198
1199 /* if there are no leaves then SCIPtreeGetLowerbound() will return infintiy */
1200 if( SCIPgetNLeaves(set->scip) <= 0 )
1201 return SCIP_OKAY;
1202
1203 debugsoldata = SCIPsetGetDebugSolData(set);
1204 assert(debugsoldata != NULL);
1205
1206 /* make sure a debug solution has been read */
1207 if( debugsoldata->debugsol == NULL )
1208 {
1209 SCIP_CALL( readSolution(set) );
1210 }
1211
1212 /* get global lower bound of tree (do not use SCIPgetLowerbound() since this adjusts the value using the primal bound) */
1213 treelowerbound = SCIPtreeGetLowerbound(set->scip->tree, set);
1214 treelowerbound = SCIPprobExternObjval(set->scip->transprob, set->scip->origprob, set, treelowerbound);
1215
1216 if( SCIPgetObjsense(set->scip) == SCIP_OBJSENSE_MINIMIZE && SCIPsetIsGT(set, treelowerbound, SCIPsolGetOrigObj(debugsoldata->debugsol)) )
1217 {
1218 SCIPerrorMessage("global lower bound %g is larger than the value of the debugging solution %g.\n", treelowerbound, SCIPsolGetOrigObj(debugsoldata->debugsol));
1219 SCIPABORT();
1220 }
1221 else if( SCIPgetObjsense(set->scip) == SCIP_OBJSENSE_MAXIMIZE && SCIPsetIsLT(set, treelowerbound, SCIPsolGetOrigObj(debugsoldata->debugsol)) )
1222 {
1223 SCIPerrorMessage("global upper bound %g is smaller than the value of the debugging solution %g.\n", treelowerbound, SCIPsolGetOrigObj(debugsoldata->debugsol));
1224 SCIPABORT();
1225 }
1226
1227 return SCIP_OKAY;
1228}
1229
1230/** checks whether local lower bound does not exceed debuging solution value */
1232 BMS_BLKMEM* blkmem, /**< block memory */
1233 SCIP_SET* set, /**< global SCIP settings */
1234 SCIP_NODE* node /**< node that will be freed */
1235 )
1236{
1237 SCIP_DEBUGSOLDATA* debugsoldata;
1238 SCIP_Bool solisinnode;
1239
1240 assert(set != NULL);
1241 assert(blkmem != NULL);
1242
1243 /* exit if we do not have a node to check */
1244 if( node == NULL )
1245 return SCIP_OKAY;
1246
1247 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1248 if( !SCIPdebugSolIsEnabled(set->scip) )
1249 return SCIP_OKAY;
1250
1251 /* check whether a debug solution is available */
1252 if( !debugSolutionAvailable(set) )
1253 return SCIP_OKAY;
1254
1255 if( SCIPgetStage(set->scip) <= SCIP_STAGE_INITSOLVE )
1256 return SCIP_OKAY;
1257
1259 return SCIP_OKAY;
1260
1261 debugsoldata = SCIPsetGetDebugSolData(set);
1262 assert(debugsoldata != NULL);
1263
1264 /* make sure a debug solution has been read */
1265 if( debugsoldata->debugsol == NULL )
1266 {
1267 SCIP_CALL( readSolution(set) );
1268 }
1269
1270 /* check local lower bound */
1271 SCIP_CALL( isSolutionInNode(blkmem, set, node, &solisinnode) );
1272
1273 /* if we are in a node that contains the given debug solution, the lower bound should not exceed the solution's objective */
1274 if( solisinnode )
1275 {
1276 SCIP_Real localbound;
1277
1278 localbound = SCIPnodeGetLowerbound(node);
1279 localbound = SCIPprobExternObjval(set->scip->transprob, set->scip->origprob, set, localbound);
1280
1281 if( SCIPgetObjsense(set->scip) == SCIP_OBJSENSE_MINIMIZE && SCIPsetIsGT(set, localbound, SCIPsolGetOrigObj(debugsoldata->debugsol)) )
1282 {
1283 SCIPerrorMessage("local lower bound %g of node #%" SCIP_LONGINT_FORMAT " at depth %d is larger than the value of the debugging solution %g contained in this node.\n",
1284 localbound, node->number, SCIPnodeGetDepth(node), SCIPsolGetOrigObj(debugsoldata->debugsol));
1285 SCIPABORT();
1286 }
1287 else if( SCIPgetObjsense(set->scip) == SCIP_OBJSENSE_MAXIMIZE && SCIPsetIsLT(set, localbound, SCIPsolGetOrigObj(debugsoldata->debugsol)) )
1288 {
1289 SCIPerrorMessage("local upper bound %g of node #%" SCIP_LONGINT_FORMAT " at depth %d is smaller than the value of the debugging solution %g contained in this node.\n",
1290 localbound, node->number, SCIPnodeGetDepth(node), SCIPsolGetOrigObj(debugsoldata->debugsol));
1291 SCIPABORT();
1292 }
1293 }
1294
1295 return SCIP_OKAY;
1296}
1297
1298/** checks whether given variable bound is valid for the debugging solution */
1300 SCIP_SET* set, /**< global SCIP settings */
1301 SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
1302 SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
1303 SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
1304 SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
1305 SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
1306 )
1307{
1308 SCIP_Real varsol;
1309 SCIP_Real vbvarsol;
1310 SCIP_Real vb;
1311
1312 assert(set != NULL);
1313 assert(var != NULL);
1314
1315 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1316 if( !SCIPdebugSolIsEnabled(set->scip) )
1317 return SCIP_OKAY;
1318
1319 /* check whether a debug solution is available */
1320 if( !debugSolutionAvailable(set) )
1321 return SCIP_OKAY;
1322
1323 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
1324 if( debugSolIsAchieved(set) )
1325 return SCIP_OKAY;
1326
1327 /* get solution value of variables */
1328 SCIP_CALL( getSolutionValue(set, var, &varsol) );
1329 SCIP_CALL( getSolutionValue(set, vbvar, &vbvarsol) );
1330
1331 /* check validity of debugging solution */
1332 if( varsol != SCIP_UNKNOWN && vbvarsol != SCIP_UNKNOWN ) /*lint !e777*/
1333 {
1334 vb = vbcoef * vbvarsol + vbconstant;
1335 if( (vbtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLT(set, varsol, vb))
1336 || (vbtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGT(set, varsol, vb)) )
1337 {
1338 SCIPerrorMessage("invalid variable bound: <%s>[%.15g] %s %.15g<%s>[%.15g] %+.15g\n",
1339 SCIPvarGetName(var), varsol, vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef,
1340 SCIPvarGetName(vbvar), vbvarsol, vbconstant);
1341 SCIPABORT();
1342 }
1343 }
1344
1345 return SCIP_OKAY;
1346}
1347
1348/** checks whether given implication is valid for the debugging solution */
1350 SCIP_SET* set, /**< global SCIP settings */
1351 SCIP_VAR* var, /**< problem variable */
1352 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
1353 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
1354 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
1355 SCIP_Real implbound /**< bound b in implication y <= b or y >= b */
1356 )
1357{
1358 SCIP_Real solval;
1359
1360 assert(set != NULL);
1361 assert(var != NULL);
1362 assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
1363
1364 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1365 if( !SCIPdebugSolIsEnabled(set->scip) )
1366 return SCIP_OKAY;
1367
1368 /* check whether a debug solution is available */
1369 if( !debugSolutionAvailable(set) )
1370 return SCIP_OKAY;
1371
1372 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
1373 if( debugSolIsAchieved(set) )
1374 return SCIP_OKAY;
1375
1376 /* get solution value of variable */
1377 SCIP_CALL( getSolutionValue(set, var, &solval) );
1378 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1379 return SCIP_OKAY;
1380 assert(SCIPsetIsFeasZero(set, solval) || SCIPsetIsFeasEQ(set, solval, 1.0));
1381
1382 /* check, whether the implication applies for the debugging solution */
1383 if( (solval > 0.5) != varfixing )
1384 return SCIP_OKAY;
1385
1386 /* get solution value of implied variable */
1387 SCIP_CALL( getSolutionValue(set, implvar, &solval) );
1388 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1389 return SCIP_OKAY;
1390
1391 if( impltype == SCIP_BOUNDTYPE_LOWER )
1392 {
1393 if( SCIPsetIsFeasLT(set, solval, implbound) )
1394 {
1395 SCIPerrorMessage("invalid implication <%s> == %d -> <%s> >= %.15g (variable has value %.15g in solution)\n",
1396 SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar), implbound, solval);
1397 SCIPABORT();
1398 }
1399 }
1400 else
1401 {
1402 if( SCIPsetIsFeasGT(set, solval, implbound) )
1403 {
1404 SCIPerrorMessage("invalid implication <%s> == %d -> <%s> <= %.15g (variable has value %.15g in solution)\n",
1405 SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar), implbound, solval);
1406 SCIPABORT();
1407 }
1408 }
1409
1410 return SCIP_OKAY;
1411}
1412
1413/** checks whether given (multi)-aggregation is valid for the debugging solution */
1415 SCIP_SET* set, /**< global SCIP settings */
1416 SCIP_VAR* var, /**< problem variable */
1417 SCIP_VAR** aggrvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
1418 SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
1419 SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
1420 int naggrvars /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
1421 )
1422{
1423 SCIP_Real solval;
1424 SCIP_Real val;
1425 int i;
1426
1427 assert(set != NULL);
1428 assert(var != NULL);
1429 assert(aggrvars != NULL);
1430 assert(scalars != NULL);
1431 assert(naggrvars >= 0);
1432
1433 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1434 if( !SCIPdebugSolIsEnabled(set->scip) )
1435 return SCIP_OKAY;
1436
1437 /* check whether a debug solution is available */
1438 if( !debugSolutionAvailable(set) )
1439 return SCIP_OKAY;
1440
1441 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
1442 if( debugSolIsAchieved(set) )
1443 return SCIP_OKAY;
1444
1445 /* get solution value of x variable */
1446 SCIP_CALL( getSolutionValue(set, var, &solval) );
1447
1448 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1449 return SCIP_OKAY;
1450
1451 val = constant;
1452
1453 for( i = 0; i < naggrvars; i++ )
1454 {
1455 SCIP_Real aggrsolval;
1456
1457 /* get solution value of y variable */
1458 SCIP_CALL( getSolutionValue(set, aggrvars[i], &aggrsolval) );
1459
1460 if( aggrsolval == SCIP_UNKNOWN ) /*lint !e777*/
1461 return SCIP_OKAY;
1462
1463 val += scalars[i] * aggrsolval;
1464 }
1465
1466 /* print debug message if the aggregation violates the debugging solution */
1467 if( !SCIPsetIsRelEQ(set, solval, val) )
1468 {
1469 if( naggrvars == 1 )
1470 {
1471 SCIP_Real aggrsolval;
1472
1473 /* get solution value of y variable */
1474 SCIP_CALL( getSolutionValue(set, aggrvars[0], &aggrsolval) );
1475
1476 SCIPerrorMessage("aggregation <%s>[%g] = %g<%s>[%g] + %g violates debugging solution (expected %g)\n",
1477 SCIPvarGetName(var), solval, scalars[0], SCIPvarGetName(aggrvars[0]), aggrsolval, constant, val);
1478 }
1479 else
1480 {
1481 SCIPerrorMessage("multi-aggregation <%s>[%g] = ... %d vars ... + %g violates debugging solution (expected %g)\n",
1482 SCIPvarGetName(var), solval, naggrvars, constant, val);
1483 }
1484 SCIPABORT();
1485 }
1486
1487 return SCIP_OKAY;
1488}
1489
1490/** check whether given clique is valid for the debugging solution */
1492 SCIP_SET* set, /**< global SCIP settings */
1493 SCIP_VAR** vars, /**< binary variables in the clique: at most one can be set to the given value */
1494 SCIP_Bool* values, /**< values of the variables in the clique; NULL to use TRUE for all vars */
1495 int nvars /**< number of variables in the clique */
1496 )
1497{
1498 SCIP_Real solval;
1499 int pos1;
1500 int pos2;
1501 int v;
1502
1503 assert(set != NULL);
1504 assert(vars != NULL);
1505
1506 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1507 if( !SCIPdebugSolIsEnabled(set->scip) )
1508 return SCIP_OKAY;
1509
1510 /* check whether a debug solution is available */
1511 if( !debugSolutionAvailable(set) )
1512 return SCIP_OKAY;
1513
1514 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
1515 if( debugSolIsAchieved(set) )
1516 return SCIP_OKAY;
1517
1518 pos1 = -1;
1519 pos2 = -1;
1520
1521 for( v = 0; v < nvars; ++v )
1522 {
1523 assert(vars[v] != NULL);
1524 assert(SCIPvarIsBinary(vars[v]));
1525
1526 /* get solution value of variable */
1527 SCIP_CALL( getSolutionValue(set, vars[v], &solval) );
1528
1529 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1530 continue;
1531
1532 assert(SCIPsetIsFeasZero(set, solval) || SCIPsetIsFeasEQ(set, solval, 1.0));
1533
1534 /* negated solution value if negated variable is in clique */
1535 if( values != NULL && values[v] == 0 )
1536 solval = 1.0 - solval;
1537
1538 if( SCIPsetIsFeasEQ(set, solval, 1.0) )
1539 {
1540 if( pos1 == -1 )
1541 pos1 = v;
1542 else
1543 {
1544 assert(pos2 == -1);
1545 pos2 = v;
1546 break;
1547 }
1548 }
1549 }
1550
1551 /* print debug message if the clique violates the debugging solution */
1552 if( pos2 != -1 )
1553 {
1554 assert(pos1 != -1);
1555 SCIPerrorMessage("clique violates debugging solution, (at least) variable <%s%s> and variable <%s%s> are both one in the debugging solution\n",
1556 (values == NULL || values[pos1]) ? "" : "~", SCIPvarGetName(vars[pos1]), (values == NULL || values[pos2]) ? "" : "~", SCIPvarGetName(vars[pos2]));
1557 SCIPABORT();
1558 }
1559
1560 return SCIP_OKAY;
1561}
1562
1563/** check, whether at least one literals is TRUE in the debugging solution */
1564static
1565SCIP_Bool debugCheckBdchginfos(
1566 SCIP_SET* set, /**< global SCIP settings */
1567 SCIP_BDCHGINFO** bdchginfos, /**< bound change informations of the conflict set */
1568 SCIP_Real* relaxedbds, /**< array with relaxed bounds which are efficient to create a valid conflict, or NULL */
1569 int nbdchginfos /**< number of bound changes in the conflict set */
1570 )
1571{
1572 SCIP_Real solval;
1573 int i;
1574
1575 /* check whether a debug solution is available */
1576 if( !debugSolutionAvailable(set) )
1577 return SCIP_OKAY;
1578
1579 assert(SCIPdebugSolIsEnabled(set->scip));
1580
1581 solval = 0.0;
1582 /* check, whether at least one literals is TRUE in the debugging solution */
1583 for( i = 0; i < nbdchginfos; ++i )
1584 {
1585 SCIP_BDCHGINFO* bdchginfo;
1586 SCIP_VAR* var;
1587 SCIP_Real newbound;
1588
1589 bdchginfo = bdchginfos[i];
1590 assert(bdchginfo != NULL);
1591
1592 var = SCIPbdchginfoGetVar(bdchginfo);
1593 assert(var != NULL);
1594
1595 if( relaxedbds != NULL )
1596 newbound = relaxedbds[i];
1597 else
1598 newbound = SCIPbdchginfoGetNewbound(bdchginfo);
1599
1600 SCIP_CALL( getSolutionValue(set, var, &solval) );
1601
1602 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1603 return TRUE;
1604
1606 {
1607 assert(SCIPsetIsLE(set, newbound, SCIPbdchginfoGetNewbound(bdchginfo)));
1608
1610 {
1611 if( SCIPsetIsLE(set, solval, newbound) )
1612 return TRUE;
1613 }
1614 else
1615 {
1616 if( SCIPsetIsLT(set, solval, newbound) )
1617 return TRUE;
1618 }
1619 }
1620 else
1621 {
1622 assert(SCIPsetIsGE(set, newbound, SCIPbdchginfoGetNewbound(bdchginfo)));
1623
1625 {
1626 if( SCIPsetIsGE(set, solval, newbound) )
1627 return TRUE;
1628 }
1629 else
1630 {
1631 if( SCIPsetIsGT(set, solval, newbound) )
1632 return TRUE;
1633 }
1634 }
1635 }
1636
1637 return FALSE;
1638}
1639
1640/** print bound change information */
1641static
1642SCIP_RETCODE printBdchginfo(
1643 SCIP_SET* set, /**< global SCIP settings */
1644 SCIP_BDCHGINFO * bdchginfo, /**< bound change information */
1645 SCIP_Real relaxedbd /**< array with relaxed bounds which are efficient to create a valid conflict, or NULL */
1646 )
1647{
1648 SCIP_Real solval;
1649
1650 /* check whether a debug solution is available */
1651 if( !debugSolutionAvailable(set) )
1652 return SCIP_OKAY;
1653
1654 /* get solution value within the debug solution */
1655 SCIP_CALL( getSolutionValue(set, SCIPbdchginfoGetVar(bdchginfo), &solval) );
1656
1657 printf(" <%s>[%.15g] %s %g(%g)", SCIPvarGetName(SCIPbdchginfoGetVar(bdchginfo)), solval,
1658 SCIPbdchginfoGetBoundtype(bdchginfo) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
1659 SCIPbdchginfoGetNewbound(bdchginfo), relaxedbd);
1660
1661 return SCIP_OKAY;
1662}
1663
1664
1665/** print bound change information */
1666static
1667SCIP_RETCODE printBdchginfos(
1668 SCIP_SET* set, /**< global SCIP settings */
1669 SCIP_BDCHGINFO** bdchginfos, /**< bound change information array */
1670 SCIP_Real* relaxedbds, /**< array with relaxed bounds which are efficient to create a valid conflict, or NULL */
1671 int nbdchginfos /**< number of bound changes in the conflict set */
1672 )
1673{
1674 int i;
1675
1676 /* check whether a debug solution is available */
1677 if( !debugSolutionAvailable(set) )
1678 return SCIP_OKAY;
1679
1680 for( i = 0; i < nbdchginfos; ++i )
1681 {
1682 SCIP_BDCHGINFO* bdchginfo;
1683
1684 bdchginfo = bdchginfos[i];
1685 assert(bdchginfo != NULL);
1686
1687 printBdchginfo(set, bdchginfo, relaxedbds != NULL ? relaxedbds[i] : SCIPbdchginfoGetNewbound(bdchginfo));
1688 }
1689
1690 return SCIP_OKAY;
1691}
1692
1693/** checks whether given conflict is valid for the debugging solution */
1695 BMS_BLKMEM* blkmem, /**< block memory */
1696 SCIP_SET* set, /**< global SCIP settings */
1697 SCIP_NODE* node, /**< node where the conflict clause is added */
1698 SCIP_BDCHGINFO** bdchginfos, /**< bound change informations of the conflict set */
1699 SCIP_Real* relaxedbds, /**< array with relaxed bounds which are efficient to create a valid conflict */
1700 int nbdchginfos /**< number of bound changes in the conflict set */
1701 )
1702{
1703 SCIP_Bool solcontained;
1704
1705 assert(set != NULL);
1706 assert(blkmem != NULL);
1707 assert(node != NULL);
1708 assert(nbdchginfos == 0 || bdchginfos != NULL);
1709
1710 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1711 if( !SCIPdebugSolIsEnabled(set->scip) )
1712 return SCIP_OKAY;
1713
1714 /* check whether a debug solution is available */
1715 if( !debugSolutionAvailable(set) )
1716 return SCIP_OKAY;
1717
1718 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
1719 if( debugSolIsAchieved(set) )
1720 return SCIP_OKAY;
1721
1722 /* check whether the debugging solution is contained in the local subproblem */
1723 SCIP_CALL( isSolutionInNode(blkmem, set, node, &solcontained) );
1724 if( !solcontained )
1725 return SCIP_OKAY;
1726
1727 /* check, whether at least one literals is TRUE in the debugging solution */
1728 if( debugCheckBdchginfos(set, bdchginfos, relaxedbds, nbdchginfos) )
1729 return SCIP_OKAY;
1730
1731 SCIPerrorMessage("invalid conflict set:");
1732
1733 /* print bound changes which are already part of the conflict set */
1734 SCIP_CALL( printBdchginfos(set, bdchginfos, relaxedbds, nbdchginfos) );
1735
1736 printf("\n");
1737 SCIPABORT();
1738
1739 return SCIP_OKAY; /*lint !e527*/
1740}
1741
1742/** checks whether given conflict graph frontier is valid for the debugging solution */
1744 BMS_BLKMEM* blkmem, /**< block memory */
1745 SCIP_SET* set, /**< global SCIP settings */
1746 SCIP_NODE* node, /**< node where the conflict clause is added */
1747 SCIP_BDCHGINFO* bdchginfo, /**< bound change info which got resolved, or NULL */
1748 SCIP_BDCHGINFO** bdchginfos, /**< bound change informations of the conflict set */
1749 SCIP_Real* relaxedbds, /**< array with relaxed bounds which are efficient to create a valid conflict */
1750 int nbdchginfos, /**< number of bound changes in the conflict set */
1751 SCIP_PQUEUE* bdchgqueue, /**< unprocessed conflict bound changes */
1752 SCIP_PQUEUE* forcedbdchgqueue /**< unprocessed conflict bound changes that must be resolved */
1753 )
1754{
1755 SCIP_BDCHGINFO** bdchgqueued;
1756 SCIP_BDCHGINFO** forcedbdchgqueued;
1757 SCIP_Bool solcontained;
1758 int nbdchgqueued;
1759 int nforcedbdchgqueued;
1760
1761 assert(set != NULL);
1762 assert(blkmem != NULL);
1763 assert(node != NULL);
1764 assert(nbdchginfos == 0 || bdchginfos != NULL);
1765
1766 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1767 if( !SCIPdebugSolIsEnabled(set->scip) )
1768 return SCIP_OKAY;
1769
1770 /* check whether a debug solution is available */
1771 if( !debugSolutionAvailable(set) )
1772 return SCIP_OKAY;
1773
1774 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
1775 if( debugSolIsAchieved(set) )
1776 return SCIP_OKAY;
1777
1778 /* check whether the debugging solution is contained in the local subproblem */
1779 SCIP_CALL( isSolutionInNode(blkmem, set, node, &solcontained) );
1780 if( !solcontained )
1781 return SCIP_OKAY;
1782
1783 /* check, whether one literals is TRUE in the debugging solution */
1784 if( debugCheckBdchginfos(set, bdchginfos, relaxedbds, nbdchginfos) )
1785 return SCIP_OKAY;
1786
1787 /* get the elements of the bound change queue */
1788 bdchgqueued = (SCIP_BDCHGINFO**)SCIPpqueueElems(bdchgqueue);
1789 nbdchgqueued = SCIPpqueueNElems(bdchgqueue);
1790
1791 /* check, whether one literals is TRUE in the debugging solution */
1792 if( debugCheckBdchginfos(set, bdchgqueued, NULL, nbdchgqueued) )
1793 return SCIP_OKAY;
1794
1795 /* get the elements of the bound change queue */
1796 forcedbdchgqueued = (SCIP_BDCHGINFO**)SCIPpqueueElems(forcedbdchgqueue);
1797 nforcedbdchgqueued = SCIPpqueueNElems(forcedbdchgqueue);
1798
1799 /* check, whether one literals is TRUE in the debugging solution */
1800 if( debugCheckBdchginfos(set, forcedbdchgqueued, NULL, nforcedbdchgqueued) )
1801 return SCIP_OKAY;
1802
1803 SCIPerrorMessage("invalid conflict frontier");
1804
1805 if( bdchginfo != NULL )
1806 {
1807 printf(" (after resolving bound change ");
1808 printBdchginfo(set, bdchginfo, SCIPbdchginfoGetNewbound(bdchginfo));
1809 printf(")");
1810 }
1811 printf(":");
1812
1813 /* print bound changes which are already part of the conflict set */
1814 SCIP_CALL( printBdchginfos(set, bdchginfos, relaxedbds, nbdchginfos) );
1815
1816 /* print bound changes which are queued */
1817 SCIP_CALL( printBdchginfos(set, bdchgqueued, NULL, nbdchgqueued) );
1818
1819 /* print bound changes which are queued in the force queue */
1820 SCIP_CALL( printBdchginfos(set, forcedbdchgqueued, NULL, nforcedbdchgqueued) );
1821
1822 printf("\n");
1823 SCIPABORT();
1824
1825 return SCIP_OKAY; /*lint !e527*/
1826}
1827
1828/** check whether the debugging solution is valid in the current node */
1830 SCIP* scip, /**< SCIP data structure */
1831 SCIP_Bool* isvalidinsubtree /**< pointer to store whether the solution is valid in the current
1832 * subtree */
1833 )
1834{
1835 SCIP_Bool solcontained;
1836
1837 *isvalidinsubtree = FALSE;
1838
1839 assert(scip->set != NULL);
1840
1841 /* when debugging was disabled the solution is not defined to be not valid in the current subtree */
1843 return SCIP_OKAY;
1844
1845 /* check whether a debug solution is available */
1846 if( !debugSolutionAvailable(scip->set) )
1847 return SCIP_OKAY;
1848
1849 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
1850 if( debugSolIsAchieved(scip->set) )
1851 return SCIP_OKAY;
1852
1853 /* check whether the debugging solution is contained in the local subproblem */
1854 SCIP_CALL( isSolutionInNode(SCIPblkmem(scip), scip->set, SCIPgetCurrentNode(scip), &solcontained) );
1855
1856 if( solcontained )
1857 *isvalidinsubtree = TRUE;
1858
1859 return SCIP_OKAY;
1860}
1861
1862/** checks whether SCIP data structure is the main SCIP (the one for which debugging is enabled) */
1863SCIP_Bool SCIPdebugIsMainscip(
1864 SCIP* scip /**< SCIP data structure */
1865 )
1866{
1867 assert(scip != NULL);
1868
1870}
1871
1872/** enabling solution debugging mechanism */
1874 SCIP* scip /**< SCIP data structure */
1875 )
1876{
1877 SCIP_DEBUGSOLDATA* debugsoldata;
1878 assert(scip != NULL);
1879 assert(scip->set != NULL);
1880
1881 debugsoldata = SCIPsetGetDebugSolData(scip->set);
1882 assert(debugsoldata != NULL);
1883
1884 debugsoldata->debugsoldisabled = FALSE;
1885}
1886
1887/** disabling solution debugging mechanism */
1889 SCIP* scip /**< SCIP data structure */
1890 )
1891{
1892 SCIP_DEBUGSOLDATA* debugsoldata;
1893 assert(scip != NULL);
1894 assert(scip->set != NULL);
1895
1896 debugsoldata = SCIPsetGetDebugSolData(scip->set);
1897 assert(debugsoldata != NULL);
1898
1899 debugsoldata->debugsoldisabled = TRUE;
1900}
1901
1902/** check if solution debugging mechanism is enabled */
1904 SCIP* scip /**< SCIP data structure */
1905 )
1906{
1907 SCIP_DEBUGSOLDATA* debugsoldata;
1908 assert(scip != NULL);
1909 assert(scip->set != NULL);
1910
1911 debugsoldata = SCIPsetGetDebugSolData(scip->set);
1912 assert(debugsoldata != NULL);
1913
1914 return (!debugsoldata->debugsoldisabled);
1915}
1916
1917/** check if SCIP is compiled with WITH_DEBUG_SOLUTION */
1919{
1920#ifdef WITH_DEBUG_SOLUTION
1921 return TRUE;
1922#else
1923 return FALSE;
1924#endif
1925}
1926
1927
1928/** propagator to force finding the debugging solution */
1929static
1930SCIP_DECL_PROPEXEC(propExecDebug)
1931{ /*lint --e{715}*/
1932 SCIP_VAR** vars;
1933 int nvars;
1934 int i;
1935
1936 assert(scip != NULL);
1937 assert(result != NULL);
1938
1939 *result = SCIP_DIDNOTFIND;
1940
1941 /* check if we are in the original problem and not in a sub MIP */
1942 if( !SCIPdebugIsMainscip(scip) )
1943 return SCIP_OKAY;
1944
1946 return SCIP_OKAY;
1947
1948 /* check whether a debug solution is available */
1949 if( !debugSolutionAvailable(scip->set) )
1950 return SCIP_OKAY;
1951
1952 /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
1953 if( debugSolIsAchieved(scip->set) )
1954 return SCIP_OKAY;
1955
1956#if 1
1957 /* solve at least one LP */
1958 if( SCIPgetNLPIterations(scip) == 0 )
1959 return SCIP_OKAY;
1960#endif
1961
1962 vars = SCIPgetOrigVars(scip);
1963 nvars = SCIPgetNOrigVars(scip);
1964 for( i = 0; i < nvars; ++i )
1965 {
1966 SCIP_Real solval;
1967 SCIP_Real lb;
1968 SCIP_Real ub;
1969 SCIP_Bool infeasible;
1970 SCIP_Bool fixed;
1971
1972 SCIP_CALL( getSolutionValue(scip->set, vars[i], &solval) );
1973 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1974 {
1975 SCIPerrorMessage("original variable without debugging solution value\n");
1976 SCIPABORT();
1977 }
1978
1979 lb = SCIPvarGetLbGlobal(vars[i]);
1980 ub = SCIPvarGetUbGlobal(vars[i]);
1981 if( SCIPisLT(scip, solval, lb) || SCIPisGT(scip, solval, ub) )
1982 {
1983 SCIPerrorMessage("solution value %.15g of <%s> outside bounds loc=[%.15g,%.15g], glb=[%.15g,%.15g]\n",
1984 solval, SCIPvarGetName(vars[i]), lb, ub, SCIPvarGetLbGlobal(vars[i]), SCIPvarGetUbGlobal(vars[i]));
1985 SCIPABORT();
1986 }
1987
1988 SCIP_CALL( SCIPfixVar(scip, vars[i], solval, &infeasible, &fixed) );
1989 if( infeasible )
1990 *result = SCIP_CUTOFF;
1991 else if( fixed )
1992 *result = SCIP_REDUCEDDOM;
1993 }
1994
1995 return SCIP_OKAY;
1996}
1997
1998/** creates the debugging propagator and includes it in SCIP */
2000 SCIP* scip /**< SCIP data structure */
2001 )
2002{
2003 assert(scip != NULL);
2004
2005 /* include propagator */
2006 SCIP_CALL( SCIPincludeProp(scip, "debug", "debugging propagator", 99999999, -1, FALSE,
2008 NULL, propExecDebug, NULL, NULL) );
2009
2010 return SCIP_OKAY;
2011}
2012
2013/** adds a solution value for a new variable in the transformed problem that has no original counterpart
2014 * a value can only be set if no value has been set for this variable before
2015 */
2017 SCIP* scip, /**< SCIP data structure */
2018 SCIP_VAR* var, /**< variable for which to add a value */
2019 SCIP_Real val /**< solution value for variable */
2020 )
2021{
2022 SCIP_DEBUGSOLDATA* debugsoldata;
2023 SCIP_Real testval;
2024 const char* varname;
2025 int i;
2026
2027 assert(scip != NULL);
2028 assert(var != NULL);
2029 assert(scip->set != NULL);
2030
2031 debugsoldata = SCIPsetGetDebugSolData(scip->set);
2032 assert(debugsoldata != NULL);
2033
2034 /* assert that we are in the SCIP instance that we are debugging and not some different (subSCIP,
2035 * auxiliary CIP, ...)
2036 */
2038 return SCIP_OKAY;
2039
2040 /* check whether a debug solution is available */
2041 if( !debugSolutionAvailable(scip->set) )
2042 return SCIP_OKAY;
2043
2044 if( debugsoldata->debugsol == NULL )
2045 {
2046 /* make sure a debug solution has been read, so we do not compare against the initial debugsolval == 0 */
2047 SCIP_CALL( readSolution(scip->set) );
2048 }
2049
2050 /* allocate memory */
2051 if( debugsoldata->nsolvals >= debugsoldata->solsize )
2052 {
2053 debugsoldata->solsize = MAX(2*debugsoldata->solsize, debugsoldata->nsolvals+1);
2054 SCIP_ALLOC( BMSreallocMemoryArray(&debugsoldata->solnames, debugsoldata->solsize) );
2055 SCIP_ALLOC( BMSreallocMemoryArray(&debugsoldata->solvals, debugsoldata->solsize) );
2056 }
2057 assert(debugsoldata->nsolvals < debugsoldata->solsize);
2058
2059 /* store solution value in sorted list */
2060 varname = SCIPvarGetName(var);
2061 for( i = debugsoldata->nsolvals; i > 0 && strcmp(varname, debugsoldata->solnames[i-1]) < 0; --i )
2062 {
2063 debugsoldata->solnames[i] = debugsoldata->solnames[i-1];
2064 debugsoldata->solvals[i] = debugsoldata->solvals[i-1];
2065 }
2066 if( i > 0 && strcmp(varname, debugsoldata->solnames[i-1]) == 0 )
2067 {
2068 if( REALABS(debugsoldata->solvals[i-1] - val) > 1e-9 )
2069 {
2070 SCIPerrorMessage("already have stored different debugging solution value (%g) for variable <%s>, cannot store %g\n", debugsoldata->solvals[i-1], varname, val);
2071 return SCIP_ERROR;
2072 }
2073 else
2074 {
2075 SCIPdebugMsg(scip, "already have stored debugging solution value %g for variable <%s>, do not store same value again\n", val, varname);
2076 for( ; i < debugsoldata->nsolvals; ++i )
2077 {
2078 debugsoldata->solnames[i] = debugsoldata->solnames[i+1];
2079 debugsoldata->solvals[i] = debugsoldata->solvals[i+1];
2080 }
2081 return SCIP_OKAY;
2082 }
2083 }
2084
2085 /* insert new solution value */
2086 SCIP_ALLOC( BMSduplicateMemoryArray(&(debugsoldata->solnames[i]), varname, strlen(varname)+1) );
2087 SCIPdebugMsg(scip, "add variable <%s>: value <%g>\n", debugsoldata->solnames[i], val);
2088 debugsoldata->solvals[i] = val;
2089 debugsoldata->nsolvals++;
2090
2091 /* update objective function value of debug solution */
2092 debugsoldata->debugsolval += debugsoldata->solvals[i] * SCIPvarGetObj(var);
2093 SCIPdebugMsg(scip, "Debug Solution value is now %g.\n", debugsoldata->debugsolval);
2094
2096 {
2097 /* add values to SCIP debug solution */
2098 SCIP_CALL( SCIPsetSolVal(scip, debugsoldata->debugsol, var, debugsoldata->solvals[i] ) );
2099 }
2100
2101 /* get solution value once to produce warning if solution was cut off */
2102 SCIPdebugGetSolVal(scip, var, &testval);
2103
2104 return SCIP_OKAY;
2105}
2106
2107#else
2108
2109/** this is a dummy method to make the SunOS gcc linker happy */
2110extern void SCIPdummyDebugMethodForSun(void);
2112{
2113 return;
2114}
2115
2116#endif
2117
2118
2119/*
2120 * debug method for LP interface, to check if the LP interface works correct
2121 */
2122#ifdef SCIP_DEBUG_LP_INTERFACE
2123
2124/* check whether coef is the r-th row of the inverse basis matrix B^-1; this is
2125 * the case if( coef * B ) is the r-th unit vector */
2127 SCIP* scip, /**< SCIP data structure */
2128 int r, /**< row number */
2129 SCIP_Real* coef /**< r-th row of the inverse basis matrix */
2130 )
2131{
2132 SCIP_Real vecval;
2133 SCIP_Real matrixval;
2134 int* basisind;
2135 int nrows;
2136 int idx;
2137 int i;
2138 int k;
2139
2140 assert(scip != NULL);
2141
2142 nrows = SCIPgetNLPRows(scip);
2143
2144 /* get basic indices for the basic matrix B */
2145 SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
2146 SCIP_CALL( SCIPgetLPBasisInd(scip, basisind) );
2147
2148 /* loop over the columns of B */
2149 for( k = 0; k < nrows; ++k )
2150 {
2151 vecval = 0.0;
2152
2153 /* indices of basic columns and rows:
2154 * - index i >= 0 corresponds to column i,
2155 * - index i < 0 to row -i-1
2156 */
2157 idx = basisind[k];
2158
2159 /* check if we have a slack variable; this is the case if idx < 0 */
2160 if( idx >= 0 )
2161 {
2162 /* loop over the rows to compute the corresponding value in the unit vector */
2163 for( i = 0; i < nrows; ++i )
2164 {
2165 SCIP_CALL( SCIPlpiGetCoef(scip->lp->lpi, i, idx, &matrixval) );
2166 vecval += coef[i] * matrixval;
2167 }
2168 }
2169 else
2170 {
2171 assert( idx < 0 );
2172
2173 /* retransform idx
2174 * - index i >= 0 corresponds to column i,
2175 * - index i < 0 to row -i-1
2176 */
2177 idx = -idx - 1;
2178 assert( idx >= 0 && idx < nrows );
2179
2180 /* since idx < 0 we are in the case of a slack variable, i.e., the corresponding column
2181 is the idx-unit vector; note that some LP solver return a -idx-unit vector */
2182 /* vecval = REALABS(coef[idx]);*/
2183 vecval = coef[idx];
2184 }
2185
2186 /* check if vecval fits to the r-th unit vector */
2187 if( k == r && !SCIPisFeasEQ(scip, vecval, 1.0) )
2188 {
2189 /* we expected a 1.0 and found something different */
2190 SCIPmessagePrintWarning(SCIPgetMessagehdlr(scip), "checked SCIPgetLPBInvRow() found value <%g> expected 1.0\n", vecval);
2191 }
2192 else if( k != r && !SCIPisFeasZero(scip, vecval) )
2193 {
2194 /* we expected a 0.0 and found something different */
2195 SCIPmessagePrintWarning(SCIPgetMessagehdlr(scip), "checked SCIPgetLPBInvRow() found value <%g> expected 0.0\n", vecval);
2196 }
2197 }
2198
2199 SCIPfreeBufferArray(scip, &basisind);
2200
2201 return SCIP_OKAY;
2202}
2203
2204#endif
2205
2206/** checks, if SCIP is in one of the feasible stages */
2207#ifndef NDEBUG
2209 SCIP* scip, /**< SCIP data structure */
2210 const char* method, /**< method that was called */
2211 SCIP_Bool init, /**< may method be called in the INIT stage? */
2212 SCIP_Bool problem, /**< may method be called in the PROBLEM stage? */
2213 SCIP_Bool transforming, /**< may method be called in the TRANSFORMING stage? */
2214 SCIP_Bool transformed, /**< may method be called in the TRANSFORMED stage? */
2215 SCIP_Bool initpresolve, /**< may method be called in the INITPRESOLVE stage? */
2216 SCIP_Bool presolving, /**< may method be called in the PRESOLVING stage? */
2217 SCIP_Bool exitpresolve, /**< may method be called in the EXITPRESOLE stage? */
2218 SCIP_Bool presolved, /**< may method be called in the PRESOLVED stage? */
2219 SCIP_Bool initsolve, /**< may method be called in the INITSOLVE stage? */
2220 SCIP_Bool solving, /**< may method be called in the SOLVING stage? */
2221 SCIP_Bool solved, /**< may method be called in the SOLVED stage? */
2222 SCIP_Bool exitsolve, /**< may method be called in the EXITSOLVE stage? */
2223 SCIP_Bool freetrans, /**< may method be called in the FREETRANS stage? */
2224 SCIP_Bool freescip /**< may method be called in the FREE stage? */
2225 )
2226{
2227 assert(scip != NULL);
2228 assert(method != NULL);
2229
2230 /*SCIPdebugMsg(scip, "called method <%s> at stage %d ------------------------------------------------\n",
2231 method, scip->set->stage);*/
2232
2233 assert(scip->mem != NULL);
2234 assert(scip->set != NULL);
2235 assert(scip->interrupt != NULL);
2236 assert(scip->dialoghdlr != NULL);
2237 assert(scip->totaltime != NULL);
2238
2239 switch( scip->set->stage )
2240 {
2241 case SCIP_STAGE_INIT:
2242 assert(scip->stat == NULL);
2243 assert(scip->origprob == NULL);
2244 assert(scip->eventfilter == NULL);
2245 assert(scip->eventqueue == NULL);
2246 assert(scip->branchcand == NULL);
2247 assert(scip->lp == NULL);
2248 assert(scip->nlp == NULL);
2249 assert(scip->primal == NULL);
2250 assert(scip->tree == NULL);
2251 assert(scip->conflict == NULL);
2252 assert(scip->transprob == NULL);
2253 assert(scip->pricestore == NULL);
2254 assert(scip->sepastore == NULL);
2255 assert(scip->cutpool == NULL);
2256 assert(scip->delayedcutpool == NULL);
2257
2258 if( !init )
2259 {
2260 SCIPerrorMessage("cannot call method <%s> in initialization stage\n", method);
2261 return SCIP_INVALIDCALL;
2262 }
2263 return SCIP_OKAY;
2264
2265 case SCIP_STAGE_PROBLEM:
2266 assert(scip->stat != NULL);
2267 assert(scip->origprob != NULL);
2268 assert(scip->eventfilter == NULL);
2269 assert(scip->eventqueue == NULL);
2270 assert(scip->branchcand == NULL);
2271 assert(scip->lp == NULL);
2272 assert(scip->nlp == NULL);
2273 assert(scip->primal == NULL);
2274 assert(scip->tree == NULL);
2275 assert(scip->conflict == NULL);
2276 assert(scip->transprob == NULL);
2277 assert(scip->pricestore == NULL);
2278 assert(scip->sepastore == NULL);
2279 assert(scip->cutpool == NULL);
2280 assert(scip->delayedcutpool == NULL);
2281
2282 if( !problem )
2283 {
2284 SCIPerrorMessage("cannot call method <%s> in problem creation stage\n", method);
2285 return SCIP_INVALIDCALL;
2286 }
2287 return SCIP_OKAY;
2288
2290 assert(scip->stat != NULL);
2291 assert(scip->origprob != NULL);
2292 assert(scip->eventfilter != NULL);
2293 assert(scip->eventqueue != NULL);
2294 assert(scip->branchcand != NULL);
2295 assert(scip->lp != NULL);
2296 assert(scip->primal != NULL);
2297 assert(scip->tree != NULL);
2298 assert(scip->conflict != NULL);
2299 assert(scip->transprob != NULL);
2300 assert(scip->pricestore == NULL);
2301 assert(scip->sepastore == NULL);
2302 assert(scip->cutpool == NULL);
2303 assert(scip->delayedcutpool == NULL);
2304
2305 if( !transforming )
2306 {
2307 SCIPerrorMessage("cannot call method <%s> in problem transformation stage\n", method);
2308 return SCIP_INVALIDCALL;
2309 }
2310 return SCIP_OKAY;
2311
2313 assert(scip->stat != NULL);
2314 assert(scip->origprob != NULL);
2315 assert(scip->eventfilter != NULL);
2316 assert(scip->eventqueue != NULL);
2317 assert(scip->branchcand != NULL);
2318 assert(scip->lp != NULL);
2319 assert(scip->primal != NULL);
2320 assert(scip->tree != NULL);
2321 assert(scip->conflict != NULL);
2322 assert(scip->transprob != NULL);
2323 assert(scip->pricestore == NULL);
2324 assert(scip->sepastore == NULL);
2325 assert(scip->cutpool == NULL);
2326 assert(scip->delayedcutpool == NULL);
2327
2328 if( !transformed )
2329 {
2330 SCIPerrorMessage("cannot call method <%s> in problem transformed stage\n", method);
2331 return SCIP_INVALIDCALL;
2332 }
2333 return SCIP_OKAY;
2334
2336 assert(scip->stat != NULL);
2337 assert(scip->origprob != NULL);
2338 assert(scip->eventfilter != NULL);
2339 assert(scip->eventqueue != NULL);
2340 assert(scip->branchcand != NULL);
2341 assert(scip->lp != NULL);
2342 assert(scip->primal != NULL);
2343 assert(scip->tree != NULL);
2344 assert(scip->conflict != NULL);
2345 assert(scip->transprob != NULL);
2346 assert(scip->pricestore == NULL);
2347 assert(scip->sepastore == NULL);
2348 assert(scip->cutpool == NULL);
2349 assert(scip->delayedcutpool == NULL);
2350
2351 if( !initpresolve )
2352 {
2353 SCIPerrorMessage("cannot call method <%s> in init presolving stage\n", method);
2354 return SCIP_INVALIDCALL;
2355 }
2356 return SCIP_OKAY;
2357
2359 assert(scip->stat != NULL);
2360 assert(scip->origprob != NULL);
2361 assert(scip->eventfilter != NULL);
2362 assert(scip->eventqueue != NULL);
2363 assert(scip->branchcand != NULL);
2364 assert(scip->lp != NULL);
2365 assert(scip->primal != NULL);
2366 assert(scip->tree != NULL);
2367 assert(scip->conflict != NULL);
2368 assert(scip->transprob != NULL);
2369 assert(scip->pricestore == NULL);
2370 assert(scip->sepastore == NULL);
2371 assert(scip->cutpool == NULL);
2372 assert(scip->delayedcutpool == NULL);
2373
2374 if( !presolving )
2375 {
2376 SCIPerrorMessage("cannot call method <%s> in presolving stage\n", method);
2377 return SCIP_INVALIDCALL;
2378 }
2379 return SCIP_OKAY;
2380
2382 assert(scip->stat != NULL);
2383 assert(scip->origprob != NULL);
2384 assert(scip->eventfilter != NULL);
2385 assert(scip->eventqueue != NULL);
2386 assert(scip->branchcand != NULL);
2387 assert(scip->lp != NULL);
2388 assert(scip->primal != NULL);
2389 assert(scip->tree != NULL);
2390 assert(scip->conflict != NULL);
2391 assert(scip->transprob != NULL);
2392 assert(scip->pricestore == NULL);
2393 assert(scip->sepastore == NULL);
2394 assert(scip->cutpool == NULL);
2395 assert(scip->delayedcutpool == NULL);
2396
2397 if( !exitpresolve )
2398 {
2399 SCIPerrorMessage("cannot call method <%s> in exit presolving stage\n", method);
2400 return SCIP_INVALIDCALL;
2401 }
2402 return SCIP_OKAY;
2403
2405 assert(scip->stat != NULL);
2406 assert(scip->origprob != NULL);
2407 assert(scip->eventfilter != NULL);
2408 assert(scip->eventqueue != NULL);
2409 assert(scip->branchcand != NULL);
2410 assert(scip->lp != NULL);
2411 assert(scip->primal != NULL);
2412 assert(scip->tree != NULL);
2413 assert(scip->conflict != NULL);
2414 assert(scip->transprob != NULL);
2415 assert(scip->pricestore == NULL);
2416 assert(scip->sepastore == NULL);
2417 assert(scip->cutpool == NULL);
2418 assert(scip->delayedcutpool == NULL);
2419
2420 if( !presolved )
2421 {
2422 SCIPerrorMessage("cannot call method <%s> in problem presolved stage\n", method);
2423 return SCIP_INVALIDCALL;
2424 }
2425 return SCIP_OKAY;
2426
2428 assert(scip->stat != NULL);
2429 assert(scip->origprob != NULL);
2430 assert(scip->eventfilter != NULL);
2431 assert(scip->eventqueue != NULL);
2432 assert(scip->branchcand != NULL);
2433 assert(scip->lp != NULL);
2434 assert(scip->primal != NULL);
2435 assert(scip->tree != NULL);
2436 assert(scip->transprob != NULL);
2437
2438 if( !initsolve )
2439 {
2440 SCIPerrorMessage("cannot call method <%s> in init solve stage\n", method);
2441 return SCIP_INVALIDCALL;
2442 }
2443 return SCIP_OKAY;
2444
2445 case SCIP_STAGE_SOLVING:
2446 assert(scip->stat != NULL);
2447 assert(scip->origprob != NULL);
2448 assert(scip->eventfilter != NULL);
2449 assert(scip->eventqueue != NULL);
2450 assert(scip->branchcand != NULL);
2451 assert(scip->lp != NULL);
2452 assert(scip->primal != NULL);
2453 assert(scip->tree != NULL);
2454 assert(scip->conflict != NULL);
2455 assert(scip->transprob != NULL);
2456 assert(scip->pricestore != NULL);
2457 assert(scip->sepastore != NULL);
2458 assert(scip->cutpool != NULL);
2459 assert(scip->delayedcutpool != NULL);
2460
2461 if( !solving )
2462 {
2463 SCIPerrorMessage("cannot call method <%s> in solving stage\n", method);
2464 return SCIP_INVALIDCALL;
2465 }
2466 return SCIP_OKAY;
2467
2468 case SCIP_STAGE_SOLVED:
2469 assert(scip->stat != NULL);
2470 assert(scip->origprob != NULL);
2471 assert(scip->eventfilter != NULL);
2472 assert(scip->eventqueue != NULL);
2473 assert(scip->branchcand != NULL);
2474 assert(scip->lp != NULL);
2475 assert(scip->primal != NULL);
2476 assert(scip->tree != NULL);
2477 assert(scip->conflict != NULL);
2478 assert(scip->transprob != NULL);
2479 assert(scip->pricestore != NULL);
2480 assert(scip->sepastore != NULL);
2481 assert(scip->cutpool != NULL);
2482 assert(scip->delayedcutpool != NULL);
2483
2484 if( !solved )
2485 {
2486 SCIPerrorMessage("cannot call method <%s> in problem solved stage\n", method);
2487 return SCIP_INVALIDCALL;
2488 }
2489 return SCIP_OKAY;
2490
2492 assert(scip->stat != NULL);
2493 assert(scip->origprob != NULL);
2494 assert(scip->eventfilter != NULL);
2495 assert(scip->eventqueue != NULL);
2496 assert(scip->branchcand != NULL);
2497 assert(scip->lp != NULL);
2498 assert(scip->primal != NULL);
2499 assert(scip->tree != NULL);
2500 assert(scip->transprob != NULL);
2501
2502 if( !exitsolve )
2503 {
2504 SCIPerrorMessage("cannot call method <%s> in solve deinitialization stage\n", method);
2505 return SCIP_INVALIDCALL;
2506 }
2507 return SCIP_OKAY;
2508
2510 assert(scip->stat != NULL);
2511 assert(scip->origprob != NULL);
2512 assert(scip->pricestore == NULL);
2513 assert(scip->sepastore == NULL);
2514 assert(scip->cutpool == NULL);
2515 assert(scip->delayedcutpool == NULL);
2516
2517 if( !freetrans )
2518 {
2519 SCIPerrorMessage("cannot call method <%s> in free transformed problem stage\n", method);
2520 return SCIP_INVALIDCALL;
2521 }
2522 return SCIP_OKAY;
2523
2524 case SCIP_STAGE_FREE:
2525 if( !freescip )
2526 {
2527 SCIPerrorMessage("cannot call method <%s> in free stage\n", method);
2528 return SCIP_INVALIDCALL;
2529 }
2530 return SCIP_OKAY;
2531
2532 default:
2533 /* note that this is in an internal SCIP error since all SCIP stages are covert in the switch above */
2534 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2535 return SCIP_ERROR;
2536 }
2537}
2538#endif
SCIP_Real * r
Definition: circlepacking.c:59
SCIP_RETCODE SCIPcheckStage(SCIP *scip, const char *method, SCIP_Bool init, SCIP_Bool problem, SCIP_Bool transforming, SCIP_Bool transformed, SCIP_Bool initpresolve, SCIP_Bool presolving, SCIP_Bool exitpresolve, SCIP_Bool presolved, SCIP_Bool initsolve, SCIP_Bool solving, SCIP_Bool solved, SCIP_Bool exitsolve, SCIP_Bool freetrans, SCIP_Bool freescip)
Definition: debug.c:2208
void SCIPdummyDebugMethodForSun(void)
Definition: debug.c:2111
methods for debugging
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:285
#define SCIPdebugCheckClique(set, vars, values, nvars)
Definition: debug.h:294
#define SCIPdebugFree(set)
Definition: debug.h:282
struct SCIP_DebugSolData SCIP_DEBUGSOLDATA
Definition: debug.h:59
#define SCIPdebugCheckRow(set, row)
Definition: debug.h:284
#define SCIPdebugSolDisable(scip)
Definition: debug.h:302
#define SCIPdebugCheckConflict(blkmem, set, node, bdchginfos, relaxedbds, nliterals)
Definition: debug.h:295
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:292
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:299
#define SCIPdebugFreeSol(set)
Definition: debug.h:279
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:286
#define SCIPdebugSolEnable(scip)
Definition: debug.h:301
#define SCIPdebugCheckGlobalLowerbound(blkmem, set)
Definition: debug.h:289
#define SCIPdebugCheckLocalLowerbound(blkmem, set, node)
Definition: debug.h:290
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:298
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition: debug.h:291
#define SCIPdebugCheckConss(scip, conss, nconss)
Definition: debug.h:283
#define SCIPdebugFreeDebugData(set)
Definition: debug.h:281
#define SCIPdebugSolIsEnabled(scip)
Definition: debug.h:303
#define SCIPdebugCheckAggregation(set, var, aggrvars, scalars, constant, naggrvars)
Definition: debug.h:293
#define SCIPdebugCheckBInvRow(scip, r, coef)
Definition: debug.h:324
#define SCIPdebugRemoveNode(blkmem, set, node)
Definition: debug.h:288
#define SCIPdebugSolIsValidInSubtree(scip, isvalidinsubtree)
Definition: debug.h:300
#define SCIPdebugReset(set)
Definition: debug.h:280
#define SCIPdebugCheckConflictFrontier(blkmem, set, node, bdchginfo, bdchginfos, relaxedbds, nliterals, bdchgqueue, forcedbdchgqueue)
Definition: debug.h:296
#define SCIPdebugIncludeProp(scip)
Definition: debug.h:297
#define SCIPdebugCheckInference(blkmem, set, node, var, newbound, boundtype)
Definition: debug.h:287
#define SCIPwithDebugSol(void)
Definition: debug.h:304
#define SCIPdebugSolDataCreate(debugsoldata)
Definition: debug.h:278
common defines and data types used in all packages of SCIP
#define NULL
Definition: def.h:266
#define SCIP_MAXSTRLEN
Definition: def.h:287
#define SCIP_Bool
Definition: def.h:91
#define SCIP_ALLOC(x)
Definition: def.h:384
#define SCIP_Real
Definition: def.h:172
#define SCIP_UNKNOWN
Definition: def.h:193
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define SCIPABORT()
Definition: def.h:345
#define REALABS(x)
Definition: def.h:196
#define SCIP_CALL(x)
Definition: def.h:373
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:153
int SCIPfeof(SCIP_FILE *stream)
Definition: fileio.c:227
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:232
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:200
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip_general.c:508
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:390
SCIP_VAR ** SCIPgetOrigVars(SCIP *scip)
Definition: scip_prob.c:2405
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip_prob.c:2432
SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
Definition: scip_prob.c:1225
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip_prob.c:2685
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3111
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3264
SCIP_RETCODE SCIPhashmapSetImage(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3326
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3077
SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
Definition: misc.c:3636
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3442
SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
Definition: lpi_clp.cpp:1771
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:88
#define SCIPdebugMsg
Definition: scip_message.h:78
void ** SCIPpqueueElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1541
int SCIPpqueueNElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1530
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17042
SCIP_RETCODE SCIPcheckCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_RESULT *result)
Definition: scip_cons.c:2136
int SCIPconsGetActiveDepth(SCIP_CONS *cons)
Definition: cons.c:8264
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8275
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8453
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8214
SCIP_RETCODE SCIPgetLPBasisInd(SCIP *scip, int *basisind)
Definition: scip_lp.c:686
int SCIPgetNLPRows(SCIP *scip)
Definition: scip_lp.c:626
SCIP_Real SCIPgetLPFeastol(SCIP *scip)
Definition: scip_lp.c:428
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:7500
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7530
int SCIPnodeGetNAddedConss(SCIP_NODE *node)
Definition: tree.c:1730
void SCIPnodeGetAddedConss(SCIP_NODE *node, SCIP_CONS **addedconss, int *naddedconss, int addedconsssize)
Definition: tree.c:1700
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7520
SCIP_RETCODE SCIPincludeProp(SCIP *scip, const char *name, const char *desc, int priority, int freq, SCIP_Bool delay, SCIP_PROPTIMING timingmask, int presolpriority, int presolmaxrounds, SCIP_PRESOLTIMING presoltiming, SCIP_DECL_PROPCOPY((*propcopy)), SCIP_DECL_PROPFREE((*propfree)), SCIP_DECL_PROPINIT((*propinit)), SCIP_DECL_PROPEXIT((*propexit)), SCIP_DECL_PROPINITPRE((*propinitpre)), SCIP_DECL_PROPEXITPRE((*propexitpre)), SCIP_DECL_PROPINITSOL((*propinitsol)), SCIP_DECL_PROPEXITSOL((*propexitsol)), SCIP_DECL_PROPPRESOL((*proppresol)), SCIP_DECL_PROPEXEC((*propexec)), SCIP_DECL_PROPRESPROP((*propresprop)), SCIP_PROPDATA *propdata)
Definition: scip_prop.c:62
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17292
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:17213
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17238
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17302
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:17401
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17351
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17258
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17248
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2165
SCIP_Real SCIPsolGetOrigObj(SCIP_SOL *sol)
Definition: sol.c:2741
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:837
SCIP_RETCODE SCIPcreateOrigSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:417
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_sol.c:1115
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1296
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip_sol.c:1073
SCIP_Bool SCIPisInRestart(SCIP *scip)
Definition: scip_solve.c:3597
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
int SCIPgetNLeaves(SCIP *scip)
Definition: scip_tree.c:272
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip_tree.c:91
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12773
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17639
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17914
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17598
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17345
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17537
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17335
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17560
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17925
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17583
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18087
int SCIPvarGetNUses(SCIP_VAR *var)
Definition: var.c:17428
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17418
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18679
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12860
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17573
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17705
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17903
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18077
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8399
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18699
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18669
void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
void SCIPprintSysError(const char *message)
Definition: misc.c:10772
int SCIPstrncasecmp(const char *s1, const char *s2, int length)
Definition: misc.c:10929
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17847
void SCIProwPrint(SCIP_ROW *row, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: lp.c:5299
static const SCIP_Real scalars[]
Definition: lp.c:5743
internal methods for LP management
memory allocation routines
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:127
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:143
#define BMSfreeMemoryNull(ptr)
Definition: memory.h:146
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:123
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:147
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:148
#define BMSallocMemory(ptr)
Definition: memory.h:118
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:427
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
SCIP_Real SCIPprobExternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:2157
internal methods for storing and manipulating the main problem
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:43
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
public data structures and miscellaneous methods
SCIP callable library.
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6293
SCIP_Bool SCIPsetIsRelEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:7076
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6663
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6641
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6597
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6257
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6707
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2952
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6619
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6064
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6239
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6275
SCIP_DEBUGSOLDATA * SCIPsetGetDebugSolData(SCIP_SET *set)
Definition: set.c:5956
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6685
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1755
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1748
#define SCIPsetDebugMsg
Definition: set.h:1784
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:134
unsigned int nboundchgs
Definition: struct_var.h:132
SCIP_DOMCHG * domchg
Definition: struct_tree.h:159
SCIP_Longint number
Definition: struct_tree.h:143
SCIP_NODE * parent
Definition: struct_tree.h:157
SCIP main data structure.
Definition: heur_padm.c:135
SCIP_Bool SCIPtreeProbing(SCIP_TREE *tree)
Definition: tree.c:8384
SCIP_Real SCIPtreeGetLowerbound(SCIP_TREE *tree, SCIP_SET *set)
Definition: tree.c:7323
internal methods for branch and bound tree
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:57
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:56
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
@ SCIP_VERBLEVEL_NORMAL
Definition: type_message.h:55
#define SCIP_DECL_SORTPTRCOMP(x)
Definition: type_misc.h:188
@ SCIP_OBJSENSE_MAXIMIZE
Definition: type_prob.h:47
@ SCIP_OBJSENSE_MINIMIZE
Definition: type_prob.h:48
#define SCIP_DECL_PROPEXEC(x)
Definition: type_prop.h:217
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_FEASIBLE
Definition: type_result.h:45
@ SCIP_REDUCEDDOM
Definition: type_result.h:51
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_NOFILE
Definition: type_retcode.h:47
@ SCIP_READERROR
Definition: type_retcode.h:45
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_INVALIDCALL
Definition: type_retcode.h:51
@ SCIP_ERROR
Definition: type_retcode.h:43
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PROBLEM
Definition: type_set.h:45
@ SCIP_STAGE_INITPRESOLVE
Definition: type_set.h:48
@ SCIP_STAGE_SOLVED
Definition: type_set.h:54
@ SCIP_STAGE_PRESOLVING
Definition: type_set.h:49
@ SCIP_STAGE_TRANSFORMED
Definition: type_set.h:47
@ SCIP_STAGE_INITSOLVE
Definition: type_set.h:52
@ SCIP_STAGE_EXITPRESOLVE
Definition: type_set.h:50
@ SCIP_STAGE_EXITSOLVE
Definition: type_set.h:55
@ SCIP_STAGE_INIT
Definition: type_set.h:44
@ SCIP_STAGE_FREE
Definition: type_set.h:57
@ SCIP_STAGE_FREETRANS
Definition: type_set.h:56
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition: type_set.h:46
@ SCIP_STAGE_PRESOLVED
Definition: type_set.h:51
enum SCIP_Stage SCIP_STAGE
Definition: type_set.h:59
@ SCIP_STATUS_UNBOUNDED
Definition: type_stat.h:63
@ SCIP_STATUS_INFORUNBD
Definition: type_stat.h:64
#define SCIP_PRESOLTIMING_FAST
Definition: type_timing.h:52
#define SCIP_PROPTIMING_ALWAYS
Definition: type_timing.h:72
@ SCIP_NODETYPE_PROBINGNODE
Definition: type_tree.h:42
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:62
@ SCIP_BOUNDCHGTYPE_BRANCHING
Definition: type_var.h:87
@ SCIP_VARSTATUS_ORIGINAL
Definition: type_var.h:49
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:162
internal methods for problem variables