Scippy

SCIP

Solving Constraint Integer Programs

reader_bnd.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_bnd.c
26 * @ingroup DEFPLUGINS_READER
27 * @brief file reader for variable bounds
28 * @author Ambros Gleixner
29 * @author Ingmar Vierhaus
30 * @author Benjamin Mueller
31 *
32 * This reader allows to read a file containing new bounds for variables of the current problem. Each line of the file
33 * should have format
34 *
35 * <variable name> <lower bound> <upper bound>
36 *
37 * where infinite bounds can be written as inf, +inf or -inf. Note that only a subset of the variables may appear in
38 * the file. Lines with unknown variable names are ignored.
39 * The writing functionality can be used in problem and transformed stages. Note that in transformed stage,
40 * the leading "t_" in the name of a transformed variable will not appear in the output. This way, bounds written in transformed stage
41 * can be read again in problem stage.
42 */
43
44/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
45
46#include "scip/pub_fileio.h"
47#include "scip/pub_message.h"
48#include "scip/pub_misc.h"
49#include "scip/pub_reader.h"
50#include "scip/pub_var.h"
51#include "scip/reader_bnd.h"
52#include "scip/scip_general.h"
53#include "scip/scip_mem.h"
54#include "scip/scip_message.h"
55#include "scip/scip_numerics.h"
56#include "scip/scip_param.h"
57#include "scip/scip_reader.h"
58#include "scip/scip_var.h"
59#include <string.h>
60
61#if !defined(_WIN32) && !defined(_WIN64)
62#include <strings.h> /*lint --e{766}*/ /* needed for strncasecmp() */
63#endif
64
65
66#define READER_NAME "bndreader"
67#define READER_DESC "file reader for variable bounds"
68#define READER_EXTENSION "bnd"
69
70#define DEFAULT_IMPROVEONLY FALSE /**< only use improving bounds */
71
72
73/** BND reader data */
74struct SCIP_ReaderData
75{
76 SCIP_Bool improveonly; /**< only use improving bounds */
77};
78
79
80/*
81 * Local methods of reader
82 */
83
84/** reads a given bound file, problem has to be in problem stage */
85static
87 SCIP* scip, /**< SCIP data structure */
88 const char* fname, /**< name of the input file */
89 SCIP_READERDATA* readerdata /**< pointer to the data of the reader */
90 )
91{
92 SCIP_RETCODE retcode;
93 SCIP_FILE* file;
94 SCIP_Bool error;
95 SCIP_Bool unknownvariablemessage;
96 SCIP_Bool usevartable;
97 int lineno;
98
99 assert(scip != NULL);
100 assert(fname != NULL);
101
102 SCIP_CALL( SCIPgetBoolParam(scip, "misc/usevartable", &usevartable) );
103
104 if( !usevartable )
105 {
106 SCIPerrorMessage("Cannot read bounds file if vartable is disabled. Make sure parameter 'misc/usevartable' is set to TRUE.\n");
107 return SCIP_READERROR;
108 }
109
110 /* open input file */
111 file = SCIPfopen(fname, "r");
112 if( file == NULL )
113 {
114 SCIPerrorMessage("cannot open file <%s> for reading\n", fname);
115 SCIPprintSysError(fname);
116 return SCIP_NOFILE;
117 }
118
119 /* read the file */
120 error = FALSE;
121 unknownvariablemessage = FALSE;
122 lineno = 0;
123 while( !SCIPfeof(file) && !error )
124 {
125 char buffer[SCIP_MAXSTRLEN];
126 char varname[SCIP_MAXSTRLEN];
127 char lbstring[SCIP_MAXSTRLEN];
128 char ubstring[SCIP_MAXSTRLEN];
129 char format[SCIP_MAXSTRLEN];
130 SCIP_VAR* var;
131 SCIP_Real lb;
132 SCIP_Real ub;
133 int nread;
134 char* endptr;
135
136 /* get next line */
137 if( SCIPfgets(buffer, (int) sizeof(buffer), file) == NULL )
138 break;
139 lineno++;
140
141 /* parse the line */
142 (void) SCIPsnprintf(format, SCIP_MAXSTRLEN, "%%%ds %%%ds %%%ds\n", SCIP_MAXSTRLEN, SCIP_MAXSTRLEN, SCIP_MAXSTRLEN);
143 (void) sscanf(buffer, format, varname, lbstring, ubstring);
144
145 retcode = SCIPparseVarName(scip, buffer, &var, &endptr);
146 if( retcode != SCIP_OKAY )
147 {
148 SCIPerrorMessage("Error parsing variable name in line %d of bounds file <%s>\n", lineno, fname);
149 error = TRUE;
150 break;
151 }
152
153 (void) SCIPsnprintf(format, SCIP_MAXSTRLEN, "%%%ds %%%ds\n", SCIP_MAXSTRLEN, SCIP_MAXSTRLEN);
154 nread = sscanf(endptr, format, lbstring, ubstring);
155 if( nread < 1 )
156 {
157 SCIPerrorMessage("invalid input line %d in bounds file <%s>: <%s>\n", lineno, fname, buffer);
158 error = TRUE;
159 break;
160 }
161
162 if( var == NULL )
163 {
164 if( !unknownvariablemessage )
165 {
166 SCIPwarningMessage(scip, "unable to parse variable name in line %d of bounds file <%s>:\n", lineno, fname);
167 SCIPwarningMessage(scip, "line is: %s", buffer);
168 SCIPwarningMessage(scip, " (further unknown variables are ignored)\n");
169 unknownvariablemessage = TRUE;
170 }
171 continue;
172 }
173
174 /* cast the lower bound value */
175 if( strncasecmp(lbstring, "inv", 3) == 0 )
176 continue;
177 else if( strncasecmp(lbstring, "+inf", 4) == 0 || strncasecmp(lbstring, "inf", 3) == 0 )
178 lb = SCIPinfinity(scip);
179 else if( strncasecmp(lbstring, "-inf", 4) == 0 )
180 lb = -SCIPinfinity(scip);
181 else
182 {
183 nread = sscanf(lbstring, "%lf", &lb);
184 if( nread != 1 )
185 {
186 SCIPerrorMessage("invalid lower bound value <%s> for variable <%s> in line %d of bounds file <%s>\n",
187 lbstring, varname, lineno, fname);
188 error = TRUE;
189 break;
190 }
191 }
192
193 /* cast the upper bound value */
194 if( strncasecmp(ubstring, "inv", 3) == 0 )
195 continue;
196 else if( strncasecmp(ubstring, "+inf", 4) == 0 || strncasecmp(ubstring, "inf", 3) == 0 )
197 ub = SCIPinfinity(scip);
198 else if( strncasecmp(ubstring, "-inf", 4) == 0 )
199 ub = -SCIPinfinity(scip);
200 else
201 {
202 /* coverity[secure_coding] */
203 nread = sscanf(ubstring, "%lf", &ub);
204 if( nread != 1 )
205 {
206 SCIPerrorMessage("invalid lower bound value <%s> for variable <%s> in line %d of bounds file <%s>\n",
207 ubstring, varname, lineno, fname);
208 error = TRUE;
209 break;
210 }
211 }
212
213 if( readerdata->improveonly )
214 {
215 if( SCIPisLT(scip, lb, SCIPvarGetLbGlobal(var)) )
216 {
217 SCIPwarningMessage(scip, "not applying lower bound value %s for variable <%s> in line %d of bounds file %s,"
218 " because it does not improve existing bound of %f\n",
219 lbstring, SCIPvarGetName(var), lineno, fname, SCIPvarGetLbGlobal(var));
220 }
221 if( SCIPisGT(scip, ub, SCIPvarGetUbGlobal(var)) )
222 {
223 SCIPwarningMessage(scip, "not applying upper bound value %s for variable <%s> in line %d of bounds file %s, "
224 "because it does not improve existing bound of %f\n",
225 ubstring, SCIPvarGetName(var), lineno, fname, SCIPvarGetUbGlobal(var));
226 }
227
228 /* collect best variable bounds */
229 lb = MAX(lb, SCIPvarGetLbGlobal(var)); /*lint !e666*/
230 ub = MIN(ub, SCIPvarGetUbGlobal(var)); /*lint !e666*/
231 }
232
233 /* note that we don't need to check if lb > ub in SCIPchgVar{Lb,Ub} */
234 retcode = SCIPchgVarLb(scip, var, lb);
235 if( retcode != SCIP_OKAY )
236 {
237 SCIPerrorMessage("Error changing lower bound for variable <%s> in line %d of bounds file <%s>\n", varname, lineno, fname);
238 error = TRUE;
239 break;
240 }
241
242 retcode = SCIPchgVarUb(scip, var, ub);
243 if( retcode != SCIP_OKAY )
244 {
245 SCIPerrorMessage("Error changing upper bound for variable <%s> in line %d of bounds file <%s>\n", varname, lineno, fname);
246 error = TRUE;
247 break;
248 }
249 }
250
251 /* close input file */
252 SCIPfclose(file);
253
254 /* return error if necessary */
255 if ( error )
256 return SCIP_READERROR;
257
258 return SCIP_OKAY;
259}
260
261
262/*
263 * Callback methods of reader
264 */
265
266/** copy method for reader plugins (called when SCIP copies plugins) */
267static
269{ /*lint --e{715}*/
270 assert(scip != NULL);
271 assert(reader != NULL);
272 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
273
274 /* call inclusion method of reader */
276
277 return SCIP_OKAY;
278}
279
280
281/** problem reading method of reader
282 *
283 * In order to determine the type of the file, we have to open it. Thus, it has to be opened
284 * twice. This might be removed, but is likely to not hurt the performance too much.
285 */
286static
288{ /*lint --e{715}*/
289 assert(reader != NULL);
290 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
291 assert(result != NULL);
292
293 *result = SCIP_DIDNOTRUN;
294
296 {
297 SCIPerrorMessage("reading of bounds file is only possible after a problem was created\n");
298 return SCIP_READERROR;
299 }
300
302 {
303 SCIPerrorMessage("reading of bounds file is only possible during problem creation stage\n");
304 return SCIP_READERROR;
305 }
306
307 /* read bounds file */
308 SCIP_CALL( readBounds(scip, filename, SCIPreaderGetData(reader)) );
309
310 *result = SCIP_SUCCESS;
311
312 return SCIP_OKAY;
313}
314
315/** outputs given bounds into a file stream */
316static
318 SCIP* scip, /**< SCIP data structure */
319 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
320 FILE* file, /**< file stream to print into, or NULL for stdout */
321 SCIP_Real lb, /**< lower bound */
322 SCIP_Real ub /**< upper bound */
323 )
324{
325 /* print lower bound */
326 if( SCIPisInfinity(scip, lb) )
327 SCIPmessageFPrintInfo(messagehdlr, file, "+inf ");
328 else if( SCIPisInfinity(scip, -lb) )
329 SCIPmessageFPrintInfo(messagehdlr, file, "-inf ");
330 else
331 SCIPmessageFPrintInfo(messagehdlr, file, "%.15" SCIP_REAL_FORMAT " ", lb);
332
333 /* print upper bound */
334 if( SCIPisInfinity(scip, ub) )
335 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
336 else if( SCIPisInfinity(scip, -ub) )
337 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
338 else
339 SCIPmessageFPrintInfo(messagehdlr, file, "%.15" SCIP_REAL_FORMAT, ub);
340}
341
342/** writes problem to file */
343static
345 SCIP* scip, /**< SCIP data structure */
346 FILE* file, /**< file stream to print into, or NULL for stdout */
347 SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
348 int nvars, /**< number of active variables in the problem */
349 SCIP_RESULT* result /**< pointer to store the result of the file writing call */
350 )
351{
352 SCIP_MESSAGEHDLR* messagehdlr;
353 SCIP_Real lb;
354 SCIP_Real ub;
355 int i;
356
357 assert(result != NULL);
358
359 messagehdlr = SCIPgetMessagehdlr(scip);
360 *result = SCIP_SUCCESS;
361
362 if( nvars == 0 )
363 {
364 SCIPwarningMessage(scip, "Problem has no variables, no bounds written.\n");
365 return SCIP_OKAY;
366 }
367
368 for( i = 0; i < nvars; ++i )
369 {
370 SCIP_VAR* var;
371 const char* varname;
372
373 var = vars[i];
374 assert( var != NULL );
375 varname = SCIPvarGetName(var);
376
377 /* strip 't_' from varname */
378 if( SCIPvarIsTransformedOrigvar(var) && strncmp(SCIPvarGetName(var), "t_", 2) == 0)
379 {
380 varname = varname + 2;
381 }
382
383 SCIPinfoMessage(scip, file, "<%s> ", varname);
384
385 /* print global bounds for transformed variables, original bounds for original variables */
386 if( !SCIPvarIsTransformed(var) )
387 {
388 lb = SCIPvarGetLbOriginal(var);
389 ub = SCIPvarGetUbOriginal(var);
390 }
391 else
392 {
393 lb = SCIPvarGetLbGlobal(var);
394 ub = SCIPvarGetUbGlobal(var);
395 }
396
397 /* print bounds into the file */
398 printBounds(scip, messagehdlr, file, lb, ub);
399 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
400 }
401
402 return SCIP_OKAY;
403}
404
405/** problem writing method of reader */
406static
408{ /*lint --e{715}*/
409 assert(reader != NULL);
410 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
411
412 SCIP_CALL( SCIPwriteBnd(scip, file, vars, nvars, result) );
413
414 return SCIP_OKAY;
415}
416
417/** destructor of reader to free reader data (called when SCIP is exiting) */
418static
420{
421 SCIP_READERDATA* readerdata;
422
423 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
424 readerdata = SCIPreaderGetData(reader);
425 assert(readerdata != NULL);
426 SCIPfreeBlockMemory(scip, &readerdata);
427
428 return SCIP_OKAY;
429}
430
431/*
432 * bnd file reader specific interface methods
433 */
434
435/** includes the bnd file reader in SCIP */
437 SCIP* scip /**< SCIP data structure */
438 )
439{
440 SCIP_READERDATA* readerdata;
441 SCIP_READER* reader;
442
443 /* create reader data */
444 SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata) );
445
446 /* include reader */
448
449 /* set non fundamental callbacks via setter functions */
450 SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyBnd) );
451 SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadBnd) );
452 SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteBnd) );
453 SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeBnd) );
454
455 /* add bnd reader parameters */
457 "reading/bndreader/improveonly", "only use improving bounds",
458 &readerdata->improveonly, FALSE, DEFAULT_IMPROVEONLY, NULL, NULL) );
459
460 return SCIP_OKAY;
461}
#define NULL
Definition: def.h:267
#define SCIP_MAXSTRLEN
Definition: def.h:288
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:243
#define SCIP_Real
Definition: def.h:173
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:239
#define SCIP_REAL_FORMAT
Definition: def.h:176
#define SCIP_CALL(x)
Definition: def.h:374
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:153
int SCIPfeof(SCIP_FILE *stream)
Definition: fileio.c:227
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:232
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:200
SCIP_RETCODE SCIPincludeReaderBnd(SCIP *scip)
Definition: reader_bnd.c:436
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:380
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:88
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:250
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
#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
SCIP_READERDATA * SCIPreaderGetData(SCIP_READER *reader)
Definition: reader.c:492
SCIP_RETCODE SCIPsetReaderFree(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERFREE((*readerfree)))
Definition: scip_reader.c:171
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
SCIP_RETCODE SCIPsetReaderWrite(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERWRITE((*readerwrite)))
Definition: scip_reader.c:219
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4676
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:18024
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17561
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4766
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip_var.c:533
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18088
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17419
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:18044
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12861
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18078
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10877
void SCIPprintSysError(const char *message)
Definition: misc.c:10769
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
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
public data structures and miscellaneous methods
public methods for input file readers
public methods for problem variables
#define DEFAULT_IMPROVEONLY
Definition: reader_bnd.c:70
static SCIP_RETCODE readBounds(SCIP *scip, const char *fname, SCIP_READERDATA *readerdata)
Definition: reader_bnd.c:86
static SCIP_DECL_READERCOPY(readerCopyBnd)
Definition: reader_bnd.c:268
static SCIP_DECL_READERWRITE(readerWriteBnd)
Definition: reader_bnd.c:407
static SCIP_DECL_READERREAD(readerReadBnd)
Definition: reader_bnd.c:287
#define READER_DESC
Definition: reader_bnd.c:67
static void printBounds(SCIP *scip, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub)
Definition: reader_bnd.c:317
#define READER_EXTENSION
Definition: reader_bnd.c:68
static SCIP_DECL_READERFREE(readerFreeBnd)
Definition: reader_bnd.c:419
#define READER_NAME
Definition: reader_bnd.c:66
static SCIP_RETCODE SCIPwriteBnd(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_RESULT *result)
Definition: reader_bnd.c:344
file reader for variable bounds
general public methods
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for reader plugins
public methods for SCIP variables
struct SCIP_ReaderData SCIP_READERDATA
Definition: type_reader.h:53
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_SUCCESS
Definition: type_result.h:58
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ 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
@ SCIP_STAGE_PROBLEM
Definition: type_set.h:45