1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2021 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /**@file scip_general.c
17 * @ingroup OTHER_CFILES
18 * @brief general public methods
19 * @author Tobias Achterberg
20 * @author Timo Berthold
21 * @author Gerald Gamrath
22 * @author Leona Gottwald
23 * @author Stefan Heinz
24 * @author Gregor Hendel
25 * @author Thorsten Koch
26 * @author Alexander Martin
27 * @author Marc Pfetsch
28 * @author Michael Winkler
29 * @author Kati Wolter
30 *
31 * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE
32 */
33
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35
36 #include "blockmemshell/memory.h"
37 #include "lpi/lpi.h"
38 #include "scip/exprinterpret.h"
39 #include "scip/clock.h"
40 #include "scip/debug.h"
41 #include "scip/dialog.h"
42 #include "scip/interrupt.h"
43 #include "scip/mem.h"
44 #include "scip/message_default.h"
45 #include "scip/nlp.h"
46 #include "scip/pub_message.h"
47 #include "scip/retcode.h"
48 #include "scip/scipbuildflags.h"
49 #include "scip/scipcoreplugins.h"
50 #include "scip/scip_general.h"
51 #include "scip/scipgithash.h"
52 #include "scip/scip_mem.h"
53 #include "scip/scip_message.h"
54 #include "scip/scip_numerics.h"
55 #include "scip/scip_prob.h"
56 #include "scip/scip_solvingstats.h"
57 #include "scip/set.h"
58 #include "scip/solve.h"
59 #include "scip/struct_mem.h"
60 #include "scip/struct_primal.h"
61 #include "scip/struct_prob.h"
62 #include "scip/struct_scip.h"
63 #include "scip/struct_set.h"
64 #include "scip/struct_stat.h"
65 #include "scip/syncstore.h"
66
67 #include <string.h>
68 #if defined(_WIN32) || defined(_WIN64)
69 #else
70 #include <strings.h> /*lint --e{766}*/
71 #endif
72
73 #ifdef SCIP_WITH_ZLIB
74 #include <zlib.h>
75 #endif
76
77 /* In debug mode, the following methods are implemented as function calls to ensure
78 * type validity.
79 * In optimized mode, the methods are implemented as defines to improve performance.
80 * However, we want to have them in the library anyways, so we have to undef the defines.
81 */
82
83 #undef SCIPgetStage
84 #undef SCIPhasPerformedPresolve
85 #undef SCIPisStopped
86
87 /** returns complete SCIP version number in the format "major . minor tech"
88 *
89 * @return complete SCIP version
90 */
91 SCIP_Real SCIPversion(
92 void
93 )
94 {
95 return (SCIP_Real)(SCIP_VERSION)/100.0;
96 }
97
98 /** returns SCIP major version
99 *
100 * @return major SCIP version
101 */
102 int SCIPmajorVersion(
103 void
104 )
105 {
106 return SCIP_VERSION/100;
107 }
108
109 /** returns SCIP minor version
110 *
111 * @return minor SCIP version
112 */
113 int SCIPminorVersion(
114 void
115 )
116 {
117 return (SCIP_VERSION/10) % 10; /*lint !e778*/
118 }
119
120 /** returns SCIP technical version
121 *
122 * @return technical SCIP version
123 */
124 int SCIPtechVersion(
125 void
126 )
127 {
128 return SCIP_VERSION % 10; /*lint !e778*/
129 }
130
131 /** returns SCIP sub version number
132 *
133 * @return subversion SCIP version
134 */
135 int SCIPsubversion(
136 void
137 )
138 {
139 return SCIP_SUBVERSION;
140 }
141
142 /** prints a version information line to a file stream via the message handler system
143 *
144 * @note If the message handler is set to a NULL pointer nothing will be printed
145 */
146 void SCIPprintVersion(
147 SCIP* scip, /**< SCIP data structure */
148 FILE* file /**< output file (or NULL for standard output) */
149 )
150 {
151 assert( scip != NULL );
152
153 SCIPmessageFPrintInfo(scip->messagehdlr, file, "SCIP version %d.%d.%d",
154 SCIPmajorVersion(), SCIPminorVersion(), SCIPtechVersion());
155 #if SCIP_SUBVERSION > 0
156 SCIPmessageFPrintInfo(scip->messagehdlr, file, ".%d", SCIPsubversion());
157 #endif
158
159 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [precision: %d byte]", (int)sizeof(SCIP_Real));
160
161 #ifndef BMS_NOBLOCKMEM
162 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [memory: block]");
163 #else
164 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [memory: standard]");
165 #endif
166 #ifndef NDEBUG
167 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [mode: debug]");
168 #else
169 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [mode: optimized]");
170 #endif
171 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [LP solver: %s]", SCIPlpiGetSolverName());
172 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [GitHash: %s]", SCIPgetGitHash());
173 SCIPmessageFPrintInfo(scip->messagehdlr, file, "\n");
174 SCIPmessageFPrintInfo(scip->messagehdlr, file, "%s\n", SCIP_COPYRIGHT);
175 }
176
177 /** prints detailed information on the compile-time flags
178 *
179 * @note If the message handler is set to a NULL pointer nothing will be printed
180 */
181 void SCIPprintBuildOptions(
182 SCIP* scip, /**< SCIP data structure */
183 FILE* file /**< output file (or NULL for standard output) */
184 )
185 {
186 assert( scip != NULL );
187
188 /* compiler */
189 SCIPmessageFPrintInfo(scip->messagehdlr, file, "Compiler: ");
190 #if defined(__INTEL_COMPILER)
191 SCIPmessageFPrintInfo(scip->messagehdlr, file, "Intel %d\n", __INTEL_COMPILER);
192 #elif defined(__clang__)
193 SCIPmessageFPrintInfo(scip->messagehdlr, file, "clang %d.%d.%d\n", __clang_major__, __clang_minor__, __clang_patchlevel__);
194 #elif defined(_MSC_VER)
195 SCIPmessageFPrintInfo(scip->messagehdlr, file, "microsoft visual c %d\n", _MSC_FULL_VER);
196 #elif defined(__GNUC__)
197 #if defined(__GNUC_PATCHLEVEL__)
198 SCIPmessageFPrintInfo(scip->messagehdlr, file, "gcc %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
199 #else
200 SCIPmessageFPrintInfo(scip->messagehdlr, file, "gcc %d.%d\n", __GNUC__, __GNUC_MINOR__);
201 #endif
202 #else
203 SCIPmessageFPrintInfo(scip->messagehdlr, file, "unknown\n");
204 #endif
205
206 /* build flags */
207 SCIPmessageFPrintInfo(scip->messagehdlr, file, "\nBuild options:\n%s", SCIPgetBuildFlags());
208 }
209
210 /** prints error message for the given SCIP_RETCODE via the error prints method */
211 void SCIPprintError(
212 SCIP_RETCODE retcode /**< SCIP return code causing the error */
213 )
214 {
215 SCIPmessagePrintError("SCIP Error (%d): ", retcode);
216 SCIPretcodePrintError(retcode);
217 SCIPmessagePrintError("\n");
218 }
219
220 /*
221 * general SCIP methods
222 */
223
224 /** internal method to create SCIP */
225 static
226 SCIP_RETCODE doScipCreate(
227 SCIP** scip /**< pointer to SCIP data structure */
228 )
229 {
230 assert(scip != NULL);
231
232 SCIP_ALLOC( BMSallocMemory(scip) );
233
234 /* all members are initialized to NULL */
235 BMSclearMemory(*scip);
236
237 /* create a default message handler */
238 SCIP_CALL( SCIPcreateMessagehdlrDefault(&(*scip)->messagehdlr, TRUE, NULL, FALSE) );
239
240 SCIP_CALL( SCIPmemCreate(&(*scip)->mem) );
241 SCIP_CALL( SCIPsetCreate(&(*scip)->set, (*scip)->messagehdlr, (*scip)->mem->setmem, *scip) );
242 SCIP_CALL( SCIPinterruptCreate(&(*scip)->interrupt) );
243 SCIP_CALL( SCIPdialoghdlrCreate((*scip)->set, &(*scip)->dialoghdlr) );
244 SCIP_CALL( SCIPclockCreate(&(*scip)->totaltime, SCIP_CLOCKTYPE_DEFAULT) );
245 SCIP_CALL( SCIPsyncstoreCreate( &(*scip)->syncstore ) );
246
247 /* include additional core functionality */
248 SCIP_CALL( SCIPincludeCorePlugins(*scip) );
249
250 SCIPclockStart((*scip)->totaltime, (*scip)->set);
251
252 SCIP_CALL( SCIPnlpInclude((*scip)->set, SCIPblkmem(*scip)) );
253
254 if( strcmp(SCIPlpiGetSolverName(), "NONE") != 0 )
255 {
256 SCIP_CALL( SCIPsetIncludeExternalCode((*scip)->set, SCIPlpiGetSolverName(), SCIPlpiGetSolverDesc()) );
257 }
258 if( strcmp(SCIPexprintGetName(), "NONE") != 0 )
259 {
260 SCIP_CALL( SCIPsetIncludeExternalCode((*scip)->set, SCIPexprintGetName(), SCIPexprintGetDesc()) );
261 }
262
263 #ifdef SCIP_WITH_ZLIB
264 SCIP_CALL( SCIPsetIncludeExternalCode((*scip)->set, "ZLIB " ZLIB_VERSION, "General purpose compression library by J. Gailly and M. Adler (zlib.net)") );
265 #endif
266
267 return SCIP_OKAY;
268 }
269
270 /** creates and initializes SCIP data structures
271 *
272 * @note The SCIP default message handler is installed. Use the method SCIPsetMessagehdlr() to install your own
273 * message handler or SCIPsetMessagehdlrLogfile() and SCIPsetMessagehdlrQuiet() to write into a log
274 * file and turn off/on the display output, respectively.
275 *
276 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
277 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
278 *
279 * @post After calling this method \SCIP reached the solving stage \ref SCIP_STAGE_INIT
280 *
281 * See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
282 */
283 SCIP_RETCODE SCIPcreate(
284 SCIP** scip /**< pointer to SCIP data structure */
285 )
286 {
287 assert(scip != NULL);
288
289 SCIP_CALL_FINALLY( doScipCreate(scip), (void)SCIPfree(scip) );
290
291 return SCIP_OKAY;
292 }
293
294 /** frees SCIP data structures
295 *
296 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
297 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
298 *
299 * @pre This method can be called if @p scip is in one of the following stages:
300 * - \ref SCIP_STAGE_INIT
301 * - \ref SCIP_STAGE_PROBLEM
302 * - \ref SCIP_STAGE_TRANSFORMED
303 * - \ref SCIP_STAGE_INITPRESOLVE
304 * - \ref SCIP_STAGE_PRESOLVING
305 * - \ref SCIP_STAGE_PRESOLVED
306 * - \ref SCIP_STAGE_EXITPRESOLVE
307 * - \ref SCIP_STAGE_SOLVING
308 * - \ref SCIP_STAGE_SOLVED
309 * - \ref SCIP_STAGE_FREE
310 *
311 * @post After calling this method \SCIP reached the solving stage \ref SCIP_STAGE_FREE
312 *
313 * See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
314 */
315 SCIP_RETCODE SCIPfree(
316 SCIP** scip /**< pointer to SCIP data structure */
317 )
318 {
319 assert(scip != NULL);
320 if( *scip == NULL )
321 return SCIP_OKAY;
322
323 SCIP_CALL( SCIPcheckStage(*scip, "SCIPfree", TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE) );
324
325 SCIP_CALL( SCIPfreeProb(*scip) );
326 assert((*scip)->set->stage == SCIP_STAGE_INIT);
327
328 /* switch stage to FREE */
329 (*scip)->set->stage = SCIP_STAGE_FREE;
330
331 SCIP_CALL( SCIPsyncstoreRelease(&(*scip)->syncstore) );
332 SCIP_CALL( SCIPsetFree(&(*scip)->set, (*scip)->mem->setmem) );
333 SCIP_CALL( SCIPdialoghdlrFree(*scip, &(*scip)->dialoghdlr) );
334 SCIPclockFree(&(*scip)->totaltime);
335 SCIPinterruptFree(&(*scip)->interrupt);
336 SCIP_CALL( SCIPmemFree(&(*scip)->mem) );
337
338 /* release message handler */
339 SCIP_CALL( SCIPmessagehdlrRelease(&(*scip)->messagehdlr) );
340
341 BMSfreeMemory(scip);
342
343 return SCIP_OKAY;
344 }
345
346 #undef SCIPgetStage
347 #undef SCIPhasPerformedPresolve
348 #undef SCIPisStopped
349
350 /** returns current stage of SCIP
351 *
352 * @return the current SCIP stage
353 *
354 * See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
355 */
356 SCIP_STAGE SCIPgetStage(
357 SCIP* scip /**< SCIP data structure */
358 )
359 {
360 assert(scip != NULL);
361 assert(scip->set != NULL);
362
363 return scip->set->stage;
364 }
365
366 /** outputs SCIP stage and solution status if applicable via the message handler
367 *
368 * @note If the message handler is set to a NULL pointer nothing will be printed
369 *
370 * @note If limits have been changed between the solution and the call to this function, the status is recomputed and
371 * thus may to correspond to the original status.
372 *
373 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
374 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
375 *
376 * See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
377 */
378 SCIP_RETCODE SCIPprintStage(
379 SCIP* scip, /**< SCIP data structure */
380 FILE* file /**< output file (or NULL for standard output) */
381 )
382 {
383 SCIP_CALL( SCIPcheckStage(scip, "SCIPprintStage", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE) );
384
385 switch( scip->set->stage )
386 {
387 case SCIP_STAGE_INIT:
388 SCIPmessageFPrintInfo(scip->messagehdlr, file, "initialization");
389 break;
390 case SCIP_STAGE_PROBLEM:
391 SCIPmessageFPrintInfo(scip->messagehdlr, file, "problem creation / modification");
392 break;
393 case SCIP_STAGE_TRANSFORMING:
394 SCIPmessageFPrintInfo(scip->messagehdlr, file, "problem transformation");
395 break;
396 case SCIP_STAGE_TRANSFORMED:
397 SCIPmessageFPrintInfo(scip->messagehdlr, file, "problem transformed");
398 break;
399 case SCIP_STAGE_INITPRESOLVE:
400 SCIPmessageFPrintInfo(scip->messagehdlr, file, "presolving is being initialized");
401 break;
402 case SCIP_STAGE_PRESOLVING:
403 if( SCIPsolveIsStopped(scip->set, scip->stat, TRUE) )
404 {
405 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving was interrupted [");
406 SCIP_CALL( SCIPprintStatus(scip, file) );
407 SCIPmessageFPrintInfo(scip->messagehdlr, file, "]");
408 }
409 else
410 SCIPmessageFPrintInfo(scip->messagehdlr, file, "presolving process is running");
411 break;
412 case SCIP_STAGE_EXITPRESOLVE:
413 SCIPmessageFPrintInfo(scip->messagehdlr, file, "presolving is being exited");
414 break;
415 case SCIP_STAGE_PRESOLVED:
416 if( SCIPsolveIsStopped(scip->set, scip->stat, TRUE) )
417 {
418 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving was interrupted [");
419 SCIP_CALL( SCIPprintStatus(scip, file) );
420 SCIPmessageFPrintInfo(scip->messagehdlr, file, "]");
421 }
422 else
423 SCIPmessageFPrintInfo(scip->messagehdlr, file, "problem is presolved");
424 break;
425 case SCIP_STAGE_INITSOLVE:
426 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving process initialization");
427 break;
428 case SCIP_STAGE_SOLVING:
429 if( SCIPsolveIsStopped(scip->set, scip->stat, TRUE) )
430 {
431 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving was interrupted [");
432 SCIP_CALL( SCIPprintStatus(scip, file) );
433 SCIPmessageFPrintInfo(scip->messagehdlr, file, "]");
434 }
435 else
436 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving process is running");
437 break;
438 case SCIP_STAGE_SOLVED:
439 SCIPmessageFPrintInfo(scip->messagehdlr, file, "problem is solved [");
440 SCIP_CALL( SCIPprintStatus(scip, file) );
441 SCIPmessageFPrintInfo(scip->messagehdlr, file, "]");
442
443 /* We output that the objective limit has been reached if no solution respecting the objective limit has been
444 * found (nlimsolsfound == 0) and the primal bound is finite. Note that it still might be that the original
445 * problem is infeasible, even without the objective limit, i.e., we cannot be sure that we actually reached the
446 * objective limit. */
447 if( scip->primal->nlimsolsfound == 0 && !SCIPisInfinity(scip, (SCIP_Real)SCIPgetObjsense(scip) * SCIPgetPrimalbound(scip)) )
448 SCIPmessageFPrintInfo(scip->messagehdlr, file, " (objective limit reached)");
449
450 break;
451 case SCIP_STAGE_EXITSOLVE:
452 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving process deinitialization");
453 break;
454 case SCIP_STAGE_FREETRANS:
455 SCIPmessageFPrintInfo(scip->messagehdlr, file, "freeing transformed problem");
456 break;
457 case SCIP_STAGE_FREE:
458 SCIPmessageFPrintInfo(scip->messagehdlr, file, "freeing SCIP");
459 break;
460 default:
461 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
462 return SCIP_INVALIDDATA;
463 }
464
465 return SCIP_OKAY;
466 }
467
468 /** gets solution status
469 *
470 * @return SCIP solution status
471 *
472 * See \ref SCIP_Status "SCIP_STATUS" for a complete list of all possible solving status.
473 */
474 SCIP_STATUS SCIPgetStatus(
475 SCIP* scip /**< SCIP data structure */
476 )
477 {
478 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetStatus", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE) );
479
480 if( scip->set->stage == SCIP_STAGE_INIT || scip->set->stage == SCIP_STAGE_FREE )
481 return SCIP_STATUS_UNKNOWN;
482 else
483 {
484 assert(scip->stat != NULL);
485
486 return scip->stat->status;
487 }
488 }
489
490 /** outputs solution status
491 *
492 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
493 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
494 *
495 * See \ref SCIP_Status "SCIP_STATUS" for a complete list of all possible solving status.
496 */
497 SCIP_RETCODE SCIPprintStatus(
498 SCIP* scip, /**< SCIP data structure */
|
(1) Event noescape: |
"SCIPprintStatus(SCIP *, FILE *)" does not free or save its parameter "file". |
499 FILE* file /**< output file (or NULL for standard output) */
500 )
501 {
502 SCIP_CALL( SCIPcheckStage(scip, "SCIPprintStatus", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE) );
503
504 switch( SCIPgetStatus(scip) )
505 {
506 case SCIP_STATUS_UNKNOWN:
507 SCIPmessageFPrintInfo(scip->messagehdlr, file, "unknown");
508 break;
509 case SCIP_STATUS_USERINTERRUPT:
510 SCIPmessageFPrintInfo(scip->messagehdlr, file, "user interrupt");
511 break;
512 case SCIP_STATUS_NODELIMIT:
513 SCIPmessageFPrintInfo(scip->messagehdlr, file, "node limit reached");
514 break;
515 case SCIP_STATUS_TOTALNODELIMIT:
516 SCIPmessageFPrintInfo(scip->messagehdlr, file, "total node limit reached");
517 break;
518 case SCIP_STATUS_STALLNODELIMIT:
519 SCIPmessageFPrintInfo(scip->messagehdlr, file, "stall node limit reached");
520 break;
521 case SCIP_STATUS_TIMELIMIT:
522 SCIPmessageFPrintInfo(scip->messagehdlr, file, "time limit reached");
523 break;
524 case SCIP_STATUS_MEMLIMIT:
525 SCIPmessageFPrintInfo(scip->messagehdlr, file, "memory limit reached");
526 break;
527 case SCIP_STATUS_GAPLIMIT:
528 SCIPmessageFPrintInfo(scip->messagehdlr, file, "gap limit reached");
529 break;
530 case SCIP_STATUS_SOLLIMIT:
531 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solution limit reached");
532 break;
533 case SCIP_STATUS_BESTSOLLIMIT:
534 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solution improvement limit reached");
535 break;
536 case SCIP_STATUS_RESTARTLIMIT:
537 SCIPmessageFPrintInfo(scip->messagehdlr, file, "restart limit reached");
538 break;
539 case SCIP_STATUS_OPTIMAL:
540 SCIPmessageFPrintInfo(scip->messagehdlr, file, "optimal solution found");
541 break;
542 case SCIP_STATUS_INFEASIBLE:
543 SCIPmessageFPrintInfo(scip->messagehdlr, file, "infeasible");
544 break;
545 case SCIP_STATUS_UNBOUNDED:
546 SCIPmessageFPrintInfo(scip->messagehdlr, file, "unbounded");
547 break;
548 case SCIP_STATUS_INFORUNBD:
549 SCIPmessageFPrintInfo(scip->messagehdlr, file, "infeasible or unbounded");
550 break;
551 case SCIP_STATUS_TERMINATE:
552 SCIPmessageFPrintInfo(scip->messagehdlr, file, "termination signal received");
553 break;
554 default:
555 SCIPerrorMessage("invalid status code <%d>\n", SCIPgetStatus(scip));
556 return SCIP_INVALIDDATA;
557 }
558
559 return SCIP_OKAY;
560 }
561
562 /** returns whether the current stage belongs to the transformed problem space
563 *
564 * @return Returns TRUE if the \SCIP instance is transformed, otherwise FALSE
565 */
566 SCIP_Bool SCIPisTransformed(
567 SCIP* scip /**< SCIP data structure */
568 )
569 {
570 assert(scip != NULL);
571
572 return ((int)scip->set->stage >= (int)SCIP_STAGE_TRANSFORMING);
573 }
574
575 /** returns whether the solution process should be probably correct
576 *
577 * @note This feature is not supported yet!
578 *
579 * @return Returns TRUE if \SCIP is exact solving mode, otherwise FALSE
580 */
581 SCIP_Bool SCIPisExactSolve(
582 SCIP* scip /**< SCIP data structure */
583 )
584 {
585 assert(scip != NULL);
586 assert(scip->set != NULL);
587
588 return (scip->set->misc_exactsolve);
589 }
590
591 /** returns whether the presolving process would be finished given no more presolving reductions are found in this
592 * presolving round
593 *
594 * Checks whether the number of presolving rounds is not exceeded and the presolving reductions found in the current
595 * presolving round suffice to trigger another presolving round.
596 *
597 * @note if subsequent presolvers find more reductions, presolving might continue even if the method returns FALSE
598 * @note does not check whether infeasibility or unboundedness was already detected in presolving (which would result
599 * in presolving being stopped although the method returns TRUE)
600 *
601 * @return Returns TRUE if presolving is finished if no further reductions are detected
602 */
603 SCIP_Bool SCIPisPresolveFinished(
604 SCIP* scip /**< SCIP data structure */
605 )
606 {
607 int maxnrounds;
608 SCIP_Bool finished;
609
610 assert(scip != NULL);
611 assert(scip->stat != NULL);
612 assert(scip->transprob != NULL);
613
614 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisPresolveFinished", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
615
616 /* get maximum number of presolving rounds */
617 maxnrounds = scip->set->presol_maxrounds;
618 if( maxnrounds == -1 )
619 maxnrounds = INT_MAX;
620
621 /* don't abort, if enough changes were applied to the variables */
622 finished = (scip->transprob->nvars == 0
623 || (scip->stat->npresolfixedvars - scip->stat->lastnpresolfixedvars
624 + scip->stat->npresolaggrvars - scip->stat->lastnpresolaggrvars
625 + scip->stat->npresolchgvartypes - scip->stat->lastnpresolchgvartypes
626 + (scip->stat->npresolchgbds - scip->stat->lastnpresolchgbds)/10.0
627 + (scip->stat->npresoladdholes - scip->stat->lastnpresoladdholes)/10.0
628 <= scip->set->presol_abortfac * scip->transprob->nvars)); /*lint !e653*/
629
630 /* don't abort, if enough changes were applied to the constraints */
631 finished = finished
632 && (scip->transprob->nconss == 0
633 || (scip->stat->npresoldelconss - scip->stat->lastnpresoldelconss
634 + scip->stat->npresoladdconss - scip->stat->lastnpresoladdconss
635 + scip->stat->npresolupgdconss - scip->stat->lastnpresolupgdconss
636 + scip->stat->npresolchgsides - scip->stat->lastnpresolchgsides
637 <= scip->set->presol_abortfac * scip->transprob->nconss));
638
639 /* don't abort, if enough changes were applied to the coefficients (assume a 1% density of non-zero elements) */
640 finished = finished
641 && (scip->transprob->nvars == 0 || scip->transprob->nconss == 0
642 || (scip->stat->npresolchgcoefs - scip->stat->lastnpresolchgcoefs
643 <= scip->set->presol_abortfac * 0.01 * scip->transprob->nvars * scip->transprob->nconss));
644
645 #ifdef SCIP_DISABLED_CODE
646 /* since 2005, we do not take cliques and implications into account when deciding whether to stop presolving */
647 /* don't abort, if enough new implications or cliques were found (assume 100 implications per variable) */
648 finished = finished
649 && (scip->stat->nimplications - scip->stat->lastnpresolimplications
650 <= scip->set->presol_abortfac * 100 * scip->transprob->nbinvars)
651 && (SCIPcliquetableGetNCliques(scip->cliquetable) - scip->stat->lastnpresolcliques
652 <= scip->set->presol_abortfac * scip->transprob->nbinvars);
653 #endif
654
655 /* abort if maximal number of presolving rounds is reached */
656 finished = finished || (scip->stat->npresolrounds + 1 >= maxnrounds);
657
658 return finished;
659 }
660
661 /** returns whether SCIP has performed presolving during the last solve
662 *
663 * @return Returns TRUE if presolving was performed during the last solve
664 */
665 SCIP_Bool SCIPhasPerformedPresolve(
666 SCIP* scip /**< SCIP data structure */
667 )
668 {
669 assert(scip != NULL);
670 assert(scip->stat != NULL);
671
672 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPhasPerformedPresolve", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
673
674 return scip->stat->performpresol;
675 }
676
677 /** returns whether the user pressed CTRL-C to interrupt the solving process
678 *
679 * @return Returns TRUE if Ctrl-C was pressed, otherwise FALSE.
680 */ /*lint -e715*/
681 SCIP_Bool SCIPpressedCtrlC(
682 SCIP* scip /**< SCIP data structure */
683 )
684 {
685 return SCIPinterrupted();
686 }
687
688 /** returns whether the solving process should be / was stopped before proving optimality;
689 * if the solving process should be / was stopped, the status returned by SCIPgetStatus() yields
690 * the reason for the premature abort
691 *
692 * @return Returns TRUE if solving process is stopped/interrupted, otherwise FALSE.
693 */
694 SCIP_Bool SCIPisStopped(
695 SCIP* scip /**< SCIP data structure */
696 )
697 {
698 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisStopped", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
699
700 return SCIPsolveIsStopped(scip->set, scip->stat, FALSE);
701 }
702
703 /** includes information about an external code linked into the SCIP library */
704 SCIP_RETCODE SCIPincludeExternalCodeInformation(
705 SCIP* scip, /**< SCIP data structure */
706 const char* name, /**< name of external code */
707 const char* description /**< description of external code, or NULL */
708 )
709 {
710 assert(scip != NULL);
711 assert(name != NULL);
712
713 SCIP_CALL( SCIPcheckStage(scip, "SCIPincludeExternalCodeInformation", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
714
715 SCIP_CALL( SCIPsetIncludeExternalCode(scip->set, name, description) );
716
717 return SCIP_OKAY;
718 }
719
720 /** returns an array of names of currently included external codes */
721 char** SCIPgetExternalCodeNames(
722 SCIP* scip /**< SCIP data structure */
723 )
724 {
725 assert(scip != NULL);
726 assert(scip->set != NULL);
727
728 return scip->set->extcodenames;
729 }
730
731 /** returns an array of the descriptions of currently included external codes
732 *
733 * @note some descriptions may be NULL
734 */
735 char** SCIPgetExternalCodeDescriptions(
736 SCIP* scip /**< SCIP data structure */
737 )
738 {
739 assert(scip != NULL);
740 assert(scip->set != NULL);
741
742 return scip->set->extcodedescs;
743 }
744
745 /** returns the number of currently included information on external codes */
746 int SCIPgetNExternalCodes(
747 SCIP* scip /**< SCIP data structure */
748 )
749 {
750 assert(scip != NULL);
751 assert(scip->set != NULL);
752
753 return scip->set->nextcodes;
754 }
755
756 /** prints information on external libraries to a file stream via the message handler system
757 *
758 * @note If the message handler is set to a NULL pointer nothing will be printed
759 */
760 void SCIPprintExternalCodes(
761 SCIP* scip, /**< SCIP data structure */
762 FILE* file /**< output file (or NULL for standard output) */
763 )
764 {
765 int i;
766
767 SCIPmessageFPrintInfo(scip->messagehdlr, file, "External libraries: ");
768 if( scip->set->nextcodes == 0 )
769 {
770 SCIPinfoMessage(scip, file, "none\n");
771 return;
772 }
773 SCIPinfoMessage(scip, file, "\n");
774
775 for( i = 0; i < scip->set->nextcodes; ++i )
776 {
777 SCIPinfoMessage(scip, file, " %-20s %s\n", scip->set->extcodenames[i], scip->set->extcodedescs[i] != NULL ? scip->set->extcodedescs[i] : "");
778 }
779 }
780