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