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
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 */
82{
84 int lineno;
87 const char* f0;
88 const char* f1;
89};
90typedef struct SmpsInput SMPSINPUT;
91
92
93/** creates the smps input structure */
94static
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
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 */
117static
119 SCIP* scip, /**< SCIP data structure */
120 SMPSINPUT** smpsi /**< smps input structure */
121 )
122{
124}
125
126/** return the current value of field 0 */
127static
128const 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. */
138static
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. */
152static
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) */
220static
221SCIP_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 */
235static
236SCIP_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;
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 */
425TERMINATE:
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}
#define NULL
Definition: def.h:267
#define SCIP_MAXSTRLEN
Definition: def.h:288
#define SCIP_Bool
Definition: def.h:91
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:395
#define SCIPABORT()
Definition: def.h:346
#define SCIP_CALL(x)
Definition: def.h:374
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:153
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:232
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:200
int SCIPstoGetNScenarios(SCIP *scip)
Definition: reader_sto.c:2841
SCIP_RETCODE SCIPreadCor(SCIP *scip, const char *filename, SCIP_RESULT *result)
Definition: reader_cor.c:187
SCIP_RETCODE SCIPreadTim(SCIP *scip, const char *filename, SCIP_RESULT *result)
Definition: reader_tim.c:878
SCIP_RETCODE SCIPreadSto(SCIP *scip, const char *filename, SCIP_RESULT *result)
Definition: reader_sto.c:2808
void SCIPsplitFilename(char *filename, char **path, char **name, char **extension, char **compression)
Definition: misc.c:11095
SCIP_RETCODE SCIPincludeReaderSmps(SCIP *scip)
Definition: reader_smps.c:450
SCIP_RETCODE SCIPgetOrigVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2357
int SCIPgetNOrigConss(SCIP *scip)
Definition: scip_prob.c:3134
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:250
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
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
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip_reader.c:147
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:557
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip_reader.c:195
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10877
void SCIPprintSysError(const char *message)
Definition: misc.c:10769
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10919
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:10818
memory allocation routines
wrapper functions to map file i/o to standard or zlib file i/o
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:43
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebugMessage
Definition: pub_message.h:96
public data structures and miscellaneous methods
public methods for input file readers
COR file reader (MPS format of the core problem for stochastic programs)
#define STO_FILEEXTENSION
Definition: reader_smps.c:68
static SCIP_RETCODE smpsinputCreate(SCIP *scip, SMPSINPUT **smpsi, SCIP_FILE *fp)
Definition: reader_smps.c:95
static SCIP_Bool smpsinputReadLine(SMPSINPUT *smpsi)
Definition: reader_smps.c:153
static SCIP_DECL_READERREAD(readerReadSmps)
Definition: reader_smps.c:236
static void clearFrom(char *buf, unsigned int pos)
Definition: reader_smps.c:139
#define TIM_FILEEXTENSION
Definition: reader_smps.c:67
#define BLANK
Definition: reader_smps.c:63
static SCIP_DECL_READERCOPY(readerCopySmps)
Definition: reader_smps.c:221
SCIP_SmpsFileType
Definition: reader_smps.c:72
@ SCIP_SMPSFILETYPE_STO
Definition: reader_smps.c:75
@ SCIP_SMPSFILETYPE_COR
Definition: reader_smps.c:73
@ SCIP_SMPSFILETYPE_TIM
Definition: reader_smps.c:74
#define READER_DESC
Definition: reader_smps.c:59
#define READER_EXTENSION
Definition: reader_smps.c:60
enum SCIP_SmpsFileType SCIP_SMPSFILETYPE
Definition: reader_smps.c:77
static void smpsinputFree(SCIP *scip, SMPSINPUT **smpsi)
Definition: reader_smps.c:118
#define LINEWIDTH
Definition: reader_smps.c:64
#define READER_NAME
Definition: reader_smps.c:58
#define SMPS_MAX_LINELEN
Definition: reader_smps.c:62
static const char * smpsinputField0(const SMPSINPUT *smpsi)
Definition: reader_smps.c:128
#define COR_FILEEXTENSION
Definition: reader_smps.c:66
SMPS file reader - SMPS files lists the cor, tim and sto files for a single instance to be read.
STO file reader - the stochastic information of an instance in SMPS format.
int SCIPtimGetNStages(SCIP *scip)
Definition: reader_tim.c:938
TIM file reader - the stage information for a stochastic programming instance in SMPS format.
public methods for memory management
public methods for message handling
public methods for global and local (sub)problems
public methods for reader plugins
const char * f1
Definition: reader_smps.c:88
SCIP_FILE * fp
Definition: reader_smps.c:83
char buf[SMPS_MAX_LINELEN]
Definition: reader_smps.c:86
const char * f0
Definition: reader_smps.c:87
int lineno
Definition: reader_smps.c:84
SCIP_Bool haserror
Definition: reader_smps.c:85
@ SCIP_SUCCESS
Definition: type_result.h:58
@ SCIP_NOFILE
Definition: type_retcode.h:47
@ SCIP_READERROR
Definition: type_retcode.h:45
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63