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