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-2025 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
    50/*
    51 * The SMPS reader coordinates the reading of the cor, tim and sto files. The public reading methods from the cor, tim
    52 * and sto readers are called from the SMPS reader. So, the header files for the cor, tim and sto readers are required.
    53 */
    54
    55#define READER_NAME "smpsreader"
    56#define READER_DESC "file reader for core problem of stochastic programs in the SMPS file format"
    57#define READER_EXTENSION "smps"
    58
    59#define SMPS_MAX_LINELEN 1024
    60#define BLANK ' '
    61#define LINEWIDTH 80
    62
    63#define COR_FILEEXTENSION "cor"
    64#define TIM_FILEEXTENSION "tim"
    65#define STO_FILEEXTENSION "sto"
    66
    67/** enum for the file types that are read by the SMPS reader */
    69{
    73};
    75
    76
    77/** smps input structure */
    79{
    81 int lineno;
    84 const char* f0;
    85 const char* f1;
    86};
    87typedef struct SmpsInput SMPSINPUT;
    88
    89
    90/** creates the smps input structure */
    91static
    93 SCIP* scip, /**< SCIP data structure */
    94 SMPSINPUT** smpsi, /**< smps input structure */
    95 SCIP_FILE* fp /**< file object for the input file */
    96 )
    97{
    98 assert(smpsi != NULL);
    99 assert(fp != NULL);
    100
    102
    103 (*smpsi)->fp = fp;
    104 (*smpsi)->lineno = 0;
    105 (*smpsi)->haserror = FALSE;
    106 (*smpsi)->buf [0] = '\0';
    107 (*smpsi)->f0 = NULL;
    108 (*smpsi)->f1 = NULL;
    109
    110 return SCIP_OKAY;
    111}
    112
    113/** free the smps input structure */
    114static
    116 SCIP* scip, /**< SCIP data structure */
    117 SMPSINPUT** smpsi /**< smps input structure */
    118 )
    119{
    121}
    122
    123/** return the current value of field 0 */
    124static
    125const char* smpsinputField0(
    126 const SMPSINPUT* smpsi /**< smps input structure */
    127 )
    128{
    129 assert(smpsi != NULL);
    130
    131 return smpsi->f0;
    132}
    133
    134/** fill the line from \p pos up to column LINEWIDTH with blanks. */
    135static
    137 char* buf, /**< buffer to clear */
    138 unsigned int pos /**< position to start the clearing process */
    139 )
    140{
    141 unsigned int i;
    142
    143 for(i = pos; i < LINEWIDTH; i++)
    144 buf[i] = BLANK;
    145 buf[LINEWIDTH] = '\0';
    146}
    147
    148/** read a smps format data line and parse the fields. */
    149static
    151 SMPSINPUT* smpsi /**< smps input structure */
    152 )
    153{
    154 unsigned int len;
    155 unsigned int i;
    156 SCIP_Bool is_marker;
    157 SCIP_Bool is_empty;
    158 char* nexttok;
    159
    160 do
    161 {
    162 smpsi->f0 = smpsi->f1 = 0;
    163 is_marker = FALSE;
    164
    165 /* Read until we have not a comment line. */
    166 do
    167 {
    168 smpsi->buf[SMPS_MAX_LINELEN-1] = '\0';
    169 if( NULL == SCIPfgets(smpsi->buf, (int) sizeof(smpsi->buf), smpsi->fp) )
    170 return FALSE;
    171 smpsi->lineno++;
    172 }
    173 while( *smpsi->buf == '*' );
    174
    175 /* Normalize line */
    176 len = (unsigned int) strlen(smpsi->buf);
    177
    178 /* replace tabs and new lines by blanks */
    179 for( i = 0; i < len; i++ )
    180 {
    181 if( (smpsi->buf[i] == '\t') || (smpsi->buf[i] == '\n') || (smpsi->buf[i] == '\r') )
    182 smpsi->buf[i] = BLANK;
    183 }
    184
    185 if( len < LINEWIDTH )
    186 clearFrom(smpsi->buf, len);
    187
    188 SCIPdebugMessage("line %d: <%s>\n", smpsi->lineno, smpsi->buf);
    189
    190 assert(strlen(smpsi->buf) >= LINEWIDTH);
    191
    192 /* Look for new section */
    193 if( *smpsi->buf != BLANK )
    194 {
    195 smpsi->f0 = SCIPstrtok(&smpsi->buf[0], " ", &nexttok);
    196
    197 assert(smpsi->f0 != 0);
    198
    199 smpsi->f1 = SCIPstrtok(NULL, " ", &nexttok);
    200
    201 return TRUE;
    202 }
    203
    204 /* check for empty lines */
    205 is_empty = (smpsi->f0 == NULL && smpsi->f1 == NULL);
    206 }
    207 while( is_marker || is_empty );
    208
    209 return TRUE;
    210}
    211
    212/*
    213 * Callback methods of reader
    214 */
    215
    216/** copy method for reader plugins (called when SCIP copies plugins) */
    217static
    218SCIP_DECL_READERCOPY(readerCopySmps)
    219{ /*lint --e{715}*/
    220 assert(scip != NULL);
    221 assert(reader != NULL);
    222 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
    223
    224 /* call inclusion method of reader */
    226
    227 return SCIP_OKAY;
    228}
    229
    230
    231/** problem reading method of reader */
    232static
    233SCIP_DECL_READERREAD(readerReadSmps)
    234{ /*lint --e{715}*/
    235 SCIP_FILE* fp;
    236 SMPSINPUT* smpsi;
    237 SCIP_RETCODE retcode = SCIP_OKAY;
    238
    239 char corfilename[SCIP_MAXSTRLEN];
    240 char timfilename[SCIP_MAXSTRLEN];
    241 char stofilename[SCIP_MAXSTRLEN];
    242 char* tmpfilename;
    243 char* probname;
    244 char* fileextension;
    245 char* fromlastslash;
    246 char parent[SCIP_MAXSTRLEN];
    247 size_t parentlen;
    248
    249 SCIP_Bool hascorfile;
    250 SCIP_Bool hastimfile;
    251 SCIP_Bool hasstofile;
    252
    253 int i;
    254
    255 assert(scip != NULL);
    256 assert(filename != NULL);
    257 assert(result != NULL);
    258
    259 *result = SCIP_DIDNOTRUN;
    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( SCIPstrcasecmp(fileextension, COR_FILEEXTENSION) == 0 )
    302 {
    303 (void) SCIPsnprintf(corfilename, SCIP_MAXSTRLEN, "%s%s", parent, smpsinputField0(smpsi));
    304 hascorfile = TRUE;
    305 }
    306 else if( SCIPstrcasecmp(fileextension, TIM_FILEEXTENSION) == 0 )
    307 {
    308 (void) SCIPsnprintf(timfilename, SCIP_MAXSTRLEN, "%s%s", parent, smpsinputField0(smpsi));
    309 hastimfile = TRUE;
    310 }
    311 else if( SCIPstrcasecmp(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
    424TERMINATE:
    425 smpsinputFree(scip, &smpsi);
    426
    427 /* freeing buffer array */
    428 SCIPfreeBufferArray(scip, &tmpfilename);
    429
    430 if( retcode == SCIP_PLUGINNOTFOUND )
    431 retcode = SCIP_READERROR;
    432
    433 if( retcode == SCIP_NOFILE || retcode == SCIP_READERROR )
    434 return retcode;
    435
    436 SCIP_CALL( retcode );
    437
    438 *result = SCIP_SUCCESS;
    439
    440 return SCIP_OKAY;
    441}
    442
    443
    444/*
    445 * reader specific interface methods
    446 */
    447
    448/** includes the smps file reader in SCIP */
    450 SCIP* scip /**< SCIP data structure */
    451 )
    452{
    453 SCIP_READER* reader;
    454
    455 /* include reader */
    457
    458 assert(reader != NULL);
    459
    460 /* set non fundamental callbacks via setter functions */
    461 SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopySmps) );
    462 SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadSmps) );
    463
    464 return SCIP_OKAY;
    465}
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #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:376
    #define SCIPABORT()
    Definition: def.h:327
    #define SCIP_CALL(x)
    Definition: def.h:355
    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:2861
    SCIP_RETCODE SCIPreadCor(SCIP *scip, const char *filename, SCIP_RESULT *result)
    Definition: reader_cor.c:200
    SCIP_RETCODE SCIPreadTim(SCIP *scip, const char *filename, SCIP_RESULT *result)
    Definition: reader_tim.c:893
    SCIP_RETCODE SCIPreadSto(SCIP *scip, const char *filename, SCIP_RESULT *result)
    Definition: reader_sto.c:2822
    void SCIPsplitFilename(char *filename, char **path, char **name, char **extension, char **compression)
    Definition: misc.c:11073
    SCIP_RETCODE SCIPincludeReaderSmps(SCIP *scip)
    Definition: reader_smps.c:449
    SCIP_RETCODE SCIPgetOrigVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2753
    int SCIPgetNOrigConss(SCIP *scip)
    Definition: scip_prob.c:3712
    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:680
    SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
    Definition: scip_reader.c:195
    int SCIPstrcasecmp(const char *s1, const char *s2)
    Definition: misc.c:10863
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    void SCIPprintSysError(const char *message)
    Definition: misc.c:10719
    int SCIPstrncpy(char *t, const char *s, int size)
    Definition: misc.c:10897
    char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
    Definition: misc.c:10768
    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:65
    static SCIP_RETCODE smpsinputCreate(SCIP *scip, SMPSINPUT **smpsi, SCIP_FILE *fp)
    Definition: reader_smps.c:92
    static SCIP_Bool smpsinputReadLine(SMPSINPUT *smpsi)
    Definition: reader_smps.c:150
    static SCIP_DECL_READERREAD(readerReadSmps)
    Definition: reader_smps.c:233
    static void clearFrom(char *buf, unsigned int pos)
    Definition: reader_smps.c:136
    #define TIM_FILEEXTENSION
    Definition: reader_smps.c:64
    #define BLANK
    Definition: reader_smps.c:60
    static SCIP_DECL_READERCOPY(readerCopySmps)
    Definition: reader_smps.c:218
    SCIP_SmpsFileType
    Definition: reader_smps.c:69
    @ SCIP_SMPSFILETYPE_STO
    Definition: reader_smps.c:72
    @ SCIP_SMPSFILETYPE_COR
    Definition: reader_smps.c:70
    @ SCIP_SMPSFILETYPE_TIM
    Definition: reader_smps.c:71
    #define READER_DESC
    Definition: reader_smps.c:56
    #define READER_EXTENSION
    Definition: reader_smps.c:57
    enum SCIP_SmpsFileType SCIP_SMPSFILETYPE
    Definition: reader_smps.c:74
    static void smpsinputFree(SCIP *scip, SMPSINPUT **smpsi)
    Definition: reader_smps.c:115
    #define LINEWIDTH
    Definition: reader_smps.c:61
    #define READER_NAME
    Definition: reader_smps.c:55
    #define SMPS_MAX_LINELEN
    Definition: reader_smps.c:59
    static const char * smpsinputField0(const SMPSINPUT *smpsi)
    Definition: reader_smps.c:125
    #define COR_FILEEXTENSION
    Definition: reader_smps.c:63
    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:975
    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:85
    SCIP_FILE * fp
    Definition: reader_smps.c:80
    char buf[SMPS_MAX_LINELEN]
    Definition: reader_smps.c:83
    const char * f0
    Definition: reader_smps.c:84
    int lineno
    Definition: reader_smps.c:81
    SCIP_Bool haserror
    Definition: reader_smps.c:82
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ 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