Scippy

SCIP

Solving Constraint Integer Programs

reader_diff.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_diff.c
17  * @brief DIFF file reader
18  * @author Jakob Witzig
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <stdlib.h>
24 #include <assert.h>
25 #include <string.h>
26 #if defined(_WIN32) || defined(_WIN64)
27 #else
28 #include <strings.h> /*lint --e{766}*/ /* needed for strncasecmp() */
29 #endif
30 #include <ctype.h>
31 
32 #include "scip/reader_diff.h"
33 
34 #define READER_NAME "diffreader"
35 #define READER_DESC "file reader for changes in the LP file"
36 #define READER_EXTENSION "diff"
37 
38 /*
39  * Data structures
40  */
41 #define LP_MAX_LINELEN 65536
42 #define LP_MAX_PUSHEDTOKENS 2
43 #define LP_INIT_COEFSSIZE 8192
44 
45 /** Section in LP File */
47 {
49 };
50 typedef enum LpSection LPSECTION;
51 
53 {
55 };
56 typedef enum LpExpType LPEXPTYPE;
57 
58 enum LpSense
59 {
61 };
62 typedef enum LpSense LPSENSE;
63 
64 /** LP reading data */
65 struct LpInput
66 {
67  SCIP_FILE* file;
68  char linebuf[LP_MAX_LINELEN+1];
69  char probname[LP_MAX_LINELEN];
70  char objname[LP_MAX_LINELEN];
71  char* token;
72  char* tokenbuf;
73  char* pushedtokens[LP_MAX_PUSHEDTOKENS];
74  int npushedtokens;
75  int linenumber;
76  int linepos;
77  LPSECTION section;
78  SCIP_OBJSENSE objsense;
79  SCIP_Bool haserror;
80  SCIP_Bool comment;
81  SCIP_Bool endline;
82 };
83 typedef struct LpInput LPINPUT;
84 
85 static const char commentchars[] = "\\";
86 
87 
88 /*
89  * Local methods (for reading)
90  */
91 
92 /** issues an error message and marks the LP data to have errors */
93 static
95  SCIP* scip, /**< SCIP data structure */
96  LPINPUT* lpinput, /**< LP reading data */
97  const char* msg /**< error message */
98  )
99 {
100  char formatstr[256];
101 
102  assert(lpinput != NULL);
103 
104  SCIPerrorMessage("Syntax error in line %d ('%s'): %s \n", lpinput->linenumber, lpinput->token, msg);
105  if( lpinput->linebuf[strlen(lpinput->linebuf)-1] == '\n' )
106  {
107  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s", lpinput->linebuf);
108  }
109  else
110  {
111  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s\n", lpinput->linebuf);
112  }
113  (void) SCIPsnprintf(formatstr, 256, " %%%ds\n", lpinput->linepos);
114  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, (const char*)formatstr, "^");
115  lpinput->section = LP_END;
116  lpinput->haserror = TRUE;
117 }
118 
119 /** returns whether a syntax error was detected */
120 static
122  LPINPUT* lpinput /**< LP reading data */
123  )
124 {
125  assert(lpinput != NULL);
126 
127  return lpinput->haserror;
128 }
129 
130 /** returns whether the given character is a token delimiter */
131 static
133  char c /**< input character */
134  )
135 {
136  switch (c)
137  {
138  case ' ':
139  case '\f':
140  case '\n':
141  case '\r':
142  case '\t':
143  case '\v':
144  case '\0':
145  return TRUE;
146  default:
147  return FALSE;
148  }
149 }
150 
151 /** returns whether the given character is a single token */
152 static
154  char c /**< input character */
155  )
156 {
157  switch (c)
158  {
159  case '-':
160  case '+':
161  case ':':
162  case '<':
163  case '>':
164  case '=':
165  case '[':
166  case ']':
167  case '*':
168  case '^':
169  return TRUE;
170  default:
171  return FALSE;
172  }
173 }
174 
175 /** returns whether the current character is member of a value string */
176 static
178  char c, /**< input character */
179  char nextc, /**< next input character */
180  SCIP_Bool firstchar, /**< is the given character the first char of the token? */
181  SCIP_Bool* hasdot, /**< pointer to update the dot flag */
182  LPEXPTYPE* exptype /**< pointer to update the exponent type */
183  )
184 {
185  assert(hasdot != NULL);
186  assert(exptype != NULL);
187 
188  if( isdigit((unsigned char)c) )
189  return TRUE;
190  else if( (*exptype == LP_EXP_NONE) && !(*hasdot) && (c == '.') && isdigit((unsigned char)nextc) )
191  {
192  *hasdot = TRUE;
193  return TRUE;
194  }
195  else if( !firstchar && (*exptype == LP_EXP_NONE) && (c == 'e' || c == 'E') )
196  {
197  if( nextc == '+' || nextc == '-' )
198  {
199  *exptype = LP_EXP_SIGNED;
200  return TRUE;
201  }
202  else if( isdigit((unsigned char)nextc) )
203  {
204  *exptype = LP_EXP_UNSIGNED;
205  return TRUE;
206  }
207  }
208  else if( (*exptype == LP_EXP_SIGNED) && (c == '+' || c == '-') )
209  {
210  *exptype = LP_EXP_UNSIGNED;
211  return TRUE;
212  }
213 
214  return FALSE;
215 }
216 
217 /** reads the next line from the input file into the line buffer; skips comments;
218  * returns whether a line could be read
219  */
220 static
222  SCIP* scip, /**< SCIP data structure */
223  LPINPUT* lpinput /**< LP reading data */
224  )
225 {
226  int i;
227 
228  assert(lpinput != NULL);
229 
230  /* if we previously detected a comment we have to parse the remaining line away if there is something left */
231  if( !lpinput->endline && lpinput->comment )
232  {
233  SCIPdebugMessage("Throwing rest of comment away.\n");
234 
235  do
236  {
237  lpinput->linebuf[LP_MAX_LINELEN-2] = '\0';
238  (void)SCIPfgets(lpinput->linebuf, (int) sizeof(lpinput->linebuf), lpinput->file);
239  }
240  while( lpinput->linebuf[LP_MAX_LINELEN-2] != '\0' );
241 
242  lpinput->comment = FALSE;
243  lpinput->endline = TRUE;
244  }
245 
246  /* read next line */
247  lpinput->linepos = 0;
248  lpinput->linebuf[LP_MAX_LINELEN-2] = '\0';
249 
250  if( SCIPfgets(lpinput->linebuf, (int) sizeof(lpinput->linebuf), lpinput->file) == NULL )
251  {
252  /* clear the line, this is really necessary here! */
253  BMSclearMemoryArray(lpinput->linebuf, LP_MAX_LINELEN);
254 
255  return FALSE;
256  }
257 
258  lpinput->linenumber++;
259 
260  /* if line is too long for our buffer correct the buffer and correct position in file */
261  if( lpinput->linebuf[LP_MAX_LINELEN-2] != '\0' )
262  {
263  char* last;
264 
265  /* buffer is full; erase last token since it might be incomplete */
266  lpinput->endline = FALSE;
267  last = strrchr(lpinput->linebuf, ' ');
268 
269  if( last == NULL )
270  {
271  SCIPwarningMessage(scip, "we read %d characters from the file; this might indicate a corrupted input file!",
272  LP_MAX_LINELEN - 2);
273  lpinput->linebuf[LP_MAX_LINELEN-2] = '\0';
274  SCIPdebugMessage("the buffer might be corrupted\n");
275  }
276  else
277  {
278  SCIPfseek(lpinput->file, -(long) strlen(last) - 1, SEEK_CUR);
279  SCIPdebugMessage("correct buffer, reread the last %ld characters\n", (long) strlen(last) + 1);
280  *last = '\0';
281  }
282  }
283  else
284  {
285  /* found end of line */
286  lpinput->endline = TRUE;
287  }
288  lpinput->linebuf[LP_MAX_LINELEN-1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
289  lpinput->comment = FALSE;
290 
291  /* skip characters after comment symbol */
292  for( i = 0; commentchars[i] != '\0'; ++i )
293  {
294  char* commentstart;
295 
296  commentstart = strchr(lpinput->linebuf, commentchars[i]);
297  if( commentstart != NULL )
298  {
299  *commentstart = '\0';
300  *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
301 
302  lpinput->comment = TRUE;
303  break;
304  }
305  }
306 
307  return TRUE;
308 }
309 
310 /** swaps the addresses of two pointers */
311 static
313  char** pointer1, /**< first pointer */
314  char** pointer2 /**< second pointer */
315  )
316 {
317  char* tmp;
318 
319  tmp = *pointer1;
320  *pointer1 = *pointer2;
321  *pointer2 = tmp;
322 }
323 
324 /** reads the next token from the input file into the token buffer; returns whether a token was read */
325 static
327  SCIP* scip, /**< SCIP data structure */
328  LPINPUT* lpinput /**< LP reading data */
329  )
330 {
331  SCIP_Bool hasdot;
332  LPEXPTYPE exptype;
333  char* buf;
334  int tokenlen;
335 
336  assert(lpinput != NULL);
337  assert(lpinput->linepos < LP_MAX_LINELEN);
338 
339  /* check the token stack */
340  if( lpinput->npushedtokens > 0 )
341  {
342  swapPointers(&lpinput->token, &lpinput->pushedtokens[lpinput->npushedtokens-1]);
343  lpinput->npushedtokens--;
344 
345  SCIPdebugMessage("(line %d) read token again: '%s'\n", lpinput->linenumber, lpinput->token);
346  return TRUE;
347  }
348 
349  /* skip delimiters */
350  buf = lpinput->linebuf;
351  while( isDelimChar(buf[lpinput->linepos]) )
352  {
353  if( buf[lpinput->linepos] == '\0' )
354  {
355  if( !getNextLine(scip, lpinput) )
356  {
357  lpinput->section = LP_END;
358  SCIPdebugMessage("(line %d) end of file\n", lpinput->linenumber);
359  return FALSE;
360  }
361  assert(lpinput->linepos == 0);
362  }
363  else
364  lpinput->linepos++;
365  }
366  assert(lpinput->linepos < LP_MAX_LINELEN);
367  assert(!isDelimChar(buf[lpinput->linepos]));
368 
369  /* check if the token is a value */
370  hasdot = FALSE;
371  exptype = LP_EXP_NONE;
372  if( isValueChar(buf[lpinput->linepos], buf[lpinput->linepos+1], TRUE, &hasdot, &exptype) )
373  {
374  /* read value token */
375  tokenlen = 0;
376  do
377  {
378  assert(tokenlen < LP_MAX_LINELEN);
379  assert(!isDelimChar(buf[lpinput->linepos]));
380  lpinput->token[tokenlen] = buf[lpinput->linepos];
381  tokenlen++;
382  lpinput->linepos++;
383  }
384  while( isValueChar(buf[lpinput->linepos], buf[lpinput->linepos+1], FALSE, &hasdot, &exptype) );
385  }
386  else
387  {
388  /* read non-value token */
389  tokenlen = 0;
390  do
391  {
392  assert(tokenlen < LP_MAX_LINELEN);
393  lpinput->token[tokenlen] = buf[lpinput->linepos];
394  tokenlen++;
395  lpinput->linepos++;
396  if( tokenlen == 1 && isTokenChar(lpinput->token[0]) )
397  break;
398  }
399  while( !isDelimChar(buf[lpinput->linepos]) && !isTokenChar(buf[lpinput->linepos]) );
400 
401  /* if the token is a power sign '^', skip a following '2'
402  * if the token is an equation sense '<', '>', or '=', skip a following '='
403  * if the token is an equality token '=' and the next character is a '<' or '>', replace the token by the inequality sense
404  */
405  if( tokenlen >= 1 && lpinput->token[tokenlen-1] == '^' && buf[lpinput->linepos] == '2' )
406  {
407  lpinput->linepos++;
408  }
409  if( tokenlen >= 1
410  && (lpinput->token[tokenlen-1] == '<' || lpinput->token[tokenlen-1] == '>' || lpinput->token[tokenlen-1] == '=')
411  && buf[lpinput->linepos] == '=' )
412  {
413  lpinput->linepos++;
414  }
415  else if( lpinput->token[tokenlen-1] == '=' && (buf[lpinput->linepos] == '<' || buf[lpinput->linepos] == '>') )
416  {
417  lpinput->token[tokenlen-1] = buf[lpinput->linepos];
418  lpinput->linepos++;
419  }
420  }
421  assert(tokenlen < LP_MAX_LINELEN);
422  lpinput->token[tokenlen] = '\0';
423 
424  SCIPdebugMessage("(line %d) read token: '%s'\n", lpinput->linenumber, lpinput->token);
425 
426  return TRUE;
427 }
428 
429 /** puts the current token on the token stack, such that it is read at the next call to getNextToken() */
430 static
432  LPINPUT* lpinput /**< LP reading data */
433  )
434 {
435  assert(lpinput != NULL);
436  assert(lpinput->npushedtokens < LP_MAX_PUSHEDTOKENS);
437 
438  swapPointers(&lpinput->pushedtokens[lpinput->npushedtokens], &lpinput->token);
439  lpinput->npushedtokens++;
440 }
441 
442 /** puts the buffered token on the token stack, such that it is read at the next call to getNextToken() */
443 static
445  LPINPUT* lpinput /**< LP reading data */
446  )
447 {
448  assert(lpinput != NULL);
449  assert(lpinput->npushedtokens < LP_MAX_PUSHEDTOKENS);
450 
451  swapPointers(&lpinput->pushedtokens[lpinput->npushedtokens], &lpinput->tokenbuf);
452  lpinput->npushedtokens++;
453 }
454 
455 /** swaps the current token with the token buffer */
456 static
458  LPINPUT* lpinput /**< LP reading data */
459  )
460 {
461  assert(lpinput != NULL);
462 
463  swapPointers(&lpinput->token, &lpinput->tokenbuf);
464 }
465 
466 /** checks whether the current token is a section identifier, and if yes, switches to the corresponding section */
467 static
469  SCIP* scip, /**< SCIP data structure */
470  LPINPUT* lpinput /**< LP reading data */
471  )
472 {
473  SCIP_Bool iscolon;
474  size_t len;
475 
476  assert(lpinput != NULL);
477 
478  /* remember first token by swapping the token buffer */
479  swapTokenBuffer(lpinput);
480 
481  /* look at next token: if this is a ':', the first token is a name and no section keyword */
482  iscolon = FALSE;
483  if( getNextToken(scip, lpinput) )
484  {
485  iscolon = (*lpinput->token == ':');
486  pushToken(lpinput);
487  }
488 
489  /* reinstall the previous token by swapping back the token buffer */
490  swapTokenBuffer(lpinput);
491 
492  /* check for ':' */
493  if( iscolon )
494  return FALSE;
495 
496  len = strlen(lpinput->token);
497  assert(len < LP_MAX_LINELEN);
498 
499  /* the section keywords are at least 2 characters up to 8 or exactly 15 characters long */
500  if( len > 1 && (len < 9 || len == 15) )
501  {
502  char token[16];
503  int c = 0;
504 
505  while( lpinput->token[c] != '\0' )
506  {
507  token[c] = toupper(lpinput->token[c]); /*lint !e734*/
508  ++c;
509  assert(c < 16);
510  }
511  token[c] = '\0';
512 
513  if( (len == 3 && strcmp(token, "MIN") == 0)
514  || (len == 7 && strcmp(token, "MINIMUM") == 0)
515  || (len == 8 && strcmp(token, "MINIMIZE") == 0) )
516  {
517  SCIPdebugMessage("(line %d) new section: OBJECTIVE\n", lpinput->linenumber);
518  lpinput->section = LP_OBJECTIVE;
519  lpinput->objsense = SCIP_OBJSENSE_MINIMIZE;
520  return TRUE;
521  }
522 
523  if( (len == 3 && strcmp(token, "MAX") == 0)
524  || (len == 7 && strcmp(token, "MAXIMUM") == 0)
525  || (len == 8 && strcmp(token, "MAXIMIZE") == 0) )
526  {
527  SCIPdebugMessage("(line %d) new section: OBJECTIVE\n", lpinput->linenumber);
528  lpinput->section = LP_OBJECTIVE;
529  lpinput->objsense = SCIP_OBJSENSE_MAXIMIZE;
530  return TRUE;
531  }
532 
533  if( len == 3 && strcmp(token, "END") == 0 )
534  {
535  SCIPdebugMessage("(line %d) new section: END\n", lpinput->linenumber);
536  lpinput->section = LP_END;
537  return TRUE;
538  }
539  }
540 
541  return FALSE;
542 }
543 
544 /** returns whether the current token is a sign */
545 static
547  LPINPUT* lpinput, /**< LP reading data */
548  int* sign /**< pointer to update the sign */
549  )
550 {
551  assert(lpinput != NULL);
552  assert(sign != NULL);
553  assert(*sign == +1 || *sign == -1);
554 
555  if( lpinput->token[1] == '\0' )
556  {
557  if( *lpinput->token == '+' )
558  return TRUE;
559  else if( *lpinput->token == '-' )
560  {
561  *sign *= -1;
562  return TRUE;
563  }
564  }
565 
566  return FALSE;
567 }
568 
569 /** returns whether the current token is a value */
570 static
572  SCIP* scip, /**< SCIP data structure */
573  LPINPUT* lpinput, /**< LP reading data */
574  SCIP_Real* value /**< pointer to store the value (unchanged, if token is no value) */
575  )
576 {
577  assert(lpinput != NULL);
578  assert(value != NULL);
579 
580  if( strcasecmp(lpinput->token, "INFINITY") == 0 || strcasecmp(lpinput->token, "INF") == 0 )
581  {
582  *value = SCIPinfinity(scip);
583  return TRUE;
584  }
585  else
586  {
587  double val;
588  char* endptr;
589 
590  val = strtod(lpinput->token, &endptr);
591  if( endptr != lpinput->token && *endptr == '\0' )
592  {
593  *value = val;
594  return TRUE;
595  }
596  }
597 
598  return FALSE;
599 }
600 
601 /** returns whether the current token is an equation sense */
602 static
604  LPINPUT* lpinput, /**< LP reading data */
605  LPSENSE* sense /**< pointer to store the equation sense, or NULL */
606  )
607 {
608  assert(lpinput != NULL);
609 
610  if( strcmp(lpinput->token, "<") == 0 )
611  {
612  if( sense != NULL )
613  *sense = LP_SENSE_LE;
614  return TRUE;
615  }
616  else if( strcmp(lpinput->token, ">") == 0 )
617  {
618  if( sense != NULL )
619  *sense = LP_SENSE_GE;
620  return TRUE;
621  }
622  else if( strcmp(lpinput->token, "=") == 0 )
623  {
624  if( sense != NULL )
625  *sense = LP_SENSE_EQ;
626  return TRUE;
627  }
628 
629  return FALSE;
630 }
631 
632 /** returns the variable with the given name, or creates a new variable if it does not exist */
633 static
635  SCIP* scip, /**< SCIP data structure */
636  char* name, /**< name of the variable */
637  SCIP_VAR** var /**< pointer to store the variable */
638  )
639 {
640  assert(name != NULL);
641  assert(var != NULL);
642 
643  *var = SCIPfindVar(scip, name);
644 
645  if( *var == NULL )
646  return SCIP_READERROR;
647 
648  return SCIP_OKAY;
649 }
650 
651 /** reads the header of the file */
652 static
654  SCIP* scip, /**< SCIP data structure */
655  LPINPUT* lpinput /**< LP reading data */
656  )
657 {
658  assert(lpinput != NULL);
659 
660  /* everything before first section is treated as comment */
661  do
662  {
663  /* get token */
664  if( !getNextToken(scip, lpinput) )
665  return SCIP_OKAY;
666  }
667  while( !isNewSection(scip, lpinput) );
668 
669  return SCIP_OKAY;
670 }
671 
672 /** reads an objective or constraint with name and coefficients */
673 static
675  SCIP* scip, /**< SCIP data structure */
676  LPINPUT* lpinput, /**< LP reading data */
677  SCIP_Bool isobjective, /**< indicates whether we are currently reading the coefficients of the objective */
678  char* name, /**< pointer to store the name of the line; must be at least of size
679  * LP_MAX_LINELEN */
680  SCIP_VAR*** vars, /**< pointer to store the array with variables (must be freed by caller) */
681  SCIP_Real** coefs, /**< pointer to store the array with coefficients (must be freed by caller) */
682  int* ncoefs, /**< pointer to store the number of coefficients */
683  SCIP_Bool* newsection /**< pointer to store whether a new section was encountered */
684  )
685 {
686  SCIP_Bool havesign;
687  SCIP_Bool havevalue;
688  SCIP_Real coef;
689  int coefsign;
690  int coefssize;
691 
692  assert(lpinput != NULL);
693  assert(name != NULL);
694  assert(vars != NULL);
695  assert(coefs != NULL);
696  assert(ncoefs != NULL);
697  assert(newsection != NULL);
698 
699  *vars = NULL;
700  *coefs = NULL;
701  *name = '\0';
702  *ncoefs = 0;
703  *newsection = FALSE;
704 
705  /* read the first token, which may be the name of the line */
706  if( getNextToken(scip, lpinput) )
707  {
708  /* check if we reached a new section */
709  if( isNewSection(scip, lpinput) )
710  {
711  *newsection = TRUE;
712  return SCIP_OKAY;
713  }
714 
715  /* remember the token in the token buffer */
716  swapTokenBuffer(lpinput);
717 
718  /* get the next token and check, whether it is a colon */
719  if( getNextToken(scip, lpinput) )
720  {
721  if( strcmp(lpinput->token, ":") == 0 )
722  {
723  /* the second token was a colon: the first token is the line name */
724  (void)SCIPmemccpy(name, lpinput->tokenbuf, '\0', LP_MAX_LINELEN);
725 
726  name[LP_MAX_LINELEN - 1] = '\0';
727  SCIPdebugMessage("(line %d) read constraint name: '%s'\n", lpinput->linenumber, name);
728  }
729  else
730  {
731  /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */
732  pushToken(lpinput);
733  pushBufferToken(lpinput);
734  }
735  }
736  else
737  {
738  /* there was only one token left: push it back onto the token stack and parse it as coefficient */
739  pushBufferToken(lpinput);
740  }
741  }
742 
743  /* initialize buffers for storing the coefficients */
744  coefssize = LP_INIT_COEFSSIZE;
745  SCIP_CALL( SCIPallocMemoryArray(scip, vars, coefssize) );
746  SCIP_CALL( SCIPallocMemoryArray(scip, coefs, coefssize) );
747 
748  /* read the coefficients */
749  coefsign = +1;
750  coef = 1.0;
751  havesign = FALSE;
752  havevalue = FALSE;
753  *ncoefs = 0;
754  while( getNextToken(scip, lpinput) )
755  {
756  SCIP_VAR* var;
757 
758  /* check if we read a sign */
759  if( isSign(lpinput, &coefsign) )
760  {
761  SCIPdebugMessage("(line %d) read coefficient sign: %+d\n", lpinput->linenumber, coefsign);
762  havesign = TRUE;
763  continue;
764  }
765 
766  /* check if we read a value */
767  if( isValue(scip, lpinput, &coef) )
768  {
769  SCIPdebugMessage("(line %d) read coefficient value: %g with sign %+d\n", lpinput->linenumber, coef, coefsign);
770  if( havevalue )
771  {
772  syntaxError(scip, lpinput, "two consecutive values.");
773  return SCIP_OKAY;
774  }
775  havevalue = TRUE;
776  continue;
777  }
778 
779  /* check if we reached an equation sense */
780  if( isSense(lpinput, NULL) )
781  {
782  if( isobjective )
783  {
784  syntaxError(scip, lpinput, "no sense allowed in objective");
785  return SCIP_OKAY;
786  }
787 
788  /* put the sense back onto the token stack */
789  pushToken(lpinput);
790  break;
791  }
792 
793  /* check if we reached a new section, that will be only allowed when having no current sign and value and if we
794  * are not in the quadratic part
795  */
796  if( (isobjective || (!havevalue && !havesign)) && isNewSection(scip, lpinput) )
797  {
798  if( havesign && !havevalue )
799  {
800  SCIPwarningMessage(scip, "skipped single sign %c without value or variable in objective\n", coefsign == 1 ? '+' : '-');
801  }
802  else if( isobjective && havevalue && !SCIPisZero(scip, coef) )
803  {
804  SCIPwarningMessage(scip, "constant term %+g in objective is skipped\n", coef * coefsign);
805  }
806 
807  *newsection = TRUE;
808  return SCIP_OKAY;
809  }
810 
811  /* check if we start a quadratic part */
812  if( *lpinput->token == '[' )
813  {
814  syntaxError(scip, lpinput, "diff reader does not support quadratic objective function.");
815  return SCIP_READERROR;
816  }
817 
818  /* all but the first coefficient need a sign */
819  if( *ncoefs > 0 && !havesign )
820  {
821  syntaxError(scip, lpinput, "expected sign ('+' or '-') or sense ('<' or '>').");
822  return SCIP_OKAY;
823  }
824 
825  /* check if the last variable should be squared */
826  if( *lpinput->token == '^' )
827  {
828  syntaxError(scip, lpinput, "diff reader does not support quadratic objective function.");
829  return SCIP_READERROR;
830  }
831  else
832  {
833  /* the token is a variable name: get the corresponding variable */
834  SCIP_CALL( getVariable(scip, lpinput->token, &var) );
835  }
836 
837  /* insert the linear coefficient */
838  SCIPdebugMessage("(line %d) read linear coefficient: %+g<%s>\n", lpinput->linenumber, coefsign * coef, SCIPvarGetName(var));
839  if( !SCIPisZero(scip, coef) )
840  {
841  /* resize the vars and coefs array if needed */
842  if( *ncoefs >= coefssize )
843  {
844  coefssize *= 2;
845  coefssize = MAX(coefssize, (*ncoefs)+1);
846  SCIP_CALL( SCIPreallocMemoryArray(scip, vars, coefssize) );
847  SCIP_CALL( SCIPreallocMemoryArray(scip, coefs, coefssize) );
848  }
849  assert(*ncoefs < coefssize);
850 
851  /* add coefficient */
852  (*vars)[*ncoefs] = var;
853  (*coefs)[*ncoefs] = coefsign * coef;
854  (*ncoefs)++;
855  }
856 
857  /* reset the flags and coefficient value for the next coefficient */
858  coefsign = +1;
859  coef = 1.0;
860  havesign = FALSE;
861  havevalue = FALSE;
862  }
863 
864  return SCIP_OKAY;
865 }
866 
867 /** reads the objective section */
868 static
870  SCIP* scip, /**< SCIP data structure */
871  LPINPUT* lpinput /**< LP reading data */
872  )
873 {
874  char name[LP_MAX_LINELEN];
875  SCIP_VAR** vars;
876  SCIP_Real* coefs;
877  int ncoefs;
878  SCIP_Bool newsection;
879 
880  assert(lpinput != NULL);
881 
882  /* read the objective coefficients */
883  SCIP_CALL( readCoefficients(scip, lpinput, TRUE, name, &vars, &coefs, &ncoefs, &newsection) );
884  if( !hasError(lpinput) )
885  {
886  int i;
887  SCIP_VAR** oldvars;
888 
889  /* set all linear coefficients to 0 */
890  oldvars = SCIPgetVars(scip);
891  for( i = 0; i < SCIPgetNVars(scip); i++ )
892  {
893  SCIP_CALL( SCIPchgVarObj(scip, oldvars[i], 0.0) );
894  }
895 
896  /* set the linear objective values */
897  for( i = 0; i < ncoefs; ++i )
898  {
899  SCIP_CALL( SCIPchgVarObj(scip, vars[i], coefs[i]) );
900  }
901  }
902 
903  /* free memory */
904  SCIPfreeMemoryArrayNull(scip, &vars);
905  SCIPfreeMemoryArrayNull(scip, &coefs);
906 
907  return SCIP_OKAY;
908 }
909 
910 /** reads a diff file */
911 static
913  SCIP* scip, /**< SCIP data structure */
914  LPINPUT* lpinput, /**< LP reading data */
915  const char* filename /**< name of the input file */
916  )
917 {
918  assert(lpinput != NULL);
919 
920  /* open file */
921  lpinput->file = SCIPfopen(filename, "r");
922  if( lpinput->file == NULL )
923  {
924  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
925  SCIPprintSysError(filename);
926  return SCIP_NOFILE;
927  }
928 
929  /* free transformed problem */
930  if( SCIPgetStage(scip) >= SCIP_STAGE_PROBLEM )
931  {
932  SCIP_CALL( SCIPfreeTransform(scip) );
933  }
934 
935  /* parse the file */
936  lpinput->section = LP_START;
937  while( lpinput->section != LP_END && !hasError(lpinput) )
938  {
939  switch( lpinput->section )
940  {
941  case LP_START:
942  SCIP_CALL( readStart(scip, lpinput) );
943  break;
944 
945  case LP_OBJECTIVE:
946  SCIP_CALL( readObjective(scip, lpinput) );
947  break;
948 
949  case LP_END: /* this is already handled in the while() loop */
950  default:
951  SCIPerrorMessage("invalid Diff file section <%d>\n", lpinput->section);
952  return SCIP_INVALIDDATA;
953  }
954  }
955 
956  /* close file */
957  SCIPfclose(lpinput->file);
958 
959  return SCIP_OKAY;
960 }
961 
962 /*
963  * Callback methods of reader
964  */
965 
966 /** copy method for reader plugins (called when SCIP copies plugins) */
967 static
968 SCIP_DECL_READERCOPY(readerCopyDiff)
969 { /*lint --e{715}*/
970  assert(scip != NULL);
971  assert(reader != NULL);
972  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
973 
974  /* call inclusion method of reader */
976 
977  return SCIP_OKAY;
978 }
979 
980 /** destructor of reader to free user data (called when SCIP is exiting) */
981 static
982 SCIP_DECL_READERFREE(readerFreeDiff)
983 { /*lint --e{715}*/
984  return SCIP_OKAY;
985 }
986 
987 /** problem reading method of reader */
988 static
989 SCIP_DECL_READERREAD(readerReadDiff)
990 { /*lint --e{715}*/
991 
992  SCIP_CALL( SCIPreadDiff(scip, reader, filename, result) );
993 
994  return SCIP_OKAY;
995 }
996 
997 /*
998  * reader specific interface methods
999  */
1000 
1001 /** includes the lp file reader in SCIP */
1003  SCIP* scip /**< SCIP data structure */
1004  )
1005 {
1006  SCIP_READERDATA* readerdata = NULL;
1007  SCIP_READER* reader;
1008 
1009  /* include reader */
1010  SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) );
1011 
1012  /* set non fundamental callbacks via setter functions */
1013  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyDiff) );
1014  SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeDiff) );
1015  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadDiff) );
1016 
1017  return SCIP_OKAY;
1018 }
1019 
1020 
1021 /** reads problem from file */
1023  SCIP* scip, /**< SCIP data structure */
1024  SCIP_READER* reader, /**< the file reader itself */
1025  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
1026  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
1027  )
1028 { /*lint --e{715}*/
1029  LPINPUT lpinput;
1030  int i;
1031 
1032  /* initialize LP input data */
1033  lpinput.file = NULL;
1034  lpinput.linebuf[0] = '\0';
1035  lpinput.probname[0] = '\0';
1036  lpinput.objname[0] = '\0';
1037  SCIP_CALL( SCIPallocMemoryArray(scip, &lpinput.token, LP_MAX_LINELEN) ); /*lint !e506*/
1038  lpinput.token[0] = '\0';
1039  SCIP_CALL( SCIPallocMemoryArray(scip, &lpinput.tokenbuf, LP_MAX_LINELEN) ); /*lint !e506*/
1040  lpinput.tokenbuf[0] = '\0';
1041  for( i = 0; i < LP_MAX_PUSHEDTOKENS; ++i )
1042  {
1043  SCIP_CALL( SCIPallocMemoryArray(scip, &(lpinput.pushedtokens[i]), LP_MAX_LINELEN) ); /*lint !e866 !e506*/
1044  }
1045 
1046  lpinput.npushedtokens = 0;
1047  lpinput.linenumber = 0;
1048  lpinput.linepos = 0;
1049  lpinput.section = LP_START;
1050  lpinput.objsense = SCIP_OBJSENSE_MINIMIZE;
1051  lpinput.haserror = FALSE;
1052  lpinput.comment = FALSE;
1053  lpinput.endline = FALSE;
1054 
1055  /* read the file */
1056  SCIP_CALL( readDiffFile(scip, &lpinput, filename) );
1057 
1058  /* free dynamically allocated memory */
1059  SCIPfreeMemoryArray(scip, &lpinput.token);
1060  SCIPfreeMemoryArray(scip, &lpinput.tokenbuf);
1061  for( i = 0; i < LP_MAX_PUSHEDTOKENS; ++i )
1062  {
1063  SCIPfreeMemoryArray(scip, &lpinput.pushedtokens[i]);
1064  }
1065 
1066  /* evaluate the result */
1067  if( lpinput.haserror )
1068  return SCIP_READERROR;
1069  else
1070  {
1071  /* set objective sense */
1072  SCIP_CALL( SCIPsetObjsense(scip, lpinput.objsense) );
1073  *result = SCIP_SUCCESS;
1074  }
1075 
1076  return SCIP_OKAY;
1077 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
static SCIP_DECL_READERCOPY(readerCopyDiff)
Definition: reader_diff.c:968
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
SCIP_RETCODE SCIPreadDiff(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result)
Definition: reader_diff.c:1022
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition: misc.c:8086
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:510
static SCIP_Bool isValueChar(char c, char nextc, SCIP_Bool firstchar, SCIP_Bool *hasdot, LPEXPTYPE *exptype)
Definition: reader_diff.c:177
static SCIP_RETCODE readDiffFile(SCIP *scip, LPINPUT *lpinput, const char *filename)
Definition: reader_diff.c:912
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1248
static SCIP_Bool getNextToken(SCIP *scip, LPINPUT *lpinput)
Definition: reader_diff.c:326
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10653
#define NULL
Definition: lpi_spx.cpp:130
static void pushToken(LPINPUT *lpinput)
Definition: reader_diff.c:431
static SCIP_Bool isValue(SCIP *scip, LPINPUT *lpinput, SCIP_Real *value)
Definition: reader_diff.c:571
#define READER_NAME
Definition: reader_diff.c:34
diff file reader
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20544
#define LP_MAX_PUSHEDTOKENS
Definition: reader_diff.c:42
static SCIP_Bool getNextLine(SCIP *scip, LPINPUT *lpinput)
Definition: reader_diff.c:221
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
#define FALSE
Definition: def.h:56
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define SCIP_CALL(x)
Definition: def.h:266
LpExpType
Definition: reader_diff.c:52
static SCIP_Bool isTokenChar(char c)
Definition: reader_diff.c:153
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:19590
static SCIP_Bool isDelimChar(char c)
Definition: reader_diff.c:132
SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
Definition: scip.c:15373
#define SCIPdebugMessage
Definition: pub_message.h:77
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
static void pushBufferToken(LPINPUT *lpinput)
Definition: reader_diff.c:444
SCIP_RETCODE SCIPsetReaderFree(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERFREE((*readerfree)))
Definition: scip.c:4625
int SCIPfseek(SCIP_FILE *stream, long offset, int whence)
Definition: fileio.c:199
static SCIP_Bool isSense(LPINPUT *lpinput, LPSENSE *sense)
Definition: reader_diff.c:603
enum LpSection LPSECTION
Definition: reader_diff.c:50
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
struct LpInput LPINPUT
Definition: reader_diff.c:83
static SCIP_RETCODE getVariable(SCIP *scip, char *name, SCIP_VAR **var)
Definition: reader_diff.c:634
static const char commentchars[]
Definition: reader_diff.c:85
#define SCIPerrorMessage
Definition: pub_message.h:45
static void swapPointers(char **pointer1, char **pointer2)
Definition: reader_diff.c:312
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:34
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:187
SCIPInterval sign(const SCIPInterval &x)
SCIP_RETCODE SCIPincludeReaderDiff(SCIP *scip)
Definition: reader_diff.c:1002
static SCIP_RETCODE readStart(SCIP *scip, LPINPUT *lpinput)
Definition: reader_diff.c:653
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
#define LP_MAX_LINELEN
Definition: reader_diff.c:41
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
static SCIP_RETCODE readCoefficients(SCIP *scip, LPINPUT *lpinput, SCIP_Bool isobjective, char *name, SCIP_VAR ***vars, SCIP_Real **coefs, int *ncoefs, SCIP_Bool *newsection)
Definition: reader_diff.c:674
#define SCIP_Bool
Definition: def.h:53
static void syntaxError(SCIP *scip, LPINPUT *lpinput, const char *msg)
Definition: reader_diff.c:94
void SCIPprintSysError(const char *message)
Definition: misc.c:8110
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
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
#define MAX(x, y)
Definition: tclique_def.h:75
enum LpSense LPSENSE
Definition: reader_diff.c:62
#define SCIPreallocMemoryArray(scip, ptr, newnum)
Definition: scip.h:20534
static SCIP_Bool hasError(LPINPUT *lpinput)
Definition: reader_diff.c:121
#define READER_DESC
Definition: reader_diff.c:35
static SCIP_DECL_READERREAD(readerReadDiff)
Definition: reader_diff.c:989
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1298
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip.c:10014
#define SCIPfreeMemoryArrayNull(scip, ptr)
Definition: scip.h:20545
#define READER_EXTENSION
Definition: reader_diff.c:36
enum LpExpType LPEXPTYPE
Definition: reader_diff.c:56
#define SCIP_Real
Definition: def.h:127
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip.c:11392
LpSection
Definition: reader_diff.c:46
static SCIP_RETCODE readObjective(SCIP *scip, LPINPUT *lpinput)
Definition: reader_diff.c:869
static SCIP_DECL_READERFREE(readerFreeDiff)
Definition: reader_diff.c:982
LpSense
Definition: reader_diff.c:58
static void swapTokenBuffer(LPINPUT *lpinput)
Definition: reader_diff.c:457
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:219
#define LP_INIT_COEFSSIZE
Definition: reader_diff.c:43
static SCIP_Bool isNewSection(SCIP *scip, LPINPUT *lpinput)
Definition: reader_diff.c:468
static SCIP_Bool isSign(LPINPUT *lpinput, int *sign)
Definition: reader_diff.c:546