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