Scippy

SCIP

Solving Constraint Integer Programs

reader_sol.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-2016 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_sol.c
17  * @brief file reader for primal solutions
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Marc Pfetsch
21  *
22  */
23 
24 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
25 
26 #include <assert.h>
27 #include <string.h>
28 #include <ctype.h>
29 
30 #include "scip/reader_sol.h"
31 #include "xml/xml.h"
32 
33 #define READER_NAME "solreader"
34 #define READER_DESC "file reader for primal solutions"
35 #define READER_EXTENSION "sol"
36 
37 
38 /*
39  * Local methods of reader
40  */
41 
42 /** reads a given SCIP solution file, problem has to be transformed in advance */
43 static
45  SCIP* scip, /**< SCIP data structure */
46  const char* fname /**< name of the input file */
47  )
48 {
49  SCIP_SOL* sol;
50  SCIP_FILE* file;
51  SCIP_Bool error;
52  SCIP_Bool unknownvariablemessage;
53  SCIP_Bool stored;
54  SCIP_Bool usevartable;
55  int lineno;
56 
57  assert(scip != NULL);
58  assert(fname != NULL);
59 
60  SCIP_CALL( SCIPgetBoolParam(scip, "misc/usevartable", &usevartable) );
61 
62  if( !usevartable )
63  {
64  SCIPerrorMessage("Cannot read solution file if vartable is disabled. Make sure parameter 'misc/usevartable' is set to TRUE.\n");
65  return SCIP_READERROR;
66  }
67 
68  /* open input file */
69  file = SCIPfopen(fname, "r");
70  if( file == NULL )
71  {
72  SCIPerrorMessage("cannot open file <%s> for reading\n", fname);
73  SCIPprintSysError(fname);
74  return SCIP_NOFILE;
75  }
76 
77  /* create zero solution */
78  SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
79 
80  /* read the file */
81  error = FALSE;
82  unknownvariablemessage = FALSE;
83  lineno = 0;
84  while( !SCIPfeof(file) && !error )
85  {
86  char buffer[SCIP_MAXSTRLEN];
87  char varname[SCIP_MAXSTRLEN];
88  char valuestring[SCIP_MAXSTRLEN];
89  char objstring[SCIP_MAXSTRLEN];
90  SCIP_VAR* var;
91  SCIP_Real value;
92  int nread;
93 
94  /* get next line */
95  if( SCIPfgets(buffer, (int) sizeof(buffer), file) == NULL )
96  break;
97  lineno++;
98 
99  /* there are some lines which may preceed the solution information */
100  if( strncasecmp(buffer, "solution status:", 16) == 0 || strncasecmp(buffer, "objective value:", 16) == 0 ||
101  strncasecmp(buffer, "Log started", 11) == 0 || strncasecmp(buffer, "Variable Name", 13) == 0 ||
102  strncasecmp(buffer, "All other variables", 19) == 0 || strncasecmp(buffer, "\n", 1) == 0 ||
103  strncasecmp(buffer, "NAME", 4) == 0 || strncasecmp(buffer, "ENDATA", 6) == 0 ) /* allow parsing of SOL-format on the MIPLIB 2003 pages */
104  continue;
105 
106  /* parse the line */
107  nread = sscanf(buffer, "%s %s %s\n", varname, valuestring, objstring);
108  if( nread < 2 )
109  {
110  SCIPerrorMessage("Invalid input line %d in solution file <%s>: <%s>.\n", lineno, fname, buffer);
111  error = TRUE;
112  break;
113  }
114 
115  /* find the variable */
116  var = SCIPfindVar(scip, varname);
117  if( var == NULL )
118  {
119  if( !unknownvariablemessage )
120  {
121  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "unknown variable <%s> in line %d of solution file <%s>\n",
122  varname, lineno, fname);
123  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " (further unknown variables are ignored)\n");
124  unknownvariablemessage = TRUE;
125  }
126  continue;
127  }
128 
129  /* cast the value */
130  if( strncasecmp(valuestring, "inv", 3) == 0 )
131  continue;
132  else if( strncasecmp(valuestring, "+inf", 4) == 0 || strncasecmp(valuestring, "inf", 3) == 0 )
133  value = SCIPinfinity(scip);
134  else if( strncasecmp(valuestring, "-inf", 4) == 0 )
135  value = -SCIPinfinity(scip);
136  else
137  {
138  nread = sscanf(valuestring, "%lf", &value);
139  if( nread != 1 )
140  {
141  SCIPerrorMessage("Invalid solution value <%s> for variable <%s> in line %d of solution file <%s>.\n",
142  valuestring, varname, lineno, fname);
143  error = TRUE;
144  break;
145  }
146  }
147 
148  /* set the solution value of the variable, if not multiaggregated */
150  {
151  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "ignored solution value for multiaggregated variable <%s>\n", SCIPvarGetName(var));
152  }
153  else
154  {
155  SCIP_RETCODE retcode;
156  retcode = SCIPsetSolVal(scip, sol, var, value);
157 
158  if( retcode == SCIP_INVALIDDATA )
159  {
161  {
162  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "ignored conflicting solution value for fixed variable <%s>\n",
163  SCIPvarGetName(var));
164  }
165  else
166  {
167  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "ignored solution value for multiaggregated variable <%s>\n",
168  SCIPvarGetName(var));
169  }
170  }
171  else
172  {
173  SCIP_CALL( retcode );
174  }
175  }
176  }
177 
178  /* close input file */
179  SCIPfclose(file);
180 
181  if( !error )
182  {
183  /* add and free the solution */
184  if( SCIPisTransformed(scip) )
185  {
186  SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, TRUE, TRUE, TRUE, &stored) );
187 
188  /* display result */
189  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "primal solution from solution file <%s> was %s\n",
190  fname, stored ? "accepted" : "rejected - solution is infeasible or objective too poor");
191  }
192  else
193  {
194  /* add primal solution to solution candidate storage, frees the solution afterwards */
195  SCIP_CALL( SCIPaddSolFree(scip, &sol, &stored) );
196 
197  /* display result */
198  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "primal solution from solution file <%s> was %s\n",
199  fname, stored ? "accepted as candidate, will be checked when solving starts" : "rejected - solution objective too poor");
200  }
201 
202  return SCIP_OKAY;
203  }
204  else
205  {
206  /* free solution */
207  SCIP_CALL( SCIPfreeSol(scip, &sol) );
208 
209  return SCIP_READERROR;
210  }
211 }
212 
213 /** reads a given xml solution file */
214 static
216  SCIP* scip, /**< SCIP data structure */
217  const char* filename /**< name of the input file */
218  )
219 {
220  SCIP_Bool unknownvariablemessage;
221  SCIP_SOL* sol;
222  SCIP_Bool error;
223  XML_NODE* start;
224  const XML_NODE* varsnode;
225  const XML_NODE* varnode;
226  const char* tag;
227 
228  assert( scip != NULL );
229  assert( filename != NULL );
230 
231  /* read xml file */
232  start = xmlProcess(filename);
233 
234  if( start == NULL )
235  {
236  SCIPerrorMessage("Some error occured during parsing the XML solution file.\n");
237  return SCIP_READERROR;
238  }
239 
240  /* create zero solution */
241  SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
242 
243  error = FALSE;
244 
245  /* find variable sections */
246  tag = "variables";
247  varsnode = xmlFindNodeMaxdepth(start, tag, 0, 3);
248  if( varsnode == NULL )
249  {
250  /* free xml data */
251  xmlFreeNode(start);
252 
253  SCIPerrorMessage("Variable section not found.\n");
254  return SCIP_READERROR;
255  }
256 
257  /* loop through all variables */
258  unknownvariablemessage = FALSE;
259  for( varnode = xmlFirstChild(varsnode); varnode != NULL; varnode = xmlNextSibl(varnode) )
260  {
261  SCIP_VAR* var;
262  const char* varname;
263  const char* varvalue;
264  SCIP_Real value;
265  int nread;
266 
267  /* find variable name */
268  varname = xmlGetAttrval(varnode, "name");
269  if( varname == NULL )
270  {
271  SCIPerrorMessage("Attribute \"name\" of variable not found.\n");
272  error = TRUE;
273  break;
274  }
275 
276  /* find the variable */
277  var = SCIPfindVar(scip, varname);
278  if( var == NULL )
279  {
280  if( !unknownvariablemessage )
281  {
282  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "unknown variable <%s> of solution file <%s>\n",
283  varname, filename);
284  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " (further unknown variables are ignored)\n");
285  unknownvariablemessage = TRUE;
286  }
287  continue;
288  }
289 
290  /* find value of variable */
291  varvalue = xmlGetAttrval(varnode, "value");
292  if( varvalue == NULL )
293  {
294  SCIPerrorMessage("Attribute \"value\" of variable not found.\n");
295  error = TRUE;
296  break;
297  }
298 
299  /* cast the value */
300  if( strncasecmp(varvalue, "inv", 3) == 0 )
301  continue;
302  else if( strncasecmp(varvalue, "+inf", 4) == 0 || strncasecmp(varvalue, "inf", 3) == 0 )
303  value = SCIPinfinity(scip);
304  else if( strncasecmp(varvalue, "-inf", 4) == 0 )
305  value = -SCIPinfinity(scip);
306  else
307  {
308  nread = sscanf(varvalue, "%lf", &value);
309  if( nread != 1 )
310  {
311  SCIPwarningMessage(scip, "invalid solution value <%s> for variable <%s> in XML solution file <%s>\n", varvalue, varname, filename);
312  error = TRUE;
313  break;
314  }
315  }
316 
317  /* set the solution value of the variable, if not multiaggregated */
319  {
320  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "ignored solution value for multiaggregated variable <%s>\n", SCIPvarGetName(var));
321  }
322  else
323  {
324  SCIP_RETCODE retcode;
325  retcode = SCIPsetSolVal(scip, sol, var, value);
326 
327  if( retcode == SCIP_INVALIDDATA )
328  {
330  {
331  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "ignored conflicting solution value for fixed variable <%s>\n",
332  SCIPvarGetName(var));
333  }
334  else
335  {
336  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "ignored solution value for multiaggregated variable <%s>\n",
337  SCIPvarGetName(var));
338  }
339  }
340  else
341  {
342  SCIP_CALL( retcode );
343  }
344  }
345  }
346 
347  if( !error )
348  {
349  SCIP_Bool stored;
350 
351  /* add and free the solution */
352  if( SCIPisTransformed(scip) )
353  {
354  SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, TRUE, TRUE, TRUE, &stored) );
355 
356  /* display result */
357  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "primal solution from solution file <%s> was %s\n",
358  filename, stored ? "accepted" : "rejected - solution is infeasible or objective too poor");
359  }
360  else
361  {
362  SCIP_CALL( SCIPaddSolFree(scip, &sol, &stored) );
363 
364  /* display result */
365  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "primal solution from solution file <%s> was %s\n",
366  filename, stored ? "accepted as candidate, will be checked when solving starts" : "rejected - solution objective too poor");
367  }
368  }
369  else
370  {
371  /* free solution */
372  SCIP_CALL( SCIPfreeSol(scip, &sol) );
373 
374  /* free xml data */
375  xmlFreeNode(start);
376 
377  return SCIP_READERROR;
378  }
379 
380  /* free xml data */
381  xmlFreeNode(start);
382 
383  return SCIP_OKAY;
384 }
385 
386 
387 /*
388  * Callback methods of reader
389  */
390 
391 /** copy method for reader plugins (called when SCIP copies plugins) */
392 static
393 SCIP_DECL_READERCOPY(readerCopySol)
394 { /*lint --e{715}*/
395  assert(scip != NULL);
396  assert(reader != NULL);
397  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
398 
399  /* call inclusion method of reader */
401 
402  return SCIP_OKAY;
403 }
404 
405 
406 /** problem reading method of reader
407  *
408  * In order to determine the type of the file, we have to open it. Thus, it has to be opened
409  * twice. This might be removed, but is likely to not hurt the performance too much.
410  */
411 static
412 SCIP_DECL_READERREAD(readerReadSol)
413 { /*lint --e{715}*/
414  SCIP_FILE* file;
415  char buffer[SCIP_MAXSTRLEN];
416  char *s;
417 
418  assert(reader != NULL);
419  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
420  assert(result != NULL);
421 
422  *result = SCIP_DIDNOTRUN;
423 
425  {
426  SCIPerrorMessage("reading of solution file is only possible after a problem was created\n");
427  return SCIP_READERROR;
428  }
429 
431  {
433  "primal solution from solution file <%s> was ignored - problem is already solved to optimality\n",
434  filename);
435  *result = SCIP_SUCCESS;
436  return SCIP_OKAY;
437  }
438 
439  /* open input file in order to determine type */
440  file = SCIPfopen(filename, "r");
441  if( file == NULL )
442  {
443  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
444  SCIPprintSysError(filename);
445  return SCIP_NOFILE;
446  }
447 
448  /* get next line */
449  if( SCIPfgets(buffer, (int) sizeof(buffer), file) == NULL )
450  {
451  SCIPerrorMessage("cannot parse file.\n");
452  return SCIP_READERROR;
453  }
454  /* close file */
455  SCIPfclose(file);
456 
457  /* decide whether it is xml */
458  s = buffer;
459 
460  /* skip spaces */
461  while( isspace((unsigned char)*s) )
462  ++s;
463  if( s[0] == '<' && s[1] == '?' && s[2] == 'x' && s[3] == 'm' && s[4] == 'l' )
464  {
465  /* read XML solution and add it to the solution pool */
466  SCIP_CALL( readXMLSol(scip, filename) );
467  }
468  else
469  {
470  /* read the solution and add it to the solution pool */
471  SCIP_CALL( readSol(scip, filename) );
472  }
473 
474  *result = SCIP_SUCCESS;
475 
476  return SCIP_OKAY;
477 }
478 
479 
480 /*
481  * sol file reader specific interface methods
482  */
483 
484 /** includes the sol file reader in SCIP */
486  SCIP* scip /**< SCIP data structure */
487  )
488 {
489  SCIP_READERDATA* readerdata;
490  SCIP_READER* reader;
491 
492  /* create reader data */
493  readerdata = NULL;
494 
495  /* include reader */
497 
498  assert(reader != NULL);
499 
500  /* set non fundamental callbacks via setter functions */
501  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopySol) );
502  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadSol) );
503 
504  return SCIP_OKAY;
505 }
506 
SCIP_RETCODE SCIPincludeReaderSol(SCIP *scip)
Definition: reader_sol.c:485
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
#define READER_NAME
Definition: reader_sol.c:33
SCIP_RETCODE SCIPaddSolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool *stored)
Definition: scip.c:36107
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:510
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1248
#define SCIP_MAXSTRLEN
Definition: def.h:201
#define NULL
Definition: lpi_spx.cpp:130
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:34843
#define FALSE
Definition: def.h:56
static SCIP_DECL_READERREAD(readerReadSol)
Definition: reader_sol.c:412
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define SCIP_CALL(x)
Definition: def.h:266
SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:36299
XML_NODE * xmlProcess(const char *filename)
Definition: xmlparse.c:1069
static SCIP_DECL_READERCOPY(readerCopySol)
Definition: reader_sol.c:393
const XML_NODE * xmlFirstChild(const XML_NODE *node)
Definition: xmlparse.c:1453
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip.c:4601
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:140
static SCIP_RETCODE readSol(SCIP *scip, const char *fname)
Definition: reader_sol.c:44
#define SCIPerrorMessage
Definition: pub_message.h:45
struct XML_NODE_struct XML_NODE
Definition: xml.h:41
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:34002
const XML_NODE * xmlFindNodeMaxdepth(const XML_NODE *node, const char *name, int depth, int maxdepth)
Definition: xmlparse.c:1403
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_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip.c:4649
struct SCIP_ReaderData SCIP_READERDATA
Definition: type_reader.h:37
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:997
#define SCIP_Bool
Definition: def.h:53
void SCIPprintSysError(const char *message)
Definition: misc.c:8110
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:801
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip.c:4563
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1298
#define READER_EXTENSION
Definition: reader_sol.c:35
const char * xmlGetAttrval(const XML_NODE *node, const char *name)
Definition: xmlparse.c:1321
file reader for primal solutions
#define SCIP_Real
Definition: def.h:127
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip.c:11392
declarations for XML parsing
#define READER_DESC
Definition: reader_sol.c:34
void xmlFreeNode(XML_NODE *node)
Definition: xmlparse.c:1259
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:219
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11481
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip.c:3740
static SCIP_RETCODE readXMLSol(SCIP *scip, const char *filename)
Definition: reader_sol.c:215
const XML_NODE * xmlNextSibl(const XML_NODE *node)
Definition: xmlparse.c:1433
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:34607