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