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