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