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