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-2018 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  nread = sscanf(ubstring, "%lf", &ub);
186  if( nread != 1 )
187  {
188  SCIPerrorMessage("invalid lower bound value <%s> for variable <%s> in line %d of bounds file <%s>\n",
189  ubstring, varname, lineno, fname);
190  error = TRUE;
191  break;
192  }
193  }
194 
195  if( readerdata->improveonly )
196  {
197  if( SCIPisLT(scip, lb, SCIPvarGetLbGlobal(var)) )
198  {
199  SCIPwarningMessage(scip, "not applying lower bound value %s for variable <%s> in line %d of bounds file %s,"
200  " because it does not improve existing bound of %f\n",
201  lbstring, SCIPvarGetName(var), lineno, fname, SCIPvarGetLbGlobal(var));
202  }
203  if( SCIPisGT(scip, ub, SCIPvarGetUbGlobal(var)) )
204  {
205  SCIPwarningMessage(scip, "not applying upper bound value %s for variable <%s> in line %d of bounds file %s, "
206  "because it does not improve existing bound of %f\n",
207  ubstring, SCIPvarGetName(var), lineno, fname, SCIPvarGetUbGlobal(var));
208  }
209 
210  /* collect best variable bounds */
211  lb = MAX(lb, SCIPvarGetLbGlobal(var)); /*lint !e666*/
212  ub = MIN(ub, SCIPvarGetUbGlobal(var)); /*lint !e666*/
213  }
214 
215  /* note that we don't need to check if lb > ub in SCIPchgVar{Lb,Ub} */
216  SCIP_CALL( SCIPchgVarLb(scip, var, lb) );
217  SCIP_CALL( SCIPchgVarUb(scip, var, ub) );
218  }
219 
220  /* close input file */
221  SCIPfclose(file);
222 
223  /* return error if necessary */
224  if ( error )
225  return SCIP_READERROR;
226 
227  return SCIP_OKAY;
228 }
229 
230 
231 /*
232  * Callback methods of reader
233  */
234 
235 /** copy method for reader plugins (called when SCIP copies plugins) */
236 static
237 SCIP_DECL_READERCOPY(readerCopyBnd)
238 { /*lint --e{715}*/
239  assert(scip != NULL);
240  assert(reader != NULL);
241  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
242 
243  /* call inclusion method of reader */
245 
246  return SCIP_OKAY;
247 }
248 
249 
250 /** problem reading method of reader
251  *
252  * In order to determine the type of the file, we have to open it. Thus, it has to be opened
253  * twice. This might be removed, but is likely to not hurt the performance too much.
254  */
255 static
256 SCIP_DECL_READERREAD(readerReadBnd)
257 { /*lint --e{715}*/
258  assert(reader != NULL);
259  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
260  assert(result != NULL);
261 
262  *result = SCIP_DIDNOTRUN;
263 
265  {
266  SCIPerrorMessage("reading of bounds file is only possible after a problem was created\n");
267  return SCIP_READERROR;
268  }
269 
271  {
272  SCIPerrorMessage("reading of bounds file is only possible during problem creation stage\n");
273  return SCIP_READERROR;
274  }
275 
276  /* read bounds file */
277  SCIP_CALL( readBounds(scip, filename, SCIPreaderGetData(reader)) );
278 
279  *result = SCIP_SUCCESS;
280 
281  return SCIP_OKAY;
282 }
283 
284 /** outputs given bounds into a file stream */
285 static
287  SCIP* scip, /**< SCIP data structure */
288  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
289  FILE* file, /**< file stream to print into, or NULL for stdout */
290  SCIP_Real lb, /**< lower bound */
291  SCIP_Real ub /**< upper bound */
292  )
293 {
294  /* print lower bound */
295  if( SCIPisInfinity(scip, lb) )
296  SCIPmessageFPrintInfo(messagehdlr, file, "+inf ");
297  else if( SCIPisInfinity(scip, -lb) )
298  SCIPmessageFPrintInfo(messagehdlr, file, "-inf ");
299  else
300  SCIPmessageFPrintInfo(messagehdlr, file, "%.15" SCIP_REAL_FORMAT " ", lb);
301 
302  /* print upper bound */
303  if( SCIPisInfinity(scip, ub) )
304  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
305  else if( SCIPisInfinity(scip, -ub) )
306  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
307  else
308  SCIPmessageFPrintInfo(messagehdlr, file, "%.15" SCIP_REAL_FORMAT, ub);
309 }
310 
311 /** writes problem to file */
312 static
314  SCIP* scip, /**< SCIP data structure */
315  FILE* file, /**< file stream to print into, or NULL for stdout */
316  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
317  int nvars, /**< number of active variables in the problem */
318  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
319  )
320 {
321  SCIP_MESSAGEHDLR* messagehdlr;
322  SCIP_Real lb;
323  SCIP_Real ub;
324  int i;
325 
326  assert(result != NULL);
327 
328  messagehdlr = SCIPgetMessagehdlr(scip);
329  *result = SCIP_SUCCESS;
330 
331  if( nvars == 0 )
332  {
333  SCIPwarningMessage(scip, "Problem has no variables, no bounds written.\n");
334  return SCIP_OKAY;
335  }
336 
337  for( i = 0; i < nvars; ++i )
338  {
339  SCIP_VAR* var;
340  const char* varname;
341 
342  var = vars[i];
343  assert( var != NULL );
344  varname = SCIPvarGetName(var);
345 
346  /* strip 't_' from varname */
347  if( SCIPvarIsTransformedOrigvar(var) && strncmp(SCIPvarGetName(var), "t_", 2) == 0)
348  {
349  varname = varname + 2;
350  }
351 
352  SCIPinfoMessage(scip, file, "<%s> ", varname);
353 
354  /* print global bounds for transformed variables, original bounds for original variables */
355  if( !SCIPvarIsTransformed(var) )
356  {
357  lb = SCIPvarGetLbOriginal(var);
358  ub = SCIPvarGetUbOriginal(var);
359  }
360  else
361  {
362  lb = SCIPvarGetLbGlobal(var);
363  ub = SCIPvarGetUbGlobal(var);
364  }
365 
366  /* print bounds into the file */
367  printBounds(scip, messagehdlr, file, lb, ub);
368  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
369  }
370 
371  return SCIP_OKAY;
372 }
373 
374 /** problem writing method of reader */
375 static
376 SCIP_DECL_READERWRITE(readerWriteBnd)
377 { /*lint --e{715}*/
378  assert(reader != NULL);
379  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
380 
381  SCIP_CALL( SCIPwriteBnd(scip, file, vars, nvars, result) );
382 
383  return SCIP_OKAY;
384 }
385 
386 /** destructor of reader to free reader data (called when SCIP is exiting) */
387 static
388 SCIP_DECL_READERFREE(readerFreeBnd)
389 {
390  SCIP_READERDATA* readerdata;
391 
392  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
393  readerdata = SCIPreaderGetData(reader);
394  assert(readerdata != NULL);
395  SCIPfreeBlockMemory(scip, &readerdata);
396 
397  return SCIP_OKAY;
398 }
399 
400 /*
401  * bnd file reader specific interface methods
402  */
403 
404 /** includes the bnd file reader in SCIP */
406  SCIP* scip /**< SCIP data structure */
407  )
408 {
409  SCIP_READERDATA* readerdata;
410  SCIP_READER* reader;
411 
412  /* create reader data */
413  SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata) );
414 
415  /* include reader */
417 
418  /* set non fundamental callbacks via setter functions */
419  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyBnd) );
420  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadBnd) );
421  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteBnd) );
422  SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeBnd) );
423 
424  /* add bnd reader parameters */
426  "reading/bndreader/improveonly", "only use improving bounds",
427  &readerdata->improveonly, FALSE, DEFAULT_IMPROVEONLY, NULL, NULL) );
428 
429  return SCIP_OKAY;
430 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define NULL
Definition: def.h:239
public methods for SCIP parameter handling
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:412
public methods for memory management
static SCIP_DECL_READERCOPY(readerCopyBnd)
Definition: reader_bnd.c:237
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17343
#define SCIP_MAXSTRLEN
Definition: def.h:260
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:547
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip_var.c:523
static SCIP_RETCODE readBounds(SCIP *scip, const char *fname, SCIP_READERDATA *readerdata)
Definition: reader_bnd.c:76
#define FALSE
Definition: def.h:65
#define READER_NAME
Definition: reader_bnd.c:56
SCIP_RETCODE SCIPincludeReaderBnd(SCIP *scip)
Definition: reader_bnd.c:405
SCIP_Real SCIPinfinity(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10017
#define TRUE
Definition: def.h:64
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
public methods for problem variables
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:114
#define READER_DESC
Definition: reader_bnd.c:57
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:171
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4613
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:97
public methods for SCIP variables
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:203
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:279
file reader for variable bounds
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:286
#define SCIP_REAL_FORMAT
Definition: def.h:153
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:140
SCIP_READERDATA * SCIPreaderGetData(SCIP_READER *reader)
Definition: reader.c:482
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17353
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17289
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17309
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12340
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
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4703
static SCIP_RETCODE SCIPwriteBnd(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_RESULT *result)
Definition: reader_bnd.c:313
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16729
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:322
#define DEFAULT_IMPROVEONLY
Definition: reader_bnd.c:60
#define SCIP_CALL(x)
Definition: def.h:351
wrapper functions to map file i/o to standard or zlib file i/o
struct SCIP_ReaderData SCIP_READERDATA
Definition: type_reader.h:37
public data structures and miscellaneous methods
#define SCIP_Bool
Definition: def.h:62
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip_reader.c:180
void SCIPprintSysError(const char *message)
Definition: misc.c:9926
#define MIN(x, y)
Definition: def.h:209
SCIP_RETCODE SCIPsetReaderWrite(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERWRITE((*readerwrite)))
Definition: scip_reader.c:290
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip_reader.c:218
general public methods
#define MAX(x, y)
Definition: def.h:208
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
static SCIP_DECL_READERFREE(readerFreeBnd)
Definition: reader_bnd.c:388
public methods for message output
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:608
static SCIP_DECL_READERREAD(readerReadBnd)
Definition: reader_bnd.c:256
#define SCIP_Real
Definition: def.h:150
public methods for input file readers
public methods for message handling
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip_reader.c:266
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16871
#define READER_EXTENSION
Definition: reader_bnd.c:58
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:219
public methods for reader plugins
SCIP_RETCODE SCIPsetReaderFree(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERFREE((*readerfree)))
Definition: scip_reader.c:242
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:129
static SCIP_DECL_READERWRITE(readerWriteBnd)
Definition: reader_bnd.c:376