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