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