Scippy

SCIP

Solving Constraint Integer Programs

reader.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.c
17  * @brief interface for input file readers
18  * @author Tobias Achterberg
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 #include <string.h>
25 #include <math.h>
26 
27 #include "scip/def.h"
28 #include "blockmemshell/memory.h"
29 #include "scip/set.h"
30 #include "scip/clock.h"
31 #include "scip/pub_misc.h"
32 #include "scip/reader.h"
33 #include "scip/prob.h"
34 #include "scip/pub_var.h"
35 #include "scip/var.h"
36 #include "scip/pub_cons.h"
37 #include "scip/cons.h"
38 
39 #include "scip/struct_reader.h"
40 
41 
42 /** copies the given reader to a new scip */
44  SCIP_READER* reader, /**< reader */
45  SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
46  )
47 {
48  assert(reader != NULL);
49  assert(set != NULL);
50  assert(set->scip != NULL);
51 
52  if( reader->readercopy != NULL )
53  {
54  SCIPdebugMessage("including reader %s in subscip %p\n", SCIPreaderGetName(reader), (void*)set->scip);
55  SCIP_CALL( reader->readercopy(set->scip, reader) );
56  }
57  return SCIP_OKAY;
58 }
59 
60 /** creates a reader */
62  SCIP_READER** reader, /**< pointer to store reader */
63  const char* name, /**< name of reader */
64  const char* desc, /**< description of reader */
65  const char* extension, /**< file extension that reader processes */
66  SCIP_DECL_READERCOPY ((*readercopy)), /**< copy method of reader or NULL if you don't want to copy your plugin into sub-SCIPs */
67  SCIP_DECL_READERFREE ((*readerfree)), /**< destructor of reader */
68  SCIP_DECL_READERREAD ((*readerread)), /**< read method */
69  SCIP_DECL_READERWRITE ((*readerwrite)), /**< write method */
70  SCIP_READERDATA* readerdata /**< reader data */
71  )
72 {
73  assert(reader != NULL);
74  assert(name != NULL);
75  assert(desc != NULL);
76  assert(extension != NULL);
77 
78  SCIP_ALLOC( BMSallocMemory(reader) );
79  SCIP_ALLOC( BMSduplicateMemoryArray(&(*reader)->name, name, strlen(name)+1) );
80  SCIP_ALLOC( BMSduplicateMemoryArray(&(*reader)->desc, desc, strlen(desc)+1) );
81  SCIP_ALLOC( BMSduplicateMemoryArray(&(*reader)->extension, extension, strlen(extension)+1) );
82  (*reader)->readercopy = readercopy;
83  (*reader)->readerfree = readerfree;
84  (*reader)->readerread = readerread;
85  (*reader)->readerwrite = readerwrite;
86  (*reader)->readerdata = readerdata;
87 
88  /* create reading clock */
89  SCIP_CALL( SCIPclockCreate(&(*reader)->readingtime, SCIP_CLOCKTYPE_DEFAULT) );
90 
91  return SCIP_OKAY;
92 }
93 
94 /** frees memory of reader */
96  SCIP_READER** reader, /**< pointer to reader data structure */
97  SCIP_SET* set /**< global SCIP settings */
98  )
99 {
100  assert(reader != NULL);
101  assert(*reader != NULL);
102  assert(set != NULL);
103 
104  /* call destructor of reader */
105  if( (*reader)->readerfree != NULL )
106  {
107  SCIP_CALL( (*reader)->readerfree(set->scip, *reader) );
108  }
109 
110  /* free clock */
111  SCIPclockFree(&(*reader)->readingtime);
112 
113  BMSfreeMemoryArray(&(*reader)->name);
114  BMSfreeMemoryArray(&(*reader)->desc);
115  BMSfreeMemoryArray(&(*reader)->extension);
116  BMSfreeMemory(reader);
117 
118  return SCIP_OKAY;
119 }
120 
121 /** returns TRUE, if reader is responsible for files with the given extension */
122 static
124  SCIP_READER* reader, /**< reader */
125  const char* extension /**< extension of the input file name */
126  )
127 {
128  assert(reader != NULL);
129  assert(reader->extension != NULL);
130 
131  return (extension != NULL && strcasecmp(reader->extension, extension) == 0)
132  || (extension == NULL && *(reader->extension) == '\0');
133 }
134 
135 /** reads problem data from file with given reader or returns SCIP_DIDNOTRUN */
137  SCIP_READER* reader, /**< reader */
138  SCIP_SET* set, /**< global SCIP settings */
139  const char* filename, /**< name of the input file */
140  const char* extension, /**< extension of the input file name */
141  SCIP_RESULT* result /**< pointer to store the result of the callback method */
142  )
143 {
144  SCIP_RETCODE retcode;
145 
146  assert(reader != NULL);
147  assert(set != NULL);
148  assert(filename != NULL);
149  assert(result != NULL);
150 
151  /* check, if reader is applicable on the given file */
152  if( readerIsApplicable(reader, extension) && reader->readerread != NULL )
153  {
154  SCIP_CLOCK* readingtime;
155 
156  /**@note we need temporary clock to measure the reading time correctly since in case of creating a new problem
157  * within the reader all clocks are reset (including the reader clocks); this resetting is necessary for
158  * example for those case we people solve several problems using the (same) interactive shell
159  */
160 
161  assert(!SCIPclockIsRunning(reader->readingtime));
162 
163  /* create a temporary clock for measuring the reading time */
165 
166  /* start timing */
167  SCIPclockStart(readingtime, set);
168 
169  /* call reader to read problem */
170  retcode = reader->readerread(set->scip, reader, filename, result);
171 
172  /* stop timing */
173  SCIPclockStop(readingtime, set);
174 
175  /* add time to reader reading clock */
177 
178  /* free the temporary clock */
179  SCIPclockFree(&readingtime);
180  }
181  else
182  {
183  *result = SCIP_DIDNOTRUN;
184  retcode = SCIP_OKAY;
185  }
186 
187  /* check for reader errors */
188  if( retcode == SCIP_NOFILE || retcode == SCIP_READERROR )
189  return retcode;
190 
191  /* check if the result code is valid in case no reader error occurred */
192  assert( *result == SCIP_DIDNOTRUN || *result == SCIP_SUCCESS );
193 
194  SCIP_CALL( retcode );
195 
196  return SCIP_OKAY;
197 }
198 
199 
200 /* reset the variable name to the given one */
201 static
203  SCIP_VAR* var, /**< variable */
204  const char* name /**< variable name */
205  )
206 {
207  const char * oldname;
208 
209  assert( var != NULL );
210  assert( name != NULL );
211 
212  /* get pointer to temporary generic name and free the memory */
213  oldname = SCIPvarGetName(var);
214  BMSfreeMemory(&oldname);
215 
216  /* reset name */
217  SCIPvarSetNamePointer(var, name);
218 }
219 
220 
221 /** writes problem data to file with given reader or returns SCIP_DIDNOTRUN */
223  SCIP_READER* reader, /**< reader */
224  SCIP_PROB* prob, /**< problem data */
225  SCIP_SET* set, /**< global SCIP settings */
226  FILE* file, /**< output file (or NULL for standard output) */
227  const char* extension, /**< file format */
228  SCIP_Bool genericnames, /**< using generic variable and constraint names? */
229  SCIP_RESULT* result /**< pointer to store the result of the callback method */
230  )
231 {
232  SCIP_RETCODE retcode;
233 
234  assert(reader != NULL);
235  assert(set != NULL);
236  assert(extension != NULL);
237  assert(result != NULL);
238 
239  /* check, if reader is applicable on the given file */
240  if( readerIsApplicable(reader, extension) && reader->readerwrite != NULL )
241  {
242  SCIP_VAR** vars;
243  int nvars;
244  SCIP_VAR** fixedvars;
245  int nfixedvars;
246  SCIP_CONS** conss;
247  int nconss;
248  int i;
249 
250  SCIP_CONS* cons;
251 
252  char* name;
253  const char* consname;
254  const char** varnames;
255  const char** fixedvarnames;
256  const char** consnames;
257 
258  varnames = NULL;
259  fixedvarnames = NULL;
260  consnames = NULL;
261 
262  vars = prob->vars;
263  nvars = prob->nvars;
264  fixedvars = prob->fixedvars;
265  nfixedvars = prob->nfixedvars;
266 
267  /* case of the transformed problem, we want to write currently valid problem */
268  if( prob->transformed )
269  {
270  SCIP_CONSHDLR** conshdlrs;
271  int nconshdlrs;
272 
273  conshdlrs = set->conshdlrs;
274  nconshdlrs = set->nconshdlrs;
275 
276  /* collect number of constraints which have to be enforced; these are the constraints which currency (locally)
277  * enabled; these also includes the local constraints
278  */
279  nconss = 0;
280  for( i = 0; i < nconshdlrs; ++i )
281  {
282  /* check if all constraints of the constraint handler should be written */
283  if( set->write_allconss )
284  nconss += SCIPconshdlrGetNConss(conshdlrs[i]);
285  else
286  nconss += SCIPconshdlrGetNEnfoConss(conshdlrs[i]);
287  }
288 
289  SCIPdebugMessage("Writing %d constraints.\n", nconss);
290 
291 
292  SCIP_ALLOC( BMSallocMemoryArray(&conss, nconss) );
293 
294  /* copy the constraints */
295  nconss = 0;
296  for( i = 0; i < nconshdlrs; ++i )
297  {
298  SCIP_CONS** conshdlrconss;
299  int nconshdlrconss;
300  int c;
301 
302  /* check if all constraints of the constraint handler should be written */
303  if( set->write_allconss )
304  {
305  conshdlrconss = SCIPconshdlrGetConss(conshdlrs[i]);
306  nconshdlrconss = SCIPconshdlrGetNConss(conshdlrs[i]);
307  }
308  else
309  {
310  conshdlrconss = SCIPconshdlrGetEnfoConss(conshdlrs[i]);
311  nconshdlrconss = SCIPconshdlrGetNEnfoConss(conshdlrs[i]);
312  }
313 
314  SCIPdebugMessage("Conshdlr <%s> has %d constraints to write from all in all %d constraints.\n", SCIPconshdlrGetName(conshdlrs[i]), nconshdlrconss, SCIPconshdlrGetNConss(conshdlrs[i]));
315 
316  for( c = 0; c < nconshdlrconss; ++c )
317  {
318  conss[nconss] = conshdlrconss[c];
319  nconss++;
320  }
321  }
322  }
323  else
324  {
325  conss = prob->conss;
326  nconss = prob->nconss;
327  }
328 
329  if( genericnames )
330  {
331  SCIP_VAR* var;
332  int size;
333 
334  /* save variable and constraint names and replace these names by generic names */
335 
336  /* allocate memory for saving the original variable and constraint names */
337  SCIP_ALLOC( BMSallocMemoryArray(&varnames, nvars) );
338  SCIP_ALLOC( BMSallocMemoryArray(&fixedvarnames, nfixedvars) );
339  SCIP_ALLOC( BMSallocMemoryArray(&consnames, nconss) );
340 
341  /* compute length of the generic variable names:
342  * - nvars + 1 to avoid log of zero
343  * - +3 (zero at end + 'x' + 1 because we round down)
344  * Example: 10 -> need 4 chars ("x10\0")
345  */
346  size = (int) log10(nvars+1.0) + 3;
347 
348  for( i = 0; i < nvars; ++i )
349  {
350  var = vars[i];
351  varnames[i] = SCIPvarGetName(var);
352 
353  SCIP_ALLOC( BMSallocMemoryArray(&name, size) );
354  (void) SCIPsnprintf(name, size, "x%d", i + set->write_genoffset);
355  SCIPvarSetNamePointer(var, name);
356  }
357 
358  /* compute length of the generic variable names */
359  size = (int) log10(nfixedvars+1.0) + 3;
360 
361  for( i = 0; i < nfixedvars; ++i )
362  {
363  var = fixedvars[i];
364  fixedvarnames[i] = SCIPvarGetName(var);
365 
366  SCIP_ALLOC( BMSallocMemoryArray(&name, size) );
367  (void) SCIPsnprintf(name, size, "y%d", i);
368  SCIPvarSetNamePointer(var, name);
369  }
370 
371  /* compute length of the generic constraint names */
372  size = (int) log10(nconss+1.0) + 3;
373 
374  for( i = 0; i < nconss; ++i )
375  {
376  cons = conss[i];
377  consnames[i] = SCIPconsGetName(cons);
378 
379  SCIP_ALLOC( BMSallocMemoryArray(&name, size) );
380  (void) SCIPsnprintf(name, size, "c%d", i);
381  SCIPconsSetNamePointer(cons, name);
382  }
383  }
384 
385  /* call reader to write problem */
386  retcode = reader->readerwrite(set->scip, reader, file, prob->name, prob->probdata, prob->transformed,
387  prob->transformed ? SCIP_OBJSENSE_MINIMIZE : prob->objsense, prob->objscale, prob->objoffset,
388  vars, nvars, prob->nbinvars, prob->nintvars, prob->nimplvars, prob->ncontvars,
389  fixedvars, nfixedvars, prob->startnvars,
390  conss, nconss, prob->maxnconss, prob->startnconss, genericnames, result);
391 
392  /* reset variable and constraint names to original names */
393  if( genericnames )
394  {
395  assert(varnames != NULL);
396  assert(fixedvarnames != NULL);
397  assert(consnames != NULL);
398 
399  for( i = 0; i < nvars; ++i )
400  resetVarname(vars[i], varnames[i]);
401 
402  for( i = 0; i < nfixedvars; ++i )
403  resetVarname(fixedvars[i], fixedvarnames[i]);
404 
405  for( i = 0; i < nconss; ++i )
406  {
407  cons = conss[i];
408 
409  /* get pointer to temporary generic name and free the memory */
410  consname = SCIPconsGetName(cons);
411  BMSfreeMemory(&consname);
412 
413  /* reset name */
414  SCIPconsSetNamePointer(cons, consnames[i]);
415  }
416 
417  /* free memory */
418  BMSfreeMemoryArray(&varnames);
419  BMSfreeMemoryArray(&fixedvarnames);
420  BMSfreeMemoryArray(&consnames);
421  }
422 
423  if( prob->transformed )
424  {
425  /* free memory */
426  BMSfreeMemoryArray(&conss);
427  }
428  }
429  else
430  {
431  *result = SCIP_DIDNOTRUN;
432  retcode = SCIP_OKAY;
433  }
434 
435  /* check for reader errors */
436  if( retcode == SCIP_WRITEERROR )
437  return retcode;
438 
439  SCIP_CALL( retcode );
440 
441  return SCIP_OKAY;
442 }
443 
444 /** gets user data of reader */
446  SCIP_READER* reader /**< reader */
447  )
448 {
449  assert(reader != NULL);
450 
451  return reader->readerdata;
452 }
453 
454 /** sets user data of reader; user has to free old data in advance! */
456  SCIP_READER* reader, /**< reader */
457  SCIP_READERDATA* readerdata /**< new reader user data */
458  )
459 {
460  assert(reader != NULL);
461 
462  reader->readerdata = readerdata;
463 }
464 
465 /** sets copy method of reader */
467  SCIP_READER* reader, /**< reader */
468  SCIP_DECL_READERCOPY ((*readercopy)) /**< copy method of reader or NULL if you don't want to copy your plugin into sub-SCIPs */
469  )
470 {
471  assert(reader != NULL);
472 
473  reader->readercopy = readercopy;
474 }
475 
476 /** sets destructor of reader */
478  SCIP_READER* reader, /**< reader */
479  SCIP_DECL_READERFREE ((*readerfree)) /**< destructor of reader */
480  )
481 {
482  assert(reader != NULL);
483 
484  reader->readerfree = readerfree;
485 }
486 
487 /** sets read method of reader */
489  SCIP_READER* reader, /**< reader */
490  SCIP_DECL_READERREAD ((*readerread)) /**< read method */
491  )
492 {
493  assert(reader != NULL);
494 
495  reader->readerread = readerread;
496 }
497 
498 /** sets write method of reader */
500  SCIP_READER* reader, /**< reader */
501  SCIP_DECL_READERWRITE ((*readerwrite)) /**< write method */
502  )
503 {
504  assert(reader != NULL);
505 
506  reader->readerwrite = readerwrite;
507 }
508 
509 /** gets name of reader */
510 const char* SCIPreaderGetName(
511  SCIP_READER* reader /**< reader */
512  )
513 {
514  assert(reader != NULL);
515 
516  return reader->name;
517 }
518 
519 /** gets description of reader */
520 const char* SCIPreaderGetDesc(
521  SCIP_READER* reader /**< reader */
522  )
523 {
524  assert(reader != NULL);
525 
526  return reader->desc;
527 }
528 
529 /** gets file extension of reader */
531  SCIP_READER* reader /**< reader */
532  )
533 {
534  assert(reader != NULL);
535 
536  return reader->extension;
537 }
538 
539 /** return whether the reader can read files */
541  SCIP_READER* reader /**< reader */
542  )
543 {
544  assert(reader != NULL);
545 
546  return (reader->readerread != NULL);
547 }
548 
549 /** return whether the reader can write files */
551  SCIP_READER* reader /**< reader */
552  )
553 {
554  assert(reader != NULL);
555 
556  return (reader->readerwrite != NULL);
557 }
558 
559 /** gets time in seconds used in this reader for reading */
561  SCIP_READER* reader /**< reader */
562  )
563 {
564  assert(reader != NULL);
565 
566  return SCIPclockGetTime(reader->readingtime);
567 }
568 
569 /** resets reading time of reader */
571  SCIP_READER* reader /**< reader */
572  )
573 {
574  assert(reader != NULL);
575 
576  /* reset reading time/clock */
577  SCIPclockReset(reader->readingtime);
578 
579  return SCIP_OKAY;
580 }
581 
582