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-2014 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  const char* varname;
262  const char* varvalue;
263  SCIP_VAR* var;
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 */
318  SCIP_CALL( SCIPsetSolVal(scip, sol, var, value) );
319  }
320 
321  if( !error )
322  {
323  SCIP_Bool stored;
324 
325  /* add and free the solution */
326  if( SCIPisTransformed(scip) )
327  {
328  SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, TRUE, TRUE, TRUE, &stored) );
329 
330  /* display result */
331  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "primal solution from solution file <%s> was %s\n",
332  filename, stored ? "accepted" : "rejected - solution is infeasible or objective too poor");
333  }
334  else
335  {
336  SCIP_CALL( SCIPaddSolFree(scip, &sol, &stored) );
337 
338  /* display result */
339  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "primal solution from solution file <%s> was %s\n",
340  filename, stored ? "accepted as candidate, will be checked when solving starts" : "rejected - solution objective too poor");
341  }
342  }
343  else
344  {
345  /* free solution */
346  SCIP_CALL( SCIPfreeSol(scip, &sol) );
347 
348  /* free xml data */
349  xmlFreeNode(start);
350 
351  return SCIP_READERROR;
352  }
353 
354  /* free xml data */
355  xmlFreeNode(start);
356 
357  return SCIP_OKAY;
358 }
359 
360 
361 /*
362  * Callback methods of reader
363  */
364 
365 /** copy method for reader plugins (called when SCIP copies plugins) */
366 static
367 SCIP_DECL_READERCOPY(readerCopySol)
368 { /*lint --e{715}*/
369  assert(scip != NULL);
370  assert(reader != NULL);
371  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
372 
373  /* call inclusion method of reader */
375 
376  return SCIP_OKAY;
377 }
378 
379 
380 /** problem reading method of reader
381  *
382  * In order to determine the type of the file, we have to open it. Thus, it has to be opened
383  * twice. This might be removed, but is likely to not hurt the performance too much.
384  */
385 static
386 SCIP_DECL_READERREAD(readerReadSol)
387 { /*lint --e{715}*/
388  SCIP_FILE* file;
389  char buffer[SCIP_MAXSTRLEN];
390  char *s;
391 
392  assert(reader != NULL);
393  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
394  assert(result != NULL);
395 
396  *result = SCIP_DIDNOTRUN;
397 
398  if( SCIPgetStage(scip) < SCIP_STAGE_PROBLEM )
399  {
400  SCIPerrorMessage("reading of solution file is only possible after a problem was created\n");
401  return SCIP_READERROR;
402  }
403 
404  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVED )
405  {
407  "primal solution from solution file <%s> was ignored - problem is already solved to optimality\n",
408  filename);
409  *result = SCIP_SUCCESS;
410  return SCIP_OKAY;
411  }
412 
413  /* open input file in order to determine type */
414  file = SCIPfopen(filename, "r");
415  if( file == NULL )
416  {
417  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
418  SCIPprintSysError(filename);
419  return SCIP_NOFILE;
420  }
421 
422  /* get next line */
423  if( SCIPfgets(buffer, (int) sizeof(buffer), file) == NULL )
424  {
425  SCIPerrorMessage("cannot parse file.\n");
426  return SCIP_READERROR;
427  }
428  /* close file */
429  SCIPfclose(file);
430 
431  /* decide whether it is xml */
432  s = buffer;
433 
434  /* skip spaces */
435  while( isspace((unsigned char)*s) )
436  ++s;
437  if( s[0] == '<' && s[1] == '?' && s[2] == 'x' && s[3] == 'm' && s[4] == 'l' )
438  {
439  /* read XML solution and add it to the solution pool */
440  SCIP_CALL( readXMLSol(scip, filename) );
441  }
442  else
443  {
444  /* read the solution and add it to the solution pool */
445  SCIP_CALL( readSol(scip, filename) );
446  }
447 
448  *result = SCIP_SUCCESS;
449 
450  return SCIP_OKAY;
451 }
452 
453 
454 /*
455  * sol file reader specific interface methods
456  */
457 
458 /** includes the sol file reader in SCIP */
460  SCIP* scip /**< SCIP data structure */
461  )
462 {
463  SCIP_READERDATA* readerdata;
464  SCIP_READER* reader;
465 
466  /* create reader data */
467  readerdata = NULL;
468 
469  /* include reader */
471 
472  assert(reader != NULL);
473 
474  /* set non fundamental callbacks via setter functions */
475  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopySol) );
476  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadSol) );
477 
478  return SCIP_OKAY;
479 }
480 
481