Scippy

SCIP

Solving Constraint Integer Programs

scipshell.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2022 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 scipshell.c
17  * @ingroup OTHER_CFILES
18  * @brief SCIP command line interface
19  * @author Tobias Achterberg
20  */
21 
22 /*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <ctype.h>
27 
28 #include "scip/scip.h"
29 #include "scip/scipdefplugins.h"
30 #include "scip/scipshell.h"
31 #include "scip/message_default.h"
32 #include "scip/reader_nl.h"
33 
34 /*
35  * Message Handler
36  */
37 
38 static
40  SCIP* scip, /**< SCIP data structure */
41  const char* filename /**< parameter file name */
42  )
43 {
44  if( SCIPfileExists(filename) )
45  {
46  SCIPinfoMessage(scip, NULL, "reading user parameter file <%s>\n", filename);
47  SCIP_CALL( SCIPreadParams(scip, filename) );
48  }
49  else
50  SCIPinfoMessage(scip, NULL, "user parameter file <%s> not found - using default parameters\n", filename);
51 
52  return SCIP_OKAY;
53 }
54 
55 static
57  SCIP* scip, /**< SCIP data structure */
58  const char* filename /**< input file name */
59  )
60 {
61  SCIP_RETCODE retcode;
62  SCIP_Bool outputorigsol = FALSE;
63 
64  /********************
65  * Problem Creation *
66  ********************/
67 
68  /** @note The message handler should be only fed line by line such the message has the chance to add string in front
69  * of each message
70  */
71  SCIPinfoMessage(scip, NULL, "\n");
72  SCIPinfoMessage(scip, NULL, "read problem <%s>\n", filename);
73  SCIPinfoMessage(scip, NULL, "============\n");
74  SCIPinfoMessage(scip, NULL, "\n");
75 
76  retcode = SCIPreadProb(scip, filename, NULL);
77 
78  switch( retcode )
79  {
80  case SCIP_NOFILE:
81  SCIPinfoMessage(scip, NULL, "file <%s> not found\n", filename);
82  return SCIP_OKAY;
84  SCIPinfoMessage(scip, NULL, "no reader for input file <%s> available\n", filename);
85  return SCIP_OKAY;
86  case SCIP_READERROR:
87  SCIPinfoMessage(scip, NULL, "error reading file <%s>\n", filename);
88  return SCIP_OKAY;
89  default:
90  SCIP_CALL( retcode );
91  } /*lint !e788*/
92 
93  /*******************
94  * Problem Solving *
95  *******************/
96 
97  /* solve problem */
98  SCIPinfoMessage(scip, NULL, "\nsolve problem\n");
99  SCIPinfoMessage(scip, NULL, "=============\n\n");
100 
101  SCIP_CALL( SCIPsolve(scip) );
102 
103  /*******************
104  * Solution Output *
105  *******************/
106 
107  SCIP_CALL( SCIPgetBoolParam(scip, "misc/outputorigsol", &outputorigsol) );
108  if ( outputorigsol )
109  {
110  SCIP_SOL* bestsol;
111 
112  SCIPinfoMessage(scip, NULL, "\nprimal solution (original space):\n");
113  SCIPinfoMessage(scip, NULL, "=================================\n\n");
114 
115  bestsol = SCIPgetBestSol(scip);
116  if ( bestsol == NULL )
117  SCIPinfoMessage(scip, NULL, "no solution available\n");
118  else
119  {
120  SCIP_SOL* origsol;
121 
122  SCIP_CALL( SCIPcreateSolCopy(scip, &origsol, bestsol) );
123  SCIP_CALL( SCIPretransformSol(scip, origsol) );
124  SCIP_CALL( SCIPprintSol(scip, origsol, NULL, FALSE) );
125  SCIP_CALL( SCIPfreeSol(scip, &origsol) );
126  }
127  }
128  else
129  {
130  SCIPinfoMessage(scip, NULL, "\nprimal solution (transformed space):\n");
131  SCIPinfoMessage(scip, NULL, "====================================\n\n");
132 
134  }
135 
136  /**************
137  * Statistics *
138  **************/
139 
140  SCIPinfoMessage(scip, NULL, "\nStatistics\n");
141  SCIPinfoMessage(scip, NULL, "==========\n\n");
142 
144 
145  return SCIP_OKAY;
146 }
147 
148 /** runs SCIP as if it was called by AMPL */
149 static
151  SCIP* scip, /**< SCIP data structure */
152  char* nlfilename, /**< name of .nl file, without the .nl */
153  const char* defaultsetname /**< name of default settings file */
154  )
155 {
156 #ifdef SCIP_WITH_AMPL
157  char fullnlfilename[SCIP_MAXSTRLEN];
158  char* logfile;
159  SCIP_Bool printstat;
160 
161  SCIP_CALL( SCIPaddBoolParam(scip, "display/statistics",
162  "whether to print statistics on a solve",
163  &printstat, FALSE, FALSE, NULL, NULL) );
164 
165  SCIP_CALL( SCIPaddStringParam(scip, "display/logfile",
166  "name of file to write SCIP log to (additionally to writing to stdout)",
167  NULL, FALSE, "", NULL, NULL) );
168 
169  SCIPprintVersion(scip, NULL);
170  SCIPinfoMessage(scip, NULL, "\n");
171 
173  SCIPinfoMessage(scip, NULL, "\n");
174 
175  if( defaultsetname != NULL )
176  {
177  SCIP_CALL( readParams(scip, defaultsetname) );
178  SCIPinfoMessage(scip, NULL, "\n");
179  }
180 
181  SCIP_CALL( SCIPgetStringParam(scip, "display/logfile", &logfile) );
182  if( *logfile )
183  SCIPsetMessagehdlrLogfile(scip, logfile);
184 
185  (void) SCIPsnprintf(fullnlfilename, SCIP_MAXSTRLEN, "%s.nl", nlfilename);
186  SCIPinfoMessage(scip, NULL, "read problem <%s>\n", fullnlfilename);
187  SCIPinfoMessage(scip, NULL, "============\n");
188  SCIPinfoMessage(scip, NULL, "\n");
189 
190  SCIP_CALL( SCIPreadProb(scip, fullnlfilename, "nl") );
191 
192  SCIPinfoMessage(scip, NULL, "\nsolve problem\n");
193  SCIPinfoMessage(scip, NULL, "=============\n\n");
194 
195  SCIP_CALL( SCIPsolve(scip) );
196 
197  SCIP_CALL( SCIPgetBoolParam(scip, "display/statistics", &printstat) );
198  if( printstat )
199  {
200  SCIPinfoMessage(scip, NULL, "\nStatistics\n");
201  SCIPinfoMessage(scip, NULL, "==========\n\n");
202 
204  }
205 
207 
208  return SCIP_OKAY;
209 
210 #else /* SCIP_WITH_AMPL */
211  SCIPerrorMessage("SCIP has been compiled without AMPL support.\n");
212  return SCIP_PLUGINNOTFOUND;
213 #endif
214 }
215 
216 /** evaluates command line parameters and runs SCIP appropriately in the given SCIP instance */
218  SCIP* scip, /**< SCIP data structure */
219  int argc, /**< number of shell parameters */
220  char** argv, /**< array with shell parameters */
221  const char* defaultsetname /**< name of default settings file */
222  )
223 { /*lint --e{850}*/
224  char* probname = NULL;
225  char* settingsname = NULL;
226  char* logname = NULL;
227  int randomseed;
228  SCIP_Bool randomseedread;
229  SCIP_Bool quiet;
230  SCIP_Bool paramerror;
232  SCIP_Bool onlyversion;
233  SCIP_Real primalreference = SCIP_UNKNOWN;
234  SCIP_Real dualreference = SCIP_UNKNOWN;
235  const char* dualrefstring;
236  const char* primalrefstring;
237  int i;
238 
239  /********************
240  * Parse parameters *
241  ********************/
242 
243  /* recognize and handle case where we were called from AMPL first */
244  if( argc >= 3 && strcmp(argv[2], "-AMPL") == 0 )
245  {
246  SCIP_CALL( fromAmpl(scip, argv[1], defaultsetname) );
247 
248  return SCIP_OKAY;
249  }
250 
251  quiet = FALSE;
252  paramerror = FALSE;
253  interactive = FALSE;
254  onlyversion = FALSE;
255  randomseedread = FALSE;
256  randomseed = 0;
257  primalrefstring = NULL;
258  dualrefstring = NULL;
259 
260  for( i = 1; i < argc; ++i )
261  {
262  if( strcmp(argv[i], "-l") == 0 )
263  {
264  i++;
265  if( i < argc )
266  logname = argv[i];
267  else
268  {
269  printf("missing log filename after parameter '-l'\n");
270  paramerror = TRUE;
271  }
272  }
273  else if( strcmp(argv[i], "-q") == 0 )
274  quiet = TRUE;
275  else if( strcmp(argv[i], "-v") == 0 )
276  onlyversion = TRUE;
277  else if( strcmp(argv[i], "--version") == 0 )
278  onlyversion = TRUE;
279  else if( strcmp(argv[i], "-s") == 0 )
280  {
281  i++;
282  if( i < argc )
283  settingsname = argv[i];
284  else
285  {
286  printf("missing settings filename after parameter '-s'\n");
287  paramerror = TRUE;
288  }
289  }
290  else if( strcmp(argv[i], "-f") == 0 )
291  {
292  i++;
293  if( i < argc )
294  probname = argv[i];
295  else
296  {
297  printf("missing problem filename after parameter '-f'\n");
298  paramerror = TRUE;
299  }
300  }
301  else if( strcmp(argv[i], "-c") == 0 )
302  {
303  i++;
304  if( i < argc )
305  {
306  SCIP_CALL( SCIPaddDialogInputLine(scip, argv[i]) );
307  interactive = TRUE;
308  }
309  else
310  {
311  printf("missing command line after parameter '-c'\n");
312  paramerror = TRUE;
313  }
314  }
315  else if( strcmp(argv[i], "-b") == 0 )
316  {
317  i++;
318  if( i < argc )
319  {
320  SCIP_FILE* file;
321 
322  file = SCIPfopen(argv[i], "r");
323  if( file == NULL )
324  {
325  printf("cannot read command batch file <%s>\n", argv[i]);
326  SCIPprintSysError(argv[i]);
327  paramerror = TRUE;
328  }
329  else
330  {
331  while( !SCIPfeof(file) )
332  {
333  char buffer[SCIP_MAXSTRLEN];
334 
335  (void)SCIPfgets(buffer, (int) sizeof(buffer), file);
336  if( buffer[0] != '\0' )
337  {
338  SCIP_CALL_FINALLY( SCIPaddDialogInputLine(scip, buffer), SCIPfclose(file) );
339  }
340  }
341  SCIPfclose(file);
342  interactive = TRUE;
343  }
344  }
345  else
346  {
347  printf("missing command batch filename after parameter '-b'\n");
348  paramerror = TRUE;
349  }
350  }
351  else if( strcmp(argv[i], "-r") == 0 )
352  {
353  /*read a random seed from the command line */
354  i++;
355  if( i < argc && isdigit(argv[i][0]) )
356  {
357  randomseed = atoi(argv[i]);
358  randomseedread = TRUE;
359  }
360  else
361  {
362  printf("Random seed parameter '-r' followed by something that is not an integer\n");
363  paramerror = TRUE;
364  }
365  }
366  else if( strcmp(argv[i], "-o") == 0 )
367  {
368  if( i >= argc - 2 )
369  {
370  printf("wrong usage of reference objective parameter '-o': -o <primref> <dualref>\n");
371  paramerror = TRUE;
372  }
373  else
374  {
375  /* do not parse the strings directly, the settings could still influence the value of +-infinity */
376  primalrefstring = argv[i + 1];
377  dualrefstring = argv[i+2];
378  }
379  i += 2;
380  }
381  else
382  {
383  printf("invalid parameter <%s>\n", argv[i]);
384  paramerror = TRUE;
385  }
386  }
387 
388  if( interactive && probname != NULL )
389  {
390  printf("cannot mix batch mode '-c' and '-b' with file mode '-f'\n");
391  paramerror = TRUE;
392  }
393 
394  if( !paramerror )
395  {
396  /***********************************
397  * create log file message handler *
398  ***********************************/
399 
400  if( quiet )
401  {
402  SCIPsetMessagehdlrQuiet(scip, quiet);
403  }
404 
405  if( logname != NULL )
406  {
407  SCIPsetMessagehdlrLogfile(scip, logname);
408  }
409 
410  /***********************************
411  * Version and library information *
412  ***********************************/
413 
414  SCIPprintVersion(scip, NULL);
415  SCIPinfoMessage(scip, NULL, "\n");
416 
418  SCIPinfoMessage(scip, NULL, "\n");
419 
420  if( onlyversion )
421  {
423  SCIPinfoMessage(scip, NULL, "\n");
424  return SCIP_OKAY;
425  }
426 
427  /*****************
428  * Load settings *
429  *****************/
430 
431  if( settingsname != NULL )
432  {
433  SCIP_CALL( readParams(scip, settingsname) );
434  }
435  else if( defaultsetname != NULL )
436  {
437  SCIP_CALL( readParams(scip, defaultsetname) );
438  }
439 
440  /************************************
441  * Change random seed, if specified *
442  ***********************************/
443  if( randomseedread )
444  {
445  SCIP_CALL( SCIPsetIntParam(scip, "randomization/randomseedshift", randomseed) );
446  }
447 
448  /**************
449  * Start SCIP *
450  **************/
451 
452  if( probname != NULL )
453  {
454  SCIP_Bool validatesolve = FALSE;
455 
456  if( primalrefstring != NULL && dualrefstring != NULL )
457  {
458  char *endptr;
459  if( ! SCIPparseReal(scip, primalrefstring, &primalreference, &endptr) ||
460  ! SCIPparseReal(scip, dualrefstring, &dualreference, &endptr) )
461  {
462  printf("error parsing primal and dual reference values for validation: %s %s\n", primalrefstring, dualrefstring);
463  return SCIP_ERROR;
464  }
465  else
466  validatesolve = TRUE;
467  }
468  SCIP_CALL( fromCommandLine(scip, probname) );
469 
470  /* validate the solve */
471  if( validatesolve )
472  {
473  SCIP_CALL( SCIPvalidateSolve(scip, primalreference, dualreference, SCIPfeastol(scip), FALSE, NULL, NULL, NULL) );
474  }
475  }
476  else
477  {
478  SCIPinfoMessage(scip, NULL, "\n");
480  }
481  }
482  else
483  {
484  printf("\nsyntax: %s [-l <logfile>] [-q] [-s <settings>] [-r <randseed>] [-f <problem>] [-b <batchfile>] [-c \"command\"]\n"
485  " -v, --version : print version and build options\n"
486  " -l <logfile> : copy output into log file\n"
487  " -q : suppress screen messages\n"
488  " -s <settings> : load parameter settings (.set) file\n"
489  " -f <problem> : load and solve problem file\n"
490  " -o <primref> <dualref> : pass primal and dual objective reference values for validation at the end of the solve\n"
491  " -b <batchfile>: load and execute dialog command batch file (can be used multiple times)\n"
492  " -r <randseed> : nonnegative integer to be used as random seed. "
493  "Has priority over random seed specified through parameter settings (.set) file\n"
494  " -c \"command\" : execute single line of dialog commands (can be used multiple times)\n",
495  argv[0]);
496 #ifdef SCIP_WITH_AMPL
497  printf("\nas AMPL solver: %s <.nl-file without the .nl> -AMPL\n", argv[0]);
498 #endif
499  printf("\n");
500  }
501 
502  return SCIP_OKAY;
503 }
504 
505 /** creates a SCIP instance with default plugins, evaluates command line parameters, runs SCIP appropriately,
506  * and frees the SCIP instance
507  */
509  int argc, /**< number of shell parameters */
510  char** argv, /**< array with shell parameters */
511  const char* defaultsetname /**< name of default settings file */
512  )
513 {
514  SCIP* scip = NULL;
515 
516  /*********
517  * Setup *
518  *********/
519 
520  /* initialize SCIP */
521  SCIP_CALL( SCIPcreate(&scip) );
522 
523  /* we explicitly enable the use of a debug solution for this main SCIP instance */
524  SCIPenableDebugSol(scip);
525 
526  /* include default SCIP plugins */
528 
529  /**********************************
530  * Process command line arguments *
531  **********************************/
532 
533  SCIP_CALL( SCIPprocessShellArguments(scip, argc, argv, defaultsetname) );
534 
535  /********************
536  * Deinitialization *
537  ********************/
538  SCIP_CALL( SCIPfree(&scip) );
539 
541 
542  return SCIP_OKAY;
543 }
SCIP_RETCODE SCIPprintBestSol(SCIP *scip, FILE *file, SCIP_Bool printzeros)
Definition: scip_sol.c:2370
SCIP_RETCODE SCIPgetStringParam(SCIP *scip, const char *name, char **value)
Definition: scip_param.c:336
#define BMScheckEmptyMemory()
Definition: memory.h:148
SCIP_Real SCIPfeastol(SCIP *scip)
default message handler
#define SCIP_MAXSTRLEN
Definition: def.h:293
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
#define SCIP_CALL_FINALLY(x, y)
Definition: def.h:426
char probname[TIM_MAX_NAMELEN]
Definition: reader_tim.c:98
#define FALSE
Definition: def.h:87
static SCIP_RETCODE fromCommandLine(SCIP *scip, const char *filename)
Definition: scipshell.c:56
void SCIPprintExternalCodes(SCIP *scip, FILE *file)
Definition: scip_general.c:760
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10755
#define TRUE
Definition: def.h:86
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
static SCIP_RETCODE readParams(SCIP *scip, const char *filename)
Definition: scipshell.c:39
SCIP_RETCODE SCIPaddStringParam(SCIP *scip, const char *name, const char *desc, char **valueptr, SCIP_Bool isadvanced, const char *defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:185
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:283
static SCIP_RETCODE interactive(SCIP *scip)
Definition: cmain.c:90
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:199
SCIP_Bool SCIPfileExists(const char *filename)
Definition: misc.c:10958
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:144
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip_sol.c:609
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip_solve.c:2613
#define SCIPerrorMessage
Definition: pub_message.h:55
SCIP command line interface.
SCIP_RETCODE SCIPreadProb(SCIP *scip, const char *filename, const char *extension)
Definition: scip_prob.c:330
int SCIPfeof(SCIP_FILE *stream)
Definition: fileio.c:218
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:34
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:191
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:241
#define NULL
Definition: lpi_spx1.cpp:155
SCIP_RETCODE SCIPrunShell(int argc, char **argv, const char *defaultsetname)
Definition: scipshell.c:508
#define SCIP_CALL(x)
Definition: def.h:384
#define SCIP_UNKNOWN
Definition: def.h:198
#define SCIP_Bool
Definition: def.h:84
SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
void SCIPprintVersion(SCIP *scip, FILE *file)
Definition: scip_general.c:146
void SCIPprintSysError(const char *message)
Definition: misc.c:10664
SCIP_RETCODE SCIPvalidateSolve(SCIP *scip, SCIP_Real primalreference, SCIP_Real dualreference, SCIP_Real reftol, SCIP_Bool quiet, SCIP_Bool *feasible, SCIP_Bool *primalboundcheck, SCIP_Bool *dualboundcheck)
void SCIPsetMessagehdlrQuiet(SCIP *scip, SCIP_Bool quiet)
Definition: scip_message.c:99
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip_param.c:478
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:976
SCIP_RETCODE SCIPretransformSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:2482
SCIP_RETCODE SCIPprocessShellArguments(SCIP *scip, int argc, char **argv, const char *defaultsetname)
Definition: scipshell.c:217
SCIP_RETCODE SCIPstartInteraction(SCIP *scip)
Definition: scip_dialog.c:233
SCIP_RETCODE SCIPwriteSolutionNl(SCIP *scip)
Definition: reader_nl.cpp:1405
AMPL .nl file reader.
static SCIP_RETCODE fromAmpl(SCIP *scip, char *nlfilename, const char *defaultsetname)
Definition: scipshell.c:150
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2304
void SCIPsetMessagehdlrLogfile(SCIP *scip, const char *filename)
Definition: scip_message.c:87
SCIP_RETCODE SCIPreadParams(SCIP *scip, const char *filename)
Definition: scip_param.c:742
#define SCIP_Real
Definition: def.h:177
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:223
default SCIP plugins
void SCIPprintBuildOptions(SCIP *scip, FILE *file)
Definition: scip_general.c:181
SCIP_RETCODE SCIPaddDialogInputLine(SCIP *scip, const char *inputline)
Definition: scip_dialog.c:183
SCIP callable library.
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:48
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:315
void SCIPenableDebugSol(SCIP *scip)
Definition: scip_debug.c:48
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip_sol.c:1766