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