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