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