1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*    Copyright (C) 2002-2021 Konrad-Zuse-Zentrum                            */
7    	/*                            fuer Informationstechnik Berlin                */
8    	/*                                                                           */
9    	/*  SCIP is distributed under the terms of the ZIB Academic License.         */
10   	/*                                                                           */
11   	/*  You should have received a copy of the ZIB Academic License              */
12   	/*  along with SCIP; see the file COPYING. If not visit scipopt.org.         */
13   	/*                                                                           */
14   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15   	
16   	/**@file   reader_fzn.c
17   	 * @ingroup DEFPLUGINS_READER
18   	 * @brief  FlatZinc file reader
19   	 * @author Timo Berthold
20   	 * @author Stefan Heinz
21   	 *
22   	 * FlatZinc is a low-level solver input language that is the target language for MiniZinc. It is designed to be easy to
23   	 * translate into the form required by a solver. For more details see https://www.minizinc.org. The format is described
24   	 * at https://github.com/MiniZinc/minizinc-doc/blob/develop/en/fzn-spec.rst.
25   	 *
26   	 * @todo Support more general constraint types
27   	 */
28   	
29   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
30   	
31   	#include "blockmemshell/memory.h"
32   	#include <ctype.h>
33   	#include "scip/cons_nonlinear.h"
34   	#include "scip/cons_and.h"
35   	#include "scip/cons_cumulative.h"
36   	#include "scip/cons_knapsack.h"
37   	#include "scip/cons_linear.h"
38   	#include "scip/cons_logicor.h"
39   	#include "scip/cons_or.h"
40   	#include "scip/cons_setppc.h"
41   	#include "scip/cons_varbound.h"
42   	#include "scip/cons_xor.h"
43   	#include "scip/pub_cons.h"
44   	#include "scip/pub_fileio.h"
45   	#include "scip/pub_message.h"
46   	#include "scip/pub_misc.h"
47   	#include "scip/pub_misc_sort.h"
48   	#include "scip/pub_reader.h"
49   	#include "scip/pub_var.h"
50   	#include "scip/reader_fzn.h"
51   	#include "scip/scip_cons.h"
52   	#include "scip/scip_mem.h"
53   	#include "scip/scip_message.h"
54   	#include "scip/scip_numerics.h"
55   	#include "scip/scip_param.h"
56   	#include "scip/scip_prob.h"
57   	#include "scip/scip_reader.h"
58   	#include "scip/scip_sol.h"
59   	#include "scip/scip_solvingstats.h"
60   	#include "scip/scip_var.h"
61   	#include <stdlib.h>
62   	#include <string.h>
63   	
64   	#ifdef ALLDIFFERENT
65   	#include "scip/cons_alldifferent.h"
66   	#endif
67   	
68   	#define READER_NAME             "fznreader"
69   	#define READER_DESC             "file reader for FlatZinc format"
70   	#define READER_EXTENSION        "fzn"
71   	
72   	
73   	#define FZN_BUFFERLEN         65536      /**< size of the line buffer for reading or writing */
74   	#define FZN_MAX_PUSHEDTOKENS  1
75   	
76   	/*
77   	 * Data structures
78   	 */
79   	
80   	/** number types */
81   	enum FznNumberType
82   	{
83   	   FZN_BOOL,
84   	   FZN_INT,
85   	   FZN_FLOAT
86   	};
87   	typedef enum FznNumberType FZNNUMBERTYPE;
88   	
89   	/** Expression type in FlatZinc File */
90   	enum FznExpType
91   	{
92   	   FZN_EXP_NONE,
93   	   FZN_EXP_UNSIGNED,
94   	   FZN_EXP_SIGNED
95   	};
96   	typedef enum FznExpType FZNEXPTYPE;
97   	
98   	/* structures to store the dimension information */
99   	struct Dimensions
100  	{
101  	   int*                  lbs;                /**< lower bounds */
102  	   int*                  ubs;                /**< upper bounds */
103  	   int                   ndims;              /**< number of dimensions */
104  	   int                   size;               /**< size of lbs and ubs */
105  	};
106  	typedef struct Dimensions DIMENSIONS;
107  	
108  	/** FlatZinc constant */
109  	struct FznConstant
110  	{
111  	   const char*           name;               /**< constant name */
112  	   FZNNUMBERTYPE         type;               /**< constant type */
113  	   SCIP_Real             value;              /**< constant value */
114  	};
115  	typedef struct FznConstant FZNCONSTANT;
116  	
117  	/** structure to store information for an array variable */
118  	struct ConstArray
119  	{
120  	   FZNCONSTANT**         constants;          /**< array of constants */
121  	   char*                 name;               /**< name of constant array */
122  	   int                   nconstants;         /**< number of constants */
123  	   FZNNUMBERTYPE         type;               /**< constant type */
124  	};
125  	typedef struct ConstArray CONSTARRAY;
126  	
127  	/** structure to store information for an array variable */
128  	struct VarArray
129  	{
130  	   SCIP_VAR**            vars;               /**< variable belonging to the variable array */
131  	   char*                 name;               /**< name of the array variable */
132  	   DIMENSIONS*           info;               /**< dimension information */
133  	   int                   nvars;              /**< number of variables */
134  	   FZNNUMBERTYPE         type;               /**< variable type */
135  	};
136  	typedef struct VarArray VARARRAY;
137  	
138  	/** data for FlatZinc reader */
139  	struct SCIP_ReaderData
140  	{
141  	   VARARRAY**            vararrays;          /**< variable arrays to output */
142  	   int                   nvararrays;         /**< number of variables */
143  	   int                   vararrayssize;      /**< size of variable array */
144  	};
145  	
146  	/** tries to creates and adds a constraint; sets parameter created to TRUE if method was successful
147  	 *
148  	 *  input:
149  	 *  - scip            : SCIP main data structure
150  	 *  - fzninput,       : FZN reading data
151  	 *  - fname,          : functions identifier name
152  	 *  - ftokens,        : function identifier tokens
153  	 *  - nftokens,       : number of function identifier tokes
154  	 *
155  	 *  output
156  	 *  - created         : pointer to store whether a constraint was created or not
157  	 */
158  	#define CREATE_CONSTRAINT(x) SCIP_RETCODE x (SCIP* scip, FZNINPUT* fzninput, const char* fname, char** ftokens, int nftokens, SCIP_Bool* created)
159  	
160  	
161  	/** FlatZinc reading data */
162  	struct FznInput
163  	{
164  	   SCIP_FILE*            file;
165  	   SCIP_HASHTABLE*       varHashtable;
166  	   SCIP_HASHTABLE*       constantHashtable;
167  	   FZNCONSTANT**         constants;
168  	   char                  linebuf[FZN_BUFFERLEN+1];
169  	   char*                 token;
170  	   char*                 pushedtokens[FZN_MAX_PUSHEDTOKENS];
171  	   int                   npushedtokens;
172  	   int                   linenumber;
173  	   int                   linepos;
174  	   int                   bufpos;
175  	   int                   nconstants;
176  	   int                   sconstants;
177  	   SCIP_OBJSENSE         objsense;
178  	   SCIP_Bool             hasdot;             /**< if the current token is a number, this bool tells if it contains a dot */
179  	   SCIP_Bool             endline;            /**< current buffer contains everything until the line ends */
180  	   SCIP_Bool             comment;            /**< current buffer contains everything until a comment starts */
181  	   SCIP_Bool             haserror;           /**< a error was detected during parsing */
182  	   SCIP_Bool             valid;
183  	   SCIP_Bool             initialconss;       /**< should model constraints be marked as initial? */
184  	   SCIP_Bool             dynamicconss;       /**< should model constraints be subject to aging? */
185  	   SCIP_Bool             dynamiccols;        /**< should columns be added and removed dynamically to the LP? */
186  	   SCIP_Bool             dynamicrows;        /**< should rows be added and removed dynamically to the LP? */
187  	
188  	   VARARRAY**            vararrays;          /**< variable arrays */
189  	   int                   nvararrays;         /**< number of variables */
190  	   int                   vararrayssize;      /**< size of variable array */
191  	
192  	   CONSTARRAY**          constarrays;        /**< constant arrays */
193  	   int                   nconstarrays;       /**< number of constant arrays */
194  	   int                   constarrayssize;    /**< size of constant array */
195  	};
196  	typedef struct FznInput FZNINPUT;
197  	
198  	/** FlatZinc writing data */
199  	struct FznOutput
200  	{
201  	   char*                 varbuffer;          /* buffer for auxiliary variables (float representatives of discrete variables) */
202  	   int                   varbufferlen;       /* current length of the above buffer */
203  	   int                   varbufferpos;       /* current filling position in the above buffer */
204  	   char*                 castbuffer;         /* buffer for int2float conversion constraints */
205  	   int                   castbufferlen;      /* current length of the above buffer */
206  	   int                   castbufferpos;      /* current filling position in the above buffer */
207  	   char*                 consbuffer;         /* buffer for all problem constraints */
208  	   int                   consbufferlen;      /* current length of the above buffer */
209  	   int                   consbufferpos;      /* current filling position in the above buffer */
210  	   int                   ndiscretevars;      /* number of discrete variables in the problem */
211  	   SCIP_Bool*            varhasfloat;        /* array which indicates, whether a discrete variable already has a float representative */
212  	};
213  	typedef struct FznOutput FZNOUTPUT;
214  	
215  	static const char delimchars[] = " \f\n\r\t\v";
216  	static const char tokenchars[] = ":<>=;{}[],()";
217  	static const char commentchars[] = "%";
218  	
219  	/*
220  	 * Hash functions
221  	 */
222  	
223  	/** gets the key (i.e. the name) of the given variable */
224  	static
225  	SCIP_DECL_HASHGETKEY(hashGetKeyVar)
226  	{  /*lint --e{715}*/
227  	   SCIP_VAR* var = (SCIP_VAR*) elem;
228  	
229  	   assert(var != NULL);
230  	   return (void*) SCIPvarGetName(var);
231  	}
232  	
233  	/** gets the key (i.e. the name) of the flatzinc constant */
234  	static
235  	SCIP_DECL_HASHGETKEY(hashGetKeyConstant)
236  	{  /*lint --e{715}*/
237  	   FZNCONSTANT* constant = (FZNCONSTANT*) elem;
238  	
239  	   assert(constant != NULL);
240  	   return (void*) constant->name;
241  	}
242  	
243  	/** comparison method for sorting variable arrays  w.r.t. to their name */
244  	static
245  	SCIP_DECL_SORTPTRCOMP(vararraysComp)
246  	{
247  	   return strcmp( ((VARARRAY*)elem1)->name, ((VARARRAY*)elem2)->name );
248  	}
249  	
250  	
251  	/** frees a given buffer char* array */
252  	static
253  	void freeStringBufferArray(
254  	   SCIP*                 scip,               /**< SCIP data structure */
255  	   char**                array,              /**< buffer array to free */
256  	   int                   nelements           /**< number of elements */
257  	   )
258  	{
259  	   int i;
260  	
261  	   for( i = nelements - 1; i >= 0; --i )
262  	      SCIPfreeBufferArray(scip, &array[i]);
263  	
264  	   SCIPfreeBufferArray(scip, &array);
265  	}
266  	
267  	/** returns whether the given character is a token delimiter */
268  	static
269  	SCIP_Bool isDelimChar(
270  	   char                  c                   /**< input character */
271  	   )
272  	{
273  	   return (c == '\0') || (strchr(delimchars, c) != NULL);
274  	}
275  	
276  	/** returns whether the given character is a single token */
277  	static
278  	SCIP_Bool isTokenChar(
279  	   char                  c                   /**< input character */
280  	   )
281  	{
282  	   return (strchr(tokenchars, c) != NULL);
283  	}
284  	
285  	/** check if the current token is equal to give char */
286  	static
287  	SCIP_Bool isChar(
288  	   const char*           token,              /**< token to be checked */
289  	   char                  c                   /**< char to compare */
290  	   )
291  	{
292  	   if( strlen(token) == 1 && *token == c )
293  	      return TRUE;
294  	
295  	   return FALSE;
296  	}
297  	
298  	/** check if the current token is Bool expression, this means false or true */
299  	static
300  	SCIP_Bool isBoolExp(
301  	   const char*           name,               /**< name to check */
302  	   SCIP_Bool*            value               /**< pointer to store the Bool value */
303  	   )
304  	{
305  	   /* check the name */
306  	   if( strlen(name) == 4 && strncmp(name, "true", 4) == 0 )
307  	   {
308  	      *value = TRUE;
309  	      return TRUE;
310  	   }
311  	   else if( strlen(name) == 1 && strncmp(name, "1", 1) == 0 )
312  	   {
313  	      /* we also allow 1 as true */
314  	      *value = TRUE;
315  	      return TRUE;
316  	   }
317  	   else if( strlen(name) == 5 && strncmp(name, "false", 5) == 0 )
318  	   {
319  	      *value = FALSE;
320  	      return TRUE;
321  	   }
322  	   else if( strlen(name) == 1 && strncmp(name, "0", 1) == 0 )
323  	   {
324  	      /* we also allow 0 as false */
325  	      *value = FALSE;
326  	      return TRUE;
327  	   }
328  	
329  	   return FALSE;
330  	}
331  	
332  	
333  	/** check if the current token is an identifier, this means [A-Za-z][A-Za-z0-9_]* */
334  	static
335  	SCIP_Bool isIdentifier(
336  	   const char*           name                /**< name to check */
337  	   )
338  	{
339  	   int i;
340  	
341  	   /* check if the identifier starts with a letter */
342  	   if( strlen(name) == 0 || !isalpha((unsigned char)name[0]) )
343  	      return FALSE;
344  	
345  	   i = 1;
346  	   while( name[i] )
347  	   {
348  	      if( !isalnum((unsigned char)name[i]) && name[i] != '_' )
349  	         return FALSE;
350  	      i++;
351  	   }
352  	
353  	   return TRUE;
354  	}
355  	
356  	/** returns whether the current character is member of a value string */
357  	static
358  	SCIP_Bool isValueChar(
359  	   char                  c,                  /**< input character */
360  	   char                  nextc,              /**< next input character */
361  	   SCIP_Bool             firstchar,          /**< is the given character the first char of the token? */
362  	   SCIP_Bool*            hasdot,             /**< pointer to update the dot flag */
363  	   FZNEXPTYPE*           exptype             /**< pointer to update the exponent type */
364  	   )
365  	{
366  	   assert(hasdot != NULL);
367  	   assert(exptype != NULL);
368  	
369  	   if( isdigit((unsigned char)c) )
370  	      return TRUE;
371  	   else if( firstchar && (c == '+' || c == '-') )
372  	      return TRUE;
373  	   else if( (*exptype == FZN_EXP_NONE) && !(*hasdot) && (c == '.') && (isdigit((unsigned char)nextc)))
374  	   {
375  	      *hasdot = TRUE;
376  	      return TRUE;
377  	   }
378  	   else if( !firstchar && (*exptype == FZN_EXP_NONE) && (c == 'e' || c == 'E') )
379  	   {
380  	      if( nextc == '+' || nextc == '-' )
381  	      {
382  	         *exptype = FZN_EXP_SIGNED;
383  	         return TRUE;
384  	      }
385  	      else if( isdigit((unsigned char)nextc) )
386  	      {
387  	         *exptype = FZN_EXP_UNSIGNED;
388  	         return TRUE;
389  	      }
390  	   }
391  	   else if( (*exptype == FZN_EXP_SIGNED) && (c == '+' || c == '-') )
392  	   {
393  	      *exptype = FZN_EXP_UNSIGNED;
394  	      return TRUE;
395  	   }
396  	
397  	   return FALSE;
398  	}
399  	
400  	/** compares two token if they are equal */
401  	static
402  	SCIP_Bool equalTokens(
403  	   const char*           token1,             /**< first token */
404  	   const char*           token2              /**< second token */
405  	   )
406  	{
407  	   assert(token1 != NULL);
408  	   assert(token2 != NULL);
409  	
410  	   if( strlen(token1) != strlen(token2) )
411  	      return FALSE;
412  	
413  	   return !strncmp(token1, token2, strlen(token2) );
414  	}
415  	
416  	/** reads the next line from the input file into the line buffer; skips comments;
417  	 *  returns whether a line could be read
418  	 */
419  	static
420  	SCIP_Bool getNextLine(
421  	   SCIP*                 scip,               /**< SCIP data structure */
422  	   FZNINPUT*             fzninput            /**< FZN reading data */
423  	   )
424  	{
425  	   int i;
426  	
427  	   assert(fzninput != NULL);
428  	
429  	   /* if we previously detected a comment we have to parse the remaining line away if there is something left */
430  	   if( !fzninput->endline && fzninput->comment )
431  	   {
432  	      SCIPdebugMsg(scip, "Throwing rest of comment away.\n");
433  	
434  	      do
435  	      {
436  	         fzninput->linebuf[FZN_BUFFERLEN-2] = '\0';
437  	         (void)SCIPfgets(fzninput->linebuf, (int) sizeof(fzninput->linebuf), fzninput->file);
438  	      }
439  	      while( fzninput->linebuf[FZN_BUFFERLEN-2] != '\0' );
440  	
441  	      fzninput->comment = FALSE;
442  	      fzninput->endline = TRUE;
443  	   }
444  	
445  	   /* clear the line */
446  	   BMSclearMemoryArray(fzninput->linebuf, FZN_BUFFERLEN);
447  	   fzninput->linebuf[FZN_BUFFERLEN-2] = '\0';
448  	
449  	   /* set line position */
450  	   if( fzninput->endline )
451  	   {
452  	      fzninput->linepos = 0;
453  	      fzninput->linenumber++;
454  	   }
455  	   else
456  	      fzninput->linepos += FZN_BUFFERLEN - 2;
457  	
458  	   if( SCIPfgets(fzninput->linebuf, (int) sizeof(fzninput->linebuf), fzninput->file) == NULL )
459  	      return FALSE;
460  	
461  	   fzninput->bufpos = 0;
462  	
463  	   if( fzninput->linebuf[FZN_BUFFERLEN-2] != '\0' )
464  	   {
465  	      char* last;
466  	
467  	      /* buffer is full; erase last token since it might be incomplete */
468  	      fzninput->endline = FALSE;
469  	      last = strrchr(fzninput->linebuf, ' ');
470  	
471  	      if( last == NULL )
472  	      {
473  	         SCIPwarningMessage(scip, "we read %d characters from the file; this might indicate a corrupted input file!\n",
474  	            FZN_BUFFERLEN - 2);
475  	         fzninput->linebuf[FZN_BUFFERLEN-2] = '\0';
476  	         SCIPdebugMsg(scip, "the buffer might be corrupted\n");
477  	      }
478  	      else
479  	      {
480  	         SCIPfseek(fzninput->file, -(long) strlen(last), SEEK_CUR);
481  	         SCIPdebugMsg(scip, "correct buffer, reread the last %ld characters\n", (long) strlen(last));
482  	         *last = '\0';
483  	      }
484  	   }
485  	   else
486  	   {
487  	      /* found end of line */
488  	      fzninput->endline = TRUE;
489  	   }
490  	
491  	   fzninput->linebuf[FZN_BUFFERLEN-1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
492  	   fzninput->comment = FALSE;
493  	
494  	   /* skip characters after comment symbol */
495  	   for( i = 0; commentchars[i] != '\0'; ++i )
496  	   {
497  	      char* commentstart;
498  	
499  	      commentstart = strchr(fzninput->linebuf, commentchars[i]);
500  	      if( commentstart != NULL )
501  	      {
502  	         *commentstart = '\0';
503  	         *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
504  	         fzninput->comment = TRUE;
505  	         break;
506  	      }
507  	   }
508  	
509  	   return TRUE;
510  	}
511  	
512  	
513  	/** reads the next token from the input file into the token buffer; returns whether a token was read */
514  	static
515  	SCIP_Bool getNextToken(
516  	   SCIP*                 scip,               /**< SCIP data structure */
517  	   FZNINPUT*             fzninput            /**< FZN reading data */
518  	   )
519  	{
520  	   SCIP_Bool hasdot;
521  	   FZNEXPTYPE exptype;
522  	   char* buf;
523  	   int tokenlen;
524  	
525  	   assert(fzninput != NULL);
526  	   assert(fzninput->bufpos < FZN_BUFFERLEN);
527  	
528  	   /* if the current line got marked as comment get the next line */
529  	   if( fzninput->comment && !getNextLine(scip, fzninput) )
530  	   {
531  	      SCIPdebugMsg(scip, "(line %d) end of file\n", fzninput->linenumber);
532  	      return FALSE;
533  	   }
534  	
535  	   /* check the token stack */
536  	   if( fzninput->npushedtokens > 0 )
537  	   {
538  	      SCIPswapPointers((void**)&fzninput->token, (void**)&fzninput->pushedtokens[fzninput->npushedtokens-1]);
539  	      fzninput->npushedtokens--;
540  	      SCIPdebugMsg(scip, "(line %d) read token again: '%s'\n", fzninput->linenumber, fzninput->token);
541  	      return TRUE;
542  	   }
543  	
544  	   /* skip delimiters */
545  	   buf = fzninput->linebuf;
546  	   while( isDelimChar(buf[fzninput->bufpos]) )
547  	   {
548  	      if( buf[fzninput->bufpos] == '\0' )
549  	      {
550  	         if( !getNextLine(scip, fzninput) )
551  	         {
552  	            SCIPdebugMsg(scip, "(line %d) end of file\n", fzninput->linenumber);
553  	            return FALSE;
554  	         }
555  	         assert(fzninput->bufpos == 0);
556  	      }
557  	      else
558  	      {
559  	         fzninput->bufpos++;
560  	         fzninput->linepos++;
561  	      }
562  	   }
563  	   assert(fzninput->bufpos < FZN_BUFFERLEN);
564  	   assert(!isDelimChar(buf[fzninput->bufpos]));
565  	
566  	   hasdot = FALSE;
567  	   exptype = FZN_EXP_NONE;
568  	
569  	   if( buf[fzninput->bufpos] == '.' && buf[fzninput->bufpos+1] == '.')
570  	   {
571  	      /* found <..> which only occurs in Ranges and is a "keyword" */
572  	      tokenlen = 2;
573  	      fzninput->bufpos += 2;
574  	      fzninput->linepos += 2;
575  	      fzninput->token[0] = '.';
576  	      fzninput->token[1] = '.';
577  	   }
578  	   else if( isValueChar(buf[fzninput->bufpos], buf[fzninput->bufpos+1], TRUE, &hasdot, &exptype) )
579  	   {
580  	      /* read value token */
581  	      tokenlen = 0;
582  	      do
583  	      {
584  	         assert(tokenlen < FZN_BUFFERLEN);
585  	         assert(!isDelimChar(buf[fzninput->bufpos]));
586  	         fzninput->token[tokenlen] = buf[fzninput->bufpos];
587  	         tokenlen++;
588  	         fzninput->bufpos++;
589  	         fzninput->linepos++;
590  	         assert(fzninput->bufpos < FZN_BUFFERLEN);
591  	      }
592  	      while( isValueChar(buf[fzninput->bufpos], buf[fzninput->bufpos+1], FALSE, &hasdot, &exptype) );
593  	
594  	      fzninput->hasdot = hasdot;
595  	   }
596  	   else
597  	   {
598  	      /* read non-value token */
599  	      tokenlen = 0;
600  	      do
601  	      {
602  	         assert(tokenlen < FZN_BUFFERLEN);
603  	         fzninput->token[tokenlen] = buf[fzninput->bufpos];
604  	         tokenlen++;
605  	         fzninput->bufpos++;
606  	         fzninput->linepos++;
607  	
608  	         /* check for annotations */
609  	         if(tokenlen == 1 && fzninput->token[0] == ':' && buf[fzninput->bufpos] == ':')
610  	         {
611  	            fzninput->token[tokenlen] = buf[fzninput->bufpos];
612  	            tokenlen++;
613  	            fzninput->bufpos++;
614  	            fzninput->linepos++;
615  	            break;
616  	         }
617  	
618  	         if( tokenlen == 1 && isTokenChar(fzninput->token[0]) )
619  	            break;
620  	      }
621  	      while( !isDelimChar(buf[fzninput->bufpos]) && !isTokenChar(buf[fzninput->bufpos]) );
622  	   }
623  	
624  	   assert(tokenlen < FZN_BUFFERLEN);
625  	   fzninput->token[tokenlen] = '\0';
626  	
627  	   SCIPdebugMsg(scip, "(line %d) read token: '%s'\n", fzninput->linenumber, fzninput->token);
628  	
629  	   return TRUE;
630  	}
631  	
632  	/** puts the current token on the token stack, such that it is read at the next call to getNextToken() */
633  	static
634  	void pushToken(
635  	   FZNINPUT*             fzninput            /**< FZN reading data */
636  	   )
637  	{
638  	   assert(fzninput != NULL);
639  	   assert(fzninput->npushedtokens < FZN_MAX_PUSHEDTOKENS);
640  	
641  	   SCIPswapPointers((void**)&fzninput->pushedtokens[fzninput->npushedtokens], (void**)&fzninput->token);
642  	   fzninput->npushedtokens++;
643  	}
644  	
645  	/** checks whether the current token is a semicolon which closes a statement */
646  	static
647  	SCIP_Bool isEndStatement(
648  	   FZNINPUT*             fzninput            /**< FZN reading data */
649  	   )
650  	{
651  	   assert(fzninput != NULL);
652  	
653  	   return isChar(fzninput->token, ';');
654  	}
655  	
656  	/** returns whether the current token is a value */
657  	static
658  	SCIP_Bool isValue(
659  	   const char*           token,              /**< token to check */
660  	   SCIP_Real*            value               /**< pointer to store the value (unchanged, if token is no value) */
661  	   )
662  	{
663  	   double val;
664  	   char* endptr;
665  	
666  	   assert(value != NULL);
667  	
668  	   val = strtod(token, &endptr);
669  	   if( endptr != token && *endptr == '\0' )
670  	   {
671  	      *value = val;
672  	      return TRUE;
673  	   }
674  	
675  	   return FALSE;
676  	}
677  	
678  	/*
679  	 * Local methods (for reading)
680  	 */
681  	
682  	/** issues an error message and marks the FlatZinc data to have errors */
683  	static
684  	void syntaxError(
685  	   SCIP*                 scip,               /**< SCIP data structure */
686  	   FZNINPUT*             fzninput,           /**< FZN reading data */
687  	   const char*           msg                 /**< error message */
688  	   )
689  	{
690  	   assert(fzninput != NULL);
691  	   assert(scip != NULL);
692  	
693  	   SCIPerrorMessage("Syntax error in line %d: %s found <%s>\n", fzninput->linenumber, msg, fzninput->token);
694  	   SCIPerrorMessage("  input: %s\n", fzninput->linebuf);
695  	
696  	   fzninput->haserror = TRUE;
697  	}
698  	
699  	/** returns whether a syntax error was detected */
700  	static
701  	SCIP_Bool hasError(
702  	   FZNINPUT*             fzninput            /**< FZN reading data */
703  	   )
704  	{
705  	   assert(fzninput != NULL);
706  	
707  	   return (fzninput->haserror || !fzninput->valid);
708  	}
709  	
710  	/** create reader data */
711  	static
712  	SCIP_RETCODE readerdataCreate(
713  	   SCIP*                 scip,               /**< SCIP data structure */
714  	   SCIP_READERDATA**     readerdata          /**< pointer to reader data */
715  	   )
716  	{
717  	   SCIP_CALL( SCIPallocBlockMemory(scip, readerdata) );
718  	
719  	   (*readerdata)->vararrays = NULL;
720  	   (*readerdata)->nvararrays = 0;
721  	   (*readerdata)->vararrayssize = 0;
722  	
723  	   return SCIP_OKAY;
724  	}
725  	
726  	/** ensure the size if the variable array */
727  	static
728  	SCIP_RETCODE ensureVararrySize(
729  	   SCIP*                 scip,               /**< SCIP data structure */
730  	   SCIP_READERDATA*      readerdata          /**< reader data */
731  	   )
732  	{
733  	   int nvararrays;
734  	   int vararrayssize;
735  	
736  	   nvararrays = readerdata->nvararrays;
737  	   vararrayssize = readerdata->vararrayssize;
738  	
739  	   if( vararrayssize == nvararrays )
740  	   {
741  	      if( vararrayssize == 0 )
742  	      {
743  	         vararrayssize = 100;
744  	         SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->vararrays, vararrayssize) );
745  	      }
746  	      else
747  	      {
748  	         vararrayssize *= 2;
749  	         SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &readerdata->vararrays, readerdata->vararrayssize, vararrayssize) );
750  	      }
751  	   }
752  	
753  	   readerdata->vararrayssize = vararrayssize;
754  	
755  	   return SCIP_OKAY;
756  	}
757  	
758  	/** ensure the size if the variable array */
759  	static
760  	SCIP_RETCODE ensureVararrySizeFznInput(
761  	   SCIP*                 scip,               /**< SCIP data structure */
762  	   FZNINPUT*             fzninput            /**< FZN reading data */
763  	   )
764  	{
765  	   int nvararrays;
766  	   int vararrayssize;
767  	
768  	   nvararrays = fzninput->nvararrays;
769  	   vararrayssize = fzninput->vararrayssize;
770  	
771  	   if( vararrayssize == nvararrays )
772  	   {
773  	      if( vararrayssize == 0 )
774  	      {
775  	         vararrayssize = 100;
776  	         SCIP_CALL( SCIPallocBlockMemoryArray(scip, &fzninput->vararrays, vararrayssize) );
777  	      }
778  	      else
779  	      {
780  	         vararrayssize *= 2;
781  	         SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &fzninput->vararrays, fzninput->vararrayssize, vararrayssize) );
782  	      }
783  	   }
784  	
785  	   fzninput->vararrayssize = vararrayssize;
786  	
787  	   return SCIP_OKAY;
788  	}
789  	
790  	/** ensure the size if the variable array */
791  	static
792  	SCIP_RETCODE ensureConstarrySizeFznInput(
793  	   SCIP*                 scip,               /**< SCIP data structure */
794  	   FZNINPUT*             fzninput            /**< FZN reading data */
795  	   )
796  	{
797  	   int nconstarrays;
798  	   int constarrayssize;
799  	
800  	   nconstarrays = fzninput->nconstarrays;
801  	   constarrayssize = fzninput->constarrayssize;
802  	
803  	   if( constarrayssize == nconstarrays )
804  	   {
805  	      if( constarrayssize == 0 )
806  	      {
807  	         constarrayssize = 100;
808  	         SCIP_CALL( SCIPallocBlockMemoryArray(scip, &fzninput->constarrays, constarrayssize) );
809  	      }
810  	      else
811  	      {
812  	         constarrayssize *= 2;
813  	         SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &fzninput->constarrays, fzninput->constarrayssize, constarrayssize) );
814  	      }
815  	   }
816  	
817  	   fzninput->constarrayssize = constarrayssize;
818  	
819  	   return SCIP_OKAY;
820  	}
821  	
822  	/** print given value in FlatZinc format to given stream */
823  	static
824  	void printValue(
825  	   SCIP*                 scip,               /**< SCIP data structure */
826  	   FILE*                 file,               /**< output file (or NULL for standard output) */
827  	   SCIP_Real             value,              /**< value to print */
828  	   FZNNUMBERTYPE         type                /**< FlatZinc number type */
829  	   )
830  	{
831  	   switch( type )
832  	   {
833  	   case FZN_BOOL:
834  	      if( value < 0.5 )
835  	         SCIPinfoMessage(scip, file, "false");
836  	      else
837  	         SCIPinfoMessage(scip, file, "true");
838  	      break;
839  	   case FZN_INT:
840  	   {
841  	      SCIP_Longint longvalue;
842  	      longvalue = SCIPconvertRealToLongint(scip, value);
843  	      SCIPinfoMessage(scip, file, "%" SCIP_LONGINT_FORMAT "", longvalue);
844  	      break;
845  	   }
846  	   case FZN_FLOAT:
847  	      if( SCIPisIntegral(scip, value) )
848  	      {
849  	         printValue(scip, file, value, FZN_INT);
850  	
851  	         /* add a ".0" to be type save */
852  	         SCIPinfoMessage(scip, file, ".0");
853  	      }
854  	      else
855  	      {
856  	         SCIPinfoMessage(scip, file, "%.1f", value);
857  	      }
858  	      break;
859  	   }
860  	}
861  	
862  	/*
863  	 * Local methods (for VARARRAY)
864  	 */
865  	
866  	/** free dimension structure */
867  	static
868  	SCIP_RETCODE copyDimensions(
869  	   SCIP*                 scip,               /**< SCIP data structure */
870  	   DIMENSIONS**          target,             /**< pointer to dimension target structure */
871  	   DIMENSIONS*           source              /**< dimension source */
872  	   )
873  	{
874  	   if( source != NULL )
875  	   {
876  	      SCIP_CALL( SCIPallocBlockMemory(scip, target) );
877  	
878  	      SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*target)->lbs, source->lbs, source->ndims) );
879  	      SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*target)->ubs, source->ubs, source->ndims) );
880  	      (*target)->ndims = source->ndims;
881  	      (*target)->size = source->ndims;
882  	   }
883  	   else
884  	      *target = NULL;
885  	
886  	   return SCIP_OKAY;
887  	}
888  	
889  	/** create variable array data structure */
890  	static
891  	SCIP_RETCODE createVararray(
892  	   SCIP*                 scip,               /**< SCIP data structure */
893  	   VARARRAY**            vararray,           /**< pointer to variable array */
894  	   const char*           name,               /**< name of the variable array */
895  	   SCIP_VAR**            vars,               /**< array of variables */
896  	   int                   nvars,              /**< number of variables */
897  	   FZNNUMBERTYPE         type,               /**< variable type */
898  	   DIMENSIONS*           info                /**< dimension information for output */
899  	   )
900  	{
901  	   /* allocate memory for the new vararray struct */
902  	   SCIP_CALL( SCIPallocBlockMemory(scip, vararray) );
903  	
904  	   /* copy variable pointers */
905  	   SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*vararray)->vars, vars, nvars) );
906  	
907  	   /* copy variable array name */
908  	   SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*vararray)->name, name, strlen(name)+1) );
909  	
910  	   SCIP_CALL( copyDimensions(scip, &(*vararray)->info, info) );
911  	
912  	   (*vararray)->nvars = nvars;
913  	   (*vararray)->type = type;
914  	
915  	   return SCIP_OKAY;
916  	}
917  	
918  	/** free dimension structure */
919  	static
920  	void freeDimensions(
921  	   SCIP*                 scip,               /**< SCIP data structure */
922  	   DIMENSIONS**          dim                 /**< pointer to dimension structure */
923  	   )
924  	{
925  	   if( *dim != NULL )
926  	   {
927  	      SCIPfreeBlockMemoryArrayNull(scip, &(*dim)->lbs, (*dim)->size);
928  	      SCIPfreeBlockMemoryArrayNull(scip, &(*dim)->ubs, (*dim)->size);
929  	      SCIPfreeBlockMemory(scip, dim);
930  	   }
931  	}
932  	
933  	/** free variable array data structure */
934  	static
935  	void freeVararray(
936  	   SCIP*                 scip,               /**< SCIP data structure */
937  	   VARARRAY**            vararray            /**< pointer to variable array */
938  	   )
939  	{
940  	   freeDimensions(scip, &(*vararray)->info);
941  	
942  	   SCIPfreeBlockMemoryArray(scip, &(*vararray)->name, strlen((*vararray)->name) + 1);
943  	   SCIPfreeBlockMemoryArray(scip, &(*vararray)->vars, (*vararray)->nvars);
944  	
945  	   SCIPfreeBlockMemory(scip, vararray);
946  	}
947  	
948  	/** searches the variable array data base if a constant array exists with the given name; if it exists it is returned */
949  	static
950  	VARARRAY* findVararray(
951  	   FZNINPUT*             fzninput,           /**< FZN reading data */
952  	   const char*           name                /**< variable array name */
953  	   )
954  	{
955  	   VARARRAY* vararray;
956  	   int c;
957  	
958  	   /* search in constants array list for a constants array with the given name */
959  	   for( c = 0; c < fzninput->nvararrays; ++c )
960  	   {
961  	      vararray = fzninput->vararrays[c];
962  	
963  	      if( equalTokens(name, vararray->name) )
964  	         return vararray;
965  	   }
966  	
967  	   return NULL;
968  	}
969  	
970  	/*
971  	 * Local methods (for CONSTARRAY)
972  	 */
973  	
974  	/** create constant array data structure */
975  	static
976  	SCIP_RETCODE createConstarray(
977  	   SCIP*                 scip,               /**< SCIP data structure */
978  	   CONSTARRAY**          constarray,         /**< pointer to constant array */
979  	   const char*           name,               /**< name of the variable array */
980  	   FZNCONSTANT**         constants,          /**< array of constants */
981  	   int                   nconstants,         /**< number of constants */
982  	   FZNNUMBERTYPE         type                /**< constant type */
983  	   )
984  	{
985  	   SCIPdebugMsg(scip, "create constant array <%s>\n", name);
986  	
987  	   /* allocate memory for the new constarray struct */
988  	   SCIP_CALL( SCIPallocBlockMemory(scip, constarray) );
989  	
990  	   /* copy constant values */
991  	   SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*constarray)->constants, constants, nconstants) );
992  	
993  	   /* copy constant array name */
994  	   SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*constarray)->name, name, strlen(name)+1) );
995  	
996  	   (*constarray)->nconstants = nconstants;
997  	   (*constarray)->type = type;
998  	
999  	   return SCIP_OKAY;
1000 	}
1001 	
1002 	/** free constant array data structure */
1003 	static
1004 	void freeConstarray(
1005 	   SCIP*                 scip,               /**< SCIP data structure */
1006 	   CONSTARRAY**          constarray          /**< pointer to constant array */
1007 	   )
1008 	{
1009 	   SCIPdebugMsg(scip, "free constant array <%s>\n", (*constarray)->name);
1010 	
1011 	   /* free variable pointers */
1012 	   SCIPfreeBlockMemoryArray(scip, &(*constarray)->constants, (*constarray)->nconstants);
1013 	
1014 	   /* free variable array name */
1015 	   SCIPfreeBlockMemoryArray(scip, &(*constarray)->name, strlen((*constarray)->name) + 1);
1016 	
1017 	   /* allocate memory for the new vararray struct */
1018 	   SCIPfreeBlockMemory(scip, constarray);
1019 	}
1020 	
1021 	/** searches the constant array data base if a constant array exists with the given name; if it exists it is returned */
1022 	static
1023 	CONSTARRAY* findConstarray(
1024 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1025 	   const char*           name                /**< constant array name */
1026 	   )
1027 	{
1028 	   CONSTARRAY* constarray;
1029 	   int c;
1030 	
1031 	   /* search in constants array list for a constants array with the given name */
1032 	   for( c = 0; c < fzninput->nconstarrays; ++c )
1033 	   {
1034 	      constarray = fzninput->constarrays[c];
1035 	
1036 	      if( equalTokens(name, constarray->name) )
1037 	         return constarray;
1038 	   }
1039 	
1040 	   return NULL;
1041 	}
1042 	
1043 	/** add variable to the reader data */
1044 	static
1045 	SCIP_RETCODE readerdataAddOutputvar(
1046 	   SCIP*                 scip,               /**< SCIP data structure */
1047 	   SCIP_READERDATA*      readerdata,         /**< reader data */
1048 	   SCIP_VAR*             var,                /**< variable to add to the reader data */
1049 	   FZNNUMBERTYPE         type                /**< variable type */
1050 	   )
1051 	{
1052 	   DIMENSIONS* info;
1053 	   const char* name;
1054 	   VARARRAY* vararray;
1055 	   int nvararrays;
1056 	
1057 	   nvararrays = readerdata->nvararrays;
1058 	
1059 	   SCIP_CALL( ensureVararrySize(scip, readerdata) );
1060 	   assert(nvararrays < readerdata->vararrayssize);
1061 	
1062 	   /* get variable name */
1063 	   name = SCIPvarGetName(var);
1064 	
1065 	   /* allocate memory for the new vararray struct */
1066 	   SCIP_CALL( SCIPallocBlockMemory(scip, &vararray) );
1067 	
1068 	   /* copy variable pointers */
1069 	   SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &vararray->vars, &var, 1) );
1070 	
1071 	   /* copy variable array name */
1072 	   SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &vararray->name, name, strlen(name)+1) );
1073 	
1074 	   SCIP_CALL( SCIPallocBlockMemory(scip, &info) );
1075 	   info->lbs = NULL;
1076 	   info->ubs = NULL;
1077 	   info->ndims = 0;
1078 	   info->size = 0;
1079 	
1080 	   vararray->info = info;
1081 	   vararray->nvars = 1;
1082 	   vararray->type = type;
1083 	
1084 	   readerdata->vararrays[nvararrays] = vararray;
1085 	   readerdata->nvararrays++;
1086 	
1087 	   return SCIP_OKAY;
1088 	}
1089 	
1090 	/** add variable to the reader data */
1091 	static
1092 	SCIP_RETCODE readerdataAddOutputvararray(
1093 	   SCIP*                 scip,               /**< SCIP data structure */
1094 	   SCIP_READERDATA*      readerdata,         /**< reader data */
1095 	   const char*           name,               /**< name of the variable array */
1096 	   SCIP_VAR**            vars,               /**< array of variable to add to the reader data */
1097 	   int                   nvars,              /**< number of variables */
1098 	   FZNNUMBERTYPE         type,               /**< variable type */
1099 	   DIMENSIONS*           info                /**< dimension information for output */
1100 	   )
1101 	{
1102 	   VARARRAY* vararray;
1103 	   int nvararrays;
1104 	
1105 	   nvararrays = readerdata->nvararrays;
1106 	
1107 	   SCIP_CALL( ensureVararrySize(scip, readerdata) );
1108 	   assert(nvararrays < readerdata->vararrayssize);
1109 	
1110 	   /* create variable array data structure */
1111 	   SCIP_CALL( createVararray(scip, &vararray, name, vars, nvars, type, info) );
1112 	
1113 	   readerdata->vararrays[nvararrays] = vararray;
1114 	   readerdata->nvararrays++;
1115 	
1116 	   return SCIP_OKAY;
1117 	}
1118 	
1119 	/** add variable to the input data */
1120 	static
1121 	SCIP_RETCODE fzninputAddVararray(
1122 	   SCIP*                 scip,               /**< SCIP data structure */
1123 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1124 	   const char*           name,               /**< name of the variable array */
1125 	   SCIP_VAR**            vars,               /**< array of variables */
1126 	   int                   nvars,              /**< number of variables */
1127 	   FZNNUMBERTYPE         type,               /**< variable type */
1128 	   DIMENSIONS*           info                /**< dimension information for output */
1129 	   )
1130 	{
1131 	   VARARRAY* vararray;
1132 	   int nvararrays;
1133 	
1134 	   nvararrays = fzninput->nvararrays;
1135 	
1136 	   SCIP_CALL( ensureVararrySizeFznInput(scip, fzninput) );
1137 	   assert(nvararrays < fzninput->vararrayssize);
1138 	
1139 	   /* create variable array data structure */
1140 	   SCIP_CALL( createVararray(scip, &vararray, name, vars, nvars, type, info) );
1141 	
1142 	   fzninput->vararrays[nvararrays] = vararray;
1143 	   fzninput->nvararrays++;
1144 	
1145 	   return SCIP_OKAY;
1146 	}
1147 	
1148 	/** add variable to the reader data */
1149 	static
1150 	SCIP_RETCODE fzninputAddConstarray(
1151 	   SCIP*                 scip,               /**< SCIP data structure */
1152 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1153 	   const char*           name,               /**< name of the variable array */
1154 	   FZNCONSTANT**         constants,          /**< array of constants */
1155 	   int                   nconstants,         /**< number of constants */
1156 	   FZNNUMBERTYPE         type                /**< variable type */
1157 	   )
1158 	{
1159 	   CONSTARRAY* constarray;
1160 	   int nconstarrays;
1161 	
1162 	   nconstarrays = fzninput->nconstarrays;
1163 	
1164 	   SCIP_CALL( ensureConstarrySizeFznInput(scip, fzninput) );
1165 	   assert(nconstarrays < fzninput->constarrayssize);
1166 	
1167 	   /* create constant array structure */
1168 	   SCIP_CALL( createConstarray(scip, &constarray, name, constants, nconstants, type) );
1169 	
1170 	   fzninput->constarrays[nconstarrays] = constarray;
1171 	   fzninput->nconstarrays++;
1172 	
1173 	   return SCIP_OKAY;
1174 	}
1175 	
1176 	/** creates, adds, and releases a quadratic constraint */
1177 	static
1178 	SCIP_RETCODE createQuadraticCons(
1179 	   SCIP*                 scip,               /**< SCIP data structure */
1180 	   const char*           name,               /**< name of constraint */
1181 	   int                   nlinvars,           /**< number of linear terms (n) */
1182 	   SCIP_VAR**            linvars,            /**< array with variables in linear part (x_i) */
1183 	   SCIP_Real*            lincoefs,           /**< array with coefficients of variables in linear part (b_i) */
1184 	   int                   nquadterms,         /**< number of quadratic terms (m) */
1185 	   SCIP_VAR**            quadvars1,          /**< array with first variables in quadratic terms (y_j) */
1186 	   SCIP_VAR**            quadvars2,          /**< array with second variables in quadratic terms (z_j) */
1187 	   SCIP_Real*            quadcoefs,          /**< array with coefficients of quadratic terms (a_j) */
1188 	   SCIP_Real             lhs,                /**< left hand side of quadratic equation (ell) */
1189 	   SCIP_Real             rhs,                /**< right hand side of quadratic equation (u) */
1190 	   SCIP_Bool             initialconss,       /**< should model constraints be marked as initial? */
1191 	   SCIP_Bool             dynamicconss,       /**< should model constraints be subject to aging? */
1192 	   SCIP_Bool             dynamicrows         /**< should rows be added and removed dynamically to the LP? */
1193 	   )
1194 	{
1195 	   SCIP_CONS* cons;
1196 	
1197 	   SCIP_CALL( SCIPcreateConsQuadraticNonlinear(scip, &cons, name, nlinvars, linvars, lincoefs, nquadterms, quadvars1,
1198 	         quadvars2, quadcoefs, lhs, rhs, initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss,
1199 	         dynamicrows) );
1200 	
1201 	   SCIPdebugPrintCons(scip, cons, NULL);
1202 	
1203 	   SCIP_CALL( SCIPaddCons(scip, cons) );
1204 	   SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1205 	
1206 	   return SCIP_OKAY;
1207 	}
1208 	
1209 	/** creates, adds, and releases a linear constraint */
1210 	static
1211 	SCIP_RETCODE createLinearCons(
1212 	   SCIP*                 scip,               /**< SCIP data structure */
1213 	   const char*           name,               /**< name of constraint */
1214 	   int                   nvars,              /**< number of nonzeros in the constraint */
1215 	   SCIP_VAR**            vars,               /**< array with variables of constraint entries */
1216 	   SCIP_Real*            vals,               /**< array with coefficients of constraint entries */
1217 	   SCIP_Real             lhs,                /**< left hand side of constraint */
1218 	   SCIP_Real             rhs,                /**< right hand side of constraint */
1219 	   SCIP_Bool             initialconss,       /**< should model constraints be marked as initial? */
1220 	   SCIP_Bool             dynamicconss,       /**< should model constraints be subject to aging? */
1221 	   SCIP_Bool             dynamicrows         /**< should rows be added and removed dynamically to the LP? */
1222 	   )
1223 	{
1224 	   SCIP_CONS* cons;
1225 	
1226 	   SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, nvars, vars, vals, lhs, rhs,
1227 	         initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss, dynamicrows, FALSE) );
1228 	
1229 	   SCIPdebugPrintCons(scip, cons, NULL);
1230 	
1231 	   SCIP_CALL( SCIPaddCons(scip, cons) );
1232 	   SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1233 	
1234 	   return SCIP_OKAY;
1235 	}
1236 	
1237 	/** create a linking between the two given identifiers */
1238 	static
1239 	SCIP_RETCODE createLinking(
1240 	   SCIP*                 scip,               /**< SCIP data structure */
1241 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1242 	   const char*           consname,           /**< name of constraint */
1243 	   const char*           name1,              /**< name of first identifier */
1244 	   const char*           name2,              /**< name of second identifier */
1245 	   SCIP_Real             lhs,                /**< left hand side of the linking */
1246 	   SCIP_Real             rhs                 /**< right hand side of the linking */
1247 	   )
1248 	{
1249 	   SCIP_VAR** vars;
1250 	   SCIP_Real vals[] = {0.0,0.0};
1251 	   SCIP_Real value1;
1252 	   SCIP_Real value2;
1253 	   int nvars;
1254 	
1255 	   nvars = 0;
1256 	   value1 = 0.0;
1257 	   value2 = 0.0;
1258 	
1259 	   SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
1260 	
1261 	   vars[nvars] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) name1);
1262 	   if( vars[nvars] != NULL )
1263 	   {
1264 	      vals[nvars] = 1.0;
1265 	      nvars++;
1266 	   }
1267 	   else if( !isValue(name1, &value1) )
1268 	   {
1269 	      FZNCONSTANT* constant;
1270 	
1271 	      constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) name1);
1272 	      assert(constant != NULL);
1273 	
1274 	      value1 = constant->value;
1275 	   }
1276 	
1277 	   vars[nvars] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) name2);
1278 	   if( vars[nvars] != NULL )
1279 	   {
1280 	      vals[nvars] = -1.0;
1281 	      nvars++;
1282 	   }
1283 	   else if( !isValue(name2, &value2) )
1284 	   {
1285 	      FZNCONSTANT* constant;
1286 	
1287 	      constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) name2);
1288 	      assert(constant != NULL);
1289 	
1290 	      value2 = constant->value;
1291 	   }
1292 	
1293 	   if( !SCIPisInfinity(scip, -lhs) )
1294 	      lhs += (value2 - value1);
1295 	
1296 	   if( !SCIPisInfinity(scip, rhs) )
1297 	      rhs += (value2 - value1);
1298 	
1299 	   SCIP_CALL( createLinearCons(scip, consname, nvars, vars, vals, lhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
1300 	
1301 	   SCIPfreeBufferArray(scip, &vars);
1302 	
1303 	   return SCIP_OKAY;
1304 	}
1305 	
1306 	/** parse array index expression */
1307 	static
1308 	void parseArrayIndex(
1309 	   SCIP*                 scip,               /**< SCIP data structure */
1310 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1311 	   int*                  idx                 /**< pointer to store the array index */
1312 	   )
1313 	{
1314 	   SCIP_Real value;
1315 	
1316 	   assert( isChar(fzninput->token, '[') );
1317 	
1318 	   /* parse array index expression */
1319 	   if( !getNextToken(scip, fzninput) || isEndStatement(fzninput) )
1320 	   {
1321 	      syntaxError(scip, fzninput, "expecting array index expression");
1322 	      return;
1323 	   }
1324 	
1325 	   if( isIdentifier(fzninput->token) )
1326 	   {
1327 	      FZNCONSTANT* constant;
1328 	
1329 	      /* identifier has to be one of a constant */
1330 	      constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, fzninput->token);
1331 	
1332 	      if( constant == NULL )
1333 	         syntaxError(scip, fzninput, "unknown index name");
1334 	      else
1335 	      {
1336 	         assert(constant->type == FZN_INT);
1337 	         *idx = (int) constant->value;
1338 	      }
1339 	   }
1340 	   else if( isValue(fzninput->token, &value) )
1341 	   {
1342 	      assert( fzninput->hasdot == FALSE );
1343 	      *idx = (int) value;
1344 	   }
1345 	   else
1346 	      syntaxError(scip, fzninput, "expecting array index expression");
1347 	}
1348 	
1349 	/** unroll assignment if it is an array access one */
1350 	static
1351 	void flattenAssignment(
1352 	   SCIP*                 scip,               /**< SCIP data structure */
1353 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1354 	   char*                 assignment          /**< assignment to unroll */
1355 	   )
1356 	{
1357 	   assert(scip != NULL);
1358 	   assert(fzninput != NULL);
1359 	
1360 	   SCIPdebugMsg(scip, "parse assignment expression\n");
1361 	
1362 	   if( !getNextToken(scip, fzninput) || isEndStatement(fzninput) )
1363 	   {
1364 	      syntaxError(scip, fzninput, "expecting more tokens");
1365 	      return;
1366 	   }
1367 	
1368 	   if( isIdentifier(fzninput->token) )
1369 	   {
1370 	      char name[FZN_BUFFERLEN];
1371 	      int idx;
1372 	
1373 	      (void) SCIPsnprintf(name, FZN_BUFFERLEN, "%s", fzninput->token);
1374 	
1375 	      if( !getNextToken(scip, fzninput) )
1376 	      {
1377 	         syntaxError(scip, fzninput, "expecting at least a semicolon to close the statement");
1378 	         return;
1379 	      }
1380 	
1381 	      /* check if it is an array access expression */
1382 	      if( isChar(fzninput->token, '[') )
1383 	      {
1384 	         idx = -1;
1385 	         parseArrayIndex(scip, fzninput, &idx);
1386 	
1387 	         assert(idx >= 0);
1388 	
1389 	         if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, ']') )
1390 	         {
1391 	            syntaxError(scip, fzninput, "expecting token <]>");
1392 	            return;
1393 	         }
1394 	
1395 	         /* put constant name or variable name together */
1396 	         (void) SCIPsnprintf(assignment, FZN_BUFFERLEN, "%s[%d]", name, idx);
1397 	      }
1398 	      else
1399 	      {
1400 	         (void) SCIPsnprintf(assignment, FZN_BUFFERLEN, "%s", name);
1401 	
1402 	         /* push the current token back for latter evaluations */
1403 	         pushToken(fzninput);
1404 	      }
1405 	   }
1406 	   else
1407 	      (void) SCIPsnprintf(assignment, FZN_BUFFERLEN, "%s", fzninput->token);
1408 	}
1409 	
1410 	/** computes w.r.t. to the given side value and relation the left and right side for a SCIP linear constraint */
1411 	static
1412 	void computeLinearConsSides(
1413 	   SCIP*                 scip,               /**< SCIP data structure */
1414 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1415 	   const char*           name,               /**< name of the relation */
1416 	   SCIP_Real             sidevalue,          /**< parsed side value */
1417 	   SCIP_Real*            lhs,                /**< pointer to left hand side */
1418 	   SCIP_Real*            rhs                 /**< pointer to right hand side */
1419 	   )
1420 	{
1421 	   SCIPdebugMsg(scip, "check relation <%s>\n", name);
1422 	
1423 	   /* compute left and right hand side of the linear constraint */
1424 	   if( equalTokens(name, "eq") )
1425 	   {
1426 	      *lhs = sidevalue;
1427 	      *rhs = sidevalue;
1428 	   }
1429 	   else if( equalTokens(name, "ge") )
1430 	   {
1431 	      *lhs = sidevalue;
1432 	   }
1433 	   else if( equalTokens(name, "le") )
1434 	   {
1435 	      *rhs = sidevalue;
1436 	   }
1437 	   else if( equalTokens(name, "gt") )
1438 	   {
1439 	      /* greater than only works if there are not continuous variables are involved */
1440 	      *lhs = sidevalue + 1.0;
1441 	   }
1442 	   else if( equalTokens(name, "lt") )
1443 	   {
1444 	      /* less than only works if there are not continuous variables are involved */
1445 	      *rhs = sidevalue - 1.0;
1446 	   }
1447 	   else
1448 	      syntaxError(scip, fzninput, "unknown relation in constraint identifier name");
1449 	
1450 	   SCIPdebugMsg(scip, "lhs = %g, rhs = %g\n", *lhs, *rhs);
1451 	}
1452 	
1453 	/** parse a list of elements which is separates by a comma */
1454 	static
1455 	SCIP_RETCODE parseList(
1456 	   SCIP*                 scip,               /**< SCIP data structure */
1457 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1458 	   char***               elements,           /**< pointer to char* array for storing the elements of the list */
1459 	   int*                  nelements,          /**< pointer to store the number of elements */
1460 	   int                   selements           /**< size of the elements char* array */
1461 	   )
1462 	{
1463 	   char assignment[FZN_BUFFERLEN];
1464 	   assert(selements > 0);
1465 	
1466 	   /* check if the list is not empty */
1467 	   if( getNextToken(scip, fzninput) && !isChar(fzninput->token, ']') )
1468 	   {
1469 	      /* push back token */
1470 	      pushToken(fzninput);
1471 	
1472 	      /* loop through the array */
1473 	      do
1474 	      {
1475 	         if(selements == *nelements)
1476 	         {
1477 	            selements *= 2;
1478 	            SCIP_CALL( SCIPreallocBufferArray(scip, elements, selements) );
1479 	         }
1480 	
1481 	         /* parse and flatten assignment */
1482 	         flattenAssignment(scip, fzninput, assignment);
1483 	
1484 	         if( hasError(fzninput) )
1485 	            break;
1486 	
1487 	         /* store assignment */
1488 	         SCIP_CALL( SCIPduplicateBufferArray(scip, &(*elements)[(*nelements)], assignment, (int) strlen(assignment) + 1) ); /*lint !e866*/
1489 	
1490 	         (*nelements)++;
1491 	      }
1492 	      while( getNextToken(scip, fzninput) && isChar(fzninput->token, ',') );
1493 	   }
1494 	   else
1495 	   {
1496 	      SCIPdebugMsg(scip, "list is empty\n");
1497 	   }
1498 	
1499 	   /* push back ']' which closes the list */
1500 	   pushToken(fzninput);
1501 	
1502 	   return SCIP_OKAY;
1503 	}
1504 	
1505 	/** parse range expression */
1506 	static
1507 	void parseRange(
1508 	   SCIP*                 scip,               /**< SCIP data structure */
1509 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1510 	   FZNNUMBERTYPE*        type,               /**< pointer to store the number type */
1511 	   SCIP_Real*            lb,                 /**< pointer to store the lower bound */
1512 	   SCIP_Real*            ub                  /**< pointer to store the upper bound */
1513 	   )
1514 	{
1515 	   if( !getNextToken(scip, fzninput) )
1516 	   {
1517 	      syntaxError(scip, fzninput, "expected left side of range");
1518 	      return;
1519 	   }
1520 	
1521 	   /* current token should be the lower bound */
1522 	   if( !isValue(fzninput->token, lb) )
1523 	   {
1524 	      syntaxError(scip, fzninput, "expected lower bound value");
1525 	      return;
1526 	   }
1527 	
1528 	   /* check if we have a float notation or an integer notation which defines the type of the variable */
1529 	   if( fzninput->hasdot || !SCIPisIntegral(scip, *lb) )
1530 	      *type = FZN_FLOAT;
1531 	   else
1532 	      *type = FZN_INT;
1533 	
1534 	   /* parse next token which should be <..> */
1535 	   if( !getNextToken(scip, fzninput) || !equalTokens(fzninput->token, "..") )
1536 	   {
1537 	      syntaxError(scip, fzninput, "expected <..>");
1538 	      return;
1539 	   }
1540 	
1541 	   /* parse upper bound */
1542 	   if( !getNextToken(scip, fzninput) || !isValue(fzninput->token, ub) )
1543 	   {
1544 	      syntaxError(scip, fzninput, "expected upper bound value");
1545 	      return;
1546 	   }
1547 	
1548 	   /* check if upper bound notation fits which lower bound notation */
1549 	   if( fzninput->hasdot != (*type == FZN_FLOAT) )
1550 	   {
1551 	      SCIPwarningMessage(scip, "lower bound and upper bound mismatch in value type, assume %s variable type\n",
1552 	         fzninput->hasdot ? "an integer" : "a continuous");
1553 	   }
1554 	}
1555 	
1556 	/** parse dimension information */
1557 	static
1558 	SCIP_RETCODE parseOutputDimensioninfo(
1559 	   SCIP*                 scip,               /**< SCIP data structure */
1560 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1561 	   DIMENSIONS**          info                /**< pointer to store the output dimension information if one */
1562 	   )
1563 	{
1564 	   FZNNUMBERTYPE type;
1565 	   SCIP_Real lb;
1566 	   SCIP_Real ub;
1567 	   int nelements;
1568 	   int size;
1569 	
1570 	   nelements = 0;
1571 	   size = 100;
1572 	
1573 	   SCIP_CALL( SCIPallocBlockMemory(scip, info) );
1574 	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*info)->lbs, size) );
1575 	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*info)->ubs, size) );
1576 	   (*info)->size = size;
1577 	
1578 	   /* check for bracket */
1579 	   if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '(') )
1580 	   {
1581 	      syntaxError(scip, fzninput, "expecting  <(> after <output_array>");
1582 	      return SCIP_OKAY;
1583 	   }
1584 	
1585 	   while( getNextToken(scip, fzninput) && !isChar(fzninput->token, ']') )
1586 	   {
1587 	      parseRange(scip, fzninput, &type, &lb, &ub);
1588 	
1589 	      if( fzninput->haserror )
1590 	         return SCIP_OKAY;
1591 	
1592 	      assert(type == FZN_INT);
1593 	
1594 	      if( nelements == size )
1595 	      {
1596 	         size *= 2;
1597 	         SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(*info)->lbs, (*info)->size, size) );
1598 	         SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(*info)->ubs, (*info)->size, size) );
1599 	         (*info)->size = size;
1600 	      }
1601 	
1602 	      /* we assume integer bounds */
1603 	      (*info)->lbs[nelements] = (int) lb;
1604 	      (*info)->ubs[nelements] = (int) ub;
1605 	      nelements++;
1606 	   }
1607 	
1608 	   (*info)->ndims = nelements;
1609 	
1610 	   /* check for colon */
1611 	   if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, ')') )
1612 	      syntaxError(scip, fzninput, "expecting  <)>");
1613 	
1614 	   return SCIP_OKAY;
1615 	}
1616 	
1617 	/** parse identifier name without annotations */
1618 	static
1619 	SCIP_RETCODE parseName(
1620 	   SCIP*                 scip,               /**< SCIP data structure */
1621 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1622 	   char*                 name,               /**< pointer to store the name */
1623 	   SCIP_Bool*            output,             /**< pointer to store if the name has the annotations to output */
1624 	   DIMENSIONS**          info                /**< pointer to store the output dimension information if one */
1625 	   )
1626 	{
1627 	   if( output != NULL )
1628 	      (*output) = FALSE;
1629 	
1630 	   /* check for colon */
1631 	   if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, ':') )
1632 	   {
1633 	      syntaxError(scip, fzninput, "expecting colon <:>");
1634 	      return SCIP_OKAY;
1635 	   }
1636 	
1637 	   /* parse identifier name */
1638 	   if( !getNextToken(scip, fzninput) || !isIdentifier(fzninput->token) )
1639 	   {
1640 	      syntaxError(scip, fzninput, "expecting identifier name");
1641 	      return SCIP_OKAY;
1642 	   }
1643 	
1644 	   /* copy identifier name */
1645 	   (void)SCIPsnprintf(name, FZN_BUFFERLEN-1, "%s", (const char*)fzninput->token);
1646 	
1647 	   /* search for an assignment; therefore, skip annotations */
1648 	   do
1649 	   {
1650 	      if( !getNextToken(scip, fzninput) )
1651 	      {
1652 	         syntaxError(scip, fzninput, "expected at least a semicolon to close statement");
1653 	         return SCIP_OKAY;
1654 	      }
1655 	
1656 	      /* check if the name has the annotation to be part of the output */
1657 	      if( equalTokens(fzninput->token, "output_var") && output != NULL )
1658 	         (*output) = TRUE;
1659 	      else if( equalTokens(fzninput->token, "output_array") && output != NULL)
1660 	      {
1661 	         (*output) = TRUE;
1662 	         assert(info != NULL);
1663 	         SCIP_CALL( parseOutputDimensioninfo(scip, fzninput, info) );
1664 	      }
1665 	
1666 	      if( isEndStatement(fzninput) )
1667 	         break;
1668 	   }
1669 	   while( !isChar(fzninput->token, '=') );
1670 	
1671 	   /* push back '=' or ';' */
1672 	   pushToken(fzninput);
1673 	
1674 	   return SCIP_OKAY;
1675 	}
1676 	
1677 	/** parse variable/constant (array) type (integer, float, bool, or set) */
1678 	static
1679 	void parseType(
1680 	   SCIP*                 scip,               /**< SCIP data structure */
1681 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1682 	   FZNNUMBERTYPE*        type,               /**< pointer to store the number type */
1683 	   SCIP_Real*            lb,                 /**< pointer to store the lower bound */
1684 	   SCIP_Real*            ub                  /**< pointer to store the lower bound */
1685 	   )
1686 	{
1687 	   if( !getNextToken(scip, fzninput) || isEndStatement(fzninput) )
1688 	   {
1689 	      syntaxError(scip, fzninput, "missing token");
1690 	      return;
1691 	   }
1692 	
1693 	   *lb = -SCIPinfinity(scip);
1694 	   *ub = SCIPinfinity(scip);
1695 	
1696 	   /* parse variable type or bounds */
1697 	   if( equalTokens(fzninput->token, "bool") )
1698 	   {
1699 	      *type = FZN_BOOL;
1700 	      *lb = 0.0;
1701 	      *ub = 1.0;
1702 	   }
1703 	   else if( equalTokens(fzninput->token, "float") )
1704 	      *type = FZN_FLOAT;
1705 	   else if( equalTokens(fzninput->token, "int") )
1706 	      *type = FZN_INT;
1707 	   else if( equalTokens(fzninput->token, "set") || isChar(fzninput->token, '{') )
1708 	   {
1709 	      SCIPwarningMessage(scip, "sets are not supported yet\n");
1710 	      fzninput->valid = FALSE;
1711 	      return;
1712 	   }
1713 	   else
1714 	   {
1715 	      /* the type is not explicitly given; it is given through the a range
1716 	       * expression; therefore, push back the current token since it
1717 	       * belongs to the range expression */
1718 	      pushToken(fzninput);
1719 	      parseRange(scip, fzninput, type, lb, ub);
1720 	
1721 	      if( fzninput->haserror )
1722 	         return;
1723 	   }
1724 	
1725 	   SCIPdebugMsg(scip, "range =  [%g,%g]\n", *lb, *ub);
1726 	
1727 	   assert(*lb <= *ub);
1728 	}
1729 	
1730 	/** applies assignment */
1731 	static
1732 	SCIP_RETCODE applyVariableAssignment(
1733 	   SCIP*                 scip,               /**< SCIP data structure */
1734 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1735 	   SCIP_VAR*             var,                /**< variable to assign something */
1736 	   FZNNUMBERTYPE         type,               /**< number type */
1737 	   const char*           assignment          /**< assignment */
1738 	   )
1739 	{
1740 	   FZNCONSTANT* constant;
1741 	   SCIP_VAR* linkVar;
1742 	   SCIP_Bool boolvalue;
1743 	   SCIP_Real realvalue;
1744 	   SCIP_Real fixvalue;
1745 	   SCIP_Real vals[] = {1.0,-1.0};
1746 	
1747 	   linkVar = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) assignment);
1748 	   constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) assignment);
1749 	
1750 	   realvalue = SCIP_INVALID;
1751 	   boolvalue = FALSE;
1752 	
1753 	   if( linkVar == NULL )
1754 	   {
1755 	      if( isBoolExp(assignment, &boolvalue) && type == FZN_BOOL )
1756 	         fixvalue = (SCIP_Real) boolvalue;
1757 	      else if( isValue(assignment, &realvalue) && type != FZN_BOOL )
1758 	         fixvalue = realvalue;
1759 	      else if( constant != NULL )
1760 	         fixvalue = constant->value;
1761 	      else
1762 	      {
1763 	         syntaxError(scip, fzninput, "assignment is not recognizable");
1764 	         return SCIP_OKAY;
1765 	      }
1766 	
1767 	      /* create fixing constraint */
1768 	      SCIP_CALL( createLinearCons(scip, "fixing", 1, &var, vals, fixvalue, fixvalue, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
1769 	   }
1770 	   else
1771 	   {
1772 	      SCIP_VAR** vars;
1773 	
1774 	      SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
1775 	      vars[0] = var;
1776 	      vars[1] = linkVar;
1777 	
1778 	      SCIP_CALL( createLinearCons(scip, "link", 2, vars, vals, 0.0, 0.0, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
1779 	
1780 	      SCIPfreeBufferArray(scip, &vars);
1781 	   }
1782 	
1783 	   return SCIP_OKAY;
1784 	}
1785 	
1786 	/** applies constant assignment expression */
1787 	static
1788 	SCIP_RETCODE createConstantAssignment(
1789 	   SCIP*                 scip,               /**< SCIP data structure */
1790 	   FZNCONSTANT**         constant,           /**< pointer to constant */
1791 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1792 	   const char*           name,               /**< constant name */
1793 	   FZNNUMBERTYPE         type,               /**< number type */
1794 	   const char*           assignment          /**< assignment to apply */
1795 	   )
1796 	{
1797 	   SCIP_Bool boolvalue;
1798 	   SCIP_Real realvalue;
1799 	   SCIP_Real value;
1800 	
1801 	   (*constant) = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) assignment);
1802 	   realvalue = SCIP_INVALID;
1803 	   boolvalue = FALSE;
1804 	
1805 	   if( *constant != NULL )
1806 	   {
1807 	      /* check if the constant type fits */
1808 	      if( type != (*constant)->type )
1809 	      {
1810 	         syntaxError(scip, fzninput, "type error");
1811 	         return SCIP_OKAY;
1812 	      }
1813 	
1814 	      value = (*constant)->value;
1815 	   }
1816 	   else if( isBoolExp(assignment, &boolvalue) && type == FZN_BOOL )
1817 	   {
1818 	      value = (SCIP_Real) boolvalue;
1819 	   }
1820 	   else if( isValue(assignment, &realvalue) && type != FZN_BOOL )
1821 	   {
1822 	      value = realvalue;
1823 	   }
1824 	   else
1825 	   {
1826 	      syntaxError(scip, fzninput, "assignment is not recognizable");
1827 	      return SCIP_OKAY;
1828 	   }
1829 	
1830 	   /* get buffer memory for FZNCONSTANT struct */
1831 	   SCIP_CALL( SCIPallocBuffer(scip, constant) );
1832 	
1833 	   (*constant)->type = type;
1834 	   SCIP_CALL( SCIPduplicateBufferArray(scip, &(*constant)->name, name, (int) strlen(name) + 1) );
1835 	   (*constant)->value = value;
1836 	
1837 	   /* store constant */
1838 	   if( fzninput->sconstants == fzninput->nconstants )
1839 	   {
1840 	      assert(fzninput->sconstants > 0);
1841 	      fzninput->sconstants *= 2;
1842 	      SCIP_CALL( SCIPreallocBufferArray(scip, &fzninput->constants, fzninput->sconstants) );
1843 	   }
1844 	
1845 	   assert(fzninput->sconstants > fzninput->nconstants);
1846 	   fzninput->constants[fzninput->nconstants] = *constant;
1847 	   fzninput->nconstants++;
1848 	
1849 	   SCIP_CALL( SCIPhashtableInsert(fzninput->constantHashtable, (void*) (*constant)) );
1850 	
1851 	   return SCIP_OKAY;
1852 	}
1853 	
1854 	/** parse array type ( (i) variable or constant; (ii) integer, float, bool, or set) */
1855 	static
1856 	void parseArrayType(
1857 	   SCIP*                 scip,               /**< SCIP data structure */
1858 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1859 	   SCIP_Bool*            isvararray,         /**< pointer to store if it is a variable or constant array */
1860 	   FZNNUMBERTYPE*        type,               /**< pointer to store number type */
1861 	   SCIP_Real*            lb,                 /**< pointer to store the lower bound */
1862 	   SCIP_Real*            ub                  /**< pointer to store the lower bound */
1863 	   )
1864 	{
1865 	   if( !getNextToken(scip, fzninput) || !equalTokens(fzninput->token, "of") )
1866 	   {
1867 	      syntaxError(scip, fzninput, "expected keyword  <of>");
1868 	      return;
1869 	   }
1870 	
1871 	   if( !getNextToken(scip, fzninput) )
1872 	   {
1873 	      syntaxError(scip, fzninput, "expected more tokens");
1874 	      return;
1875 	   }
1876 	
1877 	   /* check if it is a variable or constant array */
1878 	   if( equalTokens(fzninput->token, "var") )
1879 	      *isvararray = TRUE;
1880 	   else
1881 	   {
1882 	      /* push token back since it belongs to the type declaration */
1883 	      pushToken(fzninput);
1884 	      *isvararray = FALSE;
1885 	   }
1886 	
1887 	   /* pares array type and range */
1888 	   parseType(scip, fzninput, type, lb, ub);
1889 	}
1890 	
1891 	/** parse an array assignment */
1892 	static
1893 	SCIP_RETCODE parseArrayAssignment(
1894 	   SCIP*                 scip,               /**< SCIP data structure */
1895 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1896 	   char***               elements,           /**< pointer to string array to store the parsed elements */
1897 	   int*                  nelements,          /**< pointer to store the number of parsed elements */
1898 	   int                   selements           /**< size of the string array elements */
1899 	   )
1900 	{
1901 	   assert(scip != NULL);
1902 	   assert(fzninput != NULL);
1903 	   assert(*nelements >= 0);
1904 	   assert(selements >= *nelements);
1905 	
1906 	   /* check for opening brackets */
1907 	   if( !getNextToken(scip, fzninput) ||  !isChar(fzninput->token, '[') )
1908 	   {
1909 	      syntaxError(scip, fzninput, "expected token <[>");
1910 	      return SCIP_OKAY;
1911 	   }
1912 	
1913 	   SCIP_CALL( parseList(scip, fzninput, elements, nelements, selements) );
1914 	
1915 	   if( hasError(fzninput) )
1916 	      return SCIP_OKAY;
1917 	
1918 	   /* check for closing brackets */
1919 	   if( !getNextToken(scip, fzninput) ||  !isChar(fzninput->token, ']') )
1920 	      syntaxError(scip, fzninput, "expected token <]>");
1921 	
1922 	   return SCIP_OKAY;
1923 	}
1924 	
1925 	/** parse array dimension */
1926 	static
1927 	void parseArrayDimension(
1928 	   SCIP*                 scip,               /**< SCIP data structure */
1929 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1930 	   int*                  nelements           /**< pointer to store the size of the array */
1931 	   )
1932 	{
1933 	   FZNNUMBERTYPE type;
1934 	   SCIP_Real left;
1935 	   SCIP_Real right;
1936 	
1937 	   if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '[') )
1938 	   {
1939 	      syntaxError(scip, fzninput, "expected token <[> for array dimension");
1940 	      return;
1941 	   }
1942 	
1943 	   /* get array dimension */
1944 	   parseRange(scip, fzninput, &type, &left, &right);
1945 	
1946 	   if( fzninput->haserror )
1947 	      return;
1948 	
1949 	   if( type != FZN_INT || left != 1.0  || right <= 0.0 )
1950 	   {
1951 	      syntaxError(scip, fzninput, "invalid array dimension format");
1952 	      return;
1953 	   }
1954 	
1955 	   *nelements = (int) right;
1956 	
1957 	   if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, ']') )
1958 	   {
1959 	      syntaxError(scip, fzninput, "expected token <]> for array dimension");
1960 	      return;
1961 	   }
1962 	}
1963 	
1964 	/** creates and adds a variable to SCIP and stores it for latter use  in fzninput structure */
1965 	static
1966 	SCIP_RETCODE createVariable(
1967 	   SCIP*                 scip,               /**< SCIP data structure */
1968 	   FZNINPUT*             fzninput,           /**< FZN reading data */
1969 	   SCIP_VAR**            var,                /**< pointer to hold the created variable, or NULL */
1970 	   const char*           name,               /**< name of the variable */
1971 	   SCIP_Real             lb,                 /**< lower bound of the variable */
1972 	   SCIP_Real             ub,                 /**< upper bound of the variable */
1973 	   FZNNUMBERTYPE         type                /**< number type */
1974 	   )
1975 	{
1976 	   SCIP_VAR* varcopy;
1977 	   SCIP_VARTYPE vartype;
1978 	
1979 	   assert(scip != NULL);
1980 	   assert(fzninput != NULL);
1981 	   assert(lb <= ub);
1982 	
1983 	   switch(type)
1984 	   {
1985 	   case FZN_BOOL:
1986 	      vartype = SCIP_VARTYPE_BINARY;
1987 	      break;
1988 	   case FZN_INT:
1989 	      vartype = SCIP_VARTYPE_INTEGER;
1990 	      break;
1991 	   case FZN_FLOAT:
1992 	      vartype = SCIP_VARTYPE_CONTINUOUS;
1993 	      break;
1994 	   default:
1995 	      syntaxError(scip, fzninput, "unknown variable type");
1996 	      return SCIP_OKAY;
1997 	   }
1998 	
1999 	   /* create variable */
2000 	   SCIP_CALL( SCIPcreateVar(scip, &varcopy, name, lb, ub, 0.0, vartype, !(fzninput->dynamiccols), fzninput->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
2001 	   SCIP_CALL( SCIPaddVar(scip, varcopy) );
2002 	
2003 	   SCIPdebugMsg(scip, "created variable\n");
2004 	   SCIPdebug( SCIP_CALL( SCIPprintVar(scip, varcopy, NULL) ) );
2005 	
2006 	   /* variable name should not exist before */
2007 	   assert(SCIPhashtableRetrieve(fzninput->varHashtable, varcopy) == NULL);
2008 	
2009 	   /* insert variable into the hashmap for later use in the constraint section */
2010 	   SCIP_CALL( SCIPhashtableInsert(fzninput->varHashtable, varcopy) );
2011 	
2012 	   /* copy variable pointer before releasing the variable to keep the pointer to the variable */
2013 	   if( var != NULL )
2014 	      *var = varcopy;
2015 	
2016 	   /* release variable */
2017 	   SCIP_CALL( SCIPreleaseVar(scip, &varcopy) );
2018 	
2019 	   return SCIP_OKAY;
2020 	}
2021 	
2022 	
2023 	/** parse variable array assignment and create the variables */
2024 	static
2025 	SCIP_RETCODE parseVariableArray(
2026 	   SCIP*                 scip,               /**< SCIP data structure */
2027 	   SCIP_READERDATA*      readerdata,         /**< reader data */
2028 	   FZNINPUT*             fzninput,           /**< FZN reading data */
2029 	   const char*           name,               /**< array name */
2030 	   int                   nvars,              /**< number of variables */
2031 	   FZNNUMBERTYPE         type,               /**< number type */
2032 	   SCIP_Real             lb,                 /**< lower bound of the variables */
2033 	   SCIP_Real             ub,                 /**< lower bound of the variables */
2034 	   DIMENSIONS*           info                /**< dimension information */
2035 	   )
2036 	{
2037 	   SCIP_VAR** vars;
2038 	   char varname[FZN_BUFFERLEN];
2039 	   int v;
2040 	
2041 	   /* create variables and add them to the problem */
2042 	   SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
2043 	
2044 	   for( v = 0; v < nvars; ++v )
2045 	   {
2046 	      (void) SCIPsnprintf(varname, FZN_BUFFERLEN, "%s[%d]", name, v + 1);
2047 	
2048 	      /* create variable */
2049 	      SCIP_CALL( createVariable(scip, fzninput, &vars[v], varname, lb, ub, type) );
2050 	   }
2051 	
2052 	   if( !getNextToken(scip, fzninput) )
2053 	   {
2054 	      syntaxError(scip, fzninput, "expected semicolon");
2055 	   }
2056 	   else
2057 	   {
2058 	      if( isChar(fzninput->token, '=') )
2059 	      {
2060 	         char** assigns;
2061 	         int nassigns;
2062 	
2063 	         SCIP_CALL( SCIPallocBufferArray(scip, &assigns, nvars) );
2064 	         nassigns = 0;
2065 	
2066 	         SCIP_CALL( parseArrayAssignment(scip, fzninput, &assigns, &nassigns, nvars) );
2067 	
2068 	         if(!hasError(fzninput) )
2069 	         {
2070 	            for( v = 0; v < nvars && !hasError(fzninput); ++v )
2071 	            {
2072 	               /* parse and apply assignment */
2073 	               SCIP_CALL( applyVariableAssignment(scip, fzninput, vars[v], type, assigns[v]) );
2074 	            }
2075 	         }
2076 	
2077 	         freeStringBufferArray(scip, assigns, nassigns);
2078 	      }
2079 	      else
2080 	      {
2081 	         /* push back the ';' */
2082 	         assert( isEndStatement(fzninput) );
2083 	         pushToken(fzninput);
2084 	      }
2085 	
2086 	      if( info != NULL )
2087 	      {
2088 	         SCIP_CALL( readerdataAddOutputvararray(scip, readerdata, name, vars, nvars, type, info) );
2089 	      }
2090 	
2091 	      /* add variable information to fzninput since this array name might be used later in the fzn file */
2092 	      SCIP_CALL( fzninputAddVararray(scip, fzninput, name, vars, nvars, type, info) );
2093 	   }
2094 	
2095 	   SCIPfreeBufferArray(scip, &vars);
2096 	
2097 	   return SCIP_OKAY;
2098 	}
2099 	
2100 	/** parse constant array assignment and create the constants */
2101 	static
2102 	SCIP_RETCODE parseConstantArray(
2103 	   SCIP*                 scip,               /**< SCIP data structure */
2104 	   FZNINPUT*             fzninput,           /**< FZN reading data */
2105 	   const char*           name,               /**< array name */
2106 	   int                   nconstants,         /**< number of constants */
2107 	   FZNNUMBERTYPE         type                /**< number type */
2108 	   )
2109 	{
2110 	   FZNCONSTANT** constants;
2111 	   char** assigns;
2112 	   char constantname[FZN_BUFFERLEN];
2113 	   int nassigns;
2114 	   int c;
2115 	
2116 	   if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '=') )
2117 	   {
2118 	      syntaxError(scip, fzninput, "expected token <=>");
2119 	      return SCIP_OKAY;
2120 	   }
2121 	
2122 	   SCIP_CALL( SCIPallocBufferArray(scip, &assigns, nconstants) );
2123 	   SCIP_CALL( SCIPallocBufferArray(scip, &constants, nconstants) );
2124 	   nassigns = 0;
2125 	
2126 	   SCIP_CALL( parseArrayAssignment(scip, fzninput, &assigns, &nassigns, nconstants) );
2127 	
2128 	   if( !hasError(fzninput) )
2129 	   {
2130 	      for( c = 0; c < nconstants; ++c )
2131 	      {
2132 	         (void) SCIPsnprintf(constantname, FZN_BUFFERLEN, "%s[%d]", name, c + 1);
2133 	         SCIP_CALL( createConstantAssignment(scip, &constants[c], fzninput, constantname, type, assigns[c]) );
2134 	      }
2135 	
2136 	      /* add variable information to fzninput since this array name might be used later in the fzn file */
2137 	      SCIP_CALL( fzninputAddConstarray(scip, fzninput, name, constants, nconstants, type) );
2138 	   }
2139 	
2140 	   SCIPfreeBufferArray(scip, &constants);
2141 	   freeStringBufferArray(scip, assigns, nassigns);
2142 	
2143 	   return SCIP_OKAY;
2144 	}
2145 	
2146 	/** parse predicate expression */
2147 	static
2148 	SCIP_RETCODE parsePredicate(
2149 	   SCIP*                 scip,               /**< SCIP data structure */
2150 	   FZNINPUT*             fzninput            /**< FZN reading data */
2151 	   )
2152 	{
2153 	   assert(scip != NULL);
2154 	
2155 	   /* mark predicate expression as comment such that it gets skipped */
2156 	   fzninput->comment = TRUE;
2157 	
2158 	   return SCIP_OKAY;
2159 	}
2160 	
2161 	/** parse array expression */
2162 	static
2163 	SCIP_RETCODE parseArray(
2164 	   SCIP*                 scip,               /**< SCIP data structure */
2165 	   SCIP_READERDATA*      readerdata,         /**< reader data */
2166 	   FZNINPUT*             fzninput            /**< FZN reading data */
2167 	   )
2168 	{
2169 	   FZNNUMBERTYPE type;
2170 	   DIMENSIONS* info;
2171 	   int nelements;
2172 	   SCIP_Real lb;
2173 	   SCIP_Real ub;
2174 	   SCIP_Bool isvararray;
2175 	   SCIP_Bool output;
2176 	   char name[FZN_BUFFERLEN];
2177 	
2178 	   assert(scip != NULL);
2179 	   assert(fzninput != NULL);
2180 	
2181 	   info = NULL;
2182 	   isvararray = FALSE;
2183 	   nelements = -1;
2184 	
2185 	   SCIPdebugMsg(scip, "parse array expression\n");
2186 	
2187 	   /* parse array dimension */
2188 	   parseArrayDimension(scip, fzninput, &nelements);
2189 	   assert(hasError(fzninput) || nelements > 0);
2190 	
2191 	   if( hasError(fzninput) )
2192 	      return SCIP_OKAY;
2193 	
2194 	   /* parse array type ( (i) variable or constant; (ii) integer, float, bool, or set) */
2195 	   parseArrayType(scip, fzninput, &isvararray, &type, &lb, &ub);
2196 	
2197 	   if( hasError(fzninput) )
2198 	      return SCIP_OKAY;
2199 	
2200 	   /* parse array name */
2201 	   SCIP_CALL( parseName(scip, fzninput, name, &output, &info) );
2202 	   assert(!output || info != NULL);
2203 	
2204 	   if( hasError(fzninput) )
2205 	      return SCIP_OKAY;
2206 	
2207 	   SCIPdebugMsg(scip, "found <%s> array named <%s> of type <%s> and size <%d> with bounds [%g,%g] (output %u)\n",
2208 	      isvararray ? "variable" : "constant", name,
2209 	      type == FZN_BOOL ? "bool" : type == FZN_INT ? "integer" : "float", nelements, lb, ub, output);
2210 	
2211 	   if( isvararray )
2212 	      SCIP_CALL( parseVariableArray(scip, readerdata, fzninput, name, nelements, type, lb, ub, info) );
2213 	   else
2214 	      SCIP_CALL( parseConstantArray(scip, fzninput, name, nelements, type) );
2215 	
2216 	   freeDimensions(scip, &info);
2217 	
2218 	   return SCIP_OKAY;
2219 	}
2220 	
2221 	/** parse variable expression */
2222 	static
2223 	SCIP_RETCODE parseVariable(
2224 	   SCIP*                 scip,               /**< SCIP data structure */
2225 	   SCIP_READERDATA*      readerdata,         /**< reader data */
2226 	   FZNINPUT*             fzninput            /**< FZN reading data */
2227 	   )
2228 	{
2229 	   SCIP_VAR* var;
2230 	   FZNNUMBERTYPE type;
2231 	   SCIP_Real lb;
2232 	   SCIP_Real ub;
2233 	   SCIP_Bool output;
2234 	   char assignment[FZN_BUFFERLEN];
2235 	   char name[FZN_BUFFERLEN];
2236 	
2237 	   assert(scip != NULL);
2238 	   assert(fzninput != NULL);
2239 	
2240 	   SCIPdebugMsg(scip, "parse variable expression\n");
2241 	
2242 	   /* pares variable type and range */
2243 	   parseType(scip, fzninput, &type, &lb, &ub);
2244 	
2245 	   if( hasError(fzninput) )
2246 	      return SCIP_OKAY;
2247 	
2248 	   /* parse variable name without annotations */
2249 	   SCIP_CALL( parseName(scip, fzninput, name, &output, NULL) );
2250 	
2251 	   if( hasError(fzninput) )
2252 	      return SCIP_OKAY;
2253 	
2254 	   assert(type == FZN_BOOL || type == FZN_INT || type == FZN_FLOAT);
2255 	
2256 	   /* create variable */
2257 	   SCIP_CALL( createVariable(scip, fzninput, &var, name, lb, ub, type) );
2258 	
2259 	   /* check if the variable should be part of the output */
2260 	   if( output )
2261 	   {
2262 	      SCIP_CALL( readerdataAddOutputvar(scip, readerdata, var, type) );
2263 	   }
2264 	
2265 	   if( !getNextToken(scip, fzninput) )
2266 	   {
2267 	      syntaxError(scip, fzninput, "expected semicolon");
2268 	      return SCIP_OKAY;
2269 	   }
2270 	
2271 	   if( isChar(fzninput->token, '=') )
2272 	   {
2273 	      /* parse and flatten assignment */
2274 	      flattenAssignment(scip, fzninput, assignment);
2275 	
2276 	      /* apply assignment */
2277 	      SCIP_CALL( applyVariableAssignment(scip, fzninput, var, type, assignment) );
2278 	   }
2279 	   else
2280 	      pushToken(fzninput);
2281 	
2282 	   return SCIP_OKAY;
2283 	}
2284 	
2285 	/** parse constant expression */
2286 	static
2287 	SCIP_RETCODE parseConstant(
2288 	   SCIP*                 scip,               /**< SCIP data structure */
2289 	   FZNINPUT*             fzninput,           /**< FZN reading data */
2290 	   FZNNUMBERTYPE         type                /**< constant type */
2291 	   )
2292 	{
2293 	   FZNCONSTANT* constant;
2294 	   char name[FZN_BUFFERLEN];
2295 	   char assignment[FZN_BUFFERLEN];
2296 	
2297 	   assert(scip != NULL);
2298 	   assert(fzninput != NULL);
2299 	   assert(type == FZN_INT || type == FZN_FLOAT || type == FZN_BOOL);
2300 	
2301 	   SCIPdebugMsg(scip, "parse constant expression\n");
2302 	
2303 	   /* parse name of the constant */
2304 	   SCIP_CALL( parseName(scip, fzninput, name, NULL, NULL) );
2305 	
2306 	   if( hasError(fzninput) )
2307 	      return SCIP_OKAY;
2308 	
2309 	   if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '=') )
2310 	   {
2311 	      syntaxError(scip, fzninput, "expected token <=>");
2312 	      return SCIP_OKAY;
2313 	   }
2314 	
2315 	   /* the assignment has to be an other constant or a suitable value */
2316 	   flattenAssignment(scip, fzninput, assignment);
2317 	
2318 	   /* applies constant assignment and creates constant */
2319 	   SCIP_CALL( createConstantAssignment(scip, &constant, fzninput, name, type, assignment) );
2320 	
2321 	   return SCIP_OKAY;
2322 	}
2323 	
2324 	/** evaluates current token as constant */
2325 	static
2326 	void parseValue(
2327 	   SCIP*                 scip,               /**< SCIP data structure */
2328 	   FZNINPUT*             fzninput,           /**< FZN reading data */
2329 	   SCIP_Real*            value,              /**< pointer to store value */
2330 	   const char*           assignment          /**< assignment to parse a value */
2331 	   )
2332 	{
2333 	   if( isValue(assignment, value) )
2334 	      return;
2335 	
2336 	   /* if it is an identifier name, it has to belong to a constant or fixed variable */
2337 	   if( isIdentifier(assignment) )
2338 	   {
2339 	      FZNCONSTANT* constant;
2340 	
2341 	      /* identifier has to be one of a constant */
2342 	      constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) assignment);
2343 	
2344 	      if( constant == NULL )
2345 	      {
2346 	         SCIP_VAR* var;
2347 	
2348 	         var = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) assignment);
2349 	
2350 	         if( var == NULL )
2351 	            syntaxError(scip, fzninput, "unknown constant name");
2352 	         else
2353 	         {
2354 	            if( SCIPisEQ(scip, SCIPvarGetLbOriginal(var), SCIPvarGetUbOriginal(var)) )
2355 	               (*value) = SCIPvarGetLbOriginal(var);
2356 	            else
2357 	               syntaxError(scip, fzninput, "expected fixed variable");
2358 	         }
2359 	      }
2360 	      else
2361 	         (*value) = constant->value;
2362 	   }
2363 	   else
2364 	      syntaxError(scip, fzninput, "expected constant expression");
2365 	}
2366 	
2367 	/** parse array expression containing constants */
2368 	static
2369 	SCIP_RETCODE parseConstantArrayAssignment(
2370 	   SCIP*                 scip,               /**< SCIP data structure */
2371 	   FZNINPUT*             fzninput,           /**< FZN reading data */
2372 	   SCIP_Real**           vals,               /**< pointer to value array */
2373 	   int*                  nvals,              /**< pointer to store the number if values */
2374 	   int                   sizevals            /**< size of the vals array */
2375 	   )
2376 	{
2377 	   int c;
2378 	
2379 	   assert(*nvals <= sizevals);
2380 	
2381 	   /* check for next token */
2382 	   if( !getNextToken(scip, fzninput) )
2383 	   {
2384 	      syntaxError(scip, fzninput, "expected constant array");
2385 	      return SCIP_OKAY;
2386 	   }
2387 	
2388 	   /* check if an array is given explicitly */
2389 	   if( isChar(fzninput->token, '[') )
2390 	   {
2391 	      char** elements;
2392 	      SCIP_Real value;
2393 	      int nelements;
2394 	
2395 	      SCIP_CALL( SCIPallocBufferArray(scip, &elements, sizevals) );
2396 	      nelements = 0;
2397 	
2398 	      value = 0.0;
2399 	
2400 	      /* push back '[' which closes the list */
2401 	      pushToken(fzninput);
2402 	
2403 	      /* pares array assignment */
2404 	      SCIP_CALL( parseArrayAssignment(scip, fzninput, &elements, &nelements, sizevals) );
2405 	
2406 	      if( sizevals <= *nvals + nelements )
2407 	      {
2408 	         SCIP_CALL( SCIPreallocBufferArray(scip, vals, *nvals + nelements) );
2409 	      }
2410 	
2411 	      for( c = 0; c < nelements && !hasError(fzninput); ++c )
2412 	      {
2413 	         parseValue(scip, fzninput, &value, elements[c]);
2414 	         assert(!hasError(fzninput));
2415 	
2416 	         (*vals)[(*nvals)] = value;
2417 	         (*nvals)++;
2418 	      }
2419 	
2420 	      freeStringBufferArray(scip, elements, nelements);
2421 	   }
2422 	   else
2423 	   {
2424 	      /* array is not given explicitly; therefore, check constant array data base if the given constant array name was
2425 	       * parsed before
2426 	       */
2427 	
2428 	      CONSTARRAY* constarray;
2429 	
2430 	      constarray = findConstarray(fzninput, fzninput->token);
2431 	
2432 	      if( constarray != NULL )
2433 	      {
2434 	         /* ensure variable array size */
2435 	         if( sizevals <= *nvals + constarray->nconstants )
2436 	         {
2437 	            SCIP_CALL( SCIPreallocBufferArray(scip, vals, *nvals + constarray->nconstants) );
2438 	         }
2439 	
2440 	         for( c = 0; c < constarray->nconstants; ++c )
2441 	         {
2442 	            (*vals)[(*nvals)] = constarray->constants[c]->value;
2443 	            (*nvals)++;
2444 	         }
2445 	      }
2446 	      else
2447 	      {
2448 	         /* there is no constant array with the given name; therefore check the variable array data base if such an
2449 	          * array exist with fixed variables
2450 	          */
2451 	
2452 	         VARARRAY* vararray;
2453 	
2454 	         vararray = findVararray(fzninput, fzninput->token);
2455 	
2456 	         if( vararray == NULL )
2457 	         {
2458 	            syntaxError(scip, fzninput, "unknown constants array name");
2459 	         }
2460 	         else
2461 	         {
2462 	            /* ensure variable array size */
2463 	            if( sizevals <= *nvals + vararray->nvars )
2464 	            {
2465 	               SCIP_CALL( SCIPreallocBufferArray(scip, vals, *nvals + vararray->nvars) );
2466 	            }
2467 	
2468 	            for( c = 0; c < vararray->nvars; ++c )
2469 	            {
2470 	               SCIP_VAR* var;
2471 	
2472 	               var = vararray->vars[c];
2473 	               assert(var != NULL);
2474 	
2475 	               if( SCIPisEQ(scip, SCIPvarGetLbOriginal(var), SCIPvarGetUbOriginal(var)) )
2476 	               {
2477 	                  (*vals)[(*nvals)] = SCIPvarGetLbOriginal(var);
2478 	                  (*nvals)++;
2479 	               }
2480 	               else
2481 	               {
2482 	                  syntaxError(scip, fzninput, "variable array contains unfixed variable");
2483 	                  break;
2484 	               }
2485 	            }
2486 	         }
2487 	      }
2488 	   }
2489 	
2490 	   return SCIP_OKAY;
2491 	}
2492 	
2493 	/** parse array expression containing variables */
2494 	static
2495 	SCIP_RETCODE parseVariableArrayAssignment(
2496 	   SCIP*                 scip,               /**< SCIP data structure */
2497 	   FZNINPUT*             fzninput,           /**< FZN reading data */
2498 	   SCIP_VAR***           vars,               /**< pointer to variable array */
2499 	   int*                  nvars,              /**< pointer to store the number if variable */
2500 	   int                   sizevars            /**< size of the variable array */
2501 	   )
2502 	{
2503 	   int v;
2504 	
2505 	   assert(*nvars <= sizevars);
2506 	
2507 	   /* check for next token */
2508 	   if( !getNextToken(scip, fzninput) )
2509 	   {
2510 	      syntaxError(scip, fzninput, "expected constant array");
2511 	      return SCIP_OKAY;
2512 	   }
2513 	
2514 	   if( isChar(fzninput->token, '[') )
2515 	   {
2516 	      char** elements;
2517 	      int nelements;
2518 	
2519 	      SCIP_CALL( SCIPallocBufferArray(scip, &elements, sizevars) );
2520 	      nelements = 0;
2521 	
2522 	      /* push back '[' which closes the list */
2523 	      pushToken(fzninput);
2524 	
2525 	      SCIP_CALL( parseArrayAssignment(scip, fzninput, &elements, &nelements, sizevars) );
2526 	
2527 	      if( sizevars <= *nvars + nelements )
2528 	      {
2529 	         SCIP_CALL( SCIPreallocBufferArray(scip, vars, *nvars + nelements) );
2530 	      }
2531 	
2532 	      for( v = 0; v < nelements; ++v )
2533 	      {
2534 	         (*vars)[(*nvars)] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, elements[v]);
2535 	
2536 	         if( (*vars)[(*nvars)] == NULL )
2537 	         {
2538 	            /* since the given element does not correspond to a variable name
2539 	             * it might be the case that it is a constant which can be seen as
2540 	             * as a fixed variable
2541 	             */
2542 	
2543 	            FZNCONSTANT* constant;
2544 	            SCIP_Real value;
2545 	
2546 	            constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) elements[v]);
2547 	
2548 	            if( constant != NULL )
2549 	            {
2550 	               assert(constant->type == FZN_FLOAT);
2551 	               value = constant->value;
2552 	            }
2553 	            else if(!isValue(elements[v], &value) )
2554 	            {
2555 	               char* tmptoken;
2556 	
2557 	               tmptoken = fzninput->token;
2558 	               fzninput->token = elements[v];
2559 	               syntaxError(scip, fzninput, "expected variable name or constant");
2560 	
2561 	               fzninput->token = tmptoken;
2562 	               break;
2563 	            }
2564 	
2565 	            /* create a fixed variable */
2566 	            SCIP_CALL( createVariable(scip, fzninput, &(*vars)[*nvars], elements[v], value, value, FZN_FLOAT) );
2567 	         }
2568 	
2569 	         (*nvars)++;
2570 	      }
2571 	
2572 	      freeStringBufferArray(scip, elements, nelements);
2573 	   }
2574 	   else
2575 	   {
2576 	      VARARRAY* vararray;
2577 	
2578 	      vararray = findVararray(fzninput, fzninput->token);
2579 	
2580 	      if( vararray != NULL )
2581 	      {
2582 	         assert(vararray != NULL);
2583 	
2584 	         /* ensure variable array size */
2585 	         if( sizevars <= *nvars + vararray->nvars )
2586 	         {
2587 	            SCIP_CALL( SCIPreallocBufferArray(scip, vars, *nvars + vararray->nvars) );
2588 	         }
2589 	
2590 	         for( v = 0; v < vararray->nvars; ++v )
2591 	         {
2592 	            (*vars)[(*nvars)] = vararray->vars[v];
2593 	            (*nvars)++;
2594 	         }
2595 	      }
2596 	      else
2597 	         syntaxError(scip, fzninput, "unknown variable array name");
2598 	   }
2599 	
2600 	   return SCIP_OKAY;
2601 	}
2602 	
2603 	/** parse linking statement */
2604 	static
2605 	SCIP_RETCODE parseQuadratic(
2606 	   SCIP*                 scip,               /**< SCIP data structure */
2607 	   FZNINPUT*             fzninput,           /**< FZN reading data */
2608 	   const char*           name                /**< name of constraint */
2609 	   )
2610 	{
2611 	   char** elements;
2612 	   int nelements;
2613 	
2614 	   SCIP_CALL( SCIPallocBufferArray(scip, &elements, 3) );
2615 	   nelements = 0;
2616 	
2617 	   /* parse the list of three elements */
2618 	   SCIP_CALL( parseList(scip, fzninput, &elements, &nelements, 3) );
2619 	   assert(nelements == 3);
2620 	
2621 	   if( !hasError(fzninput) )
2622 	   {
2623 	      SCIP_VAR** vars;
2624 	      SCIP_Real* vals;
2625 	      SCIP_Real rhs;
2626 	      int v;
2627 	
2628 	      rhs = 0.0;
2629 	
2630 	      SCIP_CALL( SCIPallocBufferArray(scip, &vars, 3) );
2631 	      SCIP_CALL( SCIPallocBufferArray(scip, &vals, 3) );
2632 	
2633 	      for( v = 0; v < 3; ++v )
2634 	      {
2635 	         /* collect variable if constraint identifier is a variable */
2636 	         vars[v] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[v]);
2637 	
2638 	         /* parse the numeric value otherwise */
2639 	         if( vars[v] == NULL )
2640 	         {
2641 	            parseValue(scip, fzninput, &vals[v], elements[v]);
2642 	            assert(!hasError(fzninput));
2643 	         }
2644 	         else
2645 	            vals[v] = SCIP_INVALID;
2646 	      }
2647 	
2648 	      /* the first two identifiers are proper variables => the constraints is indeed quadratic */
2649 	      if( vars[0] != NULL && vars[1] != NULL )
2650 	      {
2651 	         SCIP_Real quadval;
2652 	         quadval = 1.0;
2653 	
2654 	         /* we might have an additional linear term or just a constant */
2655 	         if( vars[2] != NULL )
2656 	         {
2657 	            SCIP_Real linval;
2658 	            linval = -1.0;
2659 	
2660 	            SCIP_CALL( createQuadraticCons(scip, name, 1, &vars[2], &linval, 1, &vars[0], &vars[1], &quadval, rhs, rhs,
2661 	                  fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
2662 	         }
2663 	         else
2664 	         {
2665 	            rhs += vals[2];
2666 	            SCIP_CALL( createQuadraticCons(scip, name, 0, NULL, NULL, 1, &vars[0], &vars[1], &quadval, rhs, rhs,
2667 	                  fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows));
2668 	         }
2669 	      }
2670 	      else if( vars[0] != NULL || vars[1] != NULL )
2671 	      {
2672 	         int nvars;
2673 	         nvars = 1;
2674 	
2675 	         /* the left hand side of x*y = z is linear (but not constant) */
2676 	         if( vars[0] == NULL )
2677 	            SCIPswapPointers((void**)&vars[0], (void**)&vars[1]);
2678 	         else
2679 	            SCIPswapPointers((void**)&vals[0], (void**)&vals[1]);
2680 	
2681 	         /* after swapping, the variable and the coefficient should stand in front */
2682 	         assert(vars[0] != NULL && vals[0] != SCIP_INVALID ); /*lint !e777*/
2683 	
2684 	         /* the right hand side might be a variable or a constant */
2685 	         if( vars[2] != NULL )
2686 	         {
2687 	            SCIPswapPointers((void**)&vars[1], (void**)&vars[2]);
2688 	            vals[1] = -1.0;
2689 	            nvars++;
2690 	         }
2691 	         else
2692 	         {
2693 	            assert(vals[2] != SCIP_INVALID); /*lint !e777*/
2694 	            rhs += vals[2];
2695 	         }
2696 	
2697 	         SCIP_CALL( createLinearCons(scip, name, nvars, vars, vals, rhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
2698 	      }
2699 	      else
2700 	      {
2701 	         /* the left hand side of x*y = z is constant */
2702 	         assert(vals[0] != SCIP_INVALID && vals[1] != SCIP_INVALID); /*lint !e777*/
2703 	
2704 	         rhs = rhs - vals[0]*vals[1];
2705 	
2706 	         /* the right hand side might be a variable or a constant */
2707 	         if( vars[2] != NULL )
2708 	         {
2709 	            SCIP_Real val;
2710 	            val = -1.0;
2711 	            SCIP_CALL( createLinearCons(scip, name, 1, &vars[2], &val, rhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
2712 	         }
2713 	         else
2714 	         {
2715 	            assert(vals[2] != SCIP_INVALID); /*lint !e777*/
2716 	            rhs += vals[2];
2717 	            SCIP_CALL( createLinearCons(scip, name, 0, NULL, NULL, rhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
2718 	         }
2719 	      }
2720 	
2721 	      /* free buffer arrays */
2722 	      SCIPfreeBufferArray(scip, &vals);
2723 	      SCIPfreeBufferArray(scip, &vars);
2724 	   }
2725 	
2726 	   /* free elements array */
2727 	   freeStringBufferArray(scip, elements, nelements);
2728 	
2729 	   return SCIP_OKAY;
2730 	}
2731 	
2732 	/** parse aggregation statement (plus, minus, negate) */
2733 	static
2734 	SCIP_RETCODE parseAggregation(
2735 	   SCIP*                 scip,               /**< SCIP data structure */
2736 	   FZNINPUT*             fzninput,           /**< FZN reading data */
2737 	   const char*           name,               /**< name of constraint */
2738 	   const char*           type                /**< linear constraint type */
2739 	   )
2740 	{
2741 	   /* here we take care of the three expression
2742 	    *
2743 	    * - int_plus(x1,x2,x3)   -> x1 + x2 == x3
2744 	    * - int_minus(x1,x2,x3)  -> x1 - x2 == x3
2745 	    * - int_negate(x1,x2)    -> x1 + x2 == 0
2746 	    */
2747 	   char** elements;
2748 	   int nelements;
2749 	
2750 	   SCIP_CALL( SCIPallocBufferArray(scip, &elements, 3) );
2751 	   nelements = 0;
2752 	
2753 	   /* parse the list of three elements */
2754 	   SCIP_CALL( parseList(scip, fzninput, &elements, &nelements, 3) );
2755 	   assert(nelements == 3 || nelements == 2);
2756 	
2757 	   if( !hasError(fzninput) )
2758 	   {
2759 	      SCIP_VAR** vars;
2760 	      SCIP_Real* vals;
2761 	      SCIP_Real value;
2762 	      SCIP_Real rhs;
2763 	      int nvars;
2764 	
2765 	      nvars = 0;
2766 	      rhs = 0.0;
2767 	
2768 	      SCIP_CALL( SCIPallocBufferArray(scip, &vars, 3) );
2769 	      SCIP_CALL( SCIPallocBufferArray(scip, &vals, 3) );
2770 	
2771 	      /* parse first element */
2772 	      vars[nvars] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[0]);
2773 	      if( vars[nvars] == NULL )
2774 	      {
2775 	         parseValue(scip, fzninput, &value, elements[0]);
2776 	         assert(!hasError(fzninput));
2777 	
2778 	         rhs -= value;
2779 	      }
2780 	      else
2781 	      {
2782 	         vals[nvars] = 1.0;
2783 	         nvars++;
2784 	      }
2785 	
2786 	      /* parse second element */
2787 	      vars[nvars] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[1]);
2788 	      if( vars[nvars] == NULL )
2789 	      {
2790 	         parseValue(scip, fzninput, &value, elements[1]);
2791 	         assert(!hasError(fzninput));
2792 	
2793 	         if( equalTokens(type, "minus") )
2794 	            rhs += value;
2795 	         else
2796 	            rhs -= value;
2797 	      }
2798 	      else
2799 	      {
2800 	         if( equalTokens(type, "minus") )
2801 	         {
2802 	            /* in case of minus the second element get a -1.0 as coefficient */
2803 	            vals[nvars] = -1.0;
2804 	         }
2805 	         else
2806 	            vals[nvars] = 1.0;
2807 	
2808 	         nvars++;
2809 	      }
2810 	
2811 	      if( !equalTokens(type, "negate") )
2812 	      {
2813 	         /* parse third element in case of "minus" or "plus" */
2814 	         vars[nvars] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[2]);
2815 	         if( vars[nvars] == NULL )
2816 	         {
2817 	            parseValue(scip, fzninput, &value, elements[2]);
2818 	            assert(!hasError(fzninput));
2819 	
2820 	            rhs += value;
2821 	         }
2822 	         else
2823 	         {
2824 	            vals[nvars] = -1.0;
2825 	            nvars++;
2826 	         }
2827 	      }
2828 	
2829 	      SCIP_CALL( createLinearCons(scip, name, nvars, vars, vals, rhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
2830 	
2831 	      /* free buffer arrays */
2832 	      SCIPfreeBufferArray(scip, &vals);
2833 	      SCIPfreeBufferArray(scip, &vars);
2834 	   }
2835 	
2836 	   /* free elements array */
2837 	   freeStringBufferArray(scip, elements, nelements);
2838 	   return SCIP_OKAY;
2839 	}
2840 	
2841 	/** parse linking statement */
2842 	static
2843 	SCIP_RETCODE parseLinking(
2844 	   SCIP*                 scip,               /**< SCIP data structure */
2845 	   FZNINPUT*             fzninput,           /**< FZN reading data */
2846 	   const char*           name,               /**< name of constraint */
2847 	   const char*           type,               /**< linear constraint type */
2848 	   SCIP_Real             sidevalue           /**< side value of constraint */
2849 	   )
2850 	{
2851 	   char** names;
2852 	   SCIP_Real lhs = SCIP_INVALID;
2853 	   SCIP_Real rhs = SCIP_INVALID;
2854 	   int nnames;
2855 	
2856 	   nnames = 0;
2857 	   SCIP_CALL( SCIPallocBufferArray(scip, &names, 2) );
2858 	
2859 	   SCIP_CALL( parseList(scip, fzninput, &names, &nnames, 2) );
2860 	   assert(nnames == 2);
2861 	
2862 	   if( hasError(fzninput) )
2863 	      goto TERMINATE;
2864 	
2865 	   /* compute left and right side */
2866 	   computeLinearConsSides(scip, fzninput, type, sidevalue, &lhs, &rhs);
2867 	
2868 	   if( hasError(fzninput) )
2869 	      goto TERMINATE;
2870 	
2871 	   SCIP_CALL( createLinking(scip, fzninput, name, names[0], names[1], lhs, rhs) );
2872 	
2873 	 TERMINATE:
2874 	   freeStringBufferArray(scip, names, nnames);
2875 	
2876 	   return SCIP_OKAY;
2877 	}
2878 	
2879 	/** creates a linear constraint for an array operation */
2880 	static
2881 	CREATE_CONSTRAINT(createCoercionOpCons)
2882 	{  /*lint --e{715}*/
2883 	   assert(scip != NULL);
2884 	   assert(fzninput != NULL);
2885 	
2886 	   /* check if the function identifier name is array operation */
2887 	   if( !equalTokens(fname, "int2float") && !equalTokens(fname, "bool2int") )
2888 	      return SCIP_OKAY;
2889 	
2890 	   SCIP_CALL( parseLinking(scip, fzninput, fname, "eq", 0.0) );
2891 	
2892 	   *created = TRUE;
2893 	
2894 	   return SCIP_OKAY;
2895 	}
2896 	
2897 	/** creates a linear constraint for an array operation */
2898 	static
2899 	CREATE_CONSTRAINT(createSetOpCons)
2900 	{  /*lint --e{715}*/
2901 	   assert(scip != NULL);
2902 	   assert(fzninput != NULL);
2903 	
2904 	   /* check if the function identifier name is array operation */
2905 	   if( !equalTokens(ftokens[0], "set") )
2906 	      return SCIP_OKAY;
2907 	
2908 	   fzninput->valid = FALSE;
2909 	   SCIPwarningMessage(scip, "Line %d: set operations are not supported yet.\n", fzninput->linenumber);
2910 	
2911 	   return SCIP_OKAY;
2912 	}
2913 	
2914 	/** creates linear constraint for an array operation */
2915 	static
2916 	CREATE_CONSTRAINT(createArrayOpCons)
2917 	{  /*lint --e{715}*/
2918 	   assert(scip != NULL);
2919 	   assert(fzninput != NULL);
2920 	
2921 	   /* check if the function identifier name is array operation */
2922 	   if( !equalTokens(ftokens[0], "array") )
2923 	      return SCIP_OKAY;
2924 	
2925 	   fzninput->valid = FALSE;
2926 	   SCIPwarningMessage(scip, "Line %d: array operations are not supported yet.\n", fzninput->linenumber);
2927 	
2928 	   return SCIP_OKAY;
2929 	}
2930 	
2931 	/** creates a linear constraint for a logical operation */
2932 	static
2933 	CREATE_CONSTRAINT(createLogicalOpCons)
2934 	{  /*lint --e{715}*/
2935 	   assert(scip != NULL);
2936 	   assert(fzninput != NULL);
2937 	
2938 	   /* check if the function identifier name is array operation */
2939 	   if(nftokens < 2)
2940 	      return SCIP_OKAY;
2941 	
2942 	   if(equalTokens(ftokens[0], "bool") && nftokens == 2 )
2943 	   {
2944 	      char** elements;
2945 	      int nelements;
2946 	
2947 	      /* the bool_eq constraint is processed in createComparisonOpCons() */
2948 	      if( equalTokens(ftokens[1], "eq") || equalTokens(ftokens[1], "ge") || equalTokens(ftokens[1], "le")
2949 	         || equalTokens(ftokens[1], "lt") || equalTokens(ftokens[1], "gt") )
2950 	         return SCIP_OKAY;
2951 	
2952 	      SCIP_CALL( SCIPallocBufferArray(scip, &elements, 3) );
2953 	      nelements = 0;
2954 	
2955 	      SCIP_CALL( parseList(scip, fzninput, &elements, &nelements, 3) );
2956 	
2957 	      if( !hasError(fzninput) )
2958 	      {
2959 	         SCIP_CONS* cons;
2960 	         SCIP_VAR** vars;
2961 	         int v;
2962 	         int nvars;
2963 	
2964 	         if( equalTokens(ftokens[1], "ne") || equalTokens(ftokens[1], "not") )
2965 	            nvars = 2;
2966 	         else
2967 	            nvars = 3;
2968 	
2969 	         SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
2970 	
2971 	         /* collect variable if constraint identifier is a variable */
2972 	         for( v = 0; v < nvars; ++v )
2973 	         {
2974 	            vars[v] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[v]);
2975 	
2976 	            if( vars[v] == NULL )
2977 	            {
2978 	               syntaxError(scip, fzninput, "unknown variable identifier name");
2979 	               goto TERMINATE;
2980 	            }
2981 	         }
2982 	
2983 	         if( equalTokens(ftokens[1], "ne" ) || equalTokens(ftokens[1], "not") )
2984 	         {
2985 	            SCIP_Real vals[] = {1.0, 1.0};
2986 	
2987 	            SCIP_CALL( SCIPcreateConsLinear(scip, &cons, fname, 2, vars, vals, 1.0, 1.0,
2988 	                  fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
2989 	
2990 	            *created = TRUE;
2991 	         }
2992 	         else if( equalTokens(ftokens[1], "or" ) )
2993 	         {
2994 	            SCIP_CALL( SCIPcreateConsOr(scip, &cons, fname, vars[2], 2, vars,
2995 	                  fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
2996 	
2997 	            *created = TRUE;
2998 	         }
2999 	         else if( equalTokens(ftokens[1], "and") )
3000 	         {
3001 	            SCIP_CALL( SCIPcreateConsAnd(scip, &cons, fname, vars[2], 2, vars,
3002 	                  fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
3003 	
3004 	            *created = TRUE;
3005 	         }
3006 	         else if( equalTokens(ftokens[1], "xor") )
3007 	         {
3008 	            /* swap resultant to front */
3009 	            SCIPswapPointers((void**)&vars[0], (void**)&vars[2]);
3010 	
3011 	            SCIP_CALL( SCIPcreateConsXor(scip, &cons, fname, FALSE, 3, vars,
3012 	                  fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
3013 	
3014 	            *created = TRUE;
3015 	         }
3016 	         else
3017 	         {
3018 	            fzninput->valid = FALSE;
3019 	            SCIPwarningMessage(scip, "logical operation <%s> is not supported yet\n", fname);
3020 	            goto TERMINATE;
3021 	         }
3022 	
3023 	         SCIPdebugPrintCons(scip, cons, NULL);
3024 	
3025 	         SCIP_CALL( SCIPaddCons(scip, cons) );
3026 	         SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3027 	
3028 	      TERMINATE:
3029 	         SCIPfreeBufferArray(scip, &vars);
3030 	      }
3031 	
3032 	      /* free elements array */
3033 	      freeStringBufferArray(scip, elements, nelements);
3034 	   }
3035 	   else if(equalTokens(ftokens[1], "bool") && nftokens == 3 )
3036 	   {
3037 	      SCIP_CONS* cons;
3038 	      SCIP_VAR** vars;
3039 	      SCIP_VAR* resvar;
3040 	      int nvars;
3041 	      char** elements;
3042 	      int nelements;
3043 	      int size;
3044 	
3045 	      if( !equalTokens(ftokens[2], "or" ) && !equalTokens(ftokens[2], "and" ) )
3046 	      {
3047 	         fzninput->valid = FALSE;
3048 	         SCIPwarningMessage(scip, "logical operation <%s> is not supported yet\n", fname);
3049 	         return SCIP_OKAY;
3050 	      }
3051 	
3052 	      size = 10;
3053 	      nvars = 0;
3054 	
3055 	      SCIP_CALL( SCIPallocBufferArray(scip, &vars, size) );
3056 	      SCIP_CALL( SCIPallocBufferArray(scip, &elements, 1) );
3057 	      nelements = 0;
3058 	
3059 	      SCIPdebugMsg(scip, "found and constraint <%s>\n", fname);
3060 	
3061 	      /* parse operand variable array */
3062 	      SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, size) );
3063 	
3064 	      /* check error and for the comma between the variable array and side value */
3065 	      if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
3066 	      {
3067 	         if( hasError(fzninput) )
3068 	            syntaxError(scip, fzninput, "unexpected error in fzn input");
3069 	         else
3070 	            syntaxError(scip, fzninput, "expected token <,>");
3071 	
3072 	         goto TERMINATE2;
3073 	      }
3074 	
3075 	      /* parse resultant variable array */
3076 	      SCIP_CALL( parseList(scip, fzninput, &elements, &nelements, 1) );
3077 	      resvar = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[0]);
3078 	
3079 	      /* check error and for the comma between the variable array and side value */
3080 	      if( hasError(fzninput) || resvar == NULL )
3081 	      {
3082 	         if( hasError(fzninput) )
3083 	            syntaxError(scip, fzninput, "unexpected error in fzn input");
3084 	         else
3085 	            syntaxError(scip, fzninput, "unknown variable identifier name");
3086 	         goto TERMINATE2;
3087 	      }
3088 	
3089 	      /* create the constraint */
3090 	      if( equalTokens(ftokens[2], "or" ) )
3091 	      {
3092 	         SCIP_CALL( SCIPcreateConsOr(scip, &cons, fname, resvar, nvars, vars,
3093 	               fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
3094 	      }
3095 	      else
3096 	      {
3097 	         assert( equalTokens(ftokens[2], "and") );
3098 	
3099 	         SCIP_CALL( SCIPcreateConsAnd(scip, &cons, fname, resvar, nvars, vars,
3100 	               fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
3101 	      }
3102 	
3103 	      SCIPdebugPrintCons(scip, cons, NULL);
3104 	      *created = TRUE;
3105 	
3106 	      SCIP_CALL( SCIPaddCons(scip, cons) );
3107 	      SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3108 	
3109 	   TERMINATE2:
3110 	      /* free elements array */
3111 	      freeStringBufferArray(scip, elements, nelements);
3112 	      SCIPfreeBufferArray(scip, &vars);
3113 	   }
3114 	   else if( equalTokens(ftokens[1], "bool") )
3115 	   {
3116 	      fzninput->valid = FALSE;
3117 	      SCIPwarningMessage(scip, "logical operation <%s> is not supported yet\n", fname);
3118 	      return SCIP_OKAY;
3119 	   }
3120 	
3121 	   return SCIP_OKAY;
3122 	}
3123 	
3124 	/** creates a linear constraint for a comparison operation */
3125 	static
3126 	CREATE_CONSTRAINT(createComparisonOpCons)
3127 	{  /*lint --e{715}*/
3128 	   char assignment[FZN_BUFFERLEN];
3129 	
3130 	   assert(scip != NULL);
3131 	   assert(fzninput != NULL);
3132 	
3133 	   /* check if the function name ends of "reif" (reified constraint) which SCIP does not support yet */
3134 	   if( equalTokens(ftokens[nftokens - 1], "reif") )
3135 	   {
3136 	      SCIPwarningMessage(scip, "Line %d: reified constraints are not supported.\n", fzninput->linenumber);
3137 	      fzninput->valid = FALSE;
3138 	      return SCIP_OKAY;
3139 	   }
3140 	
3141 	   /* the last token can be
3142 	    * 'eq' -- equal
3143 	    * 'ne' -- not equal
3144 	    * 'lt' -- less than
3145 	    * 'gt' -- greater than
3146 	    * 'le' -- less or equal than
3147 	    * 'ge' -- greater or equal than
3148 	    *         => these are comparison constraints
3149 	    * 'plus'   -- addition
3150 	    * 'minus'  -- subtraction
3151 	    * 'negate' -- negation
3152 	    *             => these are aggregation constraints
3153 	    * 'times' -- multiplication
3154 	    *            => this is a nonlinear constraint
3155 	    */
3156 	   if( strlen(ftokens[nftokens - 1]) != 2 && nftokens != 2 )
3157 	      return SCIP_OKAY;
3158 	
3159 	   /* check if any sets are involved in the constraint */
3160 	   if( equalTokens(ftokens[0], "set") )
3161 	   {
3162 	      SCIPwarningMessage(scip, "constraints using sets are not supported\n");
3163 	      fzninput->valid = FALSE;
3164 	      return SCIP_OKAY;
3165 	   }
3166 	
3167 	   /* check if the constraint is a 'not equal' one */
3168 	   if( equalTokens(ftokens[nftokens - 1], "ne") )
3169 	   {
3170 	      SCIPwarningMessage(scip, "constraints with 'not equal' relation are not supported\n");
3171 	      fzninput->valid = FALSE;
3172 	      return SCIP_OKAY;
3173 	   }
3174 	
3175 	   /* check if the constraint contains float variable and coefficients and '<' or '>' relation */
3176 	   if( equalTokens(ftokens[0], "float") &&
3177 	      (equalTokens(ftokens[nftokens - 1], "lt") || equalTokens(ftokens[nftokens - 1], "gt") ) )
3178 	   {
3179 	      SCIPwarningMessage(scip, "constraints with '<' or '>' relation and continuous variables are not supported\n");
3180 	      fzninput->valid = FALSE;
3181 	      return SCIP_OKAY;
3182 	   }
3183 	
3184 	   if( equalTokens(ftokens[1], "lin") )
3185 	   {
3186 	      SCIP_VAR** vars;
3187 	      SCIP_Real* vals;
3188 	      SCIP_Real sidevalue;
3189 	      int nvars;
3190 	      int nvals;
3191 	      int size;
3192 	
3193 	      assert(nftokens == 3);
3194 	
3195 	      size = 10;
3196 	      nvars = 0;
3197 	      nvals = 0;
3198 	      sidevalue = SCIP_INVALID;
3199 	
3200 	      SCIP_CALL( SCIPallocBufferArray(scip, &vars, size) );
3201 	      SCIP_CALL( SCIPallocBufferArray(scip, &vals, size) );
3202 	
3203 	      SCIPdebugMsg(scip, "found linear constraint <%s>\n", fname);
3204 	
3205 	      /* pares coefficients array */
3206 	      SCIP_CALL( parseConstantArrayAssignment(scip, fzninput, &vals, &nvals, size) );
3207 	
3208 	      /* check error and for the comma between the coefficient and variable array */
3209 	      if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
3210 	      {
3211 	         if( !hasError(fzninput) )
3212 	            syntaxError(scip, fzninput, "expected token <,>");
3213 	
3214 	         goto TERMINATE;
3215 	      }
3216 	
3217 	      /* pares variable array */
3218 	      SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, size) );
3219 	
3220 	      /* check error and for the comma between the variable array and side value */
3221 	      if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
3222 	      {
3223 	         if( !hasError(fzninput) )
3224 	            syntaxError(scip, fzninput, "expected token <,>");
3225 	
3226 	         goto TERMINATE;
3227 	      }
3228 	
3229 	      /* pares sidevalue */
3230 	      flattenAssignment(scip, fzninput, assignment);
3231 	      parseValue(scip, fzninput, &sidevalue, assignment);
3232 	
3233 	      if( !hasError(fzninput) )
3234 	      {
3235 	         SCIP_Real lhs = -SCIPinfinity(scip);
3236 	         SCIP_Real rhs = SCIPinfinity(scip);
3237 	
3238 	         assert(sidevalue != SCIP_INVALID); /*lint !e777*/
3239 	
3240 	         /* compute left and right side */
3241 	         computeLinearConsSides(scip, fzninput, ftokens[2], sidevalue, &lhs, &rhs);
3242 	
3243 	         if( hasError(fzninput) )
3244 	            goto TERMINATE;
3245 	
3246 	         SCIP_CALL( createLinearCons(scip, fname, nvars, vars, vals, lhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
3247 	      }
3248 	
3249 	   TERMINATE:
3250 	      SCIPfreeBufferArray(scip, &vals);
3251 	      SCIPfreeBufferArray(scip, &vars);
3252 	   }
3253 	   else if( equalTokens(ftokens[1], "minus") || equalTokens(ftokens[1], "plus") || equalTokens(ftokens[1], "negate") )
3254 	   {
3255 	      assert(nftokens == 2);
3256 	      SCIP_CALL( parseAggregation(scip, fzninput, fname, ftokens[1]) );
3257 	   }
3258 	   else if( equalTokens(ftokens[1], "eq") || equalTokens(ftokens[1], "le") || equalTokens(ftokens[1], "ge")
3259 	      || equalTokens(ftokens[1], "lt") || equalTokens(ftokens[1], "gt") )
3260 	   {
3261 	      assert(nftokens == 2);
3262 	      SCIP_CALL( parseLinking(scip, fzninput, fname, ftokens[1], 0.0) );
3263 	   }
3264 	   else if( equalTokens(ftokens[1], "times") )
3265 	   {
3266 	      assert(nftokens == 2);
3267 	      SCIP_CALL( parseQuadratic(scip, fzninput, fname) );
3268 	   }
3269 	   else
3270 	   {
3271 	      syntaxError(scip, fzninput, "unknown constraint type");
3272 	   }
3273 	
3274 	   *created = TRUE;
3275 	
3276 	   return SCIP_OKAY;
3277 	}
3278 	
3279 	/** creates an alldifferent constraint */
3280 	static
3281 	CREATE_CONSTRAINT(createAlldifferentOpCons)
3282 	{  /*lint --e{715}*/
3283 	   SCIP_VAR** vars;
3284 	#ifdef ALLDIFFERENT
3285 	   SCIP_CONS* cons;
3286 	#endif
3287 	   int nvars;
3288 	   int size;
3289 	
3290 	   assert(scip != NULL);
3291 	   assert(fzninput != NULL);
3292 	
3293 	   /* check if the function identifier name is array operation */
3294 	   if( !equalTokens(ftokens[0], "all") || !equalTokens(ftokens[1], "different") )
3295 	      return SCIP_OKAY;
3296 	
3297 	   size = 10;
3298 	   nvars = 0;
3299 	   SCIP_CALL( SCIPallocBufferArray(scip, &vars, size) );
3300 	
3301 	   SCIPdebugMsg(scip, "parse alldifferent expression\n");
3302 	
3303 	   /* pares variable array */
3304 	   SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, size) );
3305 	
3306 	#ifdef ALLDIFFERENT
3307 	   /* create alldifferent constraint */
3308 	   SCIP_CALL( SCIPcreateConsAlldifferent(scip, &cons, fname, nvars, vars,
3309 	         fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
3310 	
3311 	   SCIPdebugPrintCons(scip, cons, NULL);
3312 	
3313 	   /* add and release the constraint to the problem */
3314 	   SCIP_CALL( SCIPaddCons(scip, cons) );
3315 	   SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3316 	
3317 	   *created = TRUE;
3318 	#endif
3319 	
3320 	   SCIPfreeBufferArray(scip, &vars);
3321 	
3322 	   return SCIP_OKAY;
3323 	}
3324 	
3325 	/** creates an alldifferent constraint */
3326 	static
3327 	CREATE_CONSTRAINT(createCumulativeOpCons)
3328 	{  /*lint --e{715}*/
3329 	   SCIP_CONS* cons;
3330 	   SCIP_VAR** vars;
3331 	   SCIP_Real* vals = NULL;
3332 	   int* durations = NULL;
3333 	   int* demands = NULL;
3334 	   SCIP_Real val;
3335 	   int capacity;
3336 	   char assignment[FZN_BUFFERLEN];
3337 	
3338 	   int nvars;
3339 	   int ndurations;
3340 	   int ndemads;
3341 	   int size;
3342 	   int i;
3343 	
3344 	   assert(scip != NULL);
3345 	   assert(fzninput != NULL);
3346 	
3347 	   /* check if the function identifier name is array operation */
3348 	   if( !equalTokens(ftokens[0], "cumulative") )
3349 	      return SCIP_OKAY;
3350 	
3351 	   size = 10;
3352 	   nvars = 0;
3353 	   ndurations = 0;
3354 	   ndemads = 0;
3355 	
3356 	   SCIPdebugMsg(scip, "parse cumulative expression\n");
3357 	
3358 	   /* pares start time variable array */
3359 	   SCIP_CALL( SCIPallocBufferArray(scip, &vars, size) );
3360 	   SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, size) );
3361 	
3362 	   /* check error and for the comma between the variable array and side value */
3363 	   if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
3364 	   {
3365 	      if( !hasError(fzninput) )
3366 	         syntaxError(scip, fzninput, "expected token <,>");
3367 	
3368 	      goto TERMINATE;
3369 	   }
3370 	
3371 	   /* pares job duration array */
3372 	   SCIP_CALL( SCIPallocBufferArray(scip, &vals, size) );
3373 	   SCIP_CALL( parseConstantArrayAssignment(scip, fzninput, &vals, &ndurations, size) );
3374 	
3375 	   SCIP_CALL( SCIPallocBufferArray(scip, &durations, ndurations) );
3376 	   for( i = 0; i < ndurations; ++i )
3377 	      durations[i] = (int)vals[i];
3378 	
3379 	   /* check error and for the comma between the variable array and side value */
3380 	   if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
3381 	   {
3382 	      if( !hasError(fzninput) )
3383 	         syntaxError(scip, fzninput, "expected token <,>");
3384 	
3385 	      goto TERMINATE;
3386 	   }
3387 	
3388 	   /* pares job demand array */
3389 	   SCIP_CALL( parseConstantArrayAssignment(scip, fzninput, &vals, &ndemads, size) );
3390 	
3391 	   SCIP_CALL( SCIPallocBufferArray(scip, &demands, ndemads) );
3392 	   for( i = 0; i < ndemads; ++i )
3393 	      demands[i] = (int)vals[i];
3394 	
3395 	   /* check error and for the comma between the variable array and side value */
3396 	   if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
3397 	   {
3398 	      if( !hasError(fzninput) )
3399 	         syntaxError(scip, fzninput, "expected token <,>");
3400 	
3401 	      goto TERMINATE;
3402 	   }
3403 	
3404 	   /* parse cumulative capacity */
3405 	   flattenAssignment(scip, fzninput, assignment);
3406 	   parseValue(scip, fzninput, &val, assignment);
3407 	   assert(!hasError(fzninput));
3408 	
3409 	   capacity = (int)val;
3410 	
3411 	   assert(nvars == ndurations);
3412 	   assert(nvars == ndemads);
3413 	
3414 	   /* create cumulative constraint */
3415 	   SCIP_CALL( SCIPcreateConsCumulative(scip, &cons, fname, nvars, vars, durations, demands, capacity,
3416 	         fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
3417 	
3418 	   SCIPdebugPrintCons(scip, cons, NULL);
3419 	
3420 	   /* add and release the constraint to the problem */
3421 	   SCIP_CALL( SCIPaddCons(scip, cons) );
3422 	   SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3423 	
3424 	   assert(!hasError(fzninput));
3425 	   *created = TRUE;
3426 	
3427 	 TERMINATE:
3428 	   /* free buffers */
3429 	   SCIPfreeBufferArrayNull(scip, &demands);
3430 	   SCIPfreeBufferArrayNull(scip, &durations);
3431 	   SCIPfreeBufferArrayNull(scip, &vals);
3432 	   SCIPfreeBufferArray(scip, &vars);
3433 	
3434 	   return SCIP_OKAY;
3435 	}
3436 	
3437 	/* function pointer array containing all function which can create a constraint */
3438 	static CREATE_CONSTRAINT((*constypes[])) =  {
3439 	   createCoercionOpCons,
3440 	   createSetOpCons,
3441 	   createLogicalOpCons,
3442 	   createArrayOpCons,
3443 	   createComparisonOpCons,
3444 	   createAlldifferentOpCons,
3445 	   createCumulativeOpCons
3446 	};
3447 	
3448 	/** size of the function pointer array */
3449 	static const int nconstypes = 7;
3450 	
3451 	
3452 	/** parse constraint expression */
3453 	static
3454 	SCIP_RETCODE parseConstraint(
3455 	   SCIP*                 scip,               /**< SCIP data structure */
3456 	   FZNINPUT*             fzninput            /**< FZN reading data */
3457 	   )
3458 	{
3459 	   SCIP_VAR* var;
3460 	   char* tokens[4];
3461 	   char* token;
3462 	   char* nexttoken;
3463 	   char name[FZN_BUFFERLEN];
3464 	   char fname[FZN_BUFFERLEN];
3465 	   SCIP_Bool created;
3466 	   int ntokens;
3467 	   int i;
3468 	   int c;
3469 	
3470 	   assert(scip != NULL);
3471 	   assert(fzninput != NULL);
3472 	
3473 	   SCIPdebugMsg(scip, "parse constraint expression\n");
3474 	
3475 	   /* get next token already flatten */
3476 	   flattenAssignment(scip, fzninput, name);
3477 	
3478 	   /* check if constraint identifier is a variable */
3479 	   var = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) name);
3480 	
3481 	   if( var != NULL )
3482 	   {
3483 	      SCIP_Real vals[] = {1.0};
3484 	
3485 	      /* create fixing constraint */
3486 	      SCIP_CALL( createLinearCons(scip, "fixing", 1, &var, vals, 1.0, 1.0, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
3487 	      return SCIP_OKAY;
3488 	   }
3489 	
3490 	   /* check constraint identifier name */
3491 	   if( !isIdentifier(name) )
3492 	   {
3493 	      syntaxError(scip, fzninput, "expected constraint identifier name");
3494 	      return SCIP_OKAY;
3495 	   }
3496 	
3497 	   /* check if we have a opening parenthesis */
3498 	   if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '(') )
3499 	   {
3500 	      syntaxError(scip, fzninput, "expected token <(>");
3501 	      return SCIP_OKAY;
3502 	   }
3503 	
3504 	   /* copy function name */
3505 	   (void) SCIPsnprintf(fname, FZN_BUFFERLEN, "%s", name);
3506 	
3507 	   /* truncate the function identifier name in separate tokens */
3508 	   token = SCIPstrtok(name, "_", &nexttoken);
3509 	   ntokens = 0;
3510 	   while( token != NULL )
3511 	   {
3512 	      if( ntokens == 4 )
3513 	         break;
3514 	
3515 	      SCIP_CALL( SCIPduplicateBufferArray(scip, &(tokens[ntokens]), token, (int) strlen(token) + 1) ); /*lint !e866*/
3516 	      ntokens++;
3517 	
3518 	      token = SCIPstrtok(NULL, "_", &nexttoken);
3519 	   }
3520 	
3521 	   assert(token == NULL || tokens[0] != NULL); /*lint !e771*/
3522 	   for( i = 0; i < ntokens; ++i )
3523 	   {
3524 	      SCIPdebugMsgPrint(scip, "%s ", tokens[i]);
3525 	   }
3526 	   SCIPdebugMsgPrint(scip, "\n");
3527 	
3528 	   created = FALSE;
3529 	
3530 	   /* loop over all methods which can create a constraint */
3531 	   for( c = 0; c < nconstypes && !created && !hasError(fzninput); ++c )
3532 	   {
3533 	      SCIP_CALL( constypes[c](scip, fzninput, fname, tokens, ntokens, &created) );
3534 	   }
3535 	
3536 	   /* check if a constraint was created */
3537 	   if( !hasError(fzninput) && !created )
3538 	   {
3539 	      fzninput->valid = FALSE;
3540 	      SCIPwarningMessage(scip, "Line %d: Constraint <%s> is not supported yet.\n", fzninput->linenumber, fname);
3541 	   }
3542 	
3543 	   /* free memory */
3544 	   for( i = ntokens - 1; i >= 0 ; --i )
3545 	   {
3546 	      SCIPfreeBufferArray(scip, &tokens[i]);
3547 	   }
3548 	
3549 	   /* check for the closing parenthesis */
3550 	   if( !hasError(fzninput) && ( !getNextToken(scip, fzninput) || !isChar(fzninput->token, ')')) )
3551 	      syntaxError(scip, fzninput, "expected token <)>");
3552 	
3553 	   return SCIP_OKAY;
3554 	}
3555 	
3556 	/** parse solve item expression */
3557 	static
3558 	SCIP_RETCODE parseSolveItem(
3559 	   SCIP*                 scip,               /**< SCIP data structure */
3560 	   FZNINPUT*             fzninput            /**< FZN reading data */
3561 	   )
3562 	{
3563 	   assert(scip != NULL);
3564 	   assert(fzninput != NULL);
3565 	
3566 	   SCIPdebugMsg(scip, "parse solve item expression\n");
3567 	
3568 	   if( !getNextToken(scip, fzninput) )
3569 	   {
3570 	      syntaxError(scip, fzninput, "expected solving specification");
3571 	      return SCIP_OKAY;
3572 	   }
3573 	
3574 	   /* check for annotations */
3575 	   if( equalTokens(fzninput->token, "::") )
3576 	   {
3577 	      /* skip the annotation */
3578 	      do
3579 	      {
3580 	         if( !getNextToken(scip, fzninput) )
3581 	            syntaxError(scip, fzninput, "expected more tokens");
3582 	      }
3583 	      while( !equalTokens(fzninput->token, "satisfy")
3584 	         && !equalTokens(fzninput->token, "minimize")
3585 	         && !equalTokens(fzninput->token, "maximize") );
3586 	   }
3587 	
3588 	   if( equalTokens(fzninput->token, "satisfy") )
3589 	   {
3590 	      SCIPdebugMsg(scip, "detected a satisfiability problem\n");
3591 	   }
3592 	   else
3593 	   {
3594 	      SCIP_VAR* var;
3595 	      FZNCONSTANT* constant;
3596 	      char name[FZN_BUFFERLEN];
3597 	
3598 	      if( equalTokens(fzninput->token, "minimize") )
3599 	      {
3600 	         fzninput->objsense = SCIP_OBJSENSE_MINIMIZE;
3601 	         SCIPdebugMsg(scip, "detected a minimization problem\n");
3602 	      }
3603 	      else
3604 	      {
3605 	         assert(equalTokens(fzninput->token, "maximize"));
3606 	         fzninput->objsense = SCIP_OBJSENSE_MAXIMIZE;
3607 	         SCIPdebugMsg(scip, "detected a maximization problem\n");
3608 	      }
3609 	
3610 	      /* parse objective coefficients */
3611 	
3612 	      /* parse and flatten assignment */
3613 	      flattenAssignment(scip, fzninput, name);
3614 	
3615 	      var = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) name);
3616 	      constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) name);
3617 	
3618 	      if( var != NULL )
3619 	      {
3620 	         SCIP_CALL(SCIPchgVarObj(scip, var, 1.0) );
3621 	      }
3622 	      else if( constant != NULL )
3623 	      {
3624 	         SCIPdebugMsg(scip, "optimizing a constant is equal to a satisfiability problem!\n");
3625 	      }
3626 	      else if( equalTokens(name, "int_float_lin") )
3627 	      {
3628 	         SCIP_VAR** vars;
3629 	         SCIP_Real* vals;
3630 	         int nvars;
3631 	         int nvals;
3632 	         int size;
3633 	         int v;
3634 	
3635 	         nvars = 0;
3636 	         nvals = 0;
3637 	         size = 10;
3638 	
3639 	         SCIP_CALL( SCIPallocBufferArray(scip, &vars, size) );
3640 	         SCIP_CALL( SCIPallocBufferArray(scip, &vals, size) );
3641 	
3642 	         SCIPdebugMsg(scip, "found linear objective\n");
3643 	
3644 	         if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '(') )
3645 	         {
3646 	            syntaxError(scip, fzninput, "expected token <(>");
3647 	            goto TERMINATE;
3648 	         }
3649 	
3650 	         /* pares coefficients array for integer variables */
3651 	         SCIP_CALL( parseConstantArrayAssignment(scip, fzninput, &vals, &nvals, size) );
3652 	
3653 	         /* check error and for the comma between the coefficient and variable array */
3654 	         if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
3655 	         {
3656 	            if( !hasError(fzninput) )
3657 	               syntaxError(scip, fzninput, "expected token <,>");
3658 	
3659 	            goto TERMINATE;
3660 	         }
3661 	
3662 	         /* pares coefficients array for continuous variables */
3663 	         SCIP_CALL( parseConstantArrayAssignment(scip, fzninput, &vals, &nvals, MAX(size, nvals)) );
3664 	
3665 	         /* check error and for the comma between the coefficient and variable array */
3666 	         if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
3667 	         {
3668 	            if( !hasError(fzninput) )
3669 	               syntaxError(scip, fzninput, "expected token <,>");
3670 	
3671 	            goto TERMINATE;
3672 	         }
3673 	
3674 	         /* pares integer variable array */
3675 	         SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, size) );
3676 	
3677 	         /* check error and for the comma between the variable array and side value */
3678 	         if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
3679 	         {
3680 	            if( !hasError(fzninput) )
3681 	               syntaxError(scip, fzninput, "expected token <,>");
3682 	
3683 	            goto TERMINATE;
3684 	         }
3685 	
3686 	         assert(nvars <= nvals);
3687 	
3688 	         /* pares continuous variable array */
3689 	         SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, MAX(size, nvars)) );
3690 	
3691 	         /* check error and for the ')' */
3692 	         if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ')') )
3693 	         {
3694 	            if( !hasError(fzninput) )
3695 	               syntaxError(scip, fzninput, "expected token <)>");
3696 	
3697 	            goto TERMINATE;
3698 	         }
3699 	
3700 	         assert( nvars == nvals );
3701 	
3702 	         for( v = 0; v < nvars; ++v )
3703 	         {
3704 	            SCIP_CALL(SCIPchgVarObj(scip, vars[v], vals[v]) );
3705 	         }
3706 	
3707 	      TERMINATE:
3708 	         SCIPfreeBufferArray(scip, &vals);
3709 	         SCIPfreeBufferArray(scip, &vars);
3710 	      }
3711 	      else
3712 	      {
3713 	         syntaxError(scip, fzninput, "unknown identifier expression for a objective function");
3714 	      }
3715 	   }
3716 	
3717 	   return SCIP_OKAY;
3718 	}
3719 	
3720 	/** reads a FlatZinc model */
3721 	static
3722 	SCIP_RETCODE readFZNFile(
3723 	   SCIP*                 scip,               /**< SCIP data structure */
3724 	   SCIP_READERDATA*      readerdata,         /**< reader data */
3725 	   FZNINPUT*             fzninput,           /**< FZN reading data */
3726 	   const char*           filename            /**< name of the input file */
3727 	   )
3728 	{
3729 	   assert(scip != NULL);
3730 	   assert(readerdata != NULL);
3731 	   assert(fzninput != NULL);
3732 	
3733 	   /* open file */
3734 	   fzninput->file = SCIPfopen(filename, "r");
3735 	   if( fzninput->file == NULL )
3736 	   {
3737 	      SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
3738 	      SCIPprintSysError(filename);
3739 	      return SCIP_NOFILE;
3740 	   }
3741 	
3742 	   /* create problem */
3743 	   SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
3744 	
3745 	   /* create two auxiliary variable for true and false values */
3746 	   SCIP_CALL( createVariable(scip, fzninput, NULL, "true", 1.0, 1.0, FZN_BOOL) );
3747 	   SCIP_CALL( createVariable(scip, fzninput, NULL, "false", 0.0, 0.0, FZN_BOOL) );
3748 	
3749 	   /* parse through statements one-by-one */
3750 	   while( !SCIPfeof( fzninput->file ) && !hasError(fzninput) )
3751 	   {
3752 	      /* read the first token (keyword) of a new statement */
3753 	      if( getNextToken(scip, fzninput) )
3754 	      {
3755 	         if( equalTokens(fzninput->token, "predicate") )
3756 	         {
3757 	            /* parse array expression containing constants or variables */
3758 	            SCIP_CALL( parsePredicate(scip, fzninput) );
3759 	         }
3760 	         else if( equalTokens(fzninput->token, "array") )
3761 	         {
3762 	            /* parse array expression containing constants or variables */
3763 	            SCIP_CALL( parseArray(scip, readerdata, fzninput) );
3764 	         }
3765 	         else if( equalTokens(fzninput->token, "constraint") )
3766 	         {
3767 	            /* parse a constraint */
3768 	            SCIP_CALL( parseConstraint(scip, fzninput) );
3769 	         }
3770 	         else if( equalTokens(fzninput->token, "int") )
3771 	         {
3772 	            /* parse an integer constant */
3773 	            SCIP_CALL( parseConstant(scip, fzninput, FZN_INT) );
3774 	         }
3775 	         else if( equalTokens(fzninput->token, "float") )
3776 	         {
3777 	            /* parse a float constant */
3778 	            SCIP_CALL( parseConstant(scip, fzninput, FZN_FLOAT) );
3779 	         }
3780 	         else if( equalTokens(fzninput->token, "bool") )
3781 	         {
3782 	            /* parse a bool constant */
3783 	            SCIP_CALL( parseConstant(scip, fzninput, FZN_BOOL) );
3784 	         }
3785 	         else if( equalTokens(fzninput->token, "set") )
3786 	         {
3787 	            /* deal with sets */
3788 	            SCIPwarningMessage(scip, "sets are not supported yet\n");
3789 	            fzninput->valid = FALSE;
3790 	            break;
3791 	         }
3792 	         else if( equalTokens(fzninput->token, "solve") )
3793 	         {
3794 	            /* parse solve item (objective sense and objective function) */
3795 	            SCIP_CALL( parseSolveItem(scip, fzninput) );
3796 	         }
3797 	         else if( equalTokens(fzninput->token, "var") )
3798 	         {
3799 	            /* parse variables */
3800 	            SCIP_CALL( parseVariable(scip, readerdata, fzninput) );
3801 	         }
3802 	         else if( equalTokens(fzninput->token, "output") )
3803 	         {
3804 	            /* the output section is the last section in the flatzinc model and can be skipped */
3805 	            SCIPdebugMsg(scip, "skip output section\n");
3806 	            break;
3807 	         }
3808 	         else
3809 	         {
3810 	            FZNNUMBERTYPE type;
3811 	            SCIP_Real lb;
3812 	            SCIP_Real ub;
3813 	
3814 	            /* check if the new statement starts with a range expression
3815 	             * which indicates a constant; therefore, push back the current token
3816 	             * since it belongs to the range expression */
3817 	            pushToken(fzninput);
3818 	
3819 	            /* parse range to detect constant type */
3820 	            parseRange(scip, fzninput, &type, &lb, &ub);
3821 	
3822 	            if( hasError(fzninput) )
3823 	               break;
3824 	
3825 	            /* parse the remaining constant statement */
3826 	            SCIP_CALL( parseConstant(scip, fzninput, type) );
3827 	
3828 	            if( hasError(fzninput) )
3829 	            {
3830 	               SCIPwarningMessage(scip, "unknown keyword <%s> skip statement\n", fzninput->token);
3831 	               SCIPABORT();
3832 	               return SCIP_OKAY;  /*lint !e527*/
3833 	            }
3834 	         }
3835 	
3836 	         if( hasError(fzninput) )
3837 	            break;
3838 	
3839 	         /* if the current statement got marked as comment continue with the next line */
3840 	         if( fzninput->comment )
3841 	            continue;
3842 	
3843 	         /* each statement should be closed with a semicolon */
3844 	         if( !getNextToken(scip, fzninput) )
3845 	            syntaxError(scip, fzninput, "expected semicolon");
3846 	
3847 	         /* check for annotations */
3848 	         if( equalTokens(fzninput->token, "::") )
3849 	         {
3850 	            /* skip the annotation */
3851 	            do
3852 	            {
3853 	               if( !getNextToken(scip, fzninput) )
3854 	                  syntaxError(scip, fzninput, "expected more tokens");
3855 	            }
3856 	            while( !isEndStatement(fzninput) );
3857 	         }
3858 	
3859 	         if( !isEndStatement(fzninput) )
3860 	            syntaxError(scip, fzninput, "expected semicolon");
3861 	      }
3862 	   }
3863 	
3864 	   /* close file */
3865 	   SCIPfclose(fzninput->file);
3866 	
3867 	   if( hasError(fzninput) )
3868 	   {
3869 	      SCIP_CALL( SCIPfreeProb(scip) );
3870 	
3871 	      /* create empty problem */
3872 	      SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
3873 	   }
3874 	   else
3875 	   {
3876 	      SCIP_CALL( SCIPsetObjsense(scip, fzninput->objsense) );
3877 	   }
3878 	
3879 	   return SCIP_OKAY;
3880 	}
3881 	
3882 	
3883 	/*
3884 	 * Local methods (for writing)
3885 	 */
3886 	
3887 	
3888 	/** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
3889 	static
3890 	SCIP_RETCODE getActiveVariables(
3891 	   SCIP*                 scip,               /**< SCIP data structure */
3892 	   SCIP_VAR**            vars,               /**< vars array to get active variables for */
3893 	   SCIP_Real*            scalars,            /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3894 	   int*                  nvars,              /**< pointer to number of variables and values in vars and vals array */
3895 	   SCIP_Real*            constant,           /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c  */
3896 	   SCIP_Bool             transformed         /**< transformed constraint? */
3897 	   )
3898 	{
3899 	   int requiredsize;                         /* number of active variables */
3900 	   int v;
3901 	
3902 	   assert( scip != NULL );
3903 	   assert( scalars != NULL );
3904 	   assert( nvars != NULL );
3905 	   assert( vars != NULL || *nvars == 0 );
3906 	   assert( constant != NULL );
3907 	
(1) Event cond_true: Condition "transformed", taking true branch.
3908 	   if( transformed )
3909 	   {
(2) Event deref_parm_in_call: Function "SCIPgetProbvarLinearSum" dereferences "vars". [details]
3910 	      SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) );
3911 	
3912 	      /* avoid overflow by reallocation */
3913 	      if( requiredsize > *nvars )
3914 	      {
3915 	         SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
3916 	         SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) );
3917 	
3918 	         SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) );
3919 	         assert( requiredsize <= *nvars );
3920 	      }
3921 	   }
3922 	   else
3923 	   {
3924 	      if( *nvars > 0 && (vars == NULL || scalars == NULL) ) /*lint !e774 !e845*/
3925 	      {
3926 	         SCIPerrorMessage("Null pointer"); /* should not happen */
3927 	         SCIPABORT();
3928 	         return SCIP_INVALIDDATA;  /*lint !e527*/
3929 	      }
3930 	
3931 	      for( v = 0; v < *nvars; ++v )
3932 	      {
3933 	         assert(vars != NULL);
3934 	         SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalars[v], constant) );
3935 	      }
3936 	   }
3937 	
3938 	   return SCIP_OKAY;
3939 	}
3940 	
3941 	/** ends the given line with '\\0' and prints it to the given file stream */
3942 	static
3943 	void writeBuffer(
3944 	   SCIP*                 scip,               /**< SCIP data structure */
3945 	   FILE*                 file,               /**< output file (or NULL for standard output) */
3946 	   char*                 buffer,             /**< line */
3947 	   int                   bufferpos           /**< number of characters in buffer */
3948 	   )
3949 	{
3950 	   assert( scip != NULL );
3951 	   assert( buffer != NULL );
3952 	
3953 	   if( bufferpos > 0 )
3954 	   {
3955 	      buffer[bufferpos] = '\0';
3956 	
3957 	      SCIPinfoMessage(scip, file, "%s", buffer);
3958 	   }
3959 	}
3960 	
3961 	/** appends extension to line and prints it to the give file stream if the line buffer get full */
3962 	static
3963 	SCIP_RETCODE appendBuffer(
3964 	   SCIP*                 scip,               /**< SCIP data structure */
3965 	   char**                buffer,             /**< buffer which should be extended */
3966 	   int*                  bufferlen,          /**< length of the buffer */
3967 	   int*                  bufferpos,          /**< current position in  the buffer */
3968 	   const char*           extension           /**< string to extend the line */
3969 	   )
3970 	{
3971 	   int newpos;
3972 	   int extlen;
3973 	
3974 	   assert( scip != NULL );
3975 	   assert( buffer != NULL );
3976 	   assert( bufferlen != NULL );
3977 	   assert( bufferpos != NULL );
3978 	   assert( extension != NULL );
3979 	
3980 	   /* avoid overflow by reallocation */
3981 	   extlen = (int)strlen(extension);
3982 	   newpos = (*bufferpos) + extlen;
3983 	   if( newpos >= (*bufferlen) )
3984 	   {
3985 	      *bufferlen = MAX( newpos, 2 * (*bufferlen) );
3986 	
3987 	      SCIP_CALL( SCIPreallocBufferArray(scip, buffer, (*bufferlen)));
3988 	   }
3989 	
3990 	   /* append extension to linebuffer (+1 because of '\0') */
3991 	   (void)SCIPstrncpy((*buffer) + (*bufferpos), extension, extlen + 1);
3992 	   *bufferpos = newpos;
3993 	
3994 	   return SCIP_OKAY;
3995 	}
3996 	
3997 	/* Writes a real value to a string with full precision, if fractional and adds a ".0" if integral */
3998 	static
3999 	void flattenFloat(
4000 	   SCIP*                 scip,               /**< SCIP data structure */
4001 	   SCIP_Real             val,                /**< value to flatten */
4002 	   char*                 buffer              /**< string buffer to print in */
4003 	   )
4004 	{
4005 	   if( SCIPisIntegral(scip, val) )
4006 	      (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.1f", SCIPround(scip, val));
4007 	   else
4008 	      (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%+.15g", val);
4009 	}
4010 	
4011 	/* print row in FZN format to file stream */
4012 	static
4013 	SCIP_RETCODE printRow(
4014 	   SCIP*                 scip,               /**< SCIP data structure */
4015 	   FZNOUTPUT*            fznoutput,          /**< output data structure containing the buffers to write to */
4016 	   const char*           type,               /**< row type ("eq", "le" or "ge") */
4017 	   SCIP_VAR**            vars,               /**< array of variables */
4018 	   SCIP_Real*            vals,               /**< array of values */
4019 	   int                   nvars,              /**< number of variables */
4020 	   SCIP_Real             rhs,                /**< right hand side */
4021 	   SCIP_Bool             hasfloats           /**< are there continuous variables or coefficients in the constraint? */
4022 	   )
4023 	{
4024 	   SCIP_VAR* var;                            /* some variable */
4025 	   int v;                                    /* variable counter */
4026 	   char buffer[FZN_BUFFERLEN];
4027 	   char buffy[FZN_BUFFERLEN];
4028 	
4029 	   assert( scip != NULL );
4030 	   assert( vars != NULL || nvars == 0 );
4031 	   assert( strcmp(type, "eq") == 0 || strcmp(type, "le") == 0 || strcmp(type, "ge") == 0 );
4032 	
4033 	   /* Add a constraint of type float_lin or int_lin, depending on whether there are continuous variables or coefficients */
4034 	   SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), "constraint ") );
4035 	   if( hasfloats )
4036 	      (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "float_lin_%s([", type);
4037 	   else
4038 	      (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "int_lin_%s([", type);
4039 	   SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
4040 	
4041 	   /* print all coefficients but the last one */
4042 	   for( v = 0; v < nvars-1; ++v )
4043 	   {
4044 	      if( hasfloats )
4045 	      {
4046 	         flattenFloat(scip, vals[v], buffy);
4047 	         (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s, ", buffy);
4048 	      }
4049 	      else
4050 	         (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.f, ", vals[v]);
4051 	      SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
4052 	   }
4053 	
4054 	   /* print last coefficient */
4055 	   if( nvars > 0 )
4056 	   {
4057 	      if( hasfloats )
4058 	      {
4059 	         flattenFloat(scip, vals[nvars-1], buffy);
4060 	         (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s", buffy);
4061 	      }
4062 	      else
4063 	         (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.f", vals[nvars-1]);
4064 	
4065 	      SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
4066 	   }
4067 	
4068 	   SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), "], [") );
4069 	
4070 	   /* print all variables but the last one */
4071 	   for( v = 0; v < nvars-1; ++v )
4072 	   {
4073 	      var = vars[v];  /*lint !e613*/
4074 	      assert( var != NULL );
4075 	
4076 	      if( hasfloats )
4077 	         (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s%s, ", SCIPvarGetName(var), SCIPvarGetProbindex(var) < fznoutput->ndiscretevars ? "_float" : "");
4078 	      else
4079 	         (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s, ", SCIPvarGetName(var) );
4080 	      SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
4081 	   }
4082 	
4083 	   /* print last variable */
4084 	   if( nvars > 0 )
4085 	   {
4086 	      assert(vars != NULL); /* for lint */
4087 	      if( hasfloats )
4088 	         (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s%s",SCIPvarGetName(vars[nvars-1]),
4089 	            SCIPvarGetProbindex(vars[nvars-1]) < fznoutput->ndiscretevars ? "_float" : "");  /*lint !e613*/
4090 	      else
4091 	         (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s", SCIPvarGetName(vars[nvars-1]));  /*lint !e613*/
4092 	
4093 	      SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos),buffer) );
4094 	   }
4095 	
4096 	   SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), "], ") );
4097 	
4098 	   /* print right hand side */
4099 	   if( SCIPisZero(scip, rhs) )
4100 	      rhs = 0.0;
4101 	
4102 	   if( hasfloats )
4103 	   {
4104 	      flattenFloat(scip, rhs, buffy);
4105 	      (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s);\n", buffy);
4106 	   }
4107 	   else
4108 	      (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.f);\n", rhs);
4109 	   SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos),buffer) );
4110 	
4111 	   return SCIP_OKAY;
4112 	}
4113 	
4114 	/** prints given linear constraint information in FZN format to file stream */
4115 	static
4116 	SCIP_RETCODE printLinearCons(
4117 	   SCIP*                 scip,               /**< SCIP data structure */
4118 	   FZNOUTPUT*            fznoutput,          /**< output data structure containing the buffers to write to */
4119 	   SCIP_VAR**            vars,               /**< array of variables */
4120 	   SCIP_Real*            vals,               /**< array of coefficients values (or NULL if all coefficient values are 1) */
4121 	   int                   nvars,              /**< number of variables */
4122 	   SCIP_Real             lhs,                /**< left hand side */
4123 	   SCIP_Real             rhs,                /**< right hand side */
4124 	   SCIP_Bool             transformed,        /**< transformed constraint? */
4125 	   SCIP_Bool             mayhavefloats       /**< may there be continuous variables in the constraint? */
4126 	   )
4127 	{
4128 	   SCIP_VAR** activevars;                    /* active problem variables of a constraint */
4129 	   SCIP_Real* activevals;                    /* coefficients in the active representation */
4130 	
4131 	   SCIP_Real activeconstant;                 /* offset (e.g., due to fixings) in the active representation */
4132 	   int nactivevars;                          /* number of active problem variables */
4133 	   int v;                                    /* variable counter */
4134 	
4135 	   char buffer[FZN_BUFFERLEN];
4136 	   SCIP_Bool hasfloats;
4137 	
4138 	   assert( scip != NULL );
4139 	   assert( vars != NULL || nvars == 0 );
4140 	   assert( fznoutput != NULL );
4141 	   assert( lhs <= rhs );
4142 	
(1) Event cond_true: Condition "-lhs >= scip->set->num_infinity", taking true branch.
(2) Event cond_false: Condition "rhs >= scip->set->num_infinity", taking false branch.
4143 	   if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
(3) Event if_end: End of if statement.
4144 	      return SCIP_OKAY;
4145 	
4146 	   /* duplicate variable and value array */
4147 	   nactivevars = nvars;
4148 	   hasfloats = FALSE;
(4) Event assign_zero: Assigning: "activevars" = "NULL".
Also see events: [var_deref_model]
4149 	   activevars = NULL;
4150 	   activeconstant = 0.0;
4151 	
(5) Event cond_false: Condition "vars != NULL", taking false branch.
4152 	   if( vars != NULL )
4153 	   {
4154 	      SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
(6) Event if_end: End of if statement.
4155 	   }
4156 	
(7) Event cond_true: Condition "vals != NULL", taking true branch.
4157 	   if( vals != NULL )
(8) Event cond_false: Condition "(activevals = BMSduplicateBufferMemoryArray_call(SCIPbuffer(scip), (void const *)vals, (size_t)(ptrdiff_t)nactivevars, 8UL /* sizeof (*activevals) */, "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-v800-rc07/scipoptsuite-8.0.0/scip/src/scip/reader_fzn.c", 4158)) == NULL", taking false branch.
(9) Event cond_false: Condition "(_restat_ = (((activevals = BMSduplicateBufferMemoryArray_call(SCIPbuffer(scip), (void const *)vals, (size_t)(ptrdiff_t)nactivevars, 8UL /* sizeof (*activevals) */, "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-v800-rc07/scipoptsuite-8.0.0/scip/src/scip/reader_fzn.c", 4158)) == NULL) ? SCIP_NOMEMORY : SCIP_OKAY)) != SCIP_OKAY", taking false branch.
(10) Event if_end: End of if statement.
(11) Event if_fallthrough: Falling through to end of if statement.
4158 	      SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
4159 	   else
4160 	   {
4161 	      SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
4162 	
4163 	      for( v = 0; v < nactivevars; ++v )
4164 	         activevals[v] = 1.0;
(12) Event if_end: End of if statement.
4165 	   }
4166 	
4167 	   /* retransform given variables to active variables */
(13) Event cond_true: Condition "nactivevars > 0", taking true branch.
4168 	   if( nactivevars > 0 )
4169 	   {
(14) Event var_deref_model: Passing null pointer "activevars" to "getActiveVariables", which dereferences it. [details]
Also see events: [assign_zero]
4170 	      SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
4171 	   }
4172 	
4173 	   /* If there may be continuous variables or coefficients in the constraint, scan for them */
4174 	   if( mayhavefloats )
4175 	   {
4176 	      /* fractional sides trigger a constraint to be of float type */
4177 	      if( !SCIPisInfinity(scip, -lhs) )
4178 	         hasfloats = hasfloats || !SCIPisIntegral(scip, lhs-activeconstant);
4179 	      if( !SCIPisInfinity(scip, rhs) )
4180 	         hasfloats = hasfloats || !SCIPisIntegral(scip, rhs-activeconstant);
4181 	
4182 	      /* any continuous variable or fractional variable coefficient triggers a constraint to be of float type */
4183 	      for( v = 0; v < nactivevars && !hasfloats; v++ )
4184 	      {
4185 	         SCIP_VAR* var;
4186 	
4187 	         assert(activevars != 0);
4188 	         var = activevars[v];
4189 	
4190 	         hasfloats = hasfloats || (SCIPvarGetType(var) != SCIP_VARTYPE_BINARY &&  SCIPvarGetType(var) != SCIP_VARTYPE_INTEGER);
4191 	         hasfloats = hasfloats || !SCIPisIntegral(scip, activevals[v]);
4192 	      }
4193 	
4194 	      /* If the constraint has to be written as float type, all discrete variables need to have a float counterpart */
4195 	      if( hasfloats )
4196 	      {
4197 	         for( v = 0; v < nactivevars; v++ )
4198 	         {
4199 	            SCIP_VAR* var;
4200 	            int idx;
4201 	
4202 	            assert(activevars != 0);
4203 	            var = activevars[v];
4204 	            idx = SCIPvarGetProbindex(var);
4205 	            assert( idx >= 0);
4206 	
4207 	            /* If there was no float representation of the variable before, add an auxiliary variable and a conversion constraint */
4208 	            if( idx < fznoutput->ndiscretevars && !fznoutput->varhasfloat[idx] )
4209 	            {
4210 	               assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY || SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
4211 	
4212 	               (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "var float: %s_float;\n", SCIPvarGetName(var));
4213 	               SCIP_CALL( appendBuffer(scip, &(fznoutput->varbuffer), &(fznoutput->varbufferlen), &(fznoutput->varbufferpos),buffer) );
4214 	
4215 	               (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "constraint int2float(%s, %s_float);\n", SCIPvarGetName(var), SCIPvarGetName(var));
4216 	               SCIP_CALL( appendBuffer(scip, &(fznoutput->castbuffer), &(fznoutput->castbufferlen), &(fznoutput->castbufferpos),buffer) );
4217 	
4218 	               fznoutput->varhasfloat[idx] = TRUE;
4219 	            }
4220 	         }
4221 	      }
4222 	   }
4223 	
4224 	   if( SCIPisEQ(scip, lhs, rhs) )
4225 	   {
4226 	      assert( !SCIPisInfinity(scip, rhs) );
4227 	
4228 	      /* equality constraint */
4229 	      SCIP_CALL( printRow(scip, fznoutput, "eq", activevars, activevals, nactivevars, rhs - activeconstant, hasfloats) );
4230 	   }
4231 	   else
4232 	   {
4233 	      if( !SCIPisInfinity(scip, -lhs) )
4234 	      {
4235 	         /* print inequality ">=" */
4236 	         SCIP_CALL( printRow(scip, fznoutput, "ge", activevars, activevals, nactivevars, lhs - activeconstant, hasfloats) );
4237 	      }
4238 	
4239 	      if( !SCIPisInfinity(scip, rhs) )
4240 	      {
4241 	         /* print inequality "<=" */
4242 	         SCIP_CALL( printRow(scip, fznoutput, "le", activevars, activevals, nactivevars, rhs - activeconstant, hasfloats) );
4243 	      }
4244 	   }
4245 	
4246 	   /* free buffer arrays */
4247 	   if( activevars != NULL )
4248 	      SCIPfreeBufferArray(scip, &activevars);
4249 	   SCIPfreeBufferArray(scip, &activevals);
4250 	
4251 	   return SCIP_OKAY;
4252 	}
4253 	
4254 	/* writes problem to a flatzinc conform file, including introduction of several auxiliary variables and constraints */
4255 	static
4256 	SCIP_RETCODE writeFzn(
4257 	   SCIP*                 scip,               /**< SCIP data structure */
4258 	   FILE*                 file,               /**< output file, or NULL if standard output should be used */
4259 	   const char*           name,               /**< problem name */
4260 	   SCIP_Bool             transformed,        /**< TRUE iff problem is the transformed problem */
4261 	   SCIP_OBJSENSE         objsense,           /**< objective sense */
4262 	   SCIP_Real             objscale,           /**< scalar applied to objective function; external objective value is
4263 	                                              *   extobj = objsense * objscale * (intobj + objoffset) */
4264 	   SCIP_Real             objoffset,          /**< objective offset from bound shifting and fixing */
4265 	   SCIP_VAR**            vars,               /**< array with active variables ordered binary, integer, implicit, continuous */
4266 	   int                   nvars,              /**< number of active variables in the problem */
4267 	   int                   nbinvars,           /**< number of binary variables */
4268 	   int                   nintvars,           /**< number of general integer variables */
4269 	   int                   nimplvars,          /**< number of implicit integer variables */
4270 	   int                   ncontvars,          /**< number of continuous variables */
4271 	   SCIP_CONS**           conss,              /**< array with constraints of the problem */
4272 	   int                   nconss,             /**< number of constraints in the problem */
4273 	   SCIP_RESULT*          result              /**< pointer to store the result of the file writing call */
4274 	   )
4275 	{
4276 	   FZNOUTPUT fznoutput;                   /* data structure for writing in fzn format */
4277 	
4278 	   SCIP_CONSHDLR* conshdlr;
4279 	   SCIP_CONS* cons;
4280 	   const char* conshdlrname;
4281 	   SCIP_VAR** consvars;                   /* variables of a specific constraint */
4282 	   SCIP_VAR* var;
4283 	   SCIP_BOUNDTYPE* boundtypes;            /* indicates whether to which side the variables are bounded */
4284 	   SCIP_Real* consvals;                   /* coefficients of a specific constraint */
4285 	
4286 	   int* boundedvars;                      /* variables which are bounded to exactly one side */
4287 	   int* floatobjvars;                     /* discrete variables which have a fractional objective coefficient */
4288 	   int* intobjvars;                       /* discrete variables which have an integral objective coefficient */
4289 	
4290 	   SCIP_Real lb;                          /* lower bound of some variable */
4291 	   SCIP_Real ub;                          /* upper bound of some variable */
4292 	
4293 	   int nboundedvars;                      /* number of variables which are bounded to exactly one side */
4294 	   int nconsvars;                         /* number of variables appearing in a specific constraint */
4295 	   int nfloatobjvars;                     /* number of discrete variables which have a fractional objective coefficient */
4296 	   int nintobjvars;                       /* number of discrete variables which have an integral objective coefficient */
4297 	   int c;                                 /* counter for the constraints */
4298 	   int v;                                 /* counter for the variables */
4299 	   const int ndiscretevars = nbinvars+nintvars;  /* number of discrete variables */
4300 	
4301 	   char varname[SCIP_MAXSTRLEN];          /* buffer for storing variable names */
4302 	   char buffer[FZN_BUFFERLEN];            /* buffer for storing auxiliary variables and constraints */
4303 	   char buffy[FZN_BUFFERLEN];
4304 	
4305 	   assert( scip != NULL );
4306 	
4307 	   /* print problem statistics as comment to file */
4308 	   SCIPinfoMessage(scip, file, "%% SCIP STATISTICS\n");
4309 	   SCIPinfoMessage(scip, file, "%% Problem name     : %s\n", name);
4310 	   SCIPinfoMessage(scip, file, "%% Variables        : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
4311 	      nvars, nbinvars, nintvars, nimplvars, ncontvars);
4312 	   SCIPinfoMessage(scip, file, "%% Constraints      : %d\n", nconss);
4313 	
4314 	   SCIP_CALL( SCIPallocBufferArray(scip, &boundedvars, nvars) );
4315 	   SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nvars) );
4316 	   nboundedvars = 0;
4317 	
4318 	   if( nvars > 0 )
4319 	      SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Problem variables %%%%%%%%%%%%\n");
4320 	
4321 	   /* write all (active) problem variables */
4322 	   for( v = 0; v < nvars; v++ )
4323 	   {
4324 	      var = vars[v];
4325 	      assert( var != NULL );
4326 	      (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s", SCIPvarGetName(var) );
4327 	
4328 	      if( transformed )
4329 	      {
4330 	         /* in case the transformed is written only local bounds are posted which are valid in the current node */
4331 	         lb = SCIPvarGetLbLocal(var);
4332 	         ub = SCIPvarGetUbLocal(var);
4333 	      }
4334 	      else
4335 	      {
4336 	         lb = SCIPvarGetLbOriginal(var);
4337 	         ub = SCIPvarGetUbOriginal(var);
4338 	      }
4339 	
4340 	      /* If a variable is bounded to both sides, the bounds are added to the declaration,
4341 	       * for variables bounded to exactly one side, an auxiliary constraint will be added later-on.
4342 	       */
4343 	      if( !SCIPisInfinity(scip, -lb) && !SCIPisInfinity(scip, ub) )
4344 	      {
4345 	         SCIP_Bool fixed;
4346 	         fixed = FALSE;
4347 	
4348 	         if( SCIPisEQ(scip, lb, ub) )
4349 	            fixed = TRUE;
4350 	
4351 	         if( v < ndiscretevars )
4352 	         {
4353 	            assert( SCIPisFeasIntegral(scip, lb) && SCIPisFeasIntegral(scip, ub) );
4354 	
4355 	            if( fixed )
4356 	               SCIPinfoMessage(scip, file, "var int: %s = %.f;\n", varname, lb);
4357 	            else
4358 	               SCIPinfoMessage(scip, file, "var %.f..%.f: %s;\n", lb, ub, varname);
4359 	         }
4360 	         else
4361 	         {
4362 	            /* Real valued bounds have to be made type conform */
4363 	            if( fixed )
4364 	            {
4365 	               flattenFloat(scip, lb, buffy);
4366 	               SCIPinfoMessage(scip, file, "var float: %s = %s;\n", varname, buffy);
4367 	            }
4368 	            else
4369 	            {
4370 	               char buffy2[FZN_BUFFERLEN];
4371 	
4372 	               flattenFloat(scip, lb, buffy);
4373 	               flattenFloat(scip, ub, buffy2);
4374 	               SCIPinfoMessage(scip, file,  "var %s..%s: %s;\n", buffy, buffy2, varname);
4375 	            }
4376 	         }
4377 	      }
4378 	      else
4379 	      {
4380 	         assert(SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
4381 	         assert( v >= nbinvars );
4382 	
4383 	         /* declare the variable without any bound */
4384 	         if( v < ndiscretevars )
4385 	            SCIPinfoMessage(scip, file, "var int: %s;\n", varname);
4386 	         else
4387 	            SCIPinfoMessage(scip, file, "var float: %s;\n", varname);
4388 	
4389 	         /* if there is a bound, store the variable and its boundtype for adding a corresponding constraint later-on */
4390 	         if( ! SCIPisInfinity(scip, ub) )
4391 	         {
4392 	            boundedvars[nboundedvars] = v;
4393 	            boundtypes[nboundedvars] = SCIP_BOUNDTYPE_UPPER;
4394 	            nboundedvars++;
4395 	         }
4396 	         if( ! SCIPisInfinity(scip, -lb) )
4397 	         {
4398 	            boundedvars[nboundedvars] = v;
4399 	            boundtypes[nboundedvars] = SCIP_BOUNDTYPE_LOWER;
4400 	            nboundedvars++;
4401 	         }
4402 	      }
4403 	   }
4404 	
4405 	   /* set up the datastructures for the auxiliary int2float variables, the casting constraints and the problem constraints */
4406 	   fznoutput.ndiscretevars = ndiscretevars;
4407 	   fznoutput.varbufferpos = 0;
4408 	   fznoutput.consbufferpos = 0;
4409 	   fznoutput.castbufferpos = 0;
4410 	
4411 	   SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.varhasfloat, ndiscretevars) );
4412 	   SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.varbuffer, FZN_BUFFERLEN) );
4413 	   SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.castbuffer, FZN_BUFFERLEN) );
4414 	   SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.consbuffer, FZN_BUFFERLEN) );
4415 	   fznoutput.consbufferlen = FZN_BUFFERLEN;
4416 	   fznoutput.varbufferlen = FZN_BUFFERLEN;
4417 	   fznoutput.castbufferlen = FZN_BUFFERLEN;
4418 	
4419 	   for( v = 0; v < ndiscretevars; v++ )
4420 	      fznoutput.varhasfloat[v] = FALSE;
4421 	   fznoutput.varbuffer[0] = '\0';
4422 	   fznoutput.consbuffer[0] = '\0';
4423 	   fznoutput.castbuffer[0] = '\0';
4424 	
4425 	   /* output all problem constraints */
4426 	   for( c = 0; c < nconss; c++ )
4427 	   {
4428 	      cons = conss[c];
4429 	      assert( cons != NULL);
4430 	
4431 	      /* in case the transformed is written only constraint are posted which are enabled in the current node */
4432 	      assert(!transformed || SCIPconsIsEnabled(cons));
4433 	
4434 	      conshdlr = SCIPconsGetHdlr(cons);
4435 	      assert( conshdlr != NULL );
4436 	
4437 	      conshdlrname = SCIPconshdlrGetName(conshdlr);
4438 	      assert( transformed == SCIPconsIsTransformed(cons) );
4439 	
4440 	      /* By now, only linear, setppc, logicor, knapsack, and varbound constraints can be written.
4441 	       * Since they are all linearizable, a linear representation of them is written.
4442 	       */
4443 	      if( strcmp(conshdlrname, "linear") == 0 )
4444 	      {
4445 	         SCIP_CALL( printLinearCons(scip, &fznoutput,
4446 	               SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
4447 	               SCIPgetLhsLinear(scip, cons),  SCIPgetRhsLinear(scip, cons), transformed, TRUE) );
4448 	      }
4449 	      else if( strcmp(conshdlrname, "setppc") == 0 )
4450 	      {
4451 	         consvars = SCIPgetVarsSetppc(scip, cons);
4452 	         nconsvars = SCIPgetNVarsSetppc(scip, cons);
4453 	
4454 	         /* Setppc constraints only differ in their lhs/rhs (+- INF or 1) */
4455 	         switch( SCIPgetTypeSetppc(scip, cons) )
4456 	         {
4457 	         case SCIP_SETPPCTYPE_PARTITIONING :
4458 	            SCIP_CALL( printLinearCons(scip, &fznoutput,
4459 	                  consvars, NULL, nconsvars, 1.0, 1.0, transformed, FALSE) );
4460 	            break;
4461 	         case SCIP_SETPPCTYPE_PACKING :
4462 	            SCIP_CALL( printLinearCons(scip, &fznoutput,
4463 	                  consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, transformed, FALSE) );
4464 	            break;
4465 	         case SCIP_SETPPCTYPE_COVERING :
4466 	            SCIP_CALL( printLinearCons(scip, &fznoutput,
4467 	                  consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), transformed, FALSE) );
4468 	            break;
4469 	         }
4470 	      }
4471 	      else if( strcmp(conshdlrname, "logicor") == 0 )
4472 	      {
4473 	         SCIP_CALL( printLinearCons(scip, &fznoutput,
4474 	               SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons),
4475 	               1.0, SCIPinfinity(scip), transformed, FALSE) );
4476 	      }
4477 	      else if( strcmp(conshdlrname, "knapsack") == 0 )
4478 	      {
4479 	         SCIP_Longint* weights;
4480 	
4481 	         consvars = SCIPgetVarsKnapsack(scip, cons);
4482 	         nconsvars = SCIPgetNVarsKnapsack(scip, cons);
4483 	
4484 	         /* copy Longint array to SCIP_Real array */
4485 	         weights = SCIPgetWeightsKnapsack(scip, cons);
4486 	         SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
4487 	         for( v = 0; v < nconsvars; ++v )
4488 	            consvals[v] = (SCIP_Real)weights[v];
4489 	
4490 	         SCIP_CALL( printLinearCons(scip, &fznoutput, consvars, consvals, nconsvars, -SCIPinfinity(scip),
4491 	               (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), transformed, FALSE) );
4492 	
4493 	         SCIPfreeBufferArray(scip, &consvals);
4494 	      }
4495 	      else if( strcmp(conshdlrname, "varbound") == 0 )
4496 	      {
4497 	         SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
4498 	         SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
4499 	
4500 	         consvars[0] = SCIPgetVarVarbound(scip, cons);
4501 	         consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
4502 	
4503 	         consvals[0] = 1.0;
4504 	         consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
4505 	
4506 	         /* Varbound constraints always consist of exactly two variables */
4507 	         SCIP_CALL( printLinearCons(scip, &fznoutput,
4508 	               consvars, consvals, 2,
4509 	               SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons), transformed, TRUE) );
4510 	
4511 	         SCIPfreeBufferArray(scip, &consvars);
4512 	         SCIPfreeBufferArray(scip, &consvals);
4513 	      }
4514 	      else if(  strcmp(conshdlrname, "cumulative") == 0 )
4515 	      {
4516 	         int* intvals;
4517 	
4518 	         consvars = SCIPgetVarsCumulative(scip, cons);
4519 	         nconsvars = SCIPgetNVarsCumulative(scip, cons);
4520 	
4521 	         SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), "cumulative([") );
4522 	
4523 	         for( v = 0; v < nconsvars; ++v )
4524 	         {
4525 	            if( v < nconsvars - 1)
4526 	               (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s, ", SCIPvarGetName(consvars[v]) );
4527 	            else
4528 	               (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s", SCIPvarGetName(consvars[v]) );
4529 	
4530 	            SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), varname) );
4531 	         }
4532 	
4533 	         SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), "], [") );
4534 	
4535 	         intvals = SCIPgetDurationsCumulative(scip, cons);
4536 	
4537 	         for( v = 0; v < nconsvars; ++v )
4538 	         {
4539 	            if( v < nconsvars - 1)
4540 	               (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d, ", intvals[v] );
4541 	            else
4542 	               (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d", intvals[v] );
4543 	
4544 	            SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), buffy) );
4545 	         }
4546 	
4547 	         SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), "], [") );
4548 	
4549 	         intvals = SCIPgetDemandsCumulative(scip, cons);
4550 	
4551 	         for( v = 0; v < nconsvars; ++v )
4552 	         {
4553 	            if( v < nconsvars - 1)
4554 	               (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d, ", intvals[v] );
4555 	            else
4556 	               (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d", intvals[v] );
4557 	
4558 	            SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), buffy) );
4559 	         }
4560 	         (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "], %d);\n", SCIPgetCapacityCumulative(scip, cons) );
4561 	
4562 	         SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), buffy) );
4563 	      }
4564 	      else
4565 	      {
4566 	         SCIPwarningMessage(scip, "constraint handler <%s> cannot print flatzinc format\n", conshdlrname );
4567 	      }
4568 	   }
4569 	
4570 	   SCIP_CALL( SCIPallocBufferArray(scip,&intobjvars,ndiscretevars) );
4571 	   SCIP_CALL( SCIPallocBufferArray(scip,&floatobjvars,nvars) );
4572 	   nintobjvars = 0;
4573 	   nfloatobjvars = 0;
4574 	
4575 	   /* scan objective function: Which variables have to be put to the float part, which to the int part? */
4576 	   for( v = 0; v < nvars; v++ )
4577 	   {
4578 	      SCIP_Real obj;
4579 	
4580 	      var = vars[v];
4581 	      obj = SCIPvarGetObj(var);
4582 	
4583 	      if( !SCIPisZero(scip,obj) )
4584 	      {
4585 	         /* only discrete variables with integral objective coefficient will be put to the int part of the objective */
4586 	         if( v < ndiscretevars && SCIPisIntegral(scip, objscale*obj) )
4587 	         {
4588 	            intobjvars[nintobjvars] = v;
4589 	            SCIPdebugMsg(scip, "variable <%s> at pos <%d,%d> has an integral obj: %f=%f*%f\n",
4590 	               SCIPvarGetName(var), nintobjvars, v, obj, objscale, SCIPvarGetObj(var));
4591 	            nintobjvars++;
4592 	         }
4593 	         else
4594 	         {
4595 	            /* if not happened yet, introduce an auxiliary variable for discrete variables with fractional coefficients */
4596 	            if( v < ndiscretevars && !fznoutput.varhasfloat[v] )
4597 	            {
4598 	               assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY || SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
4599 	
4600 	               (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "var float: %s_float;\n", SCIPvarGetName(var));
4601 	               SCIP_CALL( appendBuffer(scip, &(fznoutput.varbuffer), &(fznoutput.varbufferlen), &(fznoutput.varbufferpos),buffer) );
4602 	
4603 	               (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "constraint int2float(%s, %s_float);\n", SCIPvarGetName(var), SCIPvarGetName(var));
4604 	               SCIP_CALL( appendBuffer(scip, &(fznoutput.castbuffer), &(fznoutput.castbufferlen), &(fznoutput.castbufferpos),buffer) );
4605 	
4606 	               fznoutput.varhasfloat[v] = TRUE;
4607 	            }
4608 	
4609 	            floatobjvars[nfloatobjvars] = v;
4610 	            nfloatobjvars++;
4611 	         }
4612 	      }
4613 	   }
4614 	
4615 	   /* output all created auxiliary variables (float equivalents of discrete variables) */
4616 	   if( fznoutput.varbufferpos > 0 )
4617 	   {
4618 	      SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Auxiliary variables %%%%%%%%%%%%\n");
4619 	      writeBuffer(scip, file, fznoutput.varbuffer, fznoutput.varbufferpos );
4620 	   }
4621 	
4622 	   /* output all int2float casting/conversion constraints */
4623 	   if( fznoutput.castbufferpos > 0 )
4624 	   {
4625 	      SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Variable conversions %%%%%%%%%%%%\n");
4626 	      writeBuffer(scip, file, fznoutput.castbuffer, fznoutput.castbufferpos );
4627 	   }
4628 	
4629 	   if( nboundedvars > 0 )
4630 	      SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Variable bounds %%%%%%%%%%%%\n");
4631 	
4632 	   /* output all bounds of variables with exactly one bound*/
4633 	   for( v = 0; v < nboundedvars; v++ )
4634 	   {
4635 	      var = vars[boundedvars[v]];
4636 	
4637 	      if( SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER )
4638 	      {
4639 	         if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
4640 	            SCIPinfoMessage(scip, file,"constraint int_ge(%s, %.f);\n",SCIPvarGetName(var),
4641 	               transformed ? SCIPvarGetLbLocal(var) : SCIPvarGetLbOriginal(var));
4642 	         else
4643 	         {
4644 	            assert( boundtypes[v] == SCIP_BOUNDTYPE_UPPER );
4645 	            SCIPinfoMessage(scip, file,"constraint int_le(%s, %.f);\n",SCIPvarGetName(var),
4646 	               transformed ? SCIPvarGetUbLocal(var) : SCIPvarGetUbOriginal(var));
4647 	         }
4648 	      }
4649 	      else
4650 	      {
4651 	         assert(SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT || SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
4652 	
4653 	         if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
4654 	         {
4655 	            flattenFloat(scip, transformed ? SCIPvarGetLbLocal(var) : SCIPvarGetLbOriginal(var), buffy);
4656 	            SCIPinfoMessage(scip, file,"constraint float_ge(%s, %s);\n", SCIPvarGetName(var), buffy);
4657 	         }
4658 	         else
4659 	         {
4660 	            assert( boundtypes[v] == SCIP_BOUNDTYPE_UPPER );
4661 	            flattenFloat(scip, transformed ? SCIPvarGetUbLocal(var) : SCIPvarGetUbOriginal(var), buffy);
4662 	            SCIPinfoMessage(scip, file,"constraint float_le(%s, %s);\n",SCIPvarGetName(var), buffy);
4663 	         }
4664 	      }
4665 	   }
4666 	
4667 	   /* output all problem constraints */
4668 	   if( fznoutput.consbufferpos > 0 )
4669 	   {
4670 	      SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Problem constraints %%%%%%%%%%%%\n");
4671 	      writeBuffer(scip, file, fznoutput.consbuffer, fznoutput.consbufferpos );
4672 	   }
4673 	
4674 	   SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Objective function %%%%%%%%%%%%\n");
4675 	
4676 	   /* If there is at least one variable in the objective function write down the optimization problem, else declare it to be a satisfiability problem */
4677 	   if( nintobjvars > 0 || nfloatobjvars > 0 )
4678 	   {
4679 	      SCIPinfoMessage(scip, file, "solve %s int_float_lin([", objsense == SCIP_OBJSENSE_MINIMIZE ? "minimize" : "maximize" );
4680 	
4681 	      /* first array: coefficients (in float representation) of discrete variables with integral objective coefficient */
4682 	      for( v = 0; v < nintobjvars; v++ )
4683 	      {
4684 	         SCIP_Real obj;
4685 	         var = vars[intobjvars[v]];
4686 	         obj = objscale * SCIPvarGetObj(var);
4687 	         SCIPdebugMsg(scip, "variable <%s> at pos <%d,%d> has an integral obj: %f=%f*%f\n", SCIPvarGetName(var), v, intobjvars[v], obj, objscale, SCIPvarGetObj(var));
4688 	
4689 	         assert( SCIPisIntegral(scip, obj) );
4690 	         flattenFloat(scip, obj, buffy);
4691 	         SCIPinfoMessage(scip, file, "%s%s", buffy, v < nintobjvars-1 ? ", " : "" );
4692 	      }
4693 	
4694 	      /* second array: all other objective coefficients */
4695 	      SCIPinfoMessage(scip, file, "], [");
4696 	      for( v = 0; v < nfloatobjvars; v++ )
4697 	      {
4698 	         SCIP_Real obj;
4699 	         obj = objscale * SCIPvarGetObj(vars[floatobjvars[v]]);
4700 	         flattenFloat(scip, obj, buffy);
4701 	         assert( !SCIPisIntegral(scip, obj) || SCIPvarGetType(vars[floatobjvars[v]]) == SCIP_VARTYPE_CONTINUOUS
4702 	            || SCIPvarGetType(vars[floatobjvars[v]]) == SCIP_VARTYPE_IMPLINT);
4703 	         SCIPinfoMessage(scip, file, "%s%s", buffy, v < nfloatobjvars-1 ? ", " : "" );
4704 	      }
4705 	
4706 	      /* potentially add an objective offset */
4707 	      if( !SCIPisZero(scip, objoffset) )
4708 	      {
4709 	         flattenFloat(scip, objscale * objoffset, buffy);
4710 	         SCIPinfoMessage(scip, file, "%s%s", nfloatobjvars == 0 ? "" : ", ", buffy );
4711 	      }
4712 	
4713 	      /* third array: all discrete variables with integral objective coefficient */
4714 	      SCIPinfoMessage(scip, file, "], [");
4715 	      for( v = 0; v < nintobjvars; v++ )
4716 	         SCIPinfoMessage(scip, file, "%s%s", SCIPvarGetName(vars[intobjvars[v]]), v < nintobjvars-1 ? ", " : "" );
4717 	
4718 	      /* fourth array: all other variables with nonzero objective coefficient */
4719 	      SCIPinfoMessage(scip, file, "], [");
4720 	      for( v = 0; v < nfloatobjvars; v++ )
4721 	         SCIPinfoMessage(scip, file, "%s%s%s", SCIPvarGetName(vars[floatobjvars[v]]), floatobjvars[v] < ndiscretevars ? "_float" : "", v < nfloatobjvars-1 ? ", " : "" );
4722 	
4723 	      /* potentially add a 1.0 for the objective offset */
4724 	      if( !SCIPisZero(scip, objoffset) )
4725 	         SCIPinfoMessage(scip, file, "%s%.1f", nfloatobjvars == 0 ? "" : ", ", 1.0 );
4726 	      SCIPinfoMessage(scip, file, "]);\n");
4727 	   }
4728 	   else
4729 	      SCIPinfoMessage(scip, file, "solve satisfy;\n");
4730 	
4731 	   /* free all memory */
4732 	   SCIPfreeBufferArray(scip, &fznoutput.castbuffer);
4733 	   SCIPfreeBufferArray(scip, &fznoutput.consbuffer);
4734 	   SCIPfreeBufferArray(scip, &fznoutput.varbuffer);
4735 	
4736 	   SCIPfreeBufferArray(scip, &boundtypes);
4737 	   SCIPfreeBufferArray(scip, &boundedvars);
4738 	   SCIPfreeBufferArray(scip, &floatobjvars);
4739 	   SCIPfreeBufferArray(scip, &intobjvars);
4740 	   SCIPfreeBufferArray(scip, &fznoutput.varhasfloat);
4741 	
4742 	   *result = SCIP_SUCCESS;
4743 	   return  SCIP_OKAY;
4744 	}
4745 	
4746 	/*
4747 	 * Callback methods of reader
4748 	 */
4749 	
4750 	/** copy method for reader plugins (called when SCIP copies plugins) */
4751 	static
4752 	SCIP_DECL_READERCOPY(readerCopyFzn)
4753 	{  /*lint --e{715}*/
4754 	   assert(scip != NULL);
4755 	   assert(reader != NULL);
4756 	   assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4757 	
4758 	   /* call inclusion method of reader */
4759 	   SCIP_CALL( SCIPincludeReaderFzn(scip) );
4760 	
4761 	   return SCIP_OKAY;
4762 	}
4763 	
4764 	
4765 	/** destructor of reader to free user data (called when SCIP is exiting) */
4766 	static
4767 	SCIP_DECL_READERFREE(readerFreeFzn)
4768 	{
4769 	   SCIP_READERDATA* readerdata;
4770 	   int v;
4771 	
4772 	   readerdata = SCIPreaderGetData(reader);
4773 	   assert(readerdata != NULL);
4774 	
4775 	   /* free all variable array elements */
4776 	   for( v = 0; v < readerdata->nvararrays; ++v )
4777 	   {
4778 	      freeVararray(scip, &readerdata->vararrays[v]);
4779 	   }
4780 	
4781 	   SCIPfreeBlockMemoryArrayNull(scip, &readerdata->vararrays, readerdata->vararrayssize);
4782 	
4783 	   /* free reader data */
4784 	   SCIPfreeBlockMemory(scip, &readerdata);
4785 	
4786 	   return SCIP_OKAY;
4787 	}
4788 	
4789 	
4790 	/** problem reading method of reader */
4791 	static
4792 	SCIP_DECL_READERREAD(readerReadFzn)
4793 	{  /*lint --e{715}*/
4794 	   FZNINPUT fzninput;
4795 	   int i;
4796 	
4797 	   /* initialize FZN input data */
4798 	   fzninput.file = NULL;
4799 	   fzninput.linebuf[0] = '\0';
4800 	   SCIP_CALL( SCIPallocBufferArray(scip, &fzninput.token, FZN_BUFFERLEN) );
4801 	   fzninput.token[0] = '\0';
4802 	
4803 	   for( i = 0; i < FZN_MAX_PUSHEDTOKENS; ++i )
4804 	   {
4805 	      SCIP_CALL( SCIPallocBufferArray(scip, &(fzninput.pushedtokens[i]), FZN_BUFFERLEN) ); /*lint !e866*/
4806 	   }
4807 	
4808 	   fzninput.npushedtokens = 0;
4809 	   fzninput.linenumber = 1;
4810 	   fzninput.bufpos = 0;
4811 	   fzninput.linepos = 0;
4812 	   fzninput.objsense = SCIP_OBJSENSE_MINIMIZE;
4813 	   fzninput.endline = FALSE;
4814 	   fzninput.comment = FALSE;
4815 	   fzninput.haserror = FALSE;
4816 	   fzninput.valid = TRUE;
4817 	   fzninput.vararrays = NULL;
4818 	   fzninput.nvararrays = 0;
4819 	   fzninput.vararrayssize = 0;
4820 	   fzninput.constarrays = NULL;
4821 	   fzninput.nconstarrays = 0;
4822 	   fzninput.constarrayssize = 0;
4823 	
4824 	   SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &(fzninput.initialconss)) );
4825 	   SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &(fzninput.dynamicconss)) );
4826 	   SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &(fzninput.dynamiccols)) );
4827 	   SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &(fzninput.dynamicrows)) );
4828 	
4829 	   SCIP_CALL( SCIPhashtableCreate(&fzninput.varHashtable, SCIPblkmem(scip), SCIP_HASHSIZE_NAMES,
4830 	         hashGetKeyVar, SCIPhashKeyEqString, SCIPhashKeyValString, NULL) );
4831 	
4832 	   SCIP_CALL( SCIPhashtableCreate(&fzninput.constantHashtable, SCIPblkmem(scip), SCIP_HASHSIZE_NAMES,
4833 	         hashGetKeyConstant, SCIPhashKeyEqString, SCIPhashKeyValString, NULL) );
4834 	   SCIP_CALL( SCIPallocBufferArray(scip, &fzninput.constants, 10) );
4835 	
4836 	   fzninput.nconstants = 0;
4837 	   fzninput.sconstants = 10;
4838 	
4839 	   /* read the file */
4840 	   SCIP_CALL( readFZNFile(scip, SCIPreaderGetData(reader), &fzninput, filename) );
4841 	
4842 	   /* free dynamically allocated memory */
4843 	   for( i = fzninput.nconstants - 1; i >= 0; --i )
4844 	   {
4845 	      SCIPfreeBufferArray(scip, &fzninput.constants[i]->name);
4846 	      SCIPfreeBuffer(scip, &fzninput.constants[i]);
4847 	   }
4848 	   SCIPfreeBufferArray(scip, &fzninput.constants);
4849 	
4850 	   for( i = FZN_MAX_PUSHEDTOKENS - 1; i >= 0; --i ) /*lint !e778*/
4851 	   {
4852 	      SCIPfreeBufferArrayNull(scip, &fzninput.pushedtokens[i]);
4853 	   }
4854 	   SCIPfreeBufferArrayNull(scip, &fzninput.token);
4855 	
4856 	   /* free memory */
4857 	   SCIPhashtableFree(&fzninput.varHashtable);
4858 	   SCIPhashtableFree(&fzninput.constantHashtable);
4859 	
4860 	   /* free variable arrays */
4861 	   for( i = 0; i < fzninput.nvararrays; ++i )
4862 	   {
4863 	      freeVararray(scip, &fzninput.vararrays[i]);
4864 	   }
4865 	   SCIPfreeBlockMemoryArrayNull(scip, &(fzninput.vararrays), fzninput.vararrayssize);
4866 	
4867 	   /* free constant arrays */
4868 	   for( i = 0; i < fzninput.nconstarrays; ++i )
4869 	   {
4870 	      freeConstarray(scip, &(fzninput.constarrays[i]));
4871 	   }
4872 	   SCIPfreeBlockMemoryArrayNull(scip, &fzninput.constarrays, fzninput.constarrayssize);
4873 	
4874 	   /* evaluate the result */
4875 	   if( fzninput.haserror || ! fzninput.valid )
4876 	      return SCIP_READERROR;
4877 	
4878 	   *result = SCIP_SUCCESS;
4879 	
4880 	   return SCIP_OKAY;
4881 	}
4882 	
4883 	
4884 	/** problem writing method of reader */
4885 	static
4886 	SCIP_DECL_READERWRITE(readerWriteFzn)
4887 	{  /*lint --e{715}*/
4888 	   if( genericnames )
4889 	   {
4890 	      SCIP_CALL( writeFzn(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4891 	            nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
4892 	   }
4893 	   else
4894 	   {
4895 	      int i;
4896 	      SCIP_Bool legal;
4897 	
4898 	      legal = TRUE;
4899 	
4900 	      /* Scan whether all variable names are flatzinc conform */
4901 	      for( i = 0; i < nvars; i++ )
4902 	      {
4903 	         const char* varname;
4904 	         size_t length;
4905 	
4906 	         varname = SCIPvarGetName(vars[i]);
4907 	         length = strlen(varname);
4908 	         legal = isIdentifier(varname);
4909 	         if( !legal )
4910 	         {
4911 	            SCIPwarningMessage(scip, "The name of variable <%d>: \"%s\" is not conform to the fzn standard.\n", i, varname);
4912 	            break;
4913 	         }
4914 	
4915 	         if( length >= 7 )
4916 	            legal = (strncmp(&varname[length-6],"_float",6) != 0);
4917 	         if( !legal )
4918 	         {
4919 	            SCIPwarningMessage(scip, "The name of variable <%d>: \"%s\" ends with \"_float\" which is not supported.\n", i, varname);
4920 	            break;
4921 	         }
4922 	      }
4923 	
4924 	      /* If there is at least one name, which is not conform, use generic names */
4925 	      if( legal )
4926 	      {
4927 	         SCIP_CALL( writeFzn(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4928 	               nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
4929 	      }
4930 	      else if( transformed )
4931 	      {
4932 	         SCIPwarningMessage(scip, "Write transformed problem with generic variable names.\n");
4933 	         SCIP_CALL( SCIPprintTransProblem(scip, file, "fzn", TRUE) );
4934 	      }
4935 	      else
4936 	      {
4937 	         SCIPwarningMessage(scip, "Write original problem with generic variable names.\n");
4938 	         SCIP_CALL( SCIPprintOrigProblem(scip, file, "fzn", TRUE) );
4939 	      }
4940 	   }
4941 	
4942 	   *result = SCIP_SUCCESS;
4943 	
4944 	   return SCIP_OKAY;
4945 	}
4946 	
4947 	/*
4948 	 * reader specific interface methods
4949 	 */
4950 	
4951 	/** includes the fzn file reader in SCIP */
4952 	SCIP_RETCODE SCIPincludeReaderFzn(
4953 	   SCIP*                 scip                /**< SCIP data structure */
4954 	   )
4955 	{
4956 	   SCIP_READERDATA* readerdata;
4957 	   SCIP_READER* reader;
4958 	
4959 	   /* create fzn reader data */
4960 	   SCIP_CALL( readerdataCreate(scip, &readerdata) );
4961 	
4962 	   /* include reader */
4963 	   SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) );
4964 	
4965 	   /* set non fundamental callbacks via setter functions */
4966 	   SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyFzn) );
4967 	   SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeFzn) );
4968 	   SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadFzn) );
4969 	   SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteFzn) );
4970 	
4971 	   return SCIP_OKAY;
4972 	}
4973 	
4974 	/** print given solution in Flatzinc format w.r.t. the output annotation */
4975 	SCIP_RETCODE SCIPprintSolReaderFzn(
4976 	   SCIP*                 scip,               /**< SCIP data structure */
4977 	   SCIP_SOL*             sol,                /**< primal solution, or NULL for current LP/pseudo solution */
4978 	   FILE*                 file                /**< output file (or NULL for standard output) */
4979 	   )
4980 	{
4981 	   SCIP_READER* reader;
4982 	   SCIP_READERDATA* readerdata;
4983 	   SCIP_VAR** vars;
4984 	   VARARRAY** vararrays;
4985 	   DIMENSIONS* info;
4986 	   VARARRAY* vararray;
4987 	   FZNNUMBERTYPE type;
4988 	   SCIP_Real solvalue;
4989 	   int nvararrays;
4990 	   int nvars;
4991 	   int i;
4992 	   int v;
4993 	
4994 	   reader = SCIPfindReader(scip, READER_NAME);
4995 	   assert(reader != NULL);
4996 	
4997 	   readerdata = SCIPreaderGetData(reader);
4998 	   assert(readerdata != NULL);
4999 	
5000 	   vararrays = readerdata->vararrays;
5001 	   nvararrays = readerdata->nvararrays;
5002 	
5003 	   /* sort variable arrays */
5004 	   SCIPsortPtr((void**)vararrays, vararraysComp, nvararrays);
5005 	
5006 	   for( i = 0; i < nvararrays; ++i )
5007 	   {
5008 	      vararray = vararrays[i];
5009 	      info = vararray->info;
5010 	      vars = vararray->vars;
5011 	      nvars = vararray->nvars;
5012 	      type =  vararray->type;
5013 	
5014 	      if( info->ndims == 0 )
5015 	      {
5016 	         solvalue = SCIPgetSolVal(scip, sol, vars[0]);
5017 	
5018 	         SCIPinfoMessage(scip, file, "%s = ", vararray->name);
5019 	
5020 	         printValue(scip, file, solvalue, type);
5021 	
5022 	         SCIPinfoMessage(scip, file, ";\n");
5023 	      }
5024 	      else
5025 	      {
5026 	         SCIPinfoMessage(scip, file, "%s = array%dd(", vararray->name, info->ndims);
5027 	
5028 	         for( v = 0; v < info->ndims; ++v )
5029 	         {
5030 	            SCIPinfoMessage(scip, file, "%d..%d, ", info->lbs[v], info->ubs[v]);
5031 	         }
5032 	
5033 	         SCIPinfoMessage(scip, file, "[");
5034 	
5035 	         for( v = 0; v < nvars; ++v )
5036 	         {
5037 	            if( v > 0)
5038 	               SCIPinfoMessage(scip, file, ", ");
5039 	
5040 	            solvalue = SCIPgetSolVal(scip, sol, vars[v]);
5041 	            printValue(scip, file, solvalue, type);
5042 	         }
5043 	
5044 	         SCIPinfoMessage(scip, file, "]);\n");
5045 	      }
5046 	   }
5047 	
5048 	   SCIPinfoMessage(scip, file, "----------\n");
5049 	
5050 	   return SCIP_OKAY;
5051 	}
5052