1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*  Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SCIP; see the file LICENSE. If not visit scipopt.org.         */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file   reader_diff.c
26   	 * @ingroup DEFPLUGINS_READER
27   	 * @brief  DIFF file reader
28   	 * @author Jakob Witzig
29   	 *
30   	 * This reader allows to parse a new objective function in the style of CPLEX .lp files.
31   	 *
32   	 * The lp format is defined within the CPLEX documentation.
33   	 *
34   	 * An example of a *.diff file looks like this:
35   	 *
36   	 *  Minimize
37   	 *    obj: - STM6 + STM7
38   	 *
39   	 * Here is the objective sense set to minimize the function -STM6 + STM7.
40   	 */
41   	
42   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
43   	
44   	#include <ctype.h>
45   	#include "scip/pub_fileio.h"
46   	#include "scip/pub_message.h"
47   	#include "scip/pub_misc.h"
48   	#include "scip/pub_reader.h"
49   	#include "scip/pub_var.h"
50   	#include "scip/reader_diff.h"
51   	#include "scip/scip_general.h"
52   	#include "scip/scip_mem.h"
53   	#include "scip/scip_message.h"
54   	#include "scip/scip_numerics.h"
55   	#include "scip/scip_prob.h"
56   	#include "scip/scip_reader.h"
57   	#include "scip/scip_solve.h"
58   	#include <stdlib.h>
59   	#include <string.h>
60   	
61   	#if !defined(_WIN32) && !defined(_WIN64)
62   	#include <strings.h> /*lint --e{766}*/ /* needed for strncasecmp() */
63   	#endif
64   	
65   	#define READER_NAME             "diffreader"
66   	#define READER_DESC             "file reader for changes in the LP file"
67   	#define READER_EXTENSION        "diff"
68   	
69   	/*
70   	 * Data structures
71   	 */
72   	#define LP_MAX_LINELEN       65536
73   	#define LP_MAX_PUSHEDTOKENS  2
74   	#define LP_INIT_COEFSSIZE    8192
75   	
76   	/** Section in LP File */
77   	enum LpSection
78   	{
79   	   LP_START, LP_OBJECTIVE, LP_END
80   	};
81   	typedef enum LpSection LPSECTION;
82   	
83   	enum LpExpType
84   	{
85   	   LP_EXP_NONE, LP_EXP_UNSIGNED, LP_EXP_SIGNED
86   	};
87   	typedef enum LpExpType LPEXPTYPE;
88   	
89   	enum LpSense
90   	{
91   	   LP_SENSE_LE, LP_SENSE_GE, LP_SENSE_EQ
92   	};
93   	typedef enum LpSense LPSENSE;
94   	
95   	/** LP reading data */
96   	struct LpInput
97   	{
98   	   SCIP_FILE*            file;
99   	   char*                 linebuf;
100  	   char                  probname[LP_MAX_LINELEN];
101  	   char                  objname[LP_MAX_LINELEN];
102  	   char*                 token;
103  	   char*                 tokenbuf;
104  	   char*                 pushedtokens[LP_MAX_PUSHEDTOKENS];
105  	   int                   npushedtokens;
106  	   int                   linenumber;
107  	   int                   linepos;
108  	   int                   linebufsize;
109  	   LPSECTION             section;
110  	   SCIP_OBJSENSE         objsense;
111  	   SCIP_Bool             haserror;
112  	};
113  	typedef struct LpInput LPINPUT;
114  	
115  	static const char commentchars[] = "\\";
116  	
117  	
118  	/*
119  	 * Local methods (for reading)
120  	 */
121  	
122  	/** issues an error message and marks the LP data to have errors */
123  	static
124  	void syntaxError(
125  	   SCIP*                 scip,               /**< SCIP data structure */
126  	   LPINPUT*              lpinput,            /**< LP reading data */
127  	   const char*           msg                 /**< error message */
128  	   )
129  	{
130  	   char formatstr[256];
131  	
132  	   assert(lpinput != NULL);
133  	
134  	   SCIPerrorMessage("Syntax error in line %d ('%s'): %s \n", lpinput->linenumber, lpinput->token, msg);
135  	   if( lpinput->linebuf[lpinput->linebufsize - 1] == '\n' )
136  	   {
137  	      SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "  input: %s", lpinput->linebuf);
138  	   }
139  	   else
140  	   {
141  	      SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "  input: %s\n", lpinput->linebuf);
142  	   }
143  	   (void) SCIPsnprintf(formatstr, 256, "         %%%ds\n", lpinput->linepos);
144  	   SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, (const char*)formatstr, "^");
145  	   lpinput->section  = LP_END;
146  	   lpinput->haserror = TRUE;
147  	}
148  	
149  	/** returns whether a syntax error was detected */
150  	static
151  	SCIP_Bool hasError(
152  	   LPINPUT*              lpinput             /**< LP reading data */
153  	   )
154  	{
155  	   assert(lpinput != NULL);
156  	
157  	   return lpinput->haserror;
158  	}
159  	
160  	/** returns whether the given character is a token delimiter */
161  	static
162  	SCIP_Bool isDelimChar(
163  	   char                  c                   /**< input character */
164  	   )
165  	{
166  	   switch (c)
167  	   {
168  	   case ' ':
169  	   case '\f':
170  	   case '\n':
171  	   case '\r':
172  	   case '\t':
173  	   case '\v':
174  	   case '\0':
175  	      return TRUE;
176  	   default:
177  	      return FALSE;
178  	   }
179  	}
180  	
181  	/** returns whether the given character is a single token */
182  	static
183  	SCIP_Bool isTokenChar(
184  	   char                  c                   /**< input character */
185  	   )
186  	{
187  	   switch (c)
188  	   {
189  	   case '-':
190  	   case '+':
191  	   case ':':
192  	   case '<':
193  	   case '>':
194  	   case '=':
195  	   case '[':
196  	   case ']':
197  	   case '*':
198  	   case '^':
199  	      return TRUE;
200  	   default:
201  	      return FALSE;
202  	   }
203  	}
204  	
205  	/** returns whether the current character is member of a value string */
206  	static
207  	SCIP_Bool isValueChar(
208  	   char                  c,                  /**< input character */
209  	   char                  nextc,              /**< next input character */
210  	   SCIP_Bool             firstchar,          /**< is the given character the first char of the token? */
211  	   SCIP_Bool*            hasdot,             /**< pointer to update the dot flag */
212  	   LPEXPTYPE*            exptype             /**< pointer to update the exponent type */
213  	   )
214  	{
215  	   assert(hasdot != NULL);
216  	   assert(exptype != NULL);
217  	
218  	   if( isdigit((unsigned char)c) )
219  	      return TRUE;
220  	   else if( (*exptype == LP_EXP_NONE) && !(*hasdot) && (c == '.') && isdigit((unsigned char)nextc) )
221  	   {
222  	      *hasdot = TRUE;
223  	      return TRUE;
224  	   }
225  	   else if( !firstchar && (*exptype == LP_EXP_NONE) && (c == 'e' || c == 'E') )
226  	   {
227  	      if( nextc == '+' || nextc == '-' )
228  	      {
229  	         *exptype = LP_EXP_SIGNED;
230  	         return TRUE;
231  	      }
232  	      else if( isdigit((unsigned char)nextc) )
233  	      {
234  	         *exptype = LP_EXP_UNSIGNED;
235  	         return TRUE;
236  	      }
237  	   }
238  	   else if( (*exptype == LP_EXP_SIGNED) && (c == '+' || c == '-') )
239  	   {
240  	      *exptype = LP_EXP_UNSIGNED;
241  	      return TRUE;
242  	   }
243  	
244  	   return FALSE;
245  	}
246  	
247  	/** reads the next line from the input file into the line buffer; skips comments;
248  	 *  returns whether a line could be read
249  	 */
250  	static
251  	SCIP_Bool getNextLine(
252  	   SCIP*                 scip,               /**< SCIP data structure */
253  	   LPINPUT*              lpinput             /**< LP reading data */
254  	   )
255  	{
256  	   int i;
257  	
258  	   assert(lpinput != NULL);
259  	
260  	   /* read next line */
261  	   lpinput->linepos = 0;
262  	   lpinput->linebuf[lpinput->linebufsize - 2] = '\0';
263  	
264  	   if( SCIPfgets(lpinput->linebuf, lpinput->linebufsize, lpinput->file) == NULL )
265  	   {
266  	      /* clear the line, this is really necessary here! */
267  	      BMSclearMemoryArray(lpinput->linebuf, lpinput->linebufsize);
268  	
269  	      return FALSE;
270  	   }
271  	
272  	   lpinput->linenumber++;
273  	
274  	   /* if line is too long for our buffer reallocate buffer */
275  	   while( lpinput->linebuf[lpinput->linebufsize - 2] != '\0' )
276  	   {
277  	      int newsize;
278  	
279  	      newsize = SCIPcalcMemGrowSize(scip, lpinput->linebufsize + 1);
280  	      SCIP_CALL_ABORT( SCIPreallocBlockMemoryArray(scip, &lpinput->linebuf, lpinput->linebufsize, newsize) );
281  	
282  	      lpinput->linebuf[newsize-2] = '\0';
283  	      if ( SCIPfgets(lpinput->linebuf + lpinput->linebufsize - 1, newsize - lpinput->linebufsize + 1, lpinput->file) == NULL )
284  	         return FALSE;
285  	      lpinput->linebufsize = newsize;
286  	   }
287  	   lpinput->linebuf[lpinput->linebufsize - 1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
288  	
289  	   /* skip characters after comment symbol */
290  	   for( i = 0; commentchars[i] != '\0'; ++i )
291  	   {
292  	      char* commentstart;
293  	
294  	      commentstart = strchr(lpinput->linebuf, commentchars[i]);
295  	      if( commentstart != NULL )
296  	      {
297  	         *commentstart = '\0';
298  	         *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
299  	
300  	         break;
301  	      }
302  	   }
303  	
304  	   return TRUE;
305  	}
306  	
307  	/** swaps the addresses of two pointers */
308  	static
309  	void swapPointers(
310  	   char**                pointer1,           /**< first pointer */
311  	   char**                pointer2            /**< second pointer */
312  	   )
313  	{
314  	   char* tmp;
315  	
316  	   tmp = *pointer1;
317  	   *pointer1 = *pointer2;
318  	   *pointer2 = tmp;
319  	}
320  	
321  	/** reads the next token from the input file into the token buffer; returns whether a token was read */
322  	static
323  	SCIP_Bool getNextToken(
324  	   SCIP*                 scip,               /**< SCIP data structure */
325  	   LPINPUT*              lpinput             /**< LP reading data */
326  	   )
327  	{
328  	   SCIP_Bool hasdot;
329  	   LPEXPTYPE exptype;
330  	   char* buf;
331  	   int tokenlen;
332  	
333  	   assert(lpinput != NULL);
334  	   assert(lpinput->linepos < lpinput->linebufsize);
335  	
336  	   /* check the token stack */
337  	   if( lpinput->npushedtokens > 0 )
338  	   {
339  	      swapPointers(&lpinput->token, &lpinput->pushedtokens[lpinput->npushedtokens-1]);
340  	      lpinput->npushedtokens--;
341  	
342  	      SCIPdebugMsg(scip, "(line %d) read token again: '%s'\n", lpinput->linenumber, lpinput->token);
343  	      return TRUE;
344  	   }
345  	
346  	   /* skip delimiters */
347  	   buf = lpinput->linebuf;
348  	   while( isDelimChar(buf[lpinput->linepos]) )
349  	   {
350  	      if( buf[lpinput->linepos] == '\0' )
351  	      {
352  	         if( !getNextLine(scip, lpinput) )
353  	         {
354  	            lpinput->section = LP_END;
355  	            SCIPdebugMsg(scip, "(line %d) end of file\n", lpinput->linenumber);
356  	            return FALSE;
357  	         }
358  	         assert(lpinput->linepos == 0);
359  	         /* update buf, because the linebuffer may have been reallocated */
360  	         buf = lpinput->linebuf;
361  	      }
362  	      else
363  	         lpinput->linepos++;
364  	   }
365  	   assert(lpinput->linepos < lpinput->linebufsize);
366  	   assert(!isDelimChar(buf[lpinput->linepos]));
367  	   assert(buf[lpinput->linepos] != '\0'); /* '\0' is a delim-char, so this assert is redundant, but it helps to suppress a scan-build warning */
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  	   SCIPdebugMsg(scip, "(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
431  	void pushToken(
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
444  	void pushBufferToken(
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
457  	void swapTokenBuffer(
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
468  	SCIP_Bool isNewSection(
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  	         SCIPdebugMsg(scip, "(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  	         SCIPdebugMsg(scip, "(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  	         SCIPdebugMsg(scip, "(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
546  	SCIP_Bool isSign(
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
571  	SCIP_Bool isValue(
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
603  	SCIP_Bool isSense(
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
634  	SCIP_RETCODE getVariable(
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
653  	SCIP_RETCODE readStart(
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
674  	SCIP_RETCODE readCoefficients(
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  	   int*                  coefssize,          /**< size of vars and coefs arrays */
681  	   SCIP_VAR***           vars,               /**< pointer to store the array with variables (must be freed by caller) */
682  	   SCIP_Real**           coefs,              /**< pointer to store the array with coefficients (must be freed by caller) */
683  	   int*                  ncoefs,             /**< pointer to store the number of coefficients */
684  	   SCIP_Bool*            newsection          /**< pointer to store whether a new section was encountered */
685  	   )
686  	{
687  	   SCIP_Bool havesign;
688  	   SCIP_Bool havevalue;
689  	   SCIP_Real coef;
690  	   int coefsign;
691  	
692  	   assert(lpinput != NULL);
693  	   assert(name != NULL);
694  	   assert(coefssize != NULL);
695  	   assert(vars != NULL);
696  	   assert(coefs != NULL);
697  	   assert(ncoefs != NULL);
698  	   assert(newsection != NULL);
699  	
700  	   *coefssize = 0;
701  	   *vars = NULL;
702  	   *coefs = NULL;
703  	   *name = '\0';
704  	   *ncoefs = 0;
705  	   *newsection = FALSE;
706  	
707  	   /* read the first token, which may be the name of the line */
708  	   if( getNextToken(scip, lpinput) )
709  	   {
710  	      /* check if we reached a new section */
711  	      if( isNewSection(scip, lpinput) )
712  	      {
713  	         *newsection = TRUE;
714  	         return SCIP_OKAY;
715  	      }
716  	
717  	      /* remember the token in the token buffer */
718  	      swapTokenBuffer(lpinput);
719  	
720  	      /* get the next token and check, whether it is a colon */
721  	      if( getNextToken(scip, lpinput) )
722  	      {
723  	         if( strcmp(lpinput->token, ":") == 0 )
724  	         {
725  	            /* the second token was a colon: the first token is the line name */
726  	            (void)SCIPmemccpy(name, lpinput->tokenbuf, '\0', LP_MAX_LINELEN);
727  	
728  	            name[LP_MAX_LINELEN - 1] = '\0';
729  	            SCIPdebugMsg(scip, "(line %d) read constraint name: '%s'\n", lpinput->linenumber, name);
730  	         }
731  	         else
732  	         {
733  	            /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */
734  	            pushToken(lpinput);
735  	            pushBufferToken(lpinput);
736  	         }
737  	      }
738  	      else
739  	      {
740  	         /* there was only one token left: push it back onto the token stack and parse it as coefficient */
741  	         pushBufferToken(lpinput);
742  	      }
743  	   }
744  	
745  	   /* initialize buffers for storing the coefficients */
746  	   *coefssize = LP_INIT_COEFSSIZE;
747  	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, vars, *coefssize) );
748  	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, coefs, *coefssize) );
749  	
750  	   /* read the coefficients */
751  	   coefsign = +1;
752  	   coef = 1.0;
753  	   havesign = FALSE;
754  	   havevalue = FALSE;
755  	   *ncoefs = 0;
756  	   while( getNextToken(scip, lpinput) )
757  	   {
758  	      SCIP_VAR* var;
759  	
760  	      /* check if we read a sign */
761  	      if( isSign(lpinput, &coefsign) )
762  	      {
763  	         SCIPdebugMsg(scip, "(line %d) read coefficient sign: %+d\n", lpinput->linenumber, coefsign);
764  	         havesign = TRUE;
765  	         continue;
766  	      }
767  	
768  	      /* check if we read a value */
769  	      if( isValue(scip, lpinput, &coef) )
770  	      {
771  	         SCIPdebugMsg(scip, "(line %d) read coefficient value: %g with sign %+d\n", lpinput->linenumber, coef, coefsign);
772  	         if( havevalue )
773  	         {
774  	            syntaxError(scip, lpinput, "two consecutive values.");
775  	            return SCIP_OKAY;
776  	         }
777  	         havevalue = TRUE;
778  	         continue;
779  	      }
780  	
781  	      /* check if we reached an equation sense */
782  	      if( isSense(lpinput, NULL) )
783  	      {
784  	         if( isobjective )
785  	         {
786  	            syntaxError(scip, lpinput, "no sense allowed in objective");
787  	            return SCIP_OKAY;
788  	         }
789  	
790  	         /* put the sense back onto the token stack */
791  	         pushToken(lpinput);
792  	         break;
793  	      }
794  	
795  	      /* check if we reached a new section, that will be only allowed when having no current sign and value and if we
796  	       * are not in the quadratic part
797  	       */
798  	      if( (isobjective || (!havevalue && !havesign)) && isNewSection(scip, lpinput) )
799  	      {
800  	         if( havesign && !havevalue )
801  	         {
802  	            SCIPwarningMessage(scip, "skipped single sign %c without value or variable in objective\n", coefsign == 1 ? '+' : '-');
803  	         }
804  	         else if( isobjective && havevalue && !SCIPisZero(scip, coef) )
805  	         {
806  	            SCIPwarningMessage(scip, "constant term %+g in objective is skipped\n", coef * coefsign);
807  	         }
808  	
809  	         *newsection = TRUE;
810  	         return SCIP_OKAY;
811  	      }
812  	
813  	      /* check if we start a quadratic part */
814  	      if( *lpinput->token ==  '[' )
815  	      {
816  	         syntaxError(scip, lpinput, "diff reader does not support quadratic objective function.");
817  	         return SCIP_READERROR;
818  	      }
819  	
820  	      /* all but the first coefficient need a sign */
821  	      if( *ncoefs > 0 && !havesign )
822  	      {
823  	         syntaxError(scip, lpinput, "expected sign ('+' or '-') or sense ('<' or '>').");
824  	         return SCIP_OKAY;
825  	      }
826  	
827  	      /* check if the last variable should be squared */
828  	      if( *lpinput->token == '^' )
829  	      {
830  	         syntaxError(scip, lpinput, "diff reader does not support quadratic objective function.");
831  	         return SCIP_READERROR;
832  	      }
833  	      else
834  	      {
835  	         /* the token is a variable name: get the corresponding variable */
836  	         SCIP_CALL( getVariable(scip, lpinput->token, &var) );
837  	      }
838  	
839  	      /* insert the linear coefficient */
840  	      SCIPdebugMsg(scip, "(line %d) read linear coefficient: %+g<%s>\n", lpinput->linenumber, coefsign * coef, SCIPvarGetName(var));
841  	      if( !SCIPisZero(scip, coef) )
842  	      {
843  	         /* resize the vars and coefs array if needed */
844  	         if( *ncoefs >= *coefssize )
845  	         {
846  	            int oldcoefssize;
847  	
848  	            oldcoefssize = *coefssize;
849  	            *coefssize *= 2;
850  	            *coefssize = MAX(*coefssize, (*ncoefs)+1);
851  	            SCIP_CALL( SCIPreallocBlockMemoryArray(scip, vars, oldcoefssize, *coefssize) );
852  	            SCIP_CALL( SCIPreallocBlockMemoryArray(scip, coefs, oldcoefssize, *coefssize) );
853  	         }
854  	         assert(*ncoefs < *coefssize);
855  	
856  	         /* add coefficient */
857  	         (*vars)[*ncoefs] = var;
858  	         (*coefs)[*ncoefs] = coefsign * coef;
859  	         (*ncoefs)++;
860  	      }
861  	
862  	      /* reset the flags and coefficient value for the next coefficient */
863  	      coefsign = +1;
864  	      coef = 1.0;
865  	      havesign = FALSE;
866  	      havevalue = FALSE;
867  	   }
868  	
869  	   return SCIP_OKAY;
870  	}
871  	
872  	/** reads the objective section */
873  	static
874  	SCIP_RETCODE readObjective(
875  	   SCIP*                 scip,               /**< SCIP data structure */
876  	   LPINPUT*              lpinput             /**< LP reading data */
877  	   )
878  	{
879  	   char name[LP_MAX_LINELEN];
880  	   SCIP_VAR** vars;
881  	   SCIP_Real* coefs;
882  	   SCIP_Bool newsection;
883  	   int coefssize;
884  	   int ncoefs;
885  	
886  	   assert(lpinput != NULL);
887  	
888  	   /* read the objective coefficients */
889  	   SCIP_CALL( readCoefficients(scip, lpinput, TRUE, name, &coefssize, &vars, &coefs, &ncoefs, &newsection) );
890  	
891  	   /* change the objective function */
892  	   SCIP_CALL( SCIPchgReoptObjective(scip, lpinput->objsense, vars, coefs, ncoefs) );
893  	
894  	   /* free memory */
895  	   SCIPfreeBlockMemoryArrayNull(scip, &coefs, coefssize);
896  	   SCIPfreeBlockMemoryArrayNull(scip, &vars, coefssize);
897  	
898  	   return SCIP_OKAY; /*lint !e438*/
899  	}
900  	
901  	/** reads a diff file */
902  	static
903  	SCIP_RETCODE readDiffFile(
904  	   SCIP*                 scip,               /**< SCIP data structure */
905  	   LPINPUT*              lpinput,            /**< LP reading data */
906  	   const char*           filename            /**< name of the input file */
907  	   )
908  	{
909  	   assert(lpinput != NULL);
910  	
911  	   /* open file */
912  	   lpinput->file = SCIPfopen(filename, "r");
913  	   if( lpinput->file == NULL )
914  	   {
915  	      SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
916  	      SCIPprintSysError(filename);
917  	      return SCIP_NOFILE;
918  	   }
919  	
920  	   /* free transformed problem */
921  	   if( SCIPisReoptEnabled(scip) && SCIPgetStage(scip) > SCIP_STAGE_PROBLEM )
922  	   {
923  	      SCIP_CALL( SCIPfreeReoptSolve(scip) );
924  	   }
925  	   else
926  	   {
927  	      SCIP_CALL( SCIPfreeTransform(scip) );
928  	   }
929  	
930  	   /* parse the file */
931  	   lpinput->section = LP_START;
932  	   while( lpinput->section != LP_END && !hasError(lpinput) )
933  	   {
934  	      switch( lpinput->section )
935  	      {
936  	      case LP_START:
937  	         SCIP_CALL( readStart(scip, lpinput) );
938  	         break;
939  	
940  	      case LP_OBJECTIVE:
941  	         SCIP_CALL( readObjective(scip, lpinput) );
942  	         break;
943  	
944  	      case LP_END: /* this is already handled in the while() loop */
945  	      default:
946  	         SCIPerrorMessage("invalid Diff file section <%d>\n", lpinput->section);
947  	         return SCIP_INVALIDDATA;
948  	      }
949  	   }
950  	
951  	   /* close file */
952  	   SCIPfclose(lpinput->file);
953  	
954  	   return SCIP_OKAY;
955  	}
956  	
957  	/*
958  	 * Callback methods of reader
959  	 */
960  	
961  	/** copy method for reader plugins (called when SCIP copies plugins) */
962  	static
963  	SCIP_DECL_READERCOPY(readerCopyDiff)
964  	{  /*lint --e{715}*/
965  	   assert(scip != NULL);
966  	   assert(reader != NULL);
967  	   assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
968  	
969  	   /* call inclusion method of reader */
970  	   SCIP_CALL( SCIPincludeReaderDiff(scip) );
971  	
972  	   return SCIP_OKAY;
973  	}
974  	
975  	/** destructor of reader to free user data (called when SCIP is exiting) */
976  	static
977  	SCIP_DECL_READERFREE(readerFreeDiff)
978  	{  /*lint --e{715}*/
979  	   return SCIP_OKAY;
980  	}
981  	
982  	/** problem reading method of reader */
983  	static
984  	SCIP_DECL_READERREAD(readerReadDiff)
985  	{  /*lint --e{715}*/
986  	
987  	   SCIP_CALL( SCIPreadDiff(scip, reader, filename, result) );
988  	
989  	   return SCIP_OKAY;
990  	}
991  	
992  	/*
993  	 * reader specific interface methods
994  	 */
995  	
996  	/** includes the lp file reader in SCIP */
997  	SCIP_RETCODE SCIPincludeReaderDiff(
998  	   SCIP*                 scip                /**< SCIP data structure */
999  	   )
1000 	{
1001 	   SCIP_READER* reader;
1002 	
1003 	   /* include reader */
1004 	   SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, NULL) );
1005 	
1006 	   /* set non fundamental callbacks via setter functions */
1007 	   SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyDiff) );
1008 	   SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeDiff) );
1009 	   SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadDiff) );
1010 	
1011 	   return SCIP_OKAY;
1012 	}
1013 	
1014 	
1015 	/** reads problem from file */
1016 	SCIP_RETCODE SCIPreadDiff(
1017 	   SCIP*                 scip,               /**< SCIP data structure */
1018 	   SCIP_READER*          reader,             /**< the file reader itself */
1019 	   const char*           filename,           /**< full path and name of file to read, or NULL if stdin should be used */
1020 	   SCIP_RESULT*          result              /**< pointer to store the result of the file reading call */
1021 	   )
1022 	{  /*lint --e{715}*/
1023 	   LPINPUT lpinput;
1024 	   int i;
1025 	
1026 	   assert(scip != NULL);
1027 	   assert(reader != NULL);
1028 	
1029 	   /* initialize LP input data */
1030 	   lpinput.file = NULL;
1031 	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &lpinput.linebuf, LP_MAX_LINELEN) );
1032 	   lpinput.linebuf[0] = '\0';
1033 	   lpinput.linebufsize = LP_MAX_LINELEN;
1034 	   lpinput.probname[0] = '\0';
1035 	   lpinput.objname[0] = '\0';
1036 	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &lpinput.token, LP_MAX_LINELEN) ); /*lint !e506*/
1037 	   lpinput.token[0] = '\0';
1038 	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &lpinput.tokenbuf, LP_MAX_LINELEN) ); /*lint !e506*/
1039 	   lpinput.tokenbuf[0] = '\0';
1040 	   for( i = 0; i < LP_MAX_PUSHEDTOKENS; ++i )
1041 	   {
1042 	      SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(lpinput.pushedtokens[i]), LP_MAX_LINELEN) );  /*lint !e866 !e506*/
1043 	   }
1044 	
1045 	   lpinput.npushedtokens = 0;
1046 	   lpinput.linenumber = 0;
1047 	   lpinput.linepos = 0;
1048 	   lpinput.section = LP_START;
1049 	   lpinput.objsense = SCIP_OBJSENSE_MINIMIZE;
1050 	   lpinput.haserror = FALSE;
1051 	
1052 	   /* read the file */
1053 	   SCIP_CALL( readDiffFile(scip, &lpinput, filename) );
1054 	
1055 	   /* free dynamically allocated memory */
1056 	   for( i = 0; i < LP_MAX_PUSHEDTOKENS; ++i )
1057 	   {
1058 	      SCIPfreeBlockMemoryArray(scip, &lpinput.pushedtokens[i], LP_MAX_LINELEN);
1059 	   }
1060 	   SCIPfreeBlockMemoryArray(scip, &lpinput.tokenbuf, LP_MAX_LINELEN);
1061 	   SCIPfreeBlockMemoryArray(scip, &lpinput.token, LP_MAX_LINELEN);
1062 	   SCIPfreeBlockMemoryArray(scip, &lpinput.linebuf, lpinput.linebufsize);
1063 	
1064 	   /* evaluate the result */
1065 	   if( lpinput.haserror )
1066 	      return SCIP_READERROR;
1067 	
1068 	   *result = SCIP_SUCCESS;
1069 	
1070 	   return SCIP_OKAY;
1071 	}
1072