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