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