Scippy

SCIP

Solving Constraint Integer Programs

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