Scippy

SCIP

Solving Constraint Integer Programs

reader_tim.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-2018 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 scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file reader_tim.c
17  * @brief TIM file reader - the stage information for a stochastic programming instance in SMPS format
18  * @author Stephen J. Maher
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include "scip/pub_cons.h"
24 #include "scip/pub_fileio.h"
25 #include "scip/pub_message.h"
26 #include "scip/pub_misc.h"
27 #include "scip/pub_reader.h"
28 #include "scip/reader_cor.h"
29 #include "scip/reader_tim.h"
30 #include "scip/scip_mem.h"
31 #include "scip/scip_message.h"
32 #include "scip/scip_numerics.h"
33 #include "scip/scip_prob.h"
34 #include "scip/scip_reader.h"
35 #include <string.h>
36 
37 #define READER_NAME "timreader"
38 #define READER_DESC "file reader for the TIME file of a stochastic program in SMPS format"
39 #define READER_EXTENSION "tim"
40 
41 /*
42  * tim reader internal methods
43  */
44 
45 #define TIM_MAX_LINELEN 1025
46 #define TIM_MAX_NAMELEN 256
47 #define TIM_DEFAULT_STAGESIZE 10
48 #define TIM_DEFAULT_ARRAYSIZE 100
49 
50 #define BLANK ' '
51 
52 struct TimStage
53 {
58  int nvars;
59  int nconss;
60  int varssize;
61  int conssize;
62 };
63 typedef struct TimStage TIMSTAGE;
64 
65 /** TIM reading data */
66 struct SCIP_ReaderData
67 {
68  SCIP_Bool read; /**< flag to indicate whether the time file has been read */
69  int nstages; /**< the number of stages in the stochastic program */
70  const char** stagestartvars; /**< the variables that start each stage */
71  const char** stagestartcons; /**< the constraints that start each stage */
72  const char** stagenames; /**< the name of the stage */
73  TIMSTAGE** stages; /**< the stages for the stochastic program */
74 };
75 
76 /** enum containing all tim sections */
78 {
82 };
83 typedef enum TimSection TIMSECTION;
84 
85 /** tim input structure */
86 struct TimInput
87 {
90  int lineno;
92  char buf[TIM_MAX_LINELEN];
93  const char* f0;
94  const char* f1;
95  const char* f2;
96  const char* f3;
97  char probname[TIM_MAX_NAMELEN];
98  const char** stagestartvars;
99  const char** stagestartcons;
100  const char** stagenames;
101  int nstages;
103 };
104 typedef struct TimInput TIMINPUT;
105 
106 /** adds the variable to the given stage */
107 static
109  SCIP* scip, /**< SCIP data structure */
110  TIMSTAGE* stage, /**< the stage structure */
111  const char* varname /**< the name of the variable to add to the stage */
112  )
113 {
114  SCIP_VAR* var;
115 
116  assert(scip != NULL);
117  assert(stage != NULL);
118 
119  var = SCIPfindVar(scip, varname);
120 
121  if( var == NULL )
122  {
123  SCIPwarningMessage(scip, "This is an error. All variables should in the problem.\n");
124  return SCIP_OKAY;
125  }
126 
127  /* adding the variable to the hashmap */
128  SCIP_CALL( SCIPhashmapInsert(stage->varnametovar, (void*) varname, var) );
129 
130  /* adding the variable to the variable storage */
131  SCIP_CALL( SCIPensureBlockMemoryArray(scip, &stage->vars, &stage->varssize, stage->nvars + 1) );
132  stage->vars[stage->nvars] = var;
133  stage->nvars++;
134 
135  return SCIP_OKAY;
136 }
137 
138 /** adds the constraint to the given stage */
139 static
141  SCIP* scip, /**< SCIP data structure */
142  TIMSTAGE* stage, /**< the stage structure */
143  const char* consname /**< the name of the constraint to add to the stage */
144  )
145 {
146  SCIP_CONS* cons;
147 
148  assert(scip != NULL);
149  assert(stage != NULL);
150 
151  cons = SCIPfindCons(scip, consname);
152 
153  if( cons == NULL )
154  {
155  SCIPwarningMessage(scip, "This is an error. All constraints should in the problem.\n");
156  return SCIP_OKAY;
157  }
158 
159  /* adding the constraint to the hashmap */
160  SCIP_CALL( SCIPhashmapInsert(stage->consnametocons, (void*) consname, cons) );
161 
162  /* adding the constraint to the constraint storage */
163  SCIP_CALL( SCIPensureBlockMemoryArray(scip, &stage->conss, &stage->conssize, stage->nconss + 1) );
164  stage->conss[stage->nconss] = cons;
165  stage->nconss++;
166 
167  return SCIP_OKAY;
168 }
169 
170 /** creates the stage data */
171 static
173  SCIP* scip, /**< SCIP data structure */
174  SCIP_READER* reader, /**< the reader structure */
175  SCIP_READER* correader /**< the reader structure for the core file */
176  )
177 {
178  SCIP_READERDATA* readerdata;
179  int stage;
180  int i;
181 
182  assert(scip != NULL);
183  assert(reader != NULL);
184  assert(correader != NULL);
185 
186  readerdata = SCIPreaderGetData(reader);
187  assert(readerdata != NULL);
188 
189  stage = 0;
190 
191  /* assigning the variables to the stages */
192  for( i = 0; i < SCIPcorGetNVarNames(correader); i++ )
193  {
194  /* the first variable in the var names list should be the start of the first stage */
195  assert((stage == 0 && i == 0 && strcmp(SCIPcorGetVarName(correader, i), readerdata->stagestartvars[stage]) == 0)
196  || i > 0);
197  /* checking whether the next stage has been found */
198  if( i > 0 && stage < readerdata->nstages - 1
199  && strcmp(SCIPcorGetVarName(correader, i), readerdata->stagestartvars[stage + 1]) == 0 )
200  stage++;
201 
202  /* adding the variable to the stage */
203  SCIP_CALL( addVariableToStage(scip, readerdata->stages[stage], SCIPcorGetVarName(correader, i)) );
204  }
205 
206  stage = 0;
207 
208  /* assigning the constraint to the stages */
209  for( i = 0; i < SCIPcorGetNConsNames(correader); i++ )
210  {
211  /* checking whether the next stage has been found */
212  if( i > 0 && stage < readerdata->nstages - 1
213  && strcmp(SCIPcorGetConsName(correader, i), readerdata->stagestartcons[stage + 1]) == 0 )
214  stage++;
215 
216  /* adding the consiable to the stage */
217  SCIP_CALL( addConstraintToStage(scip, readerdata->stages[stage], SCIPcorGetConsName(correader, i)) );
218  }
219 
220  return SCIP_OKAY;
221 }
222 
223 /** creates the reader data for the time input data */
224 static
226  SCIP* scip, /**< SCIP data structure */
227  SCIP_READER* reader, /**< the reader structure */
228  TIMINPUT* timi /**< tim input structure */
229  )
230 {
231  SCIP_READERDATA* readerdata;
232  int hashmapsize;
233  int nvars;
234  int i;
235 
236  assert(scip != NULL);
237  assert(reader != NULL);
238  assert(timi != NULL);
239 
240  readerdata = SCIPreaderGetData(reader);
241 
242  assert(readerdata != NULL);
243 
244  /* getting the total number of variables in the problem. The hash maps will be of size nvars/nstages. */
245  nvars = SCIPgetNVars(scip);
246 
247  readerdata->read = TRUE;
248  readerdata->nstages = timi->nstages;
249 
250  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stagestartvars, readerdata->nstages) );
251  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stagestartcons, readerdata->nstages) );
252  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stagenames, readerdata->nstages) );
253  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stages, readerdata->nstages) );
254 
255  for( i = 0; i < readerdata->nstages; i++ )
256  {
257  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &readerdata->stagestartvars[i],
258  timi->stagestartvars[i], strlen(timi->stagestartvars[i]) + 1) ); /*lint !e866*/
259  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &readerdata->stagestartcons[i],
260  timi->stagestartcons[i], strlen(timi->stagestartcons[i]) + 1) ); /*lint !e866*/
261  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &readerdata->stagenames[i],
262  timi->stagenames[i], strlen(timi->stagenames[i]) + 1) ); /*lint !e866*/
263 
264  /* creating the data for the stages */
265  SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata->stages[i]) ); /*lint !e866*/
266  readerdata->stages[i]->nvars = 0;
267  readerdata->stages[i]->nconss = 0;
268  readerdata->stages[i]->varssize = TIM_DEFAULT_ARRAYSIZE;
269  readerdata->stages[i]->conssize = TIM_DEFAULT_ARRAYSIZE;
270  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stages[i]->vars, readerdata->stages[i]->varssize) ); /*lint !e866*/
271  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stages[i]->conss, readerdata->stages[i]->conssize) ); /*lint !e866*/
272 
273  /* creating the hashmaps */
274  hashmapsize = (int) SCIPceil(scip, (SCIP_Real) nvars/(SCIP_Real) readerdata->nstages);
275  SCIP_CALL( SCIPhashmapCreate(&readerdata->stages[i]->varnametovar, SCIPblkmem(scip), hashmapsize) );
276  SCIP_CALL( SCIPhashmapCreate(&readerdata->stages[i]->consnametocons, SCIPblkmem(scip), hashmapsize) );
277  }
278 
279  return SCIP_OKAY;
280 }
281 
282 /** free the reader data */
283 static
285  SCIP* scip, /**< SCIP data structure */
286  SCIP_READER* reader /**< the reader structure */
287  )
288 {
289  SCIP_READERDATA* readerdata;
290  int i;
291 
292  assert(scip != NULL);
293  assert(reader != NULL);
294 
295  readerdata = SCIPreaderGetData(reader);
296 
297  assert(readerdata != NULL);
298 
299  /* only free the reader data is a file has been read */
300  if( readerdata->read )
301  {
302  for( i = 0; i < readerdata->nstages; i++ )
303  {
304  /* freeing the hashmaps */
305  SCIPhashmapFree(&readerdata->stages[i]->consnametocons);
306  SCIPhashmapFree(&readerdata->stages[i]->varnametovar);
307 
308  SCIPfreeBlockMemoryArray(scip, &readerdata->stagestartvars[i], strlen(readerdata->stagestartvars[i]) + 1);
309  SCIPfreeBlockMemoryArray(scip, &readerdata->stagestartcons[i], strlen(readerdata->stagestartcons[i]) + 1);
310  SCIPfreeBlockMemoryArray(scip, &readerdata->stagenames[i], strlen(readerdata->stagenames[i]) + 1);
311 
312  /* freeing the memory for the stage data */
313  SCIPfreeBlockMemoryArray(scip, &readerdata->stages[i]->vars, readerdata->stages[i]->varssize);
314  SCIPfreeBlockMemoryArray(scip, &readerdata->stages[i]->conss, readerdata->stages[i]->conssize);
315  SCIPfreeBlockMemory(scip, &readerdata->stages[i]); /*lint !e866*/
316  }
317 
318  SCIPfreeBlockMemoryArray(scip, &readerdata->stages, readerdata->nstages);
319  SCIPfreeBlockMemoryArray(scip, &readerdata->stagenames, readerdata->nstages);
320  SCIPfreeBlockMemoryArray(scip, &readerdata->stagestartcons, readerdata->nstages);
321  SCIPfreeBlockMemoryArray(scip, &readerdata->stagestartvars, readerdata->nstages);
322  }
323 
324  SCIPfreeBlockMemory(scip, &readerdata);
325 }
326 
327 
328 /** creates the tim input structure */
329 static
331  SCIP* scip, /**< SCIP data structure */
332  TIMINPUT** timi, /**< tim input structure */
333  SCIP_FILE* fp /**< file object for the input file */
334  )
335 {
336  assert(timi != NULL);
337  assert(fp != NULL);
338 
339  SCIP_CALL( SCIPallocBlockMemory(scip, timi) );
340 
341  (*timi)->section = TIM_TIME;
342  (*timi)->fp = fp;
343  (*timi)->lineno = 0;
344  (*timi)->haserror = FALSE;
345  (*timi)->buf [0] = '\0';
346  (*timi)->probname[0] = '\0';
347  (*timi)->f0 = NULL;
348  (*timi)->f1 = NULL;
349  (*timi)->f2 = NULL;
350  (*timi)->f3 = NULL;
351  (*timi)->nstages = 0;
352  (*timi)->stagesize = TIM_DEFAULT_STAGESIZE;
353 
354  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*timi)->stagestartvars, (*timi)->stagesize) );
355  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*timi)->stagestartcons, (*timi)->stagesize) );
356  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*timi)->stagenames, (*timi)->stagesize) );
357 
358  return SCIP_OKAY;
359 }
360 
361 /** free the tim input structure */
362 static
364  SCIP* scip, /**< SCIP data structure */
365  TIMINPUT** timi /**< tim input structure */
366  )
367 {
368  int i;
369 
370  for( i = 0; i < (*timi)->nstages; i++ )
371  {
372  SCIPfreeBlockMemoryArray(scip, &(*timi)->stagestartvars[i], strlen((*timi)->stagestartvars[i]) + 1);
373  SCIPfreeBlockMemoryArray(scip, &(*timi)->stagestartcons[i], strlen((*timi)->stagestartcons[i]) + 1);
374  SCIPfreeBlockMemoryArray(scip, &(*timi)->stagenames[i], strlen((*timi)->stagenames[i]) + 1);
375  }
376 
377  SCIPfreeBlockMemoryArray(scip, &(*timi)->stagestartvars, (*timi)->stagesize);
378  SCIPfreeBlockMemoryArray(scip, &(*timi)->stagestartcons, (*timi)->stagesize);
379  SCIPfreeBlockMemoryArray(scip, &(*timi)->stagenames, (*timi)->stagesize);
380 
381  SCIPfreeBlockMemory(scip, timi);
382 }
383 
384 /** returns the current section */
385 static
387  const TIMINPUT* timi /**< tim input structure */
388  )
389 {
390  assert(timi != NULL);
391 
392  return timi->section;
393 }
394 
395 /** return the current value of field 0 */
396 static
397 const char* timinputField0(
398  const TIMINPUT* timi /**< tim input structure */
399  )
400 {
401  assert(timi != NULL);
402 
403  return timi->f0;
404 }
405 
406 /** return the current value of field 1 */
407 static
408 const char* timinputField1(
409  const TIMINPUT* timi /**< tim input structure */
410  )
411 {
412  assert(timi != NULL);
413 
414  return timi->f1;
415 }
416 
417 /** return the current value of field 2 */
418 static
419 const char* timinputField2(
420  const TIMINPUT* timi /**< tim input structure */
421  )
422 {
423  assert(timi != NULL);
424 
425  return timi->f2;
426 }
427 
428 /** return the current value of field 3 */
429 static
430 const char* timinputField3(
431  const TIMINPUT* timi /**< tim input structure */
432  )
433 {
434  assert(timi != NULL);
435 
436  return timi->f3;
437 }
438 
439 /** returns if an error was detected */
440 static
442  const TIMINPUT* timi /**< tim input structure */
443  )
444 {
445  assert(timi != NULL);
446 
447  return timi->haserror;
448 }
449 
450 /** set the section in the tim input structure to given section */
451 static
453  TIMINPUT* timi, /**< tim input structure */
454  TIMSECTION section /**< section that is set */
455  )
456 {
457  assert(timi != NULL);
458 
459  timi->section = section;
460 }
461 
462 /** set the problem name in the tim input structure to given problem name */
463 static
465  TIMINPUT* timi, /**< tim input structure */
466  const char* probname /**< name of the problem to set */
467  )
468 {
469  assert(timi != NULL);
470  assert(probname != NULL);
471  assert(strlen(probname) < sizeof(timi->probname));
472 
473  (void)SCIPmemccpy(timi->probname, probname, '\0', TIM_MAX_NAMELEN - 1);
474 }
475 
476 /** set the problem var name that starts a stage in the tim input structure to given objective name */
477 static
479  TIMINPUT* timi, /**< tim input structure */
480  SCIP* scip, /**< SCIP data structure */
481  const char* varname, /**< name of the variable that starts the stage */
482  int stagenum /**< the stage number the variable starts */
483  )
484 {
485  assert(timi != NULL);
486  assert(varname != NULL);
487 
488  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &timi->stagestartvars[stagenum], varname, strlen(varname) + 1) ); /*lint !e866*/
489 
490  return SCIP_OKAY;
491 }
492 
493 /** set the problem constraint name that starts a stage in the tim input structure to given objective name */
494 static
496  TIMINPUT* timi, /**< tim input structure */
497  SCIP* scip, /**< SCIP data structure */
498  const char* consname, /**< name of the constraint that starts the stage */
499  int stagenum /**< the stage number the constraint starts */
500  )
501 {
502  assert(timi != NULL);
503  assert(consname != NULL);
504 
505  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &timi->stagestartcons[stagenum], consname, strlen(consname) + 1) ); /*lint !e866*/
506 
507  return SCIP_OKAY;
508 }
509 
510 /** set the stage name in the tim input structure to given objective name */
511 static
513  TIMINPUT* timi, /**< tim input structure */
514  SCIP* scip, /**< SCIP data structure */
515  const char* stagename, /**< name of the stage */
516  int stagenum /**< the stage number the constraint starts */
517  )
518 {
519  assert(timi != NULL);
520  assert(stagename != NULL);
521 
522  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &timi->stagenames[stagenum], stagename, strlen(stagename) + 1) ); /*lint !e866*/
523 
524  return SCIP_OKAY;
525 }
526 
527 static
529  TIMINPUT* timi /**< tim input structure */
530  )
531 {
532  assert(timi != NULL);
533 
534  SCIPerrorMessage("Syntax error in line %d\n", timi->lineno);
535  timi->section = TIM_ENDATA;
536  timi->haserror = TRUE;
537 }
538 
539 /** fill the line from \p pos up to column 80 with blanks. */
540 static
542  char* buf, /**< buffer to clear */
543  unsigned int pos /**< position to start the clearing process */
544  )
545 {
546  unsigned int i;
547 
548  for(i = pos; i < 80; i++)
549  buf[i] = BLANK;
550  buf[80] = '\0';
551 }
552 
553 /** read a tim format data line and parse the fields. */
554 static
556  TIMINPUT* timi /**< tim input structure */
557  )
558 {
559  unsigned int len;
560  unsigned int i;
561  char* s;
562  SCIP_Bool is_empty;
563  char* nexttok;
564 
565  do
566  {
567  timi->f0 = timi->f1 = timi->f2 = timi->f3 = 0;
568 
569  /* Read until we have not a comment line. */
570  do
571  {
572  timi->buf[TIM_MAX_LINELEN-1] = '\0';
573  if( NULL == SCIPfgets(timi->buf, (int) sizeof(timi->buf), timi->fp) )
574  return FALSE;
575  timi->lineno++;
576  }
577  while( *timi->buf == '*' );
578 
579  /* Normalize line */
580  len = (unsigned int) strlen(timi->buf);
581 
582  for( i = 0; i < len; i++ )
583  if( (timi->buf[i] == '\t') || (timi->buf[i] == '\n') || (timi->buf[i] == '\r') )
584  timi->buf[i] = BLANK;
585 
586  if( len < 80 )
587  clearFrom(timi->buf, len);
588 
589  SCIPdebugMessage("line %d: <%s>\n", timi->lineno, timi->buf);
590 
591  assert(strlen(timi->buf) >= 80);
592 
593  /* Look for new section */
594  if( *timi->buf != BLANK )
595  {
596  timi->f0 = SCIPstrtok(&timi->buf[0], " ", &nexttok);
597 
598  assert(timi->f0 != 0);
599 
600  timi->f1 = SCIPstrtok(NULL, " ", &nexttok);
601 
602  return TRUE;
603  }
604 
605  s = &timi->buf[1];
606 
607  /* At this point it is not clear if we have a indicator field.
608  * If there is none (e.g. empty) f1 will be the first name field.
609  * If there is one, f2 will be the first name field.
610  *
611  * Initially comment marks '$' are only allowed in the beginning
612  * of the 2nd and 3rd name field. We test all fields but the first.
613  * This makes no difference, since if the $ is at the start of a value
614  * field, the line will be erroneous anyway.
615  */
616  do
617  {
618  if( NULL == (timi->f1 = SCIPstrtok(s, " ", &nexttok)) )
619  break;
620 
621  if( (NULL == (timi->f2 = SCIPstrtok(NULL, " ", &nexttok))) || (*timi->f2 == '$') )
622  {
623  timi->f2 = 0;
624  break;
625  }
626 
627  if( (NULL == (timi->f3 = SCIPstrtok(NULL, " ", &nexttok))) || (*timi->f3 == '$') )
628  {
629  timi->f3 = 0;
630  break;
631  }
632  }
633  while( FALSE );
634 
635  /* check for empty lines */
636  is_empty = (timi->f0 == NULL && timi->f1 == NULL);
637  }
638  while( is_empty );
639 
640  return TRUE;
641 }
642 
643 /** Process TIME section. */
644 static
646  SCIP* scip, /**< SCIP data structure */
647  TIMINPUT* timi /**< tim input structure */
648  )
649 {
650  SCIPdebugMsg(scip, "read problem name from TIME section\n");
651 
652  /* This has to be the Line with the TIME section. */
653  if( !timinputReadLine(timi) || timinputField0(timi) == NULL || strcmp(timinputField0(timi), "TIME") )
654  {
655  timinputSyntaxerror(timi);
656  return SCIP_OKAY;
657  }
658 
659  /* Sometimes the name is omitted. */
660  timinputSetProbname(timi, (timinputField1(timi) == 0) ? "_TIM_" : timinputField1(timi));
661 
662  /* This has to be a new section */
663  if( !timinputReadLine(timi) || (timinputField0(timi) == NULL) )
664  {
665  timinputSyntaxerror(timi);
666  return SCIP_OKAY;
667  }
668 
669  if( strncmp(timinputField0(timi), "PERIODS", 7) == 0 )
671  else
672  {
673  timinputSyntaxerror(timi);
674  return SCIP_OKAY;
675  }
676 
677  return SCIP_OKAY;
678 }
679 
680 /** Process PERIODS section. */
681 static
683  TIMINPUT* timi, /**< tim input structure */
684  SCIP* scip /**< SCIP data structure */
685  )
686 {
687  SCIPdebugMsg(scip, "read Periods\n");
688 
689  while( timinputReadLine(timi) )
690  {
691  if( timinputField0(timi) != NULL )
692  {
693  if( strcmp(timinputField0(timi), "PERIODS") == 0 )
695  else if( strcmp(timinputField0(timi), "ENDATA") == 0 )
697  else
698  timinputSyntaxerror(timi);
699 
700  return SCIP_OKAY;
701  }
702 
703  if( timi->nstages + 1 >= timi->stagesize )
704  {
705  SCIP_CALL( SCIPensureBlockMemoryArray(scip, &timi->stagestartvars, &timi->stagesize, timi->nstages + 1) );
706  SCIP_CALL( SCIPensureBlockMemoryArray(scip, &timi->stagestartcons, &timi->stagesize, timi->nstages + 1) );
707  SCIP_CALL( SCIPensureBlockMemoryArray(scip, &timi->stagenames, &timi->stagesize, timi->nstages + 1) );
708  }
709 
710  SCIP_CALL( timinputSetStageStartVar(timi, scip, timinputField1(timi), timi->nstages) );
711  SCIP_CALL( timinputSetStageStartCons(timi, scip, timinputField2(timi), timi->nstages) );
712  SCIP_CALL( timinputSetStageName(timi, scip, timinputField3(timi), timi->nstages) );
713 
714  timi->nstages++;
715  }
716  timinputSyntaxerror(timi);
717 
718  return SCIP_OKAY;
719 }
720 
721 
722 /** Read time data for the SMPS file format. */
723 static
725  SCIP* scip, /**< SCIP data structure */
726  SCIP_READER* reader, /**< the file reader itself */
727  const char* filename /**< name of the input file */
728  )
729 {
730  SCIP_FILE* fp;
731  TIMINPUT* timi;
732  SCIP_RETCODE retcode;
733  SCIP_Bool error = TRUE;
734 
735  assert(scip != NULL);
736  assert(filename != NULL);
737 
738  fp = SCIPfopen(filename, "r");
739  if( fp == NULL )
740  {
741  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
742  SCIPprintSysError(filename);
743 
744  return SCIP_NOFILE;
745  }
746 
747  SCIP_CALL_FINALLY( timinputCreate(scip, &timi, fp), SCIPfclose(fp) );
748 
749  SCIP_CALL_TERMINATE( retcode, readTime(scip, timi), TERMINATE );
750 
751  while( timinputSection(timi) == TIM_PERIODS )
752  {
753  SCIP_CALL_TERMINATE( retcode, readPeriods(timi, scip), TERMINATE );
754  }
755  if( timinputSection(timi) != TIM_ENDATA )
756  timinputSyntaxerror(timi);
757 
758  error = timinputHasError(timi);
759 
760  if( !error )
761  {
762  SCIP_CALL_TERMINATE( retcode, createReaderdata(scip, reader, timi), TERMINATE );
763  }
764 
765  /* cppcheck-suppress unusedLabel */
766  TERMINATE:
767  timinputFree(scip, &timi);
768  SCIPfclose(fp);
769 
770  if( error )
771  return SCIP_READERROR;
772  else
773  return SCIP_OKAY;
774 }
775 
776 /*
777  * Callback methods of reader
778  */
779 
780 /** copy method for reader plugins (called when SCIP copies plugins) */
781 static
782 SCIP_DECL_READERCOPY(readerCopyTim)
783 { /*lint --e{715}*/
784  assert(scip != NULL);
785  assert(reader != NULL);
786  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
787 
788  /* call inclusion method of reader */
790 
791  return SCIP_OKAY;
792 }
793 
794 /** destructor of reader to free user data (called when SCIP is exiting) */
795 static
796 SCIP_DECL_READERFREE(readerFreeTim)
797 {
798  freeReaderdata(scip, reader);
799 
800  return SCIP_OKAY;
801 }
802 
803 /** reads the stage information for a stochastic programming instance in SMPS format */
804 static
805 SCIP_DECL_READERREAD(readerReadTim)
806 { /*lint --e{715}*/
807  SCIP_READER* correader;
808 
809  assert(reader != NULL);
810  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
811 
812  correader = SCIPfindReader(scip, "correader");
813 
814  if( correader == NULL )
815  {
816  SCIPwarningMessage(scip, "It is necessary to include the \"cor\" reader\n");
817  (*result) = SCIP_DIDNOTRUN;
818  return SCIP_OKAY;
819  }
820 
821  /* checking whether the cor file has been read */
822  if( !SCIPcorHasRead(correader) )
823  {
824  SCIPwarningMessage(scip, "The core file must be read before the time and stochastic files.\n");
825  (*result) = SCIP_DIDNOTRUN;
826  return SCIP_OKAY;
827  }
828 
829  SCIP_CALL( SCIPreadTim(scip, filename, result) );
830 
831  return SCIP_OKAY;
832 }
833 
834 
835 /*
836  * tim file reader specific interface methods
837  */
838 
839 /** includes the tim file reader in SCIP */
841  SCIP* scip /**< SCIP data structure */
842  )
843 {
844  SCIP_READERDATA* readerdata;
845  SCIP_READER* reader;
846 
847  /* create reader data */
848  SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata) );
849  readerdata->read = FALSE;
850 
851  /* include reader */
853 
854  /* set non fundamental callbacks via setter functions */
855  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyTim) );
856  SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeTim) );
857  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadTim) );
858 
859  return SCIP_OKAY;
860 }
861 
862 
863 /** reads problem from file */
865  SCIP* scip, /**< SCIP data structure */
866  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
867  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
868  )
869 {
870  SCIP_READER* reader;
871  SCIP_RETCODE retcode;
872  SCIP_READERDATA* readerdata;
873 
874  assert(scip != NULL);
875  assert(result != NULL);
876 
877  reader = SCIPfindReader(scip, READER_NAME);
878  assert(reader != NULL);
879 
880  retcode = readTim(scip, reader, filename);
881 
882  if( retcode == SCIP_PLUGINNOTFOUND )
883  retcode = SCIP_READERROR;
884 
885  if( retcode == SCIP_NOFILE || retcode == SCIP_READERROR )
886  return retcode;
887 
888  SCIP_CALL( retcode );
889 
890  /* creating the stages */
891  SCIP_CALL( createStages(scip, reader, SCIPfindReader(scip, "correader")) );
892 
893  /* setting the read flag to TRUE */
894  readerdata = SCIPreaderGetData(reader);
895  readerdata->read = TRUE;
896 
897  *result = SCIP_SUCCESS;
898 
899  return SCIP_OKAY;
900 }
901 
902 /*
903  * Interface methods for the cor and sto files
904  */
905 
906 /* return whether the tim file has been read */
908  SCIP_READER* reader /**< the file reader itself */
909  )
910 {
911  SCIP_READERDATA* readerdata;
912 
913  assert(reader != NULL);
914  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
915 
916  readerdata = SCIPreaderGetData(reader);
917  assert(readerdata != NULL);
918 
919  return readerdata->read;
920 }
921 
922 
923 /* returns the number of stages */
925  SCIP* scip /**< SCIP data structure */
926  )
927 {
928  SCIP_READER* reader;
929  SCIP_READERDATA* readerdata;
930 
931  reader = SCIPfindReader(scip, READER_NAME);
932 
933  assert(reader != NULL);
934  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
935 
936  readerdata = SCIPreaderGetData(reader);
937  assert(readerdata != NULL);
938 
939  return readerdata->nstages;
940 }
941 
942 /* returns the name for a given stage */
944  SCIP* scip, /**< SCIP data structure */
945  int stagenum /**< the number of the requested stage */
946  )
947 {
948  SCIP_READER* reader;
949  SCIP_READERDATA* readerdata;
950 
951  reader = SCIPfindReader(scip, READER_NAME);
952 
953  assert(reader != NULL);
954  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
955 
956  readerdata = SCIPreaderGetData(reader);
957  assert(readerdata != NULL);
958  assert(stagenum >= 0 && stagenum < readerdata->nstages);
959 
960  return readerdata->stagenames[stagenum];
961 }
962 
963 /* returns the stage name for a given constraint name */
965  SCIP* scip, /**< SCIP data structure */
966  const char* consname /**< the constraint to search for */
967  )
968 {
969  SCIP_READER* reader;
970  SCIP_READERDATA* readerdata;
971  int stagenum;
972  int i;
973  int j;
974 
975  reader = SCIPfindReader(scip, READER_NAME);
976 
977  assert(reader != NULL);
978  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
979 
980  readerdata = SCIPreaderGetData(reader);
981  assert(readerdata != NULL);
982 
983  /* looping over all stages to find the provided constraint */
984  stagenum = -1;
985  for( i = 0; i < readerdata->nstages; i++ )
986  {
987  for( j = 0; j < readerdata->stages[i]->nconss; j++ )
988  {
989  if( strcmp(SCIPconsGetName(readerdata->stages[i]->conss[j]), consname) == 0 )
990  {
991  stagenum = i;
992  break;
993  }
994  }
995 
996  if( stagenum >= 0 )
997  break;
998  }
999  assert(stagenum >= 0 && stagenum < readerdata->nstages);
1000 
1001  return readerdata->stagenames[stagenum];
1002 }
1003 
1004 /* returns the number for a given stage */
1006  SCIP* scip, /**< SCIP data structure */
1007  const char* stage /**< the name of the requested stage */
1008  )
1009 {
1010  SCIP_READER* reader;
1011  SCIP_READERDATA* readerdata;
1012  int i;
1013 
1014  reader = SCIPfindReader(scip, READER_NAME);
1015 
1016  assert(reader != NULL);
1017  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
1018 
1019  readerdata = SCIPreaderGetData(reader);
1020  assert(readerdata != NULL);
1021 
1022  for( i = 0; i < readerdata->nstages; i++ )
1023  {
1024  if( strcmp(readerdata->stagenames[i], stage) == 0 )
1025  return i;
1026  }
1027 
1028  return -1;
1029 }
1030 
1031 /* returns the array of variables for a given stage */
1033  SCIP* scip, /**< SCIP data structure */
1034  int stagenum /**< the number of the requested stage */
1035  )
1036 {
1037  SCIP_READER* reader;
1038  SCIP_READERDATA* readerdata;
1039 
1040  reader = SCIPfindReader(scip, READER_NAME);
1041 
1042  assert(reader != NULL);
1043  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
1044 
1045  readerdata = SCIPreaderGetData(reader);
1046  assert(readerdata != NULL);
1047  assert(stagenum >= 0 && stagenum < readerdata->nstages);
1048 
1049  return readerdata->stages[stagenum]->vars;
1050 }
1051 
1052 /* returns an array of constraints for a given stage */
1054  SCIP* scip, /**< SCIP data structure */
1055  int stagenum /**< the number of the requested stage */
1056  )
1057 {
1058  SCIP_READER* reader;
1059  SCIP_READERDATA* readerdata;
1060 
1061  reader = SCIPfindReader(scip, READER_NAME);
1062 
1063  assert(reader != NULL);
1064  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
1065 
1066  readerdata = SCIPreaderGetData(reader);
1067  assert(readerdata != NULL);
1068  assert(stagenum >= 0 && stagenum < readerdata->nstages);
1069 
1070  return readerdata->stages[stagenum]->conss;
1071 }
1072 
1073 /* returns the number of variables for a given stage */
1075  SCIP* scip, /**< SCIP data structure */
1076  int stagenum /**< the number of the requested stage */
1077  )
1078 {
1079  SCIP_READER* reader;
1080  SCIP_READERDATA* readerdata;
1081 
1082  reader = SCIPfindReader(scip, READER_NAME);
1083 
1084  assert(reader != NULL);
1085  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
1086 
1087  readerdata = SCIPreaderGetData(reader);
1088  assert(readerdata != NULL);
1089  assert(stagenum >= 0 && stagenum < readerdata->nstages);
1090 
1091  return readerdata->stages[stagenum]->nvars;
1092 }
1093 
1094 /* returns the number of constraints for a given stage */
1096  SCIP* scip, /**< SCIP data structure */
1097  int stagenum /**< the number of the requested stage */
1098  )
1099 {
1100  SCIP_READER* reader;
1101  SCIP_READERDATA* readerdata;
1102 
1103  reader = SCIPfindReader(scip, READER_NAME);
1104 
1105  assert(reader != NULL);
1106  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
1107 
1108  readerdata = SCIPreaderGetData(reader);
1109  assert(readerdata != NULL);
1110  assert(stagenum >= 0 && stagenum < readerdata->nstages);
1111 
1112  return readerdata->stages[stagenum]->nconss;
1113 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:116
SCIP_RETCODE SCIPreadTim(SCIP *scip, const char *filename, SCIP_RESULT *result)
Definition: reader_tim.c:864
#define NULL
Definition: def.h:239
int lineno
Definition: reader_tim.c:90
static SCIP_DECL_READERREAD(readerReadTim)
Definition: reader_tim.c:805
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition: misc.c:9901
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:99
TIM file reader - the stage information for a stochastic programming instance in SMPS format...
#define TIM_DEFAULT_STAGESIZE
Definition: reader_tim.c:47
SCIP_HASHMAP * consnametocons
Definition: reader_tim.c:57
#define TIM_MAX_LINELEN
Definition: reader_tim.c:45
public methods for memory management
static SCIP_Bool timinputHasError(const TIMINPUT *timi)
Definition: reader_tim.c:441
static const char * timinputField2(const TIMINPUT *timi)
Definition: reader_tim.c:419
SCIP_HASHMAP * varnametovar
Definition: reader_tim.c:56
static TIMSECTION timinputSection(const TIMINPUT *timi)
Definition: reader_tim.c:386
const char * SCIPcorGetVarName(SCIP_READER *reader, int i)
Definition: reader_cor.c:255
COR file reader (MPS format of the core problem for stochastic programs)
#define SCIP_CALL_FINALLY(x, y)
Definition: def.h:393
const char ** stagestartvars
Definition: reader_tim.c:98
char probname[TIM_MAX_NAMELEN]
Definition: reader_tim.c:97
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:547
SCIP_VAR ** vars
Definition: reader_tim.c:54
static SCIP_RETCODE timinputSetStageStartVar(TIMINPUT *timi, SCIP *scip, const char *varname, int stagenum)
Definition: reader_tim.c:478
#define FALSE
Definition: def.h:65
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2793
enum TimSection TIMSECTION
Definition: reader_tim.c:83
int nconss
Definition: reader_tim.c:59
#define TRUE
Definition: def.h:64
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define TIM_DEFAULT_ARRAYSIZE
Definition: reader_tim.c:48
static void freeReaderdata(SCIP *scip, SCIP_READER *reader)
Definition: reader_tim.c:284
const char ** stagenames
Definition: reader_tim.c:100
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:114
SCIP_READER * SCIPfindReader(SCIP *scip, const char *name)
Definition: scip_reader.c:306
#define SCIPdebugMessage
Definition: pub_message.h:77
const char * SCIPtimConsGetStageName(SCIP *scip, const char *consname)
Definition: reader_tim.c:964
const char * f3
Definition: reader_tim.c:96
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:97
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:203
#define SCIPdebugMsg
Definition: scip_message.h:88
#define READER_DESC
Definition: reader_tim.c:38
public methods for numerical tolerances
#define TIM_MAX_NAMELEN
Definition: reader_tim.c:46
const char * f0
Definition: reader_tim.c:93
TIMSECTION section
Definition: reader_tim.c:88
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip_prob.c:2737
static void timinputSetProbname(TIMINPUT *timi, const char *probname)
Definition: reader_tim.c:464
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:140
SCIP_READERDATA * SCIPreaderGetData(SCIP_READER *reader)
Definition: reader.c:482
const char * SCIPcorGetConsName(SCIP_READER *reader, int i)
Definition: reader_cor.c:273
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:111
SCIP_Bool SCIPtimHasRead(SCIP_READER *reader)
Definition: reader_tim.c:907
public methods for managing constraints
char buf[TIM_MAX_LINELEN]
Definition: reader_tim.c:92
TimSection
Definition: reader_tim.c:77
#define SCIPerrorMessage
Definition: pub_message.h:45
int nvars
Definition: reader_tim.c:58
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:128
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:34
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:187
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8076
int SCIPcorGetNConsNames(SCIP_READER *reader)
Definition: reader_cor.c:239
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2826
int SCIPtimGetNStages(SCIP *scip)
Definition: reader_tim.c:924
SCIP_CONS * SCIPfindCons(SCIP *scip, const char *name)
Definition: scip_prob.c:2999
SCIP_CONS ** conss
Definition: reader_tim.c:55
#define SCIP_CALL(x)
Definition: def.h:351
#define SCIPensureBlockMemoryArray(scip, ptr, arraysizeptr, minsize)
Definition: scip_mem.h:113
static SCIP_DECL_READERCOPY(readerCopyTim)
Definition: reader_tim.c:782
static void clearFrom(char *buf, unsigned int pos)
Definition: reader_tim.c:541
static void timinputSyntaxerror(TIMINPUT *timi)
Definition: reader_tim.c:528
wrapper functions to map file i/o to standard or zlib file i/o
static SCIP_Bool timinputReadLine(TIMINPUT *timi)
Definition: reader_tim.c:555
struct SCIP_ReaderData SCIP_READERDATA
Definition: type_reader.h:37
#define READER_NAME
Definition: reader_tim.c:37
public data structures and miscellaneous methods
int SCIPtimFindStage(SCIP *scip, const char *stage)
Definition: reader_tim.c:1005
#define SCIP_Bool
Definition: def.h:62
static SCIP_RETCODE addConstraintToStage(SCIP *scip, TIMSTAGE *stage, const char *consname)
Definition: reader_tim.c:140
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip_reader.c:180
void SCIPprintSysError(const char *message)
Definition: misc.c:9926
static const char * timinputField3(const TIMINPUT *timi)
Definition: reader_tim.c:430
SCIP_CONS ** SCIPtimGetStageConss(SCIP *scip, int stagenum)
Definition: reader_tim.c:1053
const char * f1
Definition: reader_tim.c:94
static SCIP_RETCODE timinputCreate(SCIP *scip, TIMINPUT **timi, SCIP_FILE *fp)
Definition: reader_tim.c:330
const char * f2
Definition: reader_tim.c:95
static SCIP_RETCODE readTime(SCIP *scip, TIMINPUT *timi)
Definition: reader_tim.c:645
static SCIP_RETCODE readPeriods(TIMINPUT *timi, SCIP *scip)
Definition: reader_tim.c:682
static SCIP_RETCODE readTim(SCIP *scip, SCIP_READER *reader, const char *filename)
Definition: reader_tim.c:724
int SCIPtimGetStageNVars(SCIP *scip, int stagenum)
Definition: reader_tim.c:1074
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip_reader.c:218
static SCIP_RETCODE timinputSetStageName(TIMINPUT *timi, SCIP *scip, const char *stagename, int stagenum)
Definition: reader_tim.c:512
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2044
static SCIP_RETCODE addVariableToStage(SCIP *scip, TIMSTAGE *stage, const char *varname)
Definition: reader_tim.c:108
#define BLANK
Definition: reader_tim.c:50
int conssize
Definition: reader_tim.c:61
static SCIP_DECL_READERFREE(readerFreeTim)
Definition: reader_tim.c:796
SCIP_Bool SCIPcorHasRead(SCIP_READER *reader)
Definition: reader_cor.c:207
public methods for message output
static const char * timinputField0(const TIMINPUT *timi)
Definition: reader_tim.c:397
static SCIP_RETCODE createReaderdata(SCIP *scip, SCIP_READER *reader, TIMINPUT *timi)
Definition: reader_tim.c:225
#define READER_EXTENSION
Definition: reader_tim.c:39
const char ** stagestartcons
Definition: reader_tim.c:99
#define SCIP_Real
Definition: def.h:150
public methods for input file readers
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:372
int nstages
Definition: reader_tim.c:101
public methods for message handling
SCIP_Bool haserror
Definition: reader_tim.c:91
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip_reader.c:266
static SCIP_RETCODE timinputSetStageStartCons(TIMINPUT *timi, SCIP *scip, const char *consname, int stagenum)
Definition: reader_tim.c:495
static void timinputSetSection(TIMINPUT *timi, TIMSECTION section)
Definition: reader_tim.c:452
static void timinputFree(SCIP *scip, TIMINPUT **timi)
Definition: reader_tim.c:363
int SCIPcorGetNVarNames(SCIP_READER *reader)
Definition: reader_cor.c:223
int stagesize
Definition: reader_tim.c:102
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2874
SCIP_VAR ** SCIPtimGetStageVars(SCIP *scip, int stagenum)
Definition: reader_tim.c:1032
SCIP_FILE * fp
Definition: reader_tim.c:89
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:219
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
int SCIPtimGetStageNConss(SCIP *scip, int stagenum)
Definition: reader_tim.c:1095
public methods for reader plugins
public methods for global and local (sub)problems
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:9975
int varssize
Definition: reader_tim.c:60
static SCIP_RETCODE createStages(SCIP *scip, SCIP_READER *reader, SCIP_READER *correader)
Definition: reader_tim.c:172
const char * SCIPtimGetStageName(SCIP *scip, int stagenum)
Definition: reader_tim.c:943
static const char * timinputField1(const TIMINPUT *timi)
Definition: reader_tim.c:408
SCIP_RETCODE SCIPsetReaderFree(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERFREE((*readerfree)))
Definition: scip_reader.c:242
SCIP_RETCODE SCIPincludeReaderTim(SCIP *scip)
Definition: reader_tim.c:840