Scippy

SCIP

Solving Constraint Integer Programs

reader_smps.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-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 reader_smps.c
17  * @ingroup DEFPLUGINS_READER
18  * @brief SMPS file reader - smps files list the cor, tim and sto files for a single instance
19  * @author Stephen J. Maher
20  */
21 
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #include "blockmemshell/memory.h"
26 #include "scip/pub_fileio.h"
27 #include "scip/pub_message.h"
28 #include "scip/pub_misc.h"
29 #include "scip/pub_reader.h"
30 #include "scip/reader_cor.h"
31 #include "scip/reader_smps.h"
32 #include "scip/reader_sto.h"
33 #include "scip/reader_tim.h"
34 #include "scip/scip_mem.h"
35 #include "scip/scip_message.h"
36 #include "scip/scip_prob.h"
37 #include "scip/scip_reader.h"
38 #include <string.h>
39 
40 #if !defined(_WIN32) && !defined(_WIN64)
41 #include <strings.h> /*lint --e{766}*/ /* needed for strncasecmp() */
42 #endif
43 
44 /*
45  * The SMPS reader coordinates the reading of the cor, tim and sto files. The public reading methods from the cor, tim
46  * and sto readers are called from the SMPS reader. So, the header files for the cor, tim and sto readers are required.
47  */
48 
49 #define READER_NAME "smpsreader"
50 #define READER_DESC "file reader for core problem of stochastic programs in the SMPS file format"
51 #define READER_EXTENSION "smps"
52 
53 #define SMPS_MAX_LINELEN 1024
54 #define BLANK ' '
55 #define LINEWIDTH 80
56 
57 #define COR_FILEEXTENSION "cor"
58 #define TIM_FILEEXTENSION "tim"
59 #define STO_FILEEXTENSION "sto"
60 
61 /** enum for the file types that are read by the SMPS reader */
63 {
67 };
69 
70 
71 /** smps input structure */
72 struct SmpsInput
73 {
75  int lineno;
78  const char* f0;
79  const char* f1;
80 };
81 typedef struct SmpsInput SMPSINPUT;
82 
83 
84 /** creates the smps input structure */
85 static
87  SCIP* scip, /**< SCIP data structure */
88  SMPSINPUT** smpsi, /**< smps input structure */
89  SCIP_FILE* fp /**< file object for the input file */
90  )
91 {
92  assert(smpsi != NULL);
93  assert(fp != NULL);
94 
95  SCIP_CALL( SCIPallocBlockMemory(scip, smpsi) );
96 
97  (*smpsi)->fp = fp;
98  (*smpsi)->lineno = 0;
99  (*smpsi)->haserror = FALSE;
100  (*smpsi)->buf [0] = '\0';
101  (*smpsi)->f0 = NULL;
102  (*smpsi)->f1 = NULL;
103 
104  return SCIP_OKAY;
105 }
106 
107 /** free the smps input structure */
108 static
110  SCIP* scip, /**< SCIP data structure */
111  SMPSINPUT** smpsi /**< smps input structure */
112  )
113 {
114  SCIPfreeBlockMemory(scip, smpsi);
115 }
116 
117 /** return the current value of field 0 */
118 static
119 const char* smpsinputField0(
120  const SMPSINPUT* smpsi /**< smps input structure */
121  )
122 {
123  assert(smpsi != NULL);
124 
125  return smpsi->f0;
126 }
127 
128 /** fill the line from \p pos up to column LINEWIDTH with blanks. */
129 static
131  char* buf, /**< buffer to clear */
132  unsigned int pos /**< position to start the clearing process */
133  )
134 {
135  unsigned int i;
136 
137  for(i = pos; i < LINEWIDTH; i++)
138  buf[i] = BLANK;
139  buf[LINEWIDTH] = '\0';
140 }
141 
142 /** read a smps format data line and parse the fields. */
143 static
145  SMPSINPUT* smpsi /**< smps input structure */
146  )
147 {
148  unsigned int len;
149  unsigned int i;
150  SCIP_Bool is_marker;
151  SCIP_Bool is_empty;
152  char* nexttok;
153 
154  do
155  {
156  smpsi->f0 = smpsi->f1 = 0;
157  is_marker = FALSE;
158 
159  /* Read until we have not a comment line. */
160  do
161  {
162  smpsi->buf[SMPS_MAX_LINELEN-1] = '\0';
163  if( NULL == SCIPfgets(smpsi->buf, (int) sizeof(smpsi->buf), smpsi->fp) )
164  return FALSE;
165  smpsi->lineno++;
166  }
167  while( *smpsi->buf == '*' );
168 
169  /* Normalize line */
170  len = (unsigned int) strlen(smpsi->buf);
171 
172  /* replace tabs and new lines by blanks */
173  for( i = 0; i < len; i++ )
174  {
175  if( (smpsi->buf[i] == '\t') || (smpsi->buf[i] == '\n') || (smpsi->buf[i] == '\r') )
176  smpsi->buf[i] = BLANK;
177  }
178 
179  if( len < LINEWIDTH )
180  clearFrom(smpsi->buf, len);
181 
182  SCIPdebugMessage("line %d: <%s>\n", smpsi->lineno, smpsi->buf);
183 
184  assert(strlen(smpsi->buf) >= LINEWIDTH);
185 
186  /* Look for new section */
187  if( *smpsi->buf != BLANK )
188  {
189  smpsi->f0 = SCIPstrtok(&smpsi->buf[0], " ", &nexttok);
190 
191  assert(smpsi->f0 != 0);
192 
193  smpsi->f1 = SCIPstrtok(NULL, " ", &nexttok);
194 
195  return TRUE;
196  }
197 
198  /* check for empty lines */
199  is_empty = (smpsi->f0 == NULL && smpsi->f1 == NULL);
200  }
201  while( is_marker || is_empty );
202 
203  return TRUE;
204 }
205 
206 /*
207  * Callback methods of reader
208  */
209 
210 /** copy method for reader plugins (called when SCIP copies plugins) */
211 static
212 SCIP_DECL_READERCOPY(readerCopySmps)
213 { /*lint --e{715}*/
214  assert(scip != NULL);
215  assert(reader != NULL);
216  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
217 
218  /* call inclusion method of reader */
220 
221  return SCIP_OKAY;
222 }
223 
224 
225 /** problem reading method of reader */
226 static
227 SCIP_DECL_READERREAD(readerReadSmps)
228 { /*lint --e{715}*/
229  SCIP_FILE* fp;
230  SMPSINPUT* smpsi;
231  SCIP_RETCODE retcode = SCIP_OKAY;
232 
233  char corfilename[SCIP_MAXSTRLEN];
234  char timfilename[SCIP_MAXSTRLEN];
235  char stofilename[SCIP_MAXSTRLEN];
236  char* tmpfilename;
237  char* probname;
238  char* fileextension;
239  char* fromlastslash;
240  char parent[SCIP_MAXSTRLEN];
241  size_t parentlen;
242 
243  SCIP_Bool hascorfile;
244  SCIP_Bool hastimfile;
245  SCIP_Bool hasstofile;
246 
247  int i;
248 
249  assert(scip != NULL);
250  assert(filename != NULL);
251 
252  /* copy filename */
253  SCIP_CALL( SCIPduplicateBufferArray(scip, &tmpfilename, filename, (int)strlen(filename)+1) );
254 
255  /* getting the problem name from the SMPS file name */
256  SCIPsplitFilename(tmpfilename, NULL, &probname, NULL, NULL);
257 
258  fromlastslash = (char*) strrchr(filename, '/');
259 
260  if( fromlastslash == NULL )
261  parentlen = 0;
262  else
263  parentlen = strlen(filename) - (strlen(fromlastslash) - 1);
264 
265  (void)SCIPstrncpy(parent, filename, (int)parentlen + 1);
266 
267  fp = SCIPfopen(filename, "r");
268  if( fp == NULL )
269  {
270  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
271  SCIPprintSysError(filename);
272 
273  return SCIP_NOFILE;
274  }
275 
276  SCIP_CALL( smpsinputCreate(scip, &smpsi, fp) );
277 
278  hascorfile = FALSE;
279  hastimfile = FALSE;
280  hasstofile = FALSE;
281  while( smpsinputReadLine(smpsi) )
282  {
283  char* tmpinput;
284 
285  /* copy the input */
287  (int)strlen(smpsinputField0(smpsi))+1) ); /*lint !e666*/
288 
289  /* get extension from filename */
290  SCIPsplitFilename(tmpinput, NULL, NULL, &fileextension, NULL);
291 
292  if( strcasecmp(fileextension, COR_FILEEXTENSION) == 0 )
293  {
294  (void) SCIPsnprintf(corfilename, SCIP_MAXSTRLEN, "%s%s", parent, smpsinputField0(smpsi));
295  hascorfile = TRUE;
296  }
297  else if( strcasecmp(fileextension, TIM_FILEEXTENSION) == 0 )
298  {
299  (void) SCIPsnprintf(timfilename, SCIP_MAXSTRLEN, "%s%s", parent, smpsinputField0(smpsi));
300  hastimfile = TRUE;
301  }
302  else if( strcasecmp(fileextension, STO_FILEEXTENSION) == 0 )
303  {
304  (void) SCIPsnprintf(stofilename, SCIP_MAXSTRLEN, "%s%s", parent, smpsinputField0(smpsi));
305  hasstofile = TRUE;
306  }
307 
308  SCIPfreeBufferArray(scip, &tmpinput);
309  }
310 
311  /* printing errors if the correct files have not been provided */
312  if( !hascorfile )
313  {
314  SCIPerrorMessage("The core file has not been listed in <%s>\n", filename);
315  }
316 
317  if( !hastimfile )
318  {
319  SCIPerrorMessage("The tim file has not been listed in <%s>\n", filename);
320  }
321 
322  if( !hasstofile )
323  {
324  SCIPerrorMessage("The sto file has not been listed in <%s>\n", filename);
325  }
326 
327  /* if one of the necessary file has not been provided, then an error will be returned */
328  if( !hascorfile || !hastimfile || !hasstofile )
329  {
330  retcode = SCIP_READERROR;
331  goto TERMINATE;
332  }
333 
334  for( i = 0; i < 3; i++ )
335  {
336  int nvars;
337  int nbinvars;
338  int nintvars;
339  int nimplintvars;
340  int ncontvars;
341  SCIP_SMPSFILETYPE type;
342 
343  type = (SCIP_SMPSFILETYPE) i;
344  switch( type )
345  {
347  SCIPinfoMessage(scip, NULL, "reading core file <%s> for problem %s\n", corfilename, probname);
348  SCIPinfoMessage(scip, NULL, "============\n");
349 
350  /* reading the CORE file */
351  SCIP_CALL_TERMINATE( retcode, SCIPreadCor(scip, corfilename, result), TERMINATE );
352 
353  /* getting the variable information */
354  SCIP_CALL( SCIPgetOrigVarsData(scip, NULL, &nvars, &nbinvars, &nintvars, &nimplintvars, &ncontvars) );
356  "core problem has %d variables (%d bin, %d int, %d impl, %d cont) and %d constraints\n",
357  nvars, nbinvars, nintvars, nimplintvars, ncontvars, SCIPgetNOrigConss(scip));
358  break;
360  SCIPinfoMessage(scip, NULL, "reading the time file <%s> for problem %s\n", timfilename, probname);
361  SCIPinfoMessage(scip, NULL, "============\n");
362 
363  /* reading the TIME file */
364  SCIP_CALL_TERMINATE( retcode, SCIPreadTim(scip, timfilename, result), TERMINATE );
365 
366  SCIPinfoMessage(scip, NULL, "problem %s has %d stages\n", probname, SCIPtimGetNStages(scip));
367  break;
369 #ifdef BENDERSBRANCH
370  SCIP_Bool usebenders;
371 #endif
372 
373  SCIPinfoMessage(scip, NULL, "read problem <%s>\n", stofilename);
374  SCIPinfoMessage(scip, NULL, "============\n");
375 
376  /* reading the STO file */
377  SCIP_CALL_TERMINATE( retcode, SCIPreadSto(scip, stofilename, result), TERMINATE );
378 
379  SCIPinfoMessage(scip, NULL, "problem %s has extended with a total of %d scenarios\n", probname,
381 
382  /* getting the variable information */
383  SCIP_CALL( SCIPgetOrigVarsData(scip, NULL, &nvars, &nbinvars, &nintvars, &nimplintvars, &ncontvars) );
384 
385  /* if Benders' decomposition is used, the variable will be distributed to a number of subproblems */
386 #ifdef BENDERSBRANCH
387  SCIP_CALL( SCIPgetBoolParam(scip, "reading/sto/usebenders", &usebenders) );
388  if( usebenders )
389  {
390  SCIPinfoMessage(scip, NULL, "Benders' decomposition master problem ");
391  }
392  else
393 #endif
394  {
395  SCIPinfoMessage(scip, NULL, "deterministic equivalent problem ");
396  }
397 
399  "has %d variables (%d bin, %d int, %d impl, %d cont) and %d constraints\n",
400  nvars, nbinvars, nintvars, nimplintvars, ncontvars, SCIPgetNOrigConss(scip));
401  break;
402  /* coverity[dead_error_begin] */
403  default:
404  SCIPerrorMessage("This should not happen. Aborting.\n");
405  SCIPABORT();
406  retcode = SCIP_READERROR;
407  goto TERMINATE;
408  }
409 
410  SCIPinfoMessage(scip, NULL, "\n\n");
411  }
412 
413  SCIPfclose(fp);
414 
415  /* cppcheck-suppress unusedLabel */
416 TERMINATE:
417  smpsinputFree(scip, &smpsi);
418 
419  /* freeing buffer array */
420  SCIPfreeBufferArray(scip, &tmpfilename);
421 
422  if( retcode == SCIP_PLUGINNOTFOUND )
423  retcode = SCIP_READERROR;
424 
425  if( retcode == SCIP_NOFILE || retcode == SCIP_READERROR )
426  return retcode;
427 
428  SCIP_CALL( retcode );
429 
430  *result = SCIP_SUCCESS;
431 
432  return SCIP_OKAY;
433 }
434 
435 
436 /*
437  * reader specific interface methods
438  */
439 
440 /** includes the smps file reader in SCIP */
442  SCIP* scip /**< SCIP data structure */
443  )
444 {
445  SCIP_READER* reader;
446 
447  /* include reader */
449 
450  assert(reader != NULL);
451 
452  /* set non fundamental callbacks via setter functions */
453  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopySmps) );
454  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadSmps) );
455 
456  return SCIP_OKAY;
457 }
static SCIP_Bool smpsinputReadLine(SMPSINPUT *smpsi)
Definition: reader_smps.c:144
SCIP_EXPORT const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:548
enum SCIP_SmpsFileType SCIP_SMPSFILETYPE
Definition: reader_smps.c:68
const char * f0
Definition: reader_smps.c:78
TIM file reader - the stage information for a stochastic programming instance in SMPS format...
static SCIP_DECL_READERREAD(readerReadSmps)
Definition: reader_smps.c:227
public methods for memory management
#define BLANK
Definition: reader_smps.c:54
#define SCIP_MAXSTRLEN
Definition: def.h:279
COR file reader (MPS format of the core problem for stochastic programs)
static void clearFrom(char *buf, unsigned int pos)
Definition: reader_smps.c:130
char buf[SMPS_MAX_LINELEN]
Definition: reader_smps.c:77
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:241
SCIP_Bool haserror
Definition: reader_smps.c:76
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip_reader.c:186
#define FALSE
Definition: def.h:73
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip_reader.c:138
#define TRUE
Definition: def.h:72
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
#define READER_NAME
Definition: reader_smps.c:49
STO file reader - the stochastic information of an instance in SMPS format.
#define READER_EXTENSION
Definition: reader_smps.c:51
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:95
#define SCIPdebugMessage
Definition: pub_message.h:87
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:119
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:10562
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:123
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:78
static SCIP_RETCODE smpsinputCreate(SCIP *scip, SMPSINPUT **smpsi, SCIP_FILE *fp)
Definition: reader_smps.c:86
int lineno
Definition: reader_smps.c:75
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:144
static void smpsinputFree(SCIP *scip, SMPSINPUT **smpsi)
Definition: reader_smps.c:109
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10647
#define SCIPerrorMessage
Definition: pub_message.h:55
SCIP_RETCODE SCIPreadCor(SCIP *scip, const char *filename, SCIP_RESULT *result)
Definition: reader_cor.c:178
#define COR_FILEEXTENSION
Definition: reader_smps.c:57
static SCIP_DECL_READERCOPY(readerCopySmps)
Definition: reader_smps.c:212
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:34
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:191
int SCIPtimGetNStages(SCIP *scip)
Definition: reader_tim.c:929
#define NULL
Definition: lpi_spx1.cpp:155
#define STO_FILEEXTENSION
Definition: reader_smps.c:59
int SCIPgetNOrigConss(SCIP *scip)
Definition: scip_prob.c:3128
#define SCIP_CALL(x)
Definition: def.h:370
void SCIPsplitFilename(char *filename, char **path, char **name, char **extension, char **compression)
Definition: misc.c:10823
static const char * smpsinputField0(const SMPSINPUT *smpsi)
Definition: reader_smps.c:119
const char * f1
Definition: reader_smps.c:79
wrapper functions to map file i/o to standard or zlib file i/o
SCIP_SmpsFileType
Definition: reader_smps.c:62
public data structures and miscellaneous methods
#define SCIP_Bool
Definition: def.h:70
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip_reader.c:100
int SCIPstoGetNScenarios(SCIP *scip)
Definition: reader_sto.c:2838
public methods for message output
#define TIM_FILEEXTENSION
Definition: reader_smps.c:58
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10604
SCIP_FILE * fp
Definition: reader_smps.c:74
#define READER_DESC
Definition: reader_smps.c:50
public methods for input file readers
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:391
SMPS file reader - SMPS files lists the cor, tim and sto files for a single instance to be read...
public methods for message handling
void SCIPprintSysError(const char *message)
Definition: misc.c:10513
#define LINEWIDTH
Definition: reader_smps.c:55
SCIP_RETCODE SCIPreadSto(SCIP *scip, const char *filename, SCIP_RESULT *result)
Definition: reader_sto.c:2805
SCIP_RETCODE SCIPreadTim(SCIP *scip, const char *filename, SCIP_RESULT *result)
Definition: reader_tim.c:869
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:199
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:223
public methods for reader plugins
#define SCIPABORT()
Definition: def.h:342
public methods for global and local (sub)problems
#define SMPS_MAX_LINELEN
Definition: reader_smps.c:53
SCIP_RETCODE SCIPgetOrigVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2351
SCIP_RETCODE SCIPincludeReaderSmps(SCIP *scip)
Definition: reader_smps.c:441
memory allocation routines