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