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