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