Scippy

    SCIP

    Solving Constraint Integer Programs

    reader_sch.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_sch.c
    26 * @brief scheduling problem file reader for RCPSP/max format
    27 * @author Stefan Heinz
    28 *
    29 * This reader is capabale of parsing resource-constrained project scheduling problem with minimal and maximal time lags
    30 * (RCPSP/max) instances. The <a http://www.wior.uni-karlsruhe.de/LS_Neumann/Forschung/ProGenMax/rcpspmax.html">PSPlib</a>
    31 * provides several instances set.
    32 *
    33 */
    34
    35/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    36
    37#include <assert.h>
    38#include <string.h>
    39#include <ctype.h>
    40
    41#include "reader_sch.h"
    42#include "reader_sm.h"
    43
    45
    46
    47#define READER_NAME "schreader"
    48#define READER_DESC "scheduling file reader for sch files (RCPSP/max format)"
    49#define READER_EXTENSION "sch"
    50
    51
    52#define SCH_MAX_LINELEN 65536 /**< size of the line buffer for reading or writing */
    53
    54/*
    55 * Local methods
    56 */
    57
    58static
    60 SCIP* scip /**< SCIP data structure */
    61 )
    62{
    63 SCIP_CONS* cons;
    64 SCIP_VAR** vars;
    65 SCIP_Real* bounds;
    66 SCIP_BOUNDTYPE* boundtypes;
    67 int nvars;
    68 int v;
    69
    70 nvars = SCIPgetNVars(scip);
    71 vars = SCIPgetVars(scip);
    72
    73 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nvars) );
    74 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nvars) );
    75
    76 for( v = 0; v < nvars; ++v )
    77 {
    78 bounds[v] = SCIPvarGetLbGlobal(vars[v]);
    79 boundtypes[v] = SCIP_BOUNDTYPE_UPPER;
    80 }
    81
    82 /* add a constraint that at least one jobs needs to start at its lower bound */
    83 SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, "lowerbound", nvars, vars, boundtypes, bounds,
    85
    86 SCIP_CALL( SCIPaddCons(scip, cons) );
    88
    89 SCIPfreeBufferArray(scip, &boundtypes);
    90 SCIPfreeBufferArray(scip, &bounds);
    91
    92 return SCIP_OKAY;
    93}
    94
    95
    96
    97/** parse job id and check if only one job mode is present */
    98static
    100 SCIP* scip, /**< SCIP data structure */
    101 const char* str, /**< string to search */
    102 int* job, /**< pointer to store the parsed job id */
    103 char** endptr /**< pointer to store the final string position if successfully parsed */
    104 )
    105{
    106 int mode;
    107
    108 /* get job id */
    109 if( !SCIPstrToIntValue(str, job, endptr) )
    110 return SCIP_READERROR;
    111
    112 /* get job mode */
    113 if( !SCIPstrToIntValue(*endptr, &mode, endptr) )
    114 return SCIP_READERROR;
    115
    116 if( mode != 1 )
    117 {
    118 SCIPwarningMessage(scip, "jobs with different modes are not supported\n");
    119 return SCIP_READERROR;
    120 }
    121
    122 return SCIP_OKAY;
    123}
    124
    125/** parse job and capacities details */
    126static
    128 SCIP* scip, /**< SCIP data structure */
    129 SCIP_FILE* file, /**< file to parse */
    130 int* lineno, /**< pointer to store line number of the file */
    131 int** demands, /**< demand matrix resource job demand */
    132 SCIP_DIGRAPH* precedencegraph, /**< direct graph to store the precedence conditions */
    133 int* durations, /**< array to store the processing for each job */
    134 int* capacities, /**< array to store the different capacities */
    135 int njobs, /**< number of jobs to be parsed */
    136 int nresources /**< number of capacities to be parsed */
    137 )
    138{
    139 char buf[SCH_MAX_LINELEN];
    140 char* endptr;
    141 int j;
    142
    143 /* get data for each job including a dummy job at the beginning and a dummy job at the end */
    144 for( j = 0; j < njobs; ++j )
    145 {
    146 if( NULL != SCIPfgets(buf, (int) sizeof(buf), file) )
    147 {
    148 int* successors;
    149 int distance;
    150 int nsuccessors;
    151 int job;
    152 int s;
    153
    154 /* get job id and check if only one mode is present */
    155 SCIP_CALL( getJobId(scip, buf, &job, &endptr) );
    156
    157 SCIPdebugMessage("job %d -> ", j);
    158
    159 /* get number of direct successors */
    160 if( !SCIPstrToIntValue(endptr, &nsuccessors, &endptr) )
    161 return SCIP_READERROR;
    162
    163 /* allocate buffer to temporarily collect the successors */
    164 SCIP_CALL( SCIPallocBufferArray(scip, &successors, nsuccessors) );
    165
    166 /* parse successor job ids */
    167 for( s = 0; s < nsuccessors; ++s )
    168 {
    169 if( !SCIPstrToIntValue(endptr, &successors[s], &endptr) )
    170 return SCIP_READERROR;
    171 }
    172
    173 /* parse distances between the job and its successor and add the arc with their data to the precedence graph */
    174 for( s = 0; s < nsuccessors; ++s )
    175 {
    176 char token[SCIP_MAXSTRLEN];
    177 char* tmpptr;
    178
    179 SCIPstrCopySection(endptr, '[', ']', token, SCIP_MAXSTRLEN, &endptr);
    180
    181 if( SCIPstrToIntValue(token, &distance, &tmpptr) )
    182 {
    183 SCIP_CALL( SCIPdigraphAddArc(precedencegraph, job, successors[s], (void*)(size_t)distance) ); /*lint !e571*/
    184
    185 SCIPdebugPrintf(" %d[%d] ", successors[s], distance);
    186 }
    187 else
    188 return SCIP_READERROR;
    189 }
    190
    191 SCIPdebugPrintf("\n");
    192
    193 /* free the buffers */
    194 SCIPfreeBufferArray(scip, &successors);
    195 }
    196 else
    197 return SCIP_READERROR;
    198
    199 (*lineno)++;
    200 }
    201
    202 /* get data for each job including a dummy job at the beginning and a dummy job at the end */
    203 for( j = 0; j < njobs; ++j )
    204 {
    205 if( NULL != SCIPfgets(buf, (int) sizeof(buf), file) )
    206 {
    207 int job;
    208 int r;
    209
    210 /* get job id and check if only one mode is present */
    211 SCIP_CALL( getJobId(scip, buf, &job, &endptr) );
    212
    213 /* get processing time */
    214 if( !SCIPstrToIntValue(endptr, &durations[job], &endptr) )
    215 return SCIP_READERROR;
    216
    217 SCIPdebugMessage("job %d has a processing times: %d\n", job, durations[job]);
    218
    219 for( r = 0; r < nresources; ++r )
    220 {
    221 if( !SCIPstrToIntValue(endptr, &demands[job][r], &endptr) )
    222 return SCIP_READERROR;
    223 }
    224 }
    225 else
    226 return SCIP_READERROR;
    227
    228 (*lineno)++;
    229 }
    230
    231 /* get resources capacities */
    232 if( nresources > 0 && NULL != SCIPfgets(buf, (int) sizeof(buf), file) )
    233 {
    234 int r;
    235
    236 SCIPdebugMessage("line %d %s", *lineno, buf);
    237
    238 if( !SCIPstrToIntValue(buf, &capacities[0], &endptr) )
    239 return SCIP_READERROR;
    240
    241 SCIPdebugMessage("paresed capacities: <%d>", capacities[0]);
    242
    243 for( r = 1; r < nresources; ++r )
    244 {
    245 if( !SCIPstrToIntValue(endptr, &capacities[r], &endptr) )
    246 return SCIP_READERROR;
    247
    248 SCIPdebugPrintf(", <%d>", capacities[r]);
    249 }
    250
    251 SCIPdebugPrintf("\n");
    252 }
    253 else
    254 return SCIP_READERROR;
    255
    256 (*lineno)++;
    257
    258 return SCIP_OKAY;
    259}
    260
    261/** read file and create problem */
    262static
    264 SCIP* scip, /**< SCIP data structure */
    265 SCIP_FILE* file, /**< file to pares */
    266 const char* filename /**< name of input file */
    267 )
    268{
    269 SCIP_RETCODE retcode;
    270 char buf[SCH_MAX_LINELEN];
    271 SCIP_DIGRAPH* precedencegraph;
    272 int** demands;
    273 int* durations;
    274 int* capacities;
    275 int lineno;
    276 int njobs;
    277 int nresources;
    278 int j;
    279
    280 assert(scip != NULL);
    281 assert(file != NULL);
    282 assert(filename != NULL);
    283
    284 lineno = 0;
    285
    286 /* get number of jobs and resources */
    287 if( NULL != SCIPfgets(buf, (int) sizeof(buf), file) )
    288 {
    289 char* endptr;
    290 int value;
    291
    292 lineno++;
    293
    294 if( !SCIPstrToIntValue(buf, &value, &endptr) )
    295 return SCIP_READERROR;
    296
    297 /* note that this format includes two dummy jobs */
    298 njobs = value + 2;
    299
    300 /* get number of resources */
    301 if( !SCIPstrToIntValue(endptr, &nresources, &endptr) )
    302 return SCIP_READERROR;
    303 }
    304 else
    305 return SCIP_READERROR;
    306
    307 SCIP_CALL( SCIPallocBufferArray(scip, &capacities, nresources) );
    308 SCIP_CALL( SCIPallocBufferArray(scip, &durations, njobs) );
    309 SCIP_CALL( SCIPallocBufferArray(scip, &demands, njobs) );
    310
    311 for( j = 0; j < njobs; ++j )
    312 {
    313 SCIP_CALL( SCIPallocBufferArray(scip, &demands[j], nresources) ); /*lint !e866*/
    314 BMSclearMemoryArray(demands[j], nresources); /*lint !e866*/
    315 }
    316
    317 SCIP_CALL( SCIPcreateDigraph(scip, &precedencegraph, njobs) );
    318
    319 SCIPdebugMessage("problem has <%d> jobs and <%d> resources\n", njobs, nresources);
    320
    321 retcode = parseDetails(scip, file, &lineno, demands, precedencegraph, durations, capacities, njobs, nresources);
    322
    323 if( retcode == SCIP_OKAY )
    324 {
    325 SCIP_CALL( SCIPcreateSchedulingProblem(scip, filename, NULL, NULL, demands,
    326 precedencegraph, durations, capacities, njobs, nresources, FALSE) );
    327 }
    328
    329 /* add constraint that at least one job needs to start on its lower bound */
    331
    332 /* free the precedence graph */
    333 SCIPdigraphFree(&precedencegraph);
    334
    335 /* free buffer before evaluating the retcode */
    336 for( j = njobs - 1; j >= 0; --j )
    337 {
    338 SCIPfreeBufferArray(scip, &demands[j]);
    339 }
    340 SCIPfreeBufferArray(scip, &demands);
    341 SCIPfreeBufferArray(scip, &durations);
    342 SCIPfreeBufferArray(scip, &capacities);
    343
    344 SCIP_CALL( retcode );
    345
    346 return SCIP_OKAY;
    347}
    348
    349
    350/*
    351 * Callback methods of reader
    352 */
    353
    354/** copy method for reader plugins (called when SCIP copies plugins) */
    355static
    357{ /*lint --e{715}*/
    358 assert(scip != NULL);
    359 assert(reader != NULL);
    360 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
    361
    362 /* call inclusion method of reader handler */
    364
    365 return SCIP_OKAY;
    366}/*lint !e830*/
    367
    368/** problem reading method of reader */
    369static
    371{ /*lint --e{715}*/
    372 SCIP_FILE* file;
    373 SCIP_RETCODE retcode;
    374
    375 if( NULL == (file = SCIPfopen(filename, "r")) )
    376 {
    377 SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
    378 SCIPprintSysError(filename);
    379 return SCIP_NOFILE;
    380 }
    381
    382 /* read file */
    383 retcode = readFile(scip, file, filename);
    384
    385 /* close file */
    386 SCIPfclose(file);
    387
    388 /* check retcode after the file was closed */
    389 SCIP_CALL( retcode );
    390
    391 (*result) = SCIP_SUCCESS;
    392
    393 return SCIP_OKAY;
    394}/*lint !e830*/
    395
    396#ifdef SCIP_DISABLED_CODE
    397/** destructor of reader to free user data (called when SCIP is exiting) */
    398#define readerFreeSch NULL
    399
    400/** problem writing method of reader */
    401#define readerWriteSch NULL
    402#endif
    403
    404/*
    405 * reader specific interface methods
    406 */
    407
    408/** includes the sch file reader in SCIP */
    410 SCIP* scip /**< SCIP data structure */
    411 )
    412{
    413 SCIP_READERDATA* readerdata;
    414 SCIP_READER* reader;
    415
    416 /* create sch reader data */
    417 readerdata = NULL;
    418
    419 /* include sch reader */
    421 assert(reader != NULL);
    422
    423 SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopySch) );
    424 SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadSch) );
    425
    426 /* add reader parameters */
    428 "reading/"READER_NAME"/mipmodel", "create MIP model?",
    429 NULL, FALSE, FALSE, NULL, NULL) );
    430
    431 return SCIP_OKAY;
    432}
    SCIP_Real * r
    Definition: circlepacking.c:59
    constraint handler for bound disjunction constraints
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #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
    SCIP_RETCODE SCIPcreateConsBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
    Definition: misc.c:7739
    void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
    Definition: misc.c:7645
    SCIP_RETCODE SCIPcreateDigraph(SCIP *scip, SCIP_DIGRAPH **digraph, int nnodes)
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    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:57
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    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
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_Bool SCIPstrToIntValue(const char *str, int *value, char **endptr)
    Definition: misc.c:10924
    void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
    Definition: misc.c:10985
    void SCIPprintSysError(const char *message)
    Definition: misc.c:10719
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    struct SCIP_File SCIP_FILE
    Definition: pub_fileio.h:43
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    #define SCIPdebugPrintf
    Definition: pub_message.h:99
    static SCIP_DECL_READERCOPY(readerCopySch)
    Definition: reader_sch.c:356
    static SCIP_RETCODE addLowerboundCons(SCIP *scip)
    Definition: reader_sch.c:59
    #define READER_DESC
    Definition: reader_sch.c:48
    static SCIP_RETCODE readFile(SCIP *scip, SCIP_FILE *file, const char *filename)
    Definition: reader_sch.c:263
    static SCIP_RETCODE getJobId(SCIP *scip, const char *str, int *job, char **endptr)
    Definition: reader_sch.c:99
    static SCIP_DECL_READERREAD(readerReadSch)
    Definition: reader_sch.c:370
    #define SCH_MAX_LINELEN
    Definition: reader_sch.c:52
    #define READER_EXTENSION
    Definition: reader_sch.c:49
    SCIP_RETCODE SCIPincludeReaderSch(SCIP *scip)
    Definition: reader_sch.c:409
    static SCIP_RETCODE parseDetails(SCIP *scip, SCIP_FILE *file, int *lineno, int **demands, SCIP_DIGRAPH *precedencegraph, int *durations, int *capacities, int njobs, int nresources)
    Definition: reader_sch.c:127
    #define READER_NAME
    Definition: reader_sch.c:47
    scheduling problem file reader for RCPSP/max format
    SCIP_RETCODE SCIPcreateSchedulingProblem(SCIP *scip, const char *problemname, const char **jobnames, const char **resourcenames, int **demands, SCIP_DIGRAPH *precedencegraph, int *durations, int *capacities, int njobs, int nresources, SCIP_Bool initialize)
    Definition: reader_sm.c:747
    scheduling problem file reader for RCPSP format
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    enum SCIP_BoundType SCIP_BOUNDTYPE
    Definition: type_lp.h:60
    struct SCIP_ReaderData SCIP_READERDATA
    Definition: type_reader.h:54
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_NOFILE
    Definition: type_retcode.h:47
    @ SCIP_READERROR
    Definition: type_retcode.h:45
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63