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-2021 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file reader_fzn.c
17  * @ingroup DEFPLUGINS_READER
18  * @brief FlatZinc file reader
19  * @author Timo Berthold
20  * @author Stefan Heinz
21  *
22  * FlatZinc is a low-level solver input language that is the target language for MiniZinc. It is designed to be easy to
23  * translate into the form required by a solver. For more details see https://www.minizinc.org. The format is described
24  * at https://github.com/MiniZinc/minizinc-doc/blob/develop/en/fzn-spec.rst.
25  *
26  * @todo Support more general constraint types
27  */
28 
29 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
30 
31 #include "blockmemshell/memory.h"
32 #include <ctype.h>
33 #include "scip/cons_and.h"
34 #include "scip/cons_cumulative.h"
35 #include "scip/cons_knapsack.h"
36 #include "scip/cons_linear.h"
37 #include "scip/cons_logicor.h"
38 #include "scip/cons_or.h"
39 #include "scip/cons_quadratic.h"
40 #include "scip/cons_setppc.h"
41 #include "scip/cons_varbound.h"
42 #include "scip/cons_xor.h"
43 #include "scip/pub_cons.h"
44 #include "scip/pub_fileio.h"
45 #include "scip/pub_message.h"
46 #include "scip/pub_misc.h"
47 #include "scip/pub_misc_sort.h"
48 #include "scip/pub_reader.h"
49 #include "scip/pub_var.h"
50 #include "scip/reader_fzn.h"
51 #include "scip/scip_cons.h"
52 #include "scip/scip_mem.h"
53 #include "scip/scip_message.h"
54 #include "scip/scip_numerics.h"
55 #include "scip/scip_param.h"
56 #include "scip/scip_prob.h"
57 #include "scip/scip_reader.h"
58 #include "scip/scip_sol.h"
59 #include "scip/scip_solvingstats.h"
60 #include "scip/scip_var.h"
61 #include <stdlib.h>
62 #include <string.h>
63 
64 #ifdef ALLDIFFERENT
65 #include "scip/cons_alldifferent.h"
66 #endif
67 
68 #define READER_NAME "fznreader"
69 #define READER_DESC "file reader for FlatZinc format"
70 #define READER_EXTENSION "fzn"
71 
72 
73 #define FZN_BUFFERLEN 65536 /**< size of the line buffer for reading or writing */
74 #define FZN_MAX_PUSHEDTOKENS 1
75 
76 /*
77  * Data structures
78  */
79 
80 /** number types */
82 {
86 };
88 
89 /** Expression type in FlatZinc File */
91 {
95 };
96 typedef enum FznExpType FZNEXPTYPE;
97 
98 /* structures to store the dimension information */
99 struct Dimensions
100 {
101  int* lbs; /**< lower bounds */
102  int* ubs; /**< upper bounds */
103  int ndims; /**< number of dimensions */
104  int size; /**< size of lbs and ubs */
105 };
106 typedef struct Dimensions DIMENSIONS;
107 
108 /** FlatZinc constant */
109 struct FznConstant
110 {
111  const char* name; /**< constant name */
112  FZNNUMBERTYPE type; /**< constant type */
113  SCIP_Real value; /**< constant value */
114 };
115 typedef struct FznConstant FZNCONSTANT;
116 
117 /** structure to store information for an array variable */
118 struct ConstArray
119 {
120  FZNCONSTANT** constants; /**< array of constants */
121  char* name; /**< name of constant array */
122  int nconstants; /**< number of constants */
123  FZNNUMBERTYPE type; /**< constant type */
124 };
125 typedef struct ConstArray CONSTARRAY;
126 
127 /** structure to store information for an array variable */
128 struct VarArray
129 {
130  SCIP_VAR** vars; /**< variable belonging to the variable array */
131  char* name; /**< name of the array variable */
132  DIMENSIONS* info; /**< dimension information */
133  int nvars; /**< number of variables */
134  FZNNUMBERTYPE type; /**< variable type */
135 };
136 typedef struct VarArray VARARRAY;
137 
138 /** data for FlatZinc reader */
139 struct SCIP_ReaderData
140 {
141  VARARRAY** vararrays; /**< variable arrays to output */
142  int nvararrays; /**< number of variables */
143  int vararrayssize; /**< size of variable array */
144 };
145 
146 /** tries to creates and adds a constraint; sets parameter created to TRUE if method was successful
147  *
148  * input:
149  * - scip : SCIP main data structure
150  * - fzninput, : FZN reading data
151  * - fname, : functions identifier name
152  * - ftokens, : function identifier tokens
153  * - nftokens, : number of function identifier tokes
154  *
155  * output
156  * - created : pointer to store whether a constraint was created or not
157  */
158 #define CREATE_CONSTRAINT(x) SCIP_RETCODE x (SCIP* scip, FZNINPUT* fzninput, const char* fname, char** ftokens, int nftokens, SCIP_Bool* created)
159 
160 
161 /** FlatZinc reading data */
162 struct FznInput
163 {
164  SCIP_FILE* file;
165  SCIP_HASHTABLE* varHashtable;
166  SCIP_HASHTABLE* constantHashtable;
167  FZNCONSTANT** constants;
168  char linebuf[FZN_BUFFERLEN+1];
169  char* token;
170  char* pushedtokens[FZN_MAX_PUSHEDTOKENS];
171  int npushedtokens;
172  int linenumber;
173  int linepos;
174  int bufpos;
175  int nconstants;
176  int sconstants;
177  SCIP_OBJSENSE objsense;
178  SCIP_Bool hasdot; /**< if the current token is a number, this bool tells if it contains a dot */
179  SCIP_Bool endline; /**< current buffer contains everything until the line ends */
180  SCIP_Bool comment; /**< current buffer contains everything until a comment starts */
181  SCIP_Bool haserror; /**< a error was detected during parsing */
182  SCIP_Bool valid;
183  SCIP_Bool initialconss; /**< should model constraints be marked as initial? */
184  SCIP_Bool dynamicconss; /**< should model constraints be subject to aging? */
185  SCIP_Bool dynamiccols; /**< should columns be added and removed dynamically to the LP? */
186  SCIP_Bool dynamicrows; /**< should rows be added and removed dynamically to the LP? */
187 
188  VARARRAY** vararrays; /**< variable arrays */
189  int nvararrays; /**< number of variables */
190  int vararrayssize; /**< size of variable array */
191 
192  CONSTARRAY** constarrays; /**< constant arrays */
193  int nconstarrays; /**< number of constant arrays */
194  int constarrayssize; /**< size of constant array */
195 };
196 typedef struct FznInput FZNINPUT;
197 
198 /** FlatZinc writing data */
199 struct FznOutput
200 {
201  char* varbuffer; /* buffer for auxiliary variables (float representatives of discrete variables) */
202  int varbufferlen; /* current length of the above buffer */
203  int varbufferpos; /* current filling position in the above buffer */
204  char* castbuffer; /* buffer for int2float conversion constraints */
205  int castbufferlen; /* current length of the above buffer */
206  int castbufferpos; /* current filling position in the above buffer */
207  char* consbuffer; /* buffer for all problem constraints */
208  int consbufferlen; /* current length of the above buffer */
209  int consbufferpos; /* current filling position in the above buffer */
210  int ndiscretevars; /* number of discrete variables in the problem */
211  SCIP_Bool* varhasfloat; /* array which indicates, whether a discrete variable already has a float representative */
212 };
213 typedef struct FznOutput FZNOUTPUT;
214 
215 static const char delimchars[] = " \f\n\r\t\v";
216 static const char tokenchars[] = ":<>=;{}[],()";
217 static const char commentchars[] = "%";
218 
219 /*
220  * Hash functions
221  */
222 
223 /** gets the key (i.e. the name) of the given variable */
224 static
225 SCIP_DECL_HASHGETKEY(hashGetKeyVar)
226 { /*lint --e{715}*/
227  SCIP_VAR* var = (SCIP_VAR*) elem;
228 
229  assert(var != NULL);
230  return (void*) SCIPvarGetName(var);
231 }
232 
233 /** gets the key (i.e. the name) of the flatzinc constant */
234 static
235 SCIP_DECL_HASHGETKEY(hashGetKeyConstant)
236 { /*lint --e{715}*/
237  FZNCONSTANT* constant = (FZNCONSTANT*) elem;
238 
239  assert(constant != NULL);
240  return (void*) constant->name;
241 }
242 
243 /** comparison method for sorting variable arrays w.r.t. to their name */
244 static
245 SCIP_DECL_SORTPTRCOMP(vararraysComp)
246 {
247  return strcmp( ((VARARRAY*)elem1)->name, ((VARARRAY*)elem2)->name );
248 }
249 
250 
251 /** frees a given buffer char* array */
252 static
254  SCIP* scip, /**< SCIP data structure */
255  char** array, /**< buffer array to free */
256  int nelements /**< number of elements */
257  )
258 {
259  int i;
260 
261  for( i = nelements - 1; i >= 0; --i )
262  SCIPfreeBufferArray(scip, &array[i]);
263 
264  SCIPfreeBufferArray(scip, &array);
265 }
266 
267 /** returns whether the given character is a token delimiter */
268 static
270  char c /**< input character */
271  )
272 {
273  return (c == '\0') || (strchr(delimchars, c) != NULL);
274 }
275 
276 /** returns whether the given character is a single token */
277 static
279  char c /**< input character */
280  )
281 {
282  return (strchr(tokenchars, c) != NULL);
283 }
284 
285 /** check if the current token is equal to give char */
286 static
288  const char* token, /**< token to be checked */
289  char c /**< char to compare */
290  )
291 {
292  if( strlen(token) == 1 && *token == c )
293  return TRUE;
294 
295  return FALSE;
296 }
297 
298 /** check if the current token is Bool expression, this means false or true */
299 static
301  const char* name, /**< name to check */
302  SCIP_Bool* value /**< pointer to store the Bool value */
303  )
304 {
305  /* check the name */
306  if( strlen(name) == 4 && strncmp(name, "true", 4) == 0 )
307  {
308  *value = TRUE;
309  return TRUE;
310  }
311  else if( strlen(name) == 1 && strncmp(name, "1", 1) == 0 )
312  {
313  /* we also allow 1 as true */
314  *value = TRUE;
315  return TRUE;
316  }
317  else if( strlen(name) == 5 && strncmp(name, "false", 5) == 0 )
318  {
319  *value = FALSE;
320  return TRUE;
321  }
322  else if( strlen(name) == 1 && strncmp(name, "0", 1) == 0 )
323  {
324  /* we also allow 0 as false */
325  *value = FALSE;
326  return TRUE;
327  }
328 
329  return FALSE;
330 }
331 
332 
333 /** check if the current token is an identifier, this means [A-Za-z][A-Za-z0-9_]* */
334 static
336  const char* name /**< name to check */
337  )
338 {
339  int i;
340 
341  /* check if the identifier starts with a letter */
342  if( strlen(name) == 0 || !isalpha((unsigned char)name[0]) )
343  return FALSE;
344 
345  i = 1;
346  while( name[i] )
347  {
348  if( !isalnum((unsigned char)name[i]) && name[i] != '_' )
349  return FALSE;
350  i++;
351  }
352 
353  return TRUE;
354 }
355 
356 /** returns whether the current character is member of a value string */
357 static
359  char c, /**< input character */
360  char nextc, /**< next input character */
361  SCIP_Bool firstchar, /**< is the given character the first char of the token? */
362  SCIP_Bool* hasdot, /**< pointer to update the dot flag */
363  FZNEXPTYPE* exptype /**< pointer to update the exponent type */
364  )
365 {
366  assert(hasdot != NULL);
367  assert(exptype != NULL);
368 
369  if( isdigit((unsigned char)c) )
370  return TRUE;
371  else if( firstchar && (c == '+' || c == '-') )
372  return TRUE;
373  else if( (*exptype == FZN_EXP_NONE) && !(*hasdot) && (c == '.') && (isdigit((unsigned char)nextc)))
374  {
375  *hasdot = TRUE;
376  return TRUE;
377  }
378  else if( !firstchar && (*exptype == FZN_EXP_NONE) && (c == 'e' || c == 'E') )
379  {
380  if( nextc == '+' || nextc == '-' )
381  {
382  *exptype = FZN_EXP_SIGNED;
383  return TRUE;
384  }
385  else if( isdigit((unsigned char)nextc) )
386  {
387  *exptype = FZN_EXP_UNSIGNED;
388  return TRUE;
389  }
390  }
391  else if( (*exptype == FZN_EXP_SIGNED) && (c == '+' || c == '-') )
392  {
393  *exptype = FZN_EXP_UNSIGNED;
394  return TRUE;
395  }
396 
397  return FALSE;
398 }
399 
400 /** compares two token if they are equal */
401 static
403  const char* token1, /**< first token */
404  const char* token2 /**< second token */
405  )
406 {
407  assert(token1 != NULL);
408  assert(token2 != NULL);
409 
410  if( strlen(token1) != strlen(token2) )
411  return FALSE;
412 
413  return !strncmp(token1, token2, strlen(token2) );
414 }
415 
416 /** reads the next line from the input file into the line buffer; skips comments;
417  * returns whether a line could be read
418  */
419 static
421  SCIP* scip, /**< SCIP data structure */
422  FZNINPUT* fzninput /**< FZN reading data */
423  )
424 {
425  int i;
426 
427  assert(fzninput != NULL);
428 
429  /* if we previously detected a comment we have to parse the remaining line away if there is something left */
430  if( !fzninput->endline && fzninput->comment )
431  {
432  SCIPdebugMsg(scip, "Throwing rest of comment away.\n");
433 
434  do
435  {
436  fzninput->linebuf[FZN_BUFFERLEN-2] = '\0';
437  (void)SCIPfgets(fzninput->linebuf, (int) sizeof(fzninput->linebuf), fzninput->file);
438  }
439  while( fzninput->linebuf[FZN_BUFFERLEN-2] != '\0' );
440 
441  fzninput->comment = FALSE;
442  fzninput->endline = TRUE;
443  }
444 
445  /* clear the line */
446  BMSclearMemoryArray(fzninput->linebuf, FZN_BUFFERLEN);
447  fzninput->linebuf[FZN_BUFFERLEN-2] = '\0';
448 
449  /* set line position */
450  if( fzninput->endline )
451  {
452  fzninput->linepos = 0;
453  fzninput->linenumber++;
454  }
455  else
456  fzninput->linepos += FZN_BUFFERLEN - 2;
457 
458  if( SCIPfgets(fzninput->linebuf, (int) sizeof(fzninput->linebuf), fzninput->file) == NULL )
459  return FALSE;
460 
461  fzninput->bufpos = 0;
462 
463  if( fzninput->linebuf[FZN_BUFFERLEN-2] != '\0' )
464  {
465  char* last;
466 
467  /* buffer is full; erase last token since it might be incomplete */
468  fzninput->endline = FALSE;
469  last = strrchr(fzninput->linebuf, ' ');
470 
471  if( last == NULL )
472  {
473  SCIPwarningMessage(scip, "we read %d characters from the file; this might indicate a corrupted input file!\n",
474  FZN_BUFFERLEN - 2);
475  fzninput->linebuf[FZN_BUFFERLEN-2] = '\0';
476  SCIPdebugMsg(scip, "the buffer might be corrupted\n");
477  }
478  else
479  {
480  SCIPfseek(fzninput->file, -(long) strlen(last), SEEK_CUR);
481  SCIPdebugMsg(scip, "correct buffer, reread the last %ld characters\n", (long) strlen(last));
482  *last = '\0';
483  }
484  }
485  else
486  {
487  /* found end of line */
488  fzninput->endline = TRUE;
489  }
490 
491  fzninput->linebuf[FZN_BUFFERLEN-1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
492  fzninput->comment = FALSE;
493 
494  /* skip characters after comment symbol */
495  for( i = 0; commentchars[i] != '\0'; ++i )
496  {
497  char* commentstart;
498 
499  commentstart = strchr(fzninput->linebuf, commentchars[i]);
500  if( commentstart != NULL )
501  {
502  *commentstart = '\0';
503  *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
504  fzninput->comment = TRUE;
505  break;
506  }
507  }
508 
509  return TRUE;
510 }
511 
512 
513 /** reads the next token from the input file into the token buffer; returns whether a token was read */
514 static
516  SCIP* scip, /**< SCIP data structure */
517  FZNINPUT* fzninput /**< FZN reading data */
518  )
519 {
520  SCIP_Bool hasdot;
521  FZNEXPTYPE exptype;
522  char* buf;
523  int tokenlen;
524 
525  assert(fzninput != NULL);
526  assert(fzninput->bufpos < FZN_BUFFERLEN);
527 
528  /* if the current line got marked as comment get the next line */
529  if( fzninput->comment && !getNextLine(scip, fzninput) )
530  {
531  SCIPdebugMsg(scip, "(line %d) end of file\n", fzninput->linenumber);
532  return FALSE;
533  }
534 
535  /* check the token stack */
536  if( fzninput->npushedtokens > 0 )
537  {
538  SCIPswapPointers((void**)&fzninput->token, (void**)&fzninput->pushedtokens[fzninput->npushedtokens-1]);
539  fzninput->npushedtokens--;
540  SCIPdebugMsg(scip, "(line %d) read token again: '%s'\n", fzninput->linenumber, fzninput->token);
541  return TRUE;
542  }
543 
544  /* skip delimiters */
545  buf = fzninput->linebuf;
546  while( isDelimChar(buf[fzninput->bufpos]) )
547  {
548  if( buf[fzninput->bufpos] == '\0' )
549  {
550  if( !getNextLine(scip, fzninput) )
551  {
552  SCIPdebugMsg(scip, "(line %d) end of file\n", fzninput->linenumber);
553  return FALSE;
554  }
555  assert(fzninput->bufpos == 0);
556  }
557  else
558  {
559  fzninput->bufpos++;
560  fzninput->linepos++;
561  }
562  }
563  assert(fzninput->bufpos < FZN_BUFFERLEN);
564  assert(!isDelimChar(buf[fzninput->bufpos]));
565 
566  hasdot = FALSE;
567  exptype = FZN_EXP_NONE;
568 
569  if( buf[fzninput->bufpos] == '.' && buf[fzninput->bufpos+1] == '.')
570  {
571  /* found <..> which only occurs in Ranges and is a "keyword" */
572  tokenlen = 2;
573  fzninput->bufpos += 2;
574  fzninput->linepos += 2;
575  fzninput->token[0] = '.';
576  fzninput->token[1] = '.';
577  }
578  else if( isValueChar(buf[fzninput->bufpos], buf[fzninput->bufpos+1], TRUE, &hasdot, &exptype) )
579  {
580  /* read value token */
581  tokenlen = 0;
582  do
583  {
584  assert(tokenlen < FZN_BUFFERLEN);
585  assert(!isDelimChar(buf[fzninput->bufpos]));
586  fzninput->token[tokenlen] = buf[fzninput->bufpos];
587  tokenlen++;
588  fzninput->bufpos++;
589  fzninput->linepos++;
590  assert(fzninput->bufpos < FZN_BUFFERLEN);
591  }
592  while( isValueChar(buf[fzninput->bufpos], buf[fzninput->bufpos+1], FALSE, &hasdot, &exptype) );
593 
594  fzninput->hasdot = hasdot;
595  }
596  else
597  {
598  /* read non-value token */
599  tokenlen = 0;
600  do
601  {
602  assert(tokenlen < FZN_BUFFERLEN);
603  fzninput->token[tokenlen] = buf[fzninput->bufpos];
604  tokenlen++;
605  fzninput->bufpos++;
606  fzninput->linepos++;
607 
608  /* check for annotations */
609  if(tokenlen == 1 && fzninput->token[0] == ':' && buf[fzninput->bufpos] == ':')
610  {
611  fzninput->token[tokenlen] = buf[fzninput->bufpos];
612  tokenlen++;
613  fzninput->bufpos++;
614  fzninput->linepos++;
615  break;
616  }
617 
618  if( tokenlen == 1 && isTokenChar(fzninput->token[0]) )
619  break;
620  }
621  while( !isDelimChar(buf[fzninput->bufpos]) && !isTokenChar(buf[fzninput->bufpos]) );
622  }
623 
624  assert(tokenlen < FZN_BUFFERLEN);
625  fzninput->token[tokenlen] = '\0';
626 
627  SCIPdebugMsg(scip, "(line %d) read token: '%s'\n", fzninput->linenumber, fzninput->token);
628 
629  return TRUE;
630 }
631 
632 /** puts the current token on the token stack, such that it is read at the next call to getNextToken() */
633 static
635  FZNINPUT* fzninput /**< FZN reading data */
636  )
637 {
638  assert(fzninput != NULL);
639  assert(fzninput->npushedtokens < FZN_MAX_PUSHEDTOKENS);
640 
641  SCIPswapPointers((void**)&fzninput->pushedtokens[fzninput->npushedtokens], (void**)&fzninput->token);
642  fzninput->npushedtokens++;
643 }
644 
645 /** checks whether the current token is a semicolon which closes a statement */
646 static
648  FZNINPUT* fzninput /**< FZN reading data */
649  )
650 {
651  assert(fzninput != NULL);
652 
653  return isChar(fzninput->token, ';');
654 }
655 
656 /** returns whether the current token is a value */
657 static
659  const char* token, /**< token to check */
660  SCIP_Real* value /**< pointer to store the value (unchanged, if token is no value) */
661  )
662 {
663  double val;
664  char* endptr;
665 
666  assert(value != NULL);
667 
668  val = strtod(token, &endptr);
669  if( endptr != token && *endptr == '\0' )
670  {
671  *value = val;
672  return TRUE;
673  }
674 
675  return FALSE;
676 }
677 
678 /*
679  * Local methods (for reading)
680  */
681 
682 /** issues an error message and marks the FlatZinc data to have errors */
683 static
685  SCIP* scip, /**< SCIP data structure */
686  FZNINPUT* fzninput, /**< FZN reading data */
687  const char* msg /**< error message */
688  )
689 {
690  assert(fzninput != NULL);
691  assert(scip != NULL);
692 
693  SCIPerrorMessage("Syntax error in line %d: %s found <%s>\n", fzninput->linenumber, msg, fzninput->token);
694  SCIPerrorMessage(" input: %s\n", fzninput->linebuf);
695 
696  fzninput->haserror = TRUE;
697 }
698 
699 /** returns whether a syntax error was detected */
700 static
702  FZNINPUT* fzninput /**< FZN reading data */
703  )
704 {
705  assert(fzninput != NULL);
706 
707  return (fzninput->haserror || !fzninput->valid);
708 }
709 
710 /** create reader data */
711 static
713  SCIP* scip, /**< SCIP data structure */
714  SCIP_READERDATA** readerdata /**< pointer to reader data */
715  )
716 {
717  SCIP_CALL( SCIPallocBlockMemory(scip, readerdata) );
718 
719  (*readerdata)->vararrays = NULL;
720  (*readerdata)->nvararrays = 0;
721  (*readerdata)->vararrayssize = 0;
722 
723  return SCIP_OKAY;
724 }
725 
726 /** ensure the size if the variable array */
727 static
729  SCIP* scip, /**< SCIP data structure */
730  SCIP_READERDATA* readerdata /**< reader data */
731  )
732 {
733  int nvararrays;
734  int vararrayssize;
735 
736  nvararrays = readerdata->nvararrays;
737  vararrayssize = readerdata->vararrayssize;
738 
739  if( vararrayssize == nvararrays )
740  {
741  if( vararrayssize == 0 )
742  {
743  vararrayssize = 100;
744  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->vararrays, vararrayssize) );
745  }
746  else
747  {
748  vararrayssize *= 2;
749  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &readerdata->vararrays, readerdata->vararrayssize, vararrayssize) );
750  }
751  }
752 
753  readerdata->vararrayssize = vararrayssize;
754 
755  return SCIP_OKAY;
756 }
757 
758 /** ensure the size if the variable array */
759 static
761  SCIP* scip, /**< SCIP data structure */
762  FZNINPUT* fzninput /**< FZN reading data */
763  )
764 {
765  int nvararrays;
766  int vararrayssize;
767 
768  nvararrays = fzninput->nvararrays;
769  vararrayssize = fzninput->vararrayssize;
770 
771  if( vararrayssize == nvararrays )
772  {
773  if( vararrayssize == 0 )
774  {
775  vararrayssize = 100;
776  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &fzninput->vararrays, vararrayssize) );
777  }
778  else
779  {
780  vararrayssize *= 2;
781  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &fzninput->vararrays, fzninput->vararrayssize, vararrayssize) );
782  }
783  }
784 
785  fzninput->vararrayssize = vararrayssize;
786 
787  return SCIP_OKAY;
788 }
789 
790 /** ensure the size if the variable array */
791 static
793  SCIP* scip, /**< SCIP data structure */
794  FZNINPUT* fzninput /**< FZN reading data */
795  )
796 {
797  int nconstarrays;
798  int constarrayssize;
799 
800  nconstarrays = fzninput->nconstarrays;
801  constarrayssize = fzninput->constarrayssize;
802 
803  if( constarrayssize == nconstarrays )
804  {
805  if( constarrayssize == 0 )
806  {
807  constarrayssize = 100;
808  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &fzninput->constarrays, constarrayssize) );
809  }
810  else
811  {
812  constarrayssize *= 2;
813  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &fzninput->constarrays, fzninput->constarrayssize, constarrayssize) );
814  }
815  }
816 
817  fzninput->constarrayssize = constarrayssize;
818 
819  return SCIP_OKAY;
820 }
821 
822 /** print given value in FlatZinc format to given stream */
823 static
825  SCIP* scip, /**< SCIP data structure */
826  FILE* file, /**< output file (or NULL for standard output) */
827  SCIP_Real value, /**< value to print */
828  FZNNUMBERTYPE type /**< FlatZinc number type */
829  )
830 {
831  switch( type )
832  {
833  case FZN_BOOL:
834  if( value < 0.5 )
835  SCIPinfoMessage(scip, file, "false");
836  else
837  SCIPinfoMessage(scip, file, "true");
838  break;
839  case FZN_INT:
840  {
841  SCIP_Longint longvalue;
842  longvalue = SCIPconvertRealToLongint(scip, value);
843  SCIPinfoMessage(scip, file, "%" SCIP_LONGINT_FORMAT "", longvalue);
844  break;
845  }
846  case FZN_FLOAT:
847  if( SCIPisIntegral(scip, value) )
848  {
849  printValue(scip, file, value, FZN_INT);
850 
851  /* add a ".0" to be type save */
852  SCIPinfoMessage(scip, file, ".0");
853  }
854  else
855  {
856  SCIPinfoMessage(scip, file, "%.1f", value);
857  }
858  break;
859  }
860 }
861 
862 /*
863  * Local methods (for VARARRAY)
864  */
865 
866 /** free dimension structure */
867 static
869  SCIP* scip, /**< SCIP data structure */
870  DIMENSIONS** target, /**< pointer to dimension target structure */
871  DIMENSIONS* source /**< dimension source */
872  )
873 {
874  if( source != NULL )
875  {
876  SCIP_CALL( SCIPallocBlockMemory(scip, target) );
877 
878  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*target)->lbs, source->lbs, source->ndims) );
879  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*target)->ubs, source->ubs, source->ndims) );
880  (*target)->ndims = source->ndims;
881  (*target)->size = source->ndims;
882  }
883  else
884  *target = NULL;
885 
886  return SCIP_OKAY;
887 }
888 
889 /** create variable array data structure */
890 static
892  SCIP* scip, /**< SCIP data structure */
893  VARARRAY** vararray, /**< pointer to variable array */
894  const char* name, /**< name of the variable array */
895  SCIP_VAR** vars, /**< array of variables */
896  int nvars, /**< number of variables */
897  FZNNUMBERTYPE type, /**< variable type */
898  DIMENSIONS* info /**< dimension information for output */
899  )
900 {
901  /* allocate memory for the new vararray struct */
902  SCIP_CALL( SCIPallocBlockMemory(scip, vararray) );
903 
904  /* copy variable pointers */
905  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*vararray)->vars, vars, nvars) );
906 
907  /* copy variable array name */
908  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*vararray)->name, name, strlen(name)+1) );
909 
910  SCIP_CALL( copyDimensions(scip, &(*vararray)->info, info) );
911 
912  (*vararray)->nvars = nvars;
913  (*vararray)->type = type;
914 
915  return SCIP_OKAY;
916 }
917 
918 /** free dimension structure */
919 static
921  SCIP* scip, /**< SCIP data structure */
922  DIMENSIONS** dim /**< pointer to dimension structure */
923  )
924 {
925  if( *dim != NULL )
926  {
927  SCIPfreeBlockMemoryArrayNull(scip, &(*dim)->lbs, (*dim)->size);
928  SCIPfreeBlockMemoryArrayNull(scip, &(*dim)->ubs, (*dim)->size);
929  SCIPfreeBlockMemory(scip, dim);
930  }
931 }
932 
933 /** free variable array data structure */
934 static
936  SCIP* scip, /**< SCIP data structure */
937  VARARRAY** vararray /**< pointer to variable array */
938  )
939 {
940  freeDimensions(scip, &(*vararray)->info);
941 
942  SCIPfreeBlockMemoryArray(scip, &(*vararray)->name, strlen((*vararray)->name) + 1);
943  SCIPfreeBlockMemoryArray(scip, &(*vararray)->vars, (*vararray)->nvars);
944 
945  SCIPfreeBlockMemory(scip, vararray);
946 }
947 
948 /** searches the variable array data base if a constant array exists with the given name; if it exists it is returned */
949 static
951  FZNINPUT* fzninput, /**< FZN reading data */
952  const char* name /**< variable array name */
953  )
954 {
955  VARARRAY* vararray;
956  int c;
957 
958  /* search in constants array list for a constants array with the given name */
959  for( c = 0; c < fzninput->nvararrays; ++c )
960  {
961  vararray = fzninput->vararrays[c];
962 
963  if( equalTokens(name, vararray->name) )
964  return vararray;
965  }
966 
967  return NULL;
968 }
969 
970 /*
971  * Local methods (for CONSTARRAY)
972  */
973 
974 /** create constant array data structure */
975 static
977  SCIP* scip, /**< SCIP data structure */
978  CONSTARRAY** constarray, /**< pointer to constant array */
979  const char* name, /**< name of the variable array */
980  FZNCONSTANT** constants, /**< array of constants */
981  int nconstants, /**< number of constants */
982  FZNNUMBERTYPE type /**< constant type */
983  )
984 {
985  SCIPdebugMsg(scip, "create constant array <%s>\n", name);
986 
987  /* allocate memory for the new constarray struct */
988  SCIP_CALL( SCIPallocBlockMemory(scip, constarray) );
989 
990  /* copy constant values */
991  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*constarray)->constants, constants, nconstants) );
992 
993  /* copy constant array name */
994  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*constarray)->name, name, strlen(name)+1) );
995 
996  (*constarray)->nconstants = nconstants;
997  (*constarray)->type = type;
998 
999  return SCIP_OKAY;
1000 }
1001 
1002 /** free constant array data structure */
1003 static
1005  SCIP* scip, /**< SCIP data structure */
1006  CONSTARRAY** constarray /**< pointer to constant array */
1007  )
1008 {
1009  SCIPdebugMsg(scip, "free constant array <%s>\n", (*constarray)->name);
1010 
1011  /* free variable pointers */
1012  SCIPfreeBlockMemoryArray(scip, &(*constarray)->constants, (*constarray)->nconstants);
1013 
1014  /* free variable array name */
1015  SCIPfreeBlockMemoryArray(scip, &(*constarray)->name, strlen((*constarray)->name) + 1);
1016 
1017  /* allocate memory for the new vararray struct */
1018  SCIPfreeBlockMemory(scip, constarray);
1019 }
1020 
1021 /** searches the constant array data base if a constant array exists with the given name; if it exists it is returned */
1022 static
1024  FZNINPUT* fzninput, /**< FZN reading data */
1025  const char* name /**< constant array name */
1026  )
1027 {
1028  CONSTARRAY* constarray;
1029  int c;
1030 
1031  /* search in constants array list for a constants array with the given name */
1032  for( c = 0; c < fzninput->nconstarrays; ++c )
1033  {
1034  constarray = fzninput->constarrays[c];
1035 
1036  if( equalTokens(name, constarray->name) )
1037  return constarray;
1038  }
1039 
1040  return NULL;
1041 }
1042 
1043 /** add variable to the reader data */
1044 static
1046  SCIP* scip, /**< SCIP data structure */
1047  SCIP_READERDATA* readerdata, /**< reader data */
1048  SCIP_VAR* var, /**< variable to add to the reader data */
1049  FZNNUMBERTYPE type /**< variable type */
1050  )
1051 {
1052  DIMENSIONS* info;
1053  const char* name;
1054  VARARRAY* vararray;
1055  int nvararrays;
1056 
1057  nvararrays = readerdata->nvararrays;
1058 
1059  SCIP_CALL( ensureVararrySize(scip, readerdata) );
1060  assert(nvararrays < readerdata->vararrayssize);
1061 
1062  /* get variable name */
1063  name = SCIPvarGetName(var);
1064 
1065  /* allocate memory for the new vararray struct */
1066  SCIP_CALL( SCIPallocBlockMemory(scip, &vararray) );
1067 
1068  /* copy variable pointers */
1069  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &vararray->vars, &var, 1) );
1070 
1071  /* copy variable array name */
1072  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &vararray->name, name, strlen(name)+1) );
1073 
1074  SCIP_CALL( SCIPallocBlockMemory(scip, &info) );
1075  info->lbs = NULL;
1076  info->ubs = NULL;
1077  info->ndims = 0;
1078  info->size = 0;
1079 
1080  vararray->info = info;
1081  vararray->nvars = 1;
1082  vararray->type = type;
1083 
1084  readerdata->vararrays[nvararrays] = vararray;
1085  readerdata->nvararrays++;
1086 
1087  return SCIP_OKAY;
1088 }
1089 
1090 /** add variable to the reader data */
1091 static
1093  SCIP* scip, /**< SCIP data structure */
1094  SCIP_READERDATA* readerdata, /**< reader data */
1095  const char* name, /**< name of the variable array */
1096  SCIP_VAR** vars, /**< array of variable to add to the reader data */
1097  int nvars, /**< number of variables */
1098  FZNNUMBERTYPE type, /**< variable type */
1099  DIMENSIONS* info /**< dimension information for output */
1100  )
1101 {
1102  VARARRAY* vararray;
1103  int nvararrays;
1104 
1105  nvararrays = readerdata->nvararrays;
1106 
1107  SCIP_CALL( ensureVararrySize(scip, readerdata) );
1108  assert(nvararrays < readerdata->vararrayssize);
1109 
1110  /* create variable array data structure */
1111  SCIP_CALL( createVararray(scip, &vararray, name, vars, nvars, type, info) );
1112 
1113  readerdata->vararrays[nvararrays] = vararray;
1114  readerdata->nvararrays++;
1115 
1116  return SCIP_OKAY;
1117 }
1118 
1119 /** add variable to the input data */
1120 static
1122  SCIP* scip, /**< SCIP data structure */
1123  FZNINPUT* fzninput, /**< FZN reading data */
1124  const char* name, /**< name of the variable array */
1125  SCIP_VAR** vars, /**< array of variables */
1126  int nvars, /**< number of variables */
1127  FZNNUMBERTYPE type, /**< variable type */
1128  DIMENSIONS* info /**< dimension information for output */
1129  )
1130 {
1131  VARARRAY* vararray;
1132  int nvararrays;
1133 
1134  nvararrays = fzninput->nvararrays;
1135 
1136  SCIP_CALL( ensureVararrySizeFznInput(scip, fzninput) );
1137  assert(nvararrays < fzninput->vararrayssize);
1138 
1139  /* create variable array data structure */
1140  SCIP_CALL( createVararray(scip, &vararray, name, vars, nvars, type, info) );
1141 
1142  fzninput->vararrays[nvararrays] = vararray;
1143  fzninput->nvararrays++;
1144 
1145  return SCIP_OKAY;
1146 }
1147 
1148 /** add variable to the reader data */
1149 static
1151  SCIP* scip, /**< SCIP data structure */
1152  FZNINPUT* fzninput, /**< FZN reading data */
1153  const char* name, /**< name of the variable array */
1154  FZNCONSTANT** constants, /**< array of constants */
1155  int nconstants, /**< number of constants */
1156  FZNNUMBERTYPE type /**< variable type */
1157  )
1158 {
1159  CONSTARRAY* constarray;
1160  int nconstarrays;
1161 
1162  nconstarrays = fzninput->nconstarrays;
1163 
1164  SCIP_CALL( ensureConstarrySizeFznInput(scip, fzninput) );
1165  assert(nconstarrays < fzninput->constarrayssize);
1166 
1167  /* create constant array structure */
1168  SCIP_CALL( createConstarray(scip, &constarray, name, constants, nconstants, type) );
1169 
1170  fzninput->constarrays[nconstarrays] = constarray;
1171  fzninput->nconstarrays++;
1172 
1173  return SCIP_OKAY;
1174 }
1175 
1176 /** creates, adds, and releases a linear constraint */
1177 static
1179  SCIP* scip, /**< SCIP data structure */
1180  const char* name, /**< name of constraint */
1181  int nlinvars, /**< number of linear terms (n) */
1182  SCIP_VAR** linvars, /**< array with variables in linear part (x_i) */
1183  SCIP_Real* lincoefs, /**< array with coefficients of variables in linear part (b_i) */
1184  int nquadterms, /**< number of quadratic terms (m) */
1185  SCIP_VAR** quadvars1, /**< array with first variables in quadratic terms (y_j) */
1186  SCIP_VAR** quadvars2, /**< array with second variables in quadratic terms (z_j) */
1187  SCIP_Real* quadcoefs, /**< array with coefficients of quadratic terms (a_j) */
1188  SCIP_Real lhs, /**< left hand side of quadratic equation (ell) */
1189  SCIP_Real rhs, /**< right hand side of quadratic equation (u) */
1190  SCIP_Bool initialconss, /**< should model constraints be marked as initial? */
1191  SCIP_Bool dynamicconss, /**< should model constraints be subject to aging? */
1192  SCIP_Bool dynamicrows /**< should rows be added and removed dynamically to the LP? */
1193  )
1194 {
1195  SCIP_CONS* cons;
1196 
1197  SCIP_CALL( SCIPcreateConsQuadratic(scip, &cons, name, nlinvars, linvars, lincoefs, nquadterms, quadvars1, quadvars2, quadcoefs, lhs, rhs,
1198  initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss, dynamicrows) );
1199 
1200  SCIPdebugPrintCons(scip, cons, NULL);
1201 
1202  SCIP_CALL( SCIPaddCons(scip, cons) );
1203  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1204 
1205  return SCIP_OKAY;
1206 }
1207 
1208 /** creates, adds, and releases a linear constraint */
1209 static
1211  SCIP* scip, /**< SCIP data structure */
1212  const char* name, /**< name of constraint */
1213  int nvars, /**< number of nonzeros in the constraint */
1214  SCIP_VAR** vars, /**< array with variables of constraint entries */
1215  SCIP_Real* vals, /**< array with coefficients of constraint entries */
1216  SCIP_Real lhs, /**< left hand side of constraint */
1217  SCIP_Real rhs, /**< right hand side of constraint */
1218  SCIP_Bool initialconss, /**< should model constraints be marked as initial? */
1219  SCIP_Bool dynamicconss, /**< should model constraints be subject to aging? */
1220  SCIP_Bool dynamicrows /**< should rows be added and removed dynamically to the LP? */
1221  )
1222 {
1223  SCIP_CONS* cons;
1224 
1225  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, nvars, vars, vals, lhs, rhs,
1226  initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, dynamicconss, dynamicrows, FALSE) );
1227 
1228  SCIPdebugPrintCons(scip, cons, NULL);
1229 
1230  SCIP_CALL( SCIPaddCons(scip, cons) );
1231  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1232 
1233  return SCIP_OKAY;
1234 }
1235 
1236 /** create a linking between the two given identifiers */
1237 static
1239  SCIP* scip, /**< SCIP data structure */
1240  FZNINPUT* fzninput, /**< FZN reading data */
1241  const char* consname, /**< name of constraint */
1242  const char* name1, /**< name of first identifier */
1243  const char* name2, /**< name of second identifier */
1244  SCIP_Real lhs, /**< left hand side of the linking */
1245  SCIP_Real rhs /**< right hand side of the linking */
1246  )
1247 {
1248  SCIP_VAR** vars;
1249  SCIP_Real vals[] = {0.0,0.0};
1250  SCIP_Real value1;
1251  SCIP_Real value2;
1252  int nvars;
1253 
1254  nvars = 0;
1255  value1 = 0.0;
1256  value2 = 0.0;
1257 
1258  SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
1259 
1260  vars[nvars] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) name1);
1261  if( vars[nvars] != NULL )
1262  {
1263  vals[nvars] = 1.0;
1264  nvars++;
1265  }
1266  else if( !isValue(name1, &value1) )
1267  {
1268  FZNCONSTANT* constant;
1269 
1270  constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) name1);
1271  assert(constant != NULL);
1272 
1273  value1 = constant->value;
1274  }
1275 
1276  vars[nvars] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) name2);
1277  if( vars[nvars] != NULL )
1278  {
1279  vals[nvars] = -1.0;
1280  nvars++;
1281  }
1282  else if( !isValue(name2, &value2) )
1283  {
1284  FZNCONSTANT* constant;
1285 
1286  constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) name2);
1287  assert(constant != NULL);
1288 
1289  value2 = constant->value;
1290  }
1291 
1292  if( !SCIPisInfinity(scip, -lhs) )
1293  lhs += (value2 - value1);
1294 
1295  if( !SCIPisInfinity(scip, rhs) )
1296  rhs += (value2 - value1);
1297 
1298  SCIP_CALL( createLinearCons(scip, consname, nvars, vars, vals, lhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
1299 
1300  SCIPfreeBufferArray(scip, &vars);
1301 
1302  return SCIP_OKAY;
1303 }
1304 
1305 /** parse array index expression */
1306 static
1308  SCIP* scip, /**< SCIP data structure */
1309  FZNINPUT* fzninput, /**< FZN reading data */
1310  int* idx /**< pointer to store the array index */
1311  )
1312 {
1313  SCIP_Real value;
1314 
1315  assert( isChar(fzninput->token, '[') );
1316 
1317  /* parse array index expression */
1318  if( !getNextToken(scip, fzninput) || isEndStatement(fzninput) )
1319  {
1320  syntaxError(scip, fzninput, "expecting array index expression");
1321  return;
1322  }
1323 
1324  if( isIdentifier(fzninput->token) )
1325  {
1326  FZNCONSTANT* constant;
1327 
1328  /* identifier has to be one of a constant */
1329  constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, fzninput->token);
1330 
1331  if( constant == NULL )
1332  syntaxError(scip, fzninput, "unknown index name");
1333  else
1334  {
1335  assert(constant->type == FZN_INT);
1336  *idx = (int) constant->value;
1337  }
1338  }
1339  else if( isValue(fzninput->token, &value) )
1340  {
1341  assert( fzninput->hasdot == FALSE );
1342  *idx = (int) value;
1343  }
1344  else
1345  syntaxError(scip, fzninput, "expecting array index expression");
1346 }
1347 
1348 /** unroll assignment if it is an array access one */
1349 static
1351  SCIP* scip, /**< SCIP data structure */
1352  FZNINPUT* fzninput, /**< FZN reading data */
1353  char* assignment /**< assignment to unroll */
1354  )
1355 {
1356  assert(scip != NULL);
1357  assert(fzninput != NULL);
1358 
1359  SCIPdebugMsg(scip, "parse assignment expression\n");
1360 
1361  if( !getNextToken(scip, fzninput) || isEndStatement(fzninput) )
1362  {
1363  syntaxError(scip, fzninput, "expecting more tokens");
1364  return;
1365  }
1366 
1367  if( isIdentifier(fzninput->token) )
1368  {
1369  char name[FZN_BUFFERLEN];
1370  int idx;
1371 
1372  (void) SCIPsnprintf(name, FZN_BUFFERLEN, "%s", fzninput->token);
1373 
1374  if( !getNextToken(scip, fzninput) )
1375  {
1376  syntaxError(scip, fzninput, "expecting at least a semicolon to close the statement");
1377  return;
1378  }
1379 
1380  /* check if it is an array access expression */
1381  if( isChar(fzninput->token, '[') )
1382  {
1383  idx = -1;
1384  parseArrayIndex(scip, fzninput, &idx);
1385 
1386  assert(idx >= 0);
1387 
1388  if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, ']') )
1389  {
1390  syntaxError(scip, fzninput, "expecting token <]>");
1391  return;
1392  }
1393 
1394  /* put constant name or variable name together */
1395  (void) SCIPsnprintf(assignment, FZN_BUFFERLEN, "%s[%d]", name, idx);
1396  }
1397  else
1398  {
1399  (void) SCIPsnprintf(assignment, FZN_BUFFERLEN, "%s", name);
1400 
1401  /* push the current token back for latter evaluations */
1402  pushToken(fzninput);
1403  }
1404  }
1405  else
1406  (void) SCIPsnprintf(assignment, FZN_BUFFERLEN, "%s", fzninput->token);
1407 }
1408 
1409 /** computes w.r.t. to the given side value and relation the left and right side for a SCIP linear constraint */
1410 static
1412  SCIP* scip, /**< SCIP data structure */
1413  FZNINPUT* fzninput, /**< FZN reading data */
1414  const char* name, /**< name of the relation */
1415  SCIP_Real sidevalue, /**< parsed side value */
1416  SCIP_Real* lhs, /**< pointer to left hand side */
1417  SCIP_Real* rhs /**< pointer to right hand side */
1418  )
1419 {
1420  SCIPdebugMsg(scip, "check relation <%s>\n", name);
1421 
1422  /* compute left and right hand side of the linear constraint */
1423  if( equalTokens(name, "eq") )
1424  {
1425  *lhs = sidevalue;
1426  *rhs = sidevalue;
1427  }
1428  else if( equalTokens(name, "ge") )
1429  {
1430  *lhs = sidevalue;
1431  }
1432  else if( equalTokens(name, "le") )
1433  {
1434  *rhs = sidevalue;
1435  }
1436  else if( equalTokens(name, "gt") )
1437  {
1438  /* greater than only works if there are not continuous variables are involved */
1439  *lhs = sidevalue + 1.0;
1440  }
1441  else if( equalTokens(name, "lt") )
1442  {
1443  /* less than only works if there are not continuous variables are involved */
1444  *rhs = sidevalue - 1.0;
1445  }
1446  else
1447  syntaxError(scip, fzninput, "unknown relation in constraint identifier name");
1448 
1449  SCIPdebugMsg(scip, "lhs = %g, rhs = %g\n", *lhs, *rhs);
1450 }
1451 
1452 /** parse a list of elements which is separates by a comma */
1453 static
1455  SCIP* scip, /**< SCIP data structure */
1456  FZNINPUT* fzninput, /**< FZN reading data */
1457  char*** elements, /**< pointer to char* array for storing the elements of the list */
1458  int* nelements, /**< pointer to store the number of elements */
1459  int selements /**< size of the elements char* array */
1460  )
1461 {
1462  char assignment[FZN_BUFFERLEN];
1463  assert(selements > 0);
1464 
1465  /* check if the list is not empty */
1466  if( getNextToken(scip, fzninput) && !isChar(fzninput->token, ']') )
1467  {
1468  /* push back token */
1469  pushToken(fzninput);
1470 
1471  /* loop through the array */
1472  do
1473  {
1474  if(selements == *nelements)
1475  {
1476  selements *= 2;
1477  SCIP_CALL( SCIPreallocBufferArray(scip, elements, selements) );
1478  }
1479 
1480  /* parse and flatten assignment */
1481  flattenAssignment(scip, fzninput, assignment);
1482 
1483  if( hasError(fzninput) )
1484  break;
1485 
1486  /* store assignment */
1487  SCIP_CALL( SCIPduplicateBufferArray(scip, &(*elements)[(*nelements)], assignment, (int) strlen(assignment) + 1) ); /*lint !e866*/
1488 
1489  (*nelements)++;
1490  }
1491  while( getNextToken(scip, fzninput) && isChar(fzninput->token, ',') );
1492  }
1493  else
1494  {
1495  SCIPdebugMsg(scip, "list is empty\n");
1496  }
1497 
1498  /* push back ']' which closes the list */
1499  pushToken(fzninput);
1500 
1501  return SCIP_OKAY;
1502 }
1503 
1504 /** parse range expression */
1505 static
1507  SCIP* scip, /**< SCIP data structure */
1508  FZNINPUT* fzninput, /**< FZN reading data */
1509  FZNNUMBERTYPE* type, /**< pointer to store the number type */
1510  SCIP_Real* lb, /**< pointer to store the lower bound */
1511  SCIP_Real* ub /**< pointer to store the upper bound */
1512  )
1513 {
1514  if( !getNextToken(scip, fzninput) )
1515  {
1516  syntaxError(scip, fzninput, "expected left side of range");
1517  return;
1518  }
1519 
1520  /* current token should be the lower bound */
1521  if( !isValue(fzninput->token, lb) )
1522  {
1523  syntaxError(scip, fzninput, "expected lower bound value");
1524  return;
1525  }
1526 
1527  /* check if we have a float notation or an integer notation which defines the type of the variable */
1528  if( fzninput->hasdot || !SCIPisIntegral(scip, *lb) )
1529  *type = FZN_FLOAT;
1530  else
1531  *type = FZN_INT;
1532 
1533  /* parse next token which should be <..> */
1534  if( !getNextToken(scip, fzninput) || !equalTokens(fzninput->token, "..") )
1535  {
1536  syntaxError(scip, fzninput, "expected <..>");
1537  return;
1538  }
1539 
1540  /* parse upper bound */
1541  if( !getNextToken(scip, fzninput) || !isValue(fzninput->token, ub) )
1542  {
1543  syntaxError(scip, fzninput, "expected upper bound value");
1544  return;
1545  }
1546 
1547  /* check if upper bound notation fits which lower bound notation */
1548  if( fzninput->hasdot != (*type == FZN_FLOAT) )
1549  {
1550  SCIPwarningMessage(scip, "lower bound and upper bound mismatch in value type, assume %s variable type\n",
1551  fzninput->hasdot ? "an integer" : "a continuous");
1552  }
1553 }
1554 
1555 /** parse dimension information */
1556 static
1558  SCIP* scip, /**< SCIP data structure */
1559  FZNINPUT* fzninput, /**< FZN reading data */
1560  DIMENSIONS** info /**< pointer to store the output dimension information if one */
1561  )
1562 {
1563  FZNNUMBERTYPE type;
1564  SCIP_Real lb;
1565  SCIP_Real ub;
1566  int nelements;
1567  int size;
1568 
1569  nelements = 0;
1570  size = 100;
1571 
1572  SCIP_CALL( SCIPallocBlockMemory(scip, info) );
1573  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*info)->lbs, size) );
1574  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*info)->ubs, size) );
1575  (*info)->size = size;
1576 
1577  /* check for bracket */
1578  if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '(') )
1579  {
1580  syntaxError(scip, fzninput, "expecting <(> after <output_array>");
1581  return SCIP_OKAY;
1582  }
1583 
1584  while( getNextToken(scip, fzninput) && !isChar(fzninput->token, ']') )
1585  {
1586  parseRange(scip, fzninput, &type, &lb, &ub);
1587 
1588  if( fzninput->haserror )
1589  return SCIP_OKAY;
1590 
1591  assert(type == FZN_INT);
1592 
1593  if( nelements == size )
1594  {
1595  size *= 2;
1596  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(*info)->lbs, (*info)->size, size) );
1597  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(*info)->ubs, (*info)->size, size) );
1598  (*info)->size = size;
1599  }
1600 
1601  /* we assume integer bounds */
1602  (*info)->lbs[nelements] = (int) lb;
1603  (*info)->ubs[nelements] = (int) ub;
1604  nelements++;
1605  }
1606 
1607  (*info)->ndims = nelements;
1608 
1609  /* check for colon */
1610  if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, ')') )
1611  syntaxError(scip, fzninput, "expecting <)>");
1612 
1613  return SCIP_OKAY;
1614 }
1615 
1616 /** parse identifier name without annotations */
1617 static
1619  SCIP* scip, /**< SCIP data structure */
1620  FZNINPUT* fzninput, /**< FZN reading data */
1621  char* name, /**< pointer to store the name */
1622  SCIP_Bool* output, /**< pointer to store if the name has the annotations to output */
1623  DIMENSIONS** info /**< pointer to store the output dimension information if one */
1624  )
1625 {
1626  if( output != NULL )
1627  (*output) = FALSE;
1628 
1629  /* check for colon */
1630  if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, ':') )
1631  {
1632  syntaxError(scip, fzninput, "expecting colon <:>");
1633  return SCIP_OKAY;
1634  }
1635 
1636  /* parse identifier name */
1637  if( !getNextToken(scip, fzninput) || !isIdentifier(fzninput->token) )
1638  {
1639  syntaxError(scip, fzninput, "expecting identifier name");
1640  return SCIP_OKAY;
1641  }
1642 
1643  /* copy identifier name */
1644  (void)SCIPsnprintf(name, FZN_BUFFERLEN-1, "%s", (const char*)fzninput->token);
1645 
1646  /* search for an assignment; therefore, skip annotations */
1647  do
1648  {
1649  if( !getNextToken(scip, fzninput) )
1650  {
1651  syntaxError(scip, fzninput, "expected at least a semicolon to close statement");
1652  return SCIP_OKAY;
1653  }
1654 
1655  /* check if the name has the annotation to be part of the output */
1656  if( equalTokens(fzninput->token, "output_var") && output != NULL )
1657  (*output) = TRUE;
1658  else if( equalTokens(fzninput->token, "output_array") && output != NULL)
1659  {
1660  (*output) = TRUE;
1661  assert(info != NULL);
1662  SCIP_CALL( parseOutputDimensioninfo(scip, fzninput, info) );
1663  }
1664 
1665  if( isEndStatement(fzninput) )
1666  break;
1667  }
1668  while( !isChar(fzninput->token, '=') );
1669 
1670  /* push back '=' or ';' */
1671  pushToken(fzninput);
1672 
1673  return SCIP_OKAY;
1674 }
1675 
1676 /** parse variable/constant (array) type (integer, float, bool, or set) */
1677 static
1679  SCIP* scip, /**< SCIP data structure */
1680  FZNINPUT* fzninput, /**< FZN reading data */
1681  FZNNUMBERTYPE* type, /**< pointer to store the number type */
1682  SCIP_Real* lb, /**< pointer to store the lower bound */
1683  SCIP_Real* ub /**< pointer to store the lower bound */
1684  )
1685 {
1686  if( !getNextToken(scip, fzninput) || isEndStatement(fzninput) )
1687  {
1688  syntaxError(scip, fzninput, "missing token");
1689  return;
1690  }
1691 
1692  *lb = -SCIPinfinity(scip);
1693  *ub = SCIPinfinity(scip);
1694 
1695  /* parse variable type or bounds */
1696  if( equalTokens(fzninput->token, "bool") )
1697  {
1698  *type = FZN_BOOL;
1699  *lb = 0.0;
1700  *ub = 1.0;
1701  }
1702  else if( equalTokens(fzninput->token, "float") )
1703  *type = FZN_FLOAT;
1704  else if( equalTokens(fzninput->token, "int") )
1705  *type = FZN_INT;
1706  else if( equalTokens(fzninput->token, "set") || isChar(fzninput->token, '{') )
1707  {
1708  SCIPwarningMessage(scip, "sets are not supported yet\n");
1709  fzninput->valid = FALSE;
1710  return;
1711  }
1712  else
1713  {
1714  /* the type is not explicitly given; it is given through the a range
1715  * expression; therefore, push back the current token since it
1716  * belongs to the range expression */
1717  pushToken(fzninput);
1718  parseRange(scip, fzninput, type, lb, ub);
1719 
1720  if( fzninput->haserror )
1721  return;
1722  }
1723 
1724  SCIPdebugMsg(scip, "range = [%g,%g]\n", *lb, *ub);
1725 
1726  assert(*lb <= *ub);
1727 }
1728 
1729 /** applies assignment */
1730 static
1732  SCIP* scip, /**< SCIP data structure */
1733  FZNINPUT* fzninput, /**< FZN reading data */
1734  SCIP_VAR* var, /**< variable to assign something */
1735  FZNNUMBERTYPE type, /**< number type */
1736  const char* assignment /**< assignment */
1737  )
1738 {
1739  FZNCONSTANT* constant;
1740  SCIP_VAR* linkVar;
1741  SCIP_Bool boolvalue;
1742  SCIP_Real realvalue;
1743  SCIP_Real fixvalue;
1744  SCIP_Real vals[] = {1.0,-1.0};
1745 
1746  linkVar = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) assignment);
1747  constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) assignment);
1748 
1749  realvalue = SCIP_INVALID;
1750  boolvalue = FALSE;
1751 
1752  if( linkVar == NULL )
1753  {
1754  if( isBoolExp(assignment, &boolvalue) && type == FZN_BOOL )
1755  fixvalue = (SCIP_Real) boolvalue;
1756  else if( isValue(assignment, &realvalue) && type != FZN_BOOL )
1757  fixvalue = realvalue;
1758  else if( constant != NULL )
1759  fixvalue = constant->value;
1760  else
1761  {
1762  syntaxError(scip, fzninput, "assignment is not recognizable");
1763  return SCIP_OKAY;
1764  }
1765 
1766  /* create fixing constraint */
1767  SCIP_CALL( createLinearCons(scip, "fixing", 1, &var, vals, fixvalue, fixvalue, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
1768  }
1769  else
1770  {
1771  SCIP_VAR** vars;
1772 
1773  SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
1774  vars[0] = var;
1775  vars[1] = linkVar;
1776 
1777  SCIP_CALL( createLinearCons(scip, "link", 2, vars, vals, 0.0, 0.0, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
1778 
1779  SCIPfreeBufferArray(scip, &vars);
1780  }
1781 
1782  return SCIP_OKAY;
1783 }
1784 
1785 /** applies constant assignment expression */
1786 static
1788  SCIP* scip, /**< SCIP data structure */
1789  FZNCONSTANT** constant, /**< pointer to constant */
1790  FZNINPUT* fzninput, /**< FZN reading data */
1791  const char* name, /**< constant name */
1792  FZNNUMBERTYPE type, /**< number type */
1793  const char* assignment /**< assignment to apply */
1794  )
1795 {
1796  SCIP_Bool boolvalue;
1797  SCIP_Real realvalue;
1798  SCIP_Real value;
1799 
1800  (*constant) = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) assignment);
1801  realvalue = SCIP_INVALID;
1802  boolvalue = FALSE;
1803 
1804  if( *constant != NULL )
1805  {
1806  /* check if the constant type fits */
1807  if( type != (*constant)->type )
1808  {
1809  syntaxError(scip, fzninput, "type error");
1810  return SCIP_OKAY;
1811  }
1812 
1813  value = (*constant)->value;
1814  }
1815  else if( isBoolExp(assignment, &boolvalue) && type == FZN_BOOL )
1816  {
1817  value = (SCIP_Real) boolvalue;
1818  }
1819  else if( isValue(assignment, &realvalue) && type != FZN_BOOL )
1820  {
1821  value = realvalue;
1822  }
1823  else
1824  {
1825  syntaxError(scip, fzninput, "assignment is not recognizable");
1826  return SCIP_OKAY;
1827  }
1828 
1829  /* get buffer memory for FZNCONSTANT struct */
1830  SCIP_CALL( SCIPallocBuffer(scip, constant) );
1831 
1832  (*constant)->type = type;
1833  SCIP_CALL( SCIPduplicateBufferArray(scip, &(*constant)->name, name, (int) strlen(name) + 1) );
1834  (*constant)->value = value;
1835 
1836  /* store constant */
1837  if( fzninput->sconstants == fzninput->nconstants )
1838  {
1839  assert(fzninput->sconstants > 0);
1840  fzninput->sconstants *= 2;
1841  SCIP_CALL( SCIPreallocBufferArray(scip, &fzninput->constants, fzninput->sconstants) );
1842  }
1843 
1844  assert(fzninput->sconstants > fzninput->nconstants);
1845  fzninput->constants[fzninput->nconstants] = *constant;
1846  fzninput->nconstants++;
1847 
1848  SCIP_CALL( SCIPhashtableInsert(fzninput->constantHashtable, (void*) (*constant)) );
1849 
1850  return SCIP_OKAY;
1851 }
1852 
1853 /** parse array type ( (i) variable or constant; (ii) integer, float, bool, or set) */
1854 static
1856  SCIP* scip, /**< SCIP data structure */
1857  FZNINPUT* fzninput, /**< FZN reading data */
1858  SCIP_Bool* isvararray, /**< pointer to store if it is a variable or constant array */
1859  FZNNUMBERTYPE* type, /**< pointer to store number type */
1860  SCIP_Real* lb, /**< pointer to store the lower bound */
1861  SCIP_Real* ub /**< pointer to store the lower bound */
1862  )
1863 {
1864  if( !getNextToken(scip, fzninput) || !equalTokens(fzninput->token, "of") )
1865  {
1866  syntaxError(scip, fzninput, "expected keyword <of>");
1867  return;
1868  }
1869 
1870  if( !getNextToken(scip, fzninput) )
1871  {
1872  syntaxError(scip, fzninput, "expected more tokens");
1873  return;
1874  }
1875 
1876  /* check if it is a variable or constant array */
1877  if( equalTokens(fzninput->token, "var") )
1878  *isvararray = TRUE;
1879  else
1880  {
1881  /* push token back since it belongs to the type declaration */
1882  pushToken(fzninput);
1883  *isvararray = FALSE;
1884  }
1885 
1886  /* pares array type and range */
1887  parseType(scip, fzninput, type, lb, ub);
1888 }
1889 
1890 /** parse an array assignment */
1891 static
1893  SCIP* scip, /**< SCIP data structure */
1894  FZNINPUT* fzninput, /**< FZN reading data */
1895  char*** elements, /**< pointer to string array to store the parsed elements */
1896  int* nelements, /**< pointer to store the number of parsed elements */
1897  int selements /**< size of the string array elements */
1898  )
1899 {
1900  assert(scip != NULL);
1901  assert(fzninput != NULL);
1902  assert(*nelements >= 0);
1903  assert(selements >= *nelements);
1904 
1905  /* check for opening brackets */
1906  if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '[') )
1907  {
1908  syntaxError(scip, fzninput, "expected token <[>");
1909  return SCIP_OKAY;
1910  }
1911 
1912  SCIP_CALL( parseList(scip, fzninput, elements, nelements, selements) );
1913 
1914  if( hasError(fzninput) )
1915  return SCIP_OKAY;
1916 
1917  /* check for closing brackets */
1918  if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, ']') )
1919  syntaxError(scip, fzninput, "expected token <]>");
1920 
1921  return SCIP_OKAY;
1922 }
1923 
1924 /** parse array dimension */
1925 static
1927  SCIP* scip, /**< SCIP data structure */
1928  FZNINPUT* fzninput, /**< FZN reading data */
1929  int* nelements /**< pointer to store the size of the array */
1930  )
1931 {
1932  FZNNUMBERTYPE type;
1933  SCIP_Real left;
1934  SCIP_Real right;
1935 
1936  if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '[') )
1937  {
1938  syntaxError(scip, fzninput, "expected token <[> for array dimension");
1939  return;
1940  }
1941 
1942  /* get array dimension */
1943  parseRange(scip, fzninput, &type, &left, &right);
1944 
1945  if( fzninput->haserror )
1946  return;
1947 
1948  if( type != FZN_INT || left != 1.0 || right <= 0.0 )
1949  {
1950  syntaxError(scip, fzninput, "invalid array dimension format");
1951  return;
1952  }
1953 
1954  *nelements = (int) right;
1955 
1956  if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, ']') )
1957  {
1958  syntaxError(scip, fzninput, "expected token <]> for array dimension");
1959  return;
1960  }
1961 }
1962 
1963 /** creates and adds a variable to SCIP and stores it for latter use in fzninput structure */
1964 static
1966  SCIP* scip, /**< SCIP data structure */
1967  FZNINPUT* fzninput, /**< FZN reading data */
1968  SCIP_VAR** var, /**< pointer to hold the created variable, or NULL */
1969  const char* name, /**< name of the variable */
1970  SCIP_Real lb, /**< lower bound of the variable */
1971  SCIP_Real ub, /**< upper bound of the variable */
1972  FZNNUMBERTYPE type /**< number type */
1973  )
1974 {
1975  SCIP_VAR* varcopy;
1976  SCIP_VARTYPE vartype;
1977 
1978  assert(scip != NULL);
1979  assert(fzninput != NULL);
1980  assert(lb <= ub);
1981 
1982  switch(type)
1983  {
1984  case FZN_BOOL:
1985  vartype = SCIP_VARTYPE_BINARY;
1986  break;
1987  case FZN_INT:
1988  vartype = SCIP_VARTYPE_INTEGER;
1989  break;
1990  case FZN_FLOAT:
1991  vartype = SCIP_VARTYPE_CONTINUOUS;
1992  break;
1993  default:
1994  syntaxError(scip, fzninput, "unknown variable type");
1995  return SCIP_OKAY;
1996  }
1997 
1998  /* create variable */
1999  SCIP_CALL( SCIPcreateVar(scip, &varcopy, name, lb, ub, 0.0, vartype, !(fzninput->dynamiccols), fzninput->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
2000  SCIP_CALL( SCIPaddVar(scip, varcopy) );
2001 
2002  SCIPdebugMsg(scip, "created variable\n");
2003  SCIPdebug( SCIP_CALL( SCIPprintVar(scip, varcopy, NULL) ) );
2004 
2005  /* variable name should not exist before */
2006  assert(SCIPhashtableRetrieve(fzninput->varHashtable, varcopy) == NULL);
2007 
2008  /* insert variable into the hashmap for later use in the constraint section */
2009  SCIP_CALL( SCIPhashtableInsert(fzninput->varHashtable, varcopy) );
2010 
2011  /* copy variable pointer before releasing the variable to keep the pointer to the variable */
2012  if( var != NULL )
2013  *var = varcopy;
2014 
2015  /* release variable */
2016  SCIP_CALL( SCIPreleaseVar(scip, &varcopy) );
2017 
2018  return SCIP_OKAY;
2019 }
2020 
2021 
2022 /** parse variable array assignment and create the variables */
2023 static
2025  SCIP* scip, /**< SCIP data structure */
2026  SCIP_READERDATA* readerdata, /**< reader data */
2027  FZNINPUT* fzninput, /**< FZN reading data */
2028  const char* name, /**< array name */
2029  int nvars, /**< number of variables */
2030  FZNNUMBERTYPE type, /**< number type */
2031  SCIP_Real lb, /**< lower bound of the variables */
2032  SCIP_Real ub, /**< lower bound of the variables */
2033  DIMENSIONS* info /**< dimension information */
2034  )
2035 {
2036  SCIP_VAR** vars;
2037  char varname[FZN_BUFFERLEN];
2038  int v;
2039 
2040  /* create variables and add them to the problem */
2041  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
2042 
2043  for( v = 0; v < nvars; ++v )
2044  {
2045  (void) SCIPsnprintf(varname, FZN_BUFFERLEN, "%s[%d]", name, v + 1);
2046 
2047  /* create variable */
2048  SCIP_CALL( createVariable(scip, fzninput, &vars[v], varname, lb, ub, type) );
2049  }
2050 
2051  if( !getNextToken(scip, fzninput) )
2052  {
2053  syntaxError(scip, fzninput, "expected semicolon");
2054  }
2055  else
2056  {
2057  if( isChar(fzninput->token, '=') )
2058  {
2059  char** assigns;
2060  int nassigns;
2061 
2062  SCIP_CALL( SCIPallocBufferArray(scip, &assigns, nvars) );
2063  nassigns = 0;
2064 
2065  SCIP_CALL( parseArrayAssignment(scip, fzninput, &assigns, &nassigns, nvars) );
2066 
2067  if(!hasError(fzninput) )
2068  {
2069  for( v = 0; v < nvars && !hasError(fzninput); ++v )
2070  {
2071  /* parse and apply assignment */
2072  SCIP_CALL( applyVariableAssignment(scip, fzninput, vars[v], type, assigns[v]) );
2073  }
2074  }
2075 
2076  freeStringBufferArray(scip, assigns, nassigns);
2077  }
2078  else
2079  {
2080  /* push back the ';' */
2081  assert( isEndStatement(fzninput) );
2082  pushToken(fzninput);
2083  }
2084 
2085  if( info != NULL )
2086  {
2087  SCIP_CALL( readerdataAddOutputvararray(scip, readerdata, name, vars, nvars, type, info) );
2088  }
2089 
2090  /* add variable information to fzninput since this array name might be used later in the fzn file */
2091  SCIP_CALL( fzninputAddVararray(scip, fzninput, name, vars, nvars, type, info) );
2092  }
2093 
2094  SCIPfreeBufferArray(scip, &vars);
2095 
2096  return SCIP_OKAY;
2097 }
2098 
2099 /** parse constant array assignment and create the constants */
2100 static
2102  SCIP* scip, /**< SCIP data structure */
2103  FZNINPUT* fzninput, /**< FZN reading data */
2104  const char* name, /**< array name */
2105  int nconstants, /**< number of constants */
2106  FZNNUMBERTYPE type /**< number type */
2107  )
2108 {
2109  FZNCONSTANT** constants;
2110  char** assigns;
2111  char constantname[FZN_BUFFERLEN];
2112  int nassigns;
2113  int c;
2114 
2115  if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '=') )
2116  {
2117  syntaxError(scip, fzninput, "expected token <=>");
2118  return SCIP_OKAY;
2119  }
2120 
2121  SCIP_CALL( SCIPallocBufferArray(scip, &assigns, nconstants) );
2122  SCIP_CALL( SCIPallocBufferArray(scip, &constants, nconstants) );
2123  nassigns = 0;
2124 
2125  SCIP_CALL( parseArrayAssignment(scip, fzninput, &assigns, &nassigns, nconstants) );
2126 
2127  if( !hasError(fzninput) )
2128  {
2129  for( c = 0; c < nconstants; ++c )
2130  {
2131  (void) SCIPsnprintf(constantname, FZN_BUFFERLEN, "%s[%d]", name, c + 1);
2132  SCIP_CALL( createConstantAssignment(scip, &constants[c], fzninput, constantname, type, assigns[c]) );
2133  }
2134 
2135  /* add variable information to fzninput since this array name might be used later in the fzn file */
2136  SCIP_CALL( fzninputAddConstarray(scip, fzninput, name, constants, nconstants, type) );
2137  }
2138 
2139  SCIPfreeBufferArray(scip, &constants);
2140  freeStringBufferArray(scip, assigns, nassigns);
2141 
2142  return SCIP_OKAY;
2143 }
2144 
2145 /** parse predicate expression */
2146 static
2148  SCIP* scip, /**< SCIP data structure */
2149  FZNINPUT* fzninput /**< FZN reading data */
2150  )
2151 {
2152  assert(scip != NULL);
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(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(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(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(type, "minus") )
2793  rhs += value;
2794  else
2795  rhs -= value;
2796  }
2797  else
2798  {
2799  if( equalTokens(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(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(fname, "int2float") && !equalTokens(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(ftokens[0], "set") )
2905  return SCIP_OKAY;
2906 
2907  fzninput->valid = FALSE;
2908  SCIPwarningMessage(scip, "Line %d: set operations are not supported yet.\n", fzninput->linenumber);
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(ftokens[0], "array") )
2922  return SCIP_OKAY;
2923 
2924  fzninput->valid = FALSE;
2925  SCIPwarningMessage(scip, "Line %d: array operations are not supported yet.\n", fzninput->linenumber);
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(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(ftokens[1], "eq") || equalTokens(ftokens[1], "ge") || equalTokens(ftokens[1], "le")
2948  || equalTokens(ftokens[1], "lt") || equalTokens(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(ftokens[1], "ne") || equalTokens(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(ftokens[1], "ne" ) || equalTokens(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(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(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(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(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(ftokens[2], "or" ) && !equalTokens(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(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(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(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(ftokens[nftokens - 1], "reif") )
3134  {
3135  SCIPwarningMessage(scip, "Line %d: reified constraints are not supported.\n", fzninput->linenumber);
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(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(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(ftokens[0], "float") &&
3176  (equalTokens(ftokens[nftokens - 1], "lt") || equalTokens(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(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, &vals);
3250  SCIPfreeBufferArray(scip, &vars);
3251  }
3252  else if( equalTokens(ftokens[1], "minus") || equalTokens(ftokens[1], "plus") || equalTokens(ftokens[1], "negate") )
3253  {
3254  assert(nftokens == 2);
3255  SCIP_CALL( parseAggregation(scip, fzninput, fname, ftokens[1]) );
3256  }
3257  else if( equalTokens(ftokens[1], "eq") || equalTokens(ftokens[1], "le") || equalTokens(ftokens[1], "ge")
3258  || equalTokens(ftokens[1], "lt") || equalTokens(ftokens[1], "gt") )
3259  {
3260  assert(nftokens == 2);
3261  SCIP_CALL( parseLinking(scip, fzninput, fname, ftokens[1], 0.0) );
3262  }
3263  else if( equalTokens(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(ftokens[0], "all") || !equalTokens(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(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 const 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, "Line %d: Constraint <%s> is not supported yet.\n", fzninput->linenumber, 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(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(fzninput->token, "satisfy")
3583  && !equalTokens(fzninput->token, "minimize")
3584  && !equalTokens(fzninput->token, "maximize") );
3585  }
3586 
3587  if( equalTokens(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(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(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(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, &vals);
3708  SCIPfreeBufferArray(scip, &vars);
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(fzninput->token, "predicate") )
3755  {
3756  /* parse array expression containing constants or variables */
3757  SCIP_CALL( parsePredicate(scip, fzninput) );
3758  }
3759  else if( equalTokens(fzninput->token, "array") )
3760  {
3761  /* parse array expression containing constants or variables */
3762  SCIP_CALL( parseArray(scip, readerdata, fzninput) );
3763  }
3764  else if( equalTokens(fzninput->token, "constraint") )
3765  {
3766  /* parse a constraint */
3767  SCIP_CALL( parseConstraint(scip, fzninput) );
3768  }
3769  else if( equalTokens(fzninput->token, "int") )
3770  {
3771  /* parse an integer constant */
3772  SCIP_CALL( parseConstant(scip, fzninput, FZN_INT) );
3773  }
3774  else if( equalTokens(fzninput->token, "float") )
3775  {
3776  /* parse a float constant */
3777  SCIP_CALL( parseConstant(scip, fzninput, FZN_FLOAT) );
3778  }
3779  else if( equalTokens(fzninput->token, "bool") )
3780  {
3781  /* parse a bool constant */
3782  SCIP_CALL( parseConstant(scip, fzninput, FZN_BOOL) );
3783  }
3784  else if( equalTokens(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(fzninput->token, "solve") )
3792  {
3793  /* parse solve item (objective sense and objective function) */
3794  SCIP_CALL( parseSolveItem(scip, fzninput) );
3795  }
3796  else if( equalTokens(fzninput->token, "var") )
3797  {
3798  /* parse variables */
3799  SCIP_CALL( parseVariable(scip, readerdata, fzninput) );
3800  }
3801  else if( equalTokens(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(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  {
3923  if( *nvars > 0 && (vars == NULL || scalars == NULL) ) /*lint !e774 !e845*/
3924  {
3925  SCIPerrorMessage("Null pointer"); /* should not happen */
3926  SCIPABORT();
3927  return SCIP_INVALIDDATA; /*lint !e527*/
3928  }
3929 
3930  for( v = 0; v < *nvars; ++v )
3931  {
3932  assert(vars != NULL);
3933  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalars[v], constant) );
3934  }
3935  }
3936 
3937  return SCIP_OKAY;
3938 }
3939 
3940 /** ends the given line with '\\0' and prints it to the given file stream */
3941 static
3943  SCIP* scip, /**< SCIP data structure */
3944  FILE* file, /**< output file (or NULL for standard output) */
3945  char* buffer, /**< line */
3946  int bufferpos /**< number of characters in buffer */
3947  )
3948 {
3949  assert( scip != NULL );
3950  assert( buffer != NULL );
3951 
3952  if( bufferpos > 0 )
3953  {
3954  buffer[bufferpos] = '\0';
3955 
3956  SCIPinfoMessage(scip, file, "%s", buffer);
3957  }
3958 }
3959 
3960 /** appends extension to line and prints it to the give file stream if the line buffer get full */
3961 static
3963  SCIP* scip, /**< SCIP data structure */
3964  char** buffer, /**< buffer which should be extended */
3965  int* bufferlen, /**< length of the buffer */
3966  int* bufferpos, /**< current position in the buffer */
3967  const char* extension /**< string to extend the line */
3968  )
3969 {
3970  int newpos;
3971  int extlen;
3972 
3973  assert( scip != NULL );
3974  assert( buffer != NULL );
3975  assert( bufferlen != NULL );
3976  assert( bufferpos != NULL );
3977  assert( extension != NULL );
3978 
3979  /* avoid overflow by reallocation */
3980  extlen = (int)strlen(extension);
3981  newpos = (*bufferpos) + extlen;
3982  if( newpos >= (*bufferlen) )
3983  {
3984  *bufferlen = MAX( newpos, 2 * (*bufferlen) );
3985 
3986  SCIP_CALL( SCIPreallocBufferArray(scip, buffer, (*bufferlen)));
3987  }
3988 
3989  /* append extension to linebuffer (+1 because of '\0') */
3990  (void)SCIPstrncpy((*buffer) + (*bufferpos), extension, extlen + 1);
3991  *bufferpos = newpos;
3992 
3993  return SCIP_OKAY;
3994 }
3995 
3996 /* Writes a real value to a string with full precision, if fractional and adds a ".0" if integral */
3997 static
3999  SCIP* scip, /**< SCIP data structure */
4000  SCIP_Real val, /**< value to flatten */
4001  char* buffer /**< string buffer to print in */
4002  )
4003 {
4004  if( SCIPisIntegral(scip, val) )
4005  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.1f", SCIPround(scip, val));
4006  else
4007  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%+.15g", val);
4008 }
4009 
4010 /* print row in FZN format to file stream */
4011 static
4013  SCIP* scip, /**< SCIP data structure */
4014  FZNOUTPUT* fznoutput, /**< output data structure containing the buffers to write to */
4015  const char* type, /**< row type ("eq", "le" or "ge") */
4016  SCIP_VAR** vars, /**< array of variables */
4017  SCIP_Real* vals, /**< array of values */
4018  int nvars, /**< number of variables */
4019  SCIP_Real rhs, /**< right hand side */
4020  SCIP_Bool hasfloats /**< are there continuous variables or coefficients in the constraint? */
4021  )
4022 {
4023  SCIP_VAR* var; /* some variable */
4024  int v; /* variable counter */
4025  char buffer[FZN_BUFFERLEN];
4026  char buffy[FZN_BUFFERLEN];
4027 
4028  assert( scip != NULL );
4029  assert( vars != NULL || nvars == 0 );
4030  assert( strcmp(type, "eq") == 0 || strcmp(type, "le") == 0 || strcmp(type, "ge") == 0 );
4031 
4032  /* Add a constraint of type float_lin or int_lin, depending on whether there are continuous variables or coefficients */
4033  SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), "constraint ") );
4034  if( hasfloats )
4035  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "float_lin_%s([", type);
4036  else
4037  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "int_lin_%s([", type);
4038  SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
4039 
4040  /* print all coefficients but the last one */
4041  for( v = 0; v < nvars-1; ++v )
4042  {
4043  if( hasfloats )
4044  {
4045  flattenFloat(scip, vals[v], buffy);
4046  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s, ", buffy);
4047  }
4048  else
4049  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.f, ", vals[v]);
4050  SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
4051  }
4052 
4053  /* print last coefficient */
4054  if( nvars > 0 )
4055  {
4056  if( hasfloats )
4057  {
4058  flattenFloat(scip, vals[nvars-1], buffy);
4059  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s", buffy);
4060  }
4061  else
4062  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.f", vals[nvars-1]);
4063 
4064  SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
4065  }
4066 
4067  SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), "], [") );
4068 
4069  /* print all variables but the last one */
4070  for( v = 0; v < nvars-1; ++v )
4071  {
4072  var = vars[v]; /*lint !e613*/
4073  assert( var != NULL );
4074 
4075  if( hasfloats )
4076  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s%s, ", SCIPvarGetName(var), SCIPvarGetProbindex(var) < fznoutput->ndiscretevars ? "_float" : "");
4077  else
4078  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s, ", SCIPvarGetName(var) );
4079  SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
4080  }
4081 
4082  /* print last variable */
4083  if( nvars > 0 )
4084  {
4085  assert(vars != NULL); /* for lint */
4086  if( hasfloats )
4087  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s%s",SCIPvarGetName(vars[nvars-1]),
4088  SCIPvarGetProbindex(vars[nvars-1]) < fznoutput->ndiscretevars ? "_float" : ""); /*lint !e613*/
4089  else
4090  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s", SCIPvarGetName(vars[nvars-1])); /*lint !e613*/
4091 
4092  SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos),buffer) );
4093  }
4094 
4095  SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), "], ") );
4096 
4097  /* print right hand side */
4098  if( SCIPisZero(scip, rhs) )
4099  rhs = 0.0;
4100 
4101  if( hasfloats )
4102  {
4103  flattenFloat(scip, rhs, buffy);
4104  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s);\n", buffy);
4105  }
4106  else
4107  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.f);\n", rhs);
4108  SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos),buffer) );
4109 
4110  return SCIP_OKAY;
4111 }
4112 
4113 /** prints given linear constraint information in FZN format to file stream */
4114 static
4116  SCIP* scip, /**< SCIP data structure */
4117  FZNOUTPUT* fznoutput, /**< output data structure containing the buffers to write to */
4118  SCIP_VAR** vars, /**< array of variables */
4119  SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
4120  int nvars, /**< number of variables */
4121  SCIP_Real lhs, /**< left hand side */
4122  SCIP_Real rhs, /**< right hand side */
4123  SCIP_Bool transformed, /**< transformed constraint? */
4124  SCIP_Bool mayhavefloats /**< may there be continuous variables in the constraint? */
4125  )
4126 {
4127  SCIP_VAR** activevars; /* active problem variables of a constraint */
4128  SCIP_Real* activevals; /* coefficients in the active representation */
4129 
4130  SCIP_Real activeconstant; /* offset (e.g., due to fixings) in the active representation */
4131  int nactivevars; /* number of active problem variables */
4132  int v; /* variable counter */
4133 
4134  char buffer[FZN_BUFFERLEN];
4135  SCIP_Bool hasfloats;
4136 
4137  assert( scip != NULL );
4138  assert( vars != NULL || nvars == 0 );
4139  assert( fznoutput != NULL );
4140  assert( lhs <= rhs );
4141 
4142  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
4143  return SCIP_OKAY;
4144 
4145  /* duplicate variable and value array */
4146  nactivevars = nvars;
4147  hasfloats = FALSE;
4148  activevars = NULL;
4149  activeconstant = 0.0;
4150 
4151  if( vars != NULL )
4152  {
4153  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
4154  }
4155 
4156  if( vals != NULL )
4157  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
4158  else
4159  {
4160  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
4161 
4162  for( v = 0; v < nactivevars; ++v )
4163  activevals[v] = 1.0;
4164  }
4165 
4166  /* retransform given variables to active variables */
4167  if( nactivevars > 0 )
4168  {
4169  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
4170  }
4171 
4172  /* If there may be continuous variables or coefficients in the constraint, scan for them */
4173  if( mayhavefloats )
4174  {
4175  /* fractional sides trigger a constraint to be of float type */
4176  if( !SCIPisInfinity(scip, -lhs) )
4177  hasfloats = hasfloats || !SCIPisIntegral(scip, lhs-activeconstant);
4178  if( !SCIPisInfinity(scip, rhs) )
4179  hasfloats = hasfloats || !SCIPisIntegral(scip, rhs-activeconstant);
4180 
4181  /* any continuous variable or fractional variable coefficient triggers a constraint to be of float type */
4182  for( v = 0; v < nactivevars && !hasfloats; v++ )
4183  {
4184  SCIP_VAR* var;
4185 
4186  assert(activevars != 0);
4187  var = activevars[v];
4188 
4189  hasfloats = hasfloats || (SCIPvarGetType(var) != SCIP_VARTYPE_BINARY && SCIPvarGetType(var) != SCIP_VARTYPE_INTEGER);
4190  hasfloats = hasfloats || !SCIPisIntegral(scip, activevals[v]);
4191  }
4192 
4193  /* If the constraint has to be written as float type, all discrete variables need to have a float counterpart */
4194  if( hasfloats )
4195  {
4196  for( v = 0; v < nactivevars; v++ )
4197  {
4198  SCIP_VAR* var;
4199  int idx;
4200 
4201  assert(activevars != 0);
4202  var = activevars[v];
4203  idx = SCIPvarGetProbindex(var);
4204  assert( idx >= 0);
4205 
4206  /* If there was no float representation of the variable before, add an auxiliary variable and a conversion constraint */
4207  if( idx < fznoutput->ndiscretevars && !fznoutput->varhasfloat[idx] )
4208  {
4210 
4211  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "var float: %s_float;\n", SCIPvarGetName(var));
4212  SCIP_CALL( appendBuffer(scip, &(fznoutput->varbuffer), &(fznoutput->varbufferlen), &(fznoutput->varbufferpos),buffer) );
4213 
4214  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "constraint int2float(%s, %s_float);\n", SCIPvarGetName(var), SCIPvarGetName(var));
4215  SCIP_CALL( appendBuffer(scip, &(fznoutput->castbuffer), &(fznoutput->castbufferlen), &(fznoutput->castbufferpos),buffer) );
4216 
4217  fznoutput->varhasfloat[idx] = TRUE;
4218  }
4219  }
4220  }
4221  }
4222 
4223  if( SCIPisEQ(scip, lhs, rhs) )
4224  {
4225  assert( !SCIPisInfinity(scip, rhs) );
4226 
4227  /* equality constraint */
4228  SCIP_CALL( printRow(scip, fznoutput, "eq", activevars, activevals, nactivevars, rhs - activeconstant, hasfloats) );
4229  }
4230  else
4231  {
4232  if( !SCIPisInfinity(scip, -lhs) )
4233  {
4234  /* print inequality ">=" */
4235  SCIP_CALL( printRow(scip, fznoutput, "ge", activevars, activevals, nactivevars, lhs - activeconstant, hasfloats) );
4236  }
4237 
4238  if( !SCIPisInfinity(scip, rhs) )
4239  {
4240  /* print inequality "<=" */
4241  SCIP_CALL( printRow(scip, fznoutput, "le", activevars, activevals, nactivevars, rhs - activeconstant, hasfloats) );
4242  }
4243  }
4244 
4245  /* free buffer arrays */
4246  if( activevars != NULL )
4247  SCIPfreeBufferArray(scip, &activevars);
4248  SCIPfreeBufferArray(scip, &activevals);
4249 
4250  return SCIP_OKAY;
4251 }
4252 
4253 /* writes problem to a flatzinc conform file, including introduction of several auxiliary variables and constraints */
4254 static
4256  SCIP* scip, /**< SCIP data structure */
4257  FILE* file, /**< output file, or NULL if standard output should be used */
4258  const char* name, /**< problem name */
4259  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4260  SCIP_OBJSENSE objsense, /**< objective sense */
4261  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4262  * extobj = objsense * objscale * (intobj + objoffset) */
4263  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4264  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
4265  int nvars, /**< number of active variables in the problem */
4266  int nbinvars, /**< number of binary variables */
4267  int nintvars, /**< number of general integer variables */
4268  int nimplvars, /**< number of implicit integer variables */
4269  int ncontvars, /**< number of continuous variables */
4270  SCIP_CONS** conss, /**< array with constraints of the problem */
4271  int nconss, /**< number of constraints in the problem */
4272  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4273  )
4274 {
4275  FZNOUTPUT fznoutput; /* data structure for writing in fzn format */
4276 
4277  SCIP_CONSHDLR* conshdlr;
4278  SCIP_CONS* cons;
4279  const char* conshdlrname;
4280  SCIP_VAR** consvars; /* variables of a specific constraint */
4281  SCIP_VAR* var;
4282  SCIP_BOUNDTYPE* boundtypes; /* indicates whether to which side the variables are bounded */
4283  SCIP_Real* consvals; /* coefficients of a specific constraint */
4284 
4285  int* boundedvars; /* variables which are bounded to exactly one side */
4286  int* floatobjvars; /* discrete variables which have a fractional objective coefficient */
4287  int* intobjvars; /* discrete variables which have an integral objective coefficient */
4288 
4289  SCIP_Real lb; /* lower bound of some variable */
4290  SCIP_Real ub; /* upper bound of some variable */
4291 
4292  int nboundedvars; /* number of variables which are bounded to exactly one side */
4293  int nconsvars; /* number of variables appearing in a specific constraint */
4294  int nfloatobjvars; /* number of discrete variables which have a fractional objective coefficient */
4295  int nintobjvars; /* number of discrete variables which have an integral objective coefficient */
4296  int c; /* counter for the constraints */
4297  int v; /* counter for the variables */
4298  const int ndiscretevars = nbinvars+nintvars; /* number of discrete variables */
4299 
4300  char varname[SCIP_MAXSTRLEN]; /* buffer for storing variable names */
4301  char buffer[FZN_BUFFERLEN]; /* buffer for storing auxiliary variables and constraints */
4302  char buffy[FZN_BUFFERLEN];
4303 
4304  assert( scip != NULL );
4305 
4306  /* print problem statistics as comment to file */
4307  SCIPinfoMessage(scip, file, "%% SCIP STATISTICS\n");
4308  SCIPinfoMessage(scip, file, "%% Problem name : %s\n", name);
4309  SCIPinfoMessage(scip, file, "%% Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
4310  nvars, nbinvars, nintvars, nimplvars, ncontvars);
4311  SCIPinfoMessage(scip, file, "%% Constraints : %d\n", nconss);
4312 
4313  SCIP_CALL( SCIPallocBufferArray(scip, &boundedvars, nvars) );
4314  SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nvars) );
4315  nboundedvars = 0;
4316 
4317  if( nvars > 0 )
4318  SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Problem variables %%%%%%%%%%%%\n");
4319 
4320  /* write all (active) problem variables */
4321  for( v = 0; v < nvars; v++ )
4322  {
4323  var = vars[v];
4324  assert( var != NULL );
4325  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s", SCIPvarGetName(var) );
4326 
4327  if( transformed )
4328  {
4329  /* in case the transformed is written only local bounds are posted which are valid in the current node */
4330  lb = SCIPvarGetLbLocal(var);
4331  ub = SCIPvarGetUbLocal(var);
4332  }
4333  else
4334  {
4335  lb = SCIPvarGetLbOriginal(var);
4336  ub = SCIPvarGetUbOriginal(var);
4337  }
4338 
4339  /* If a variable is bounded to both sides, the bounds are added to the declaration,
4340  * for variables bounded to exactly one side, an auxiliary constraint will be added later-on.
4341  */
4342  if( !SCIPisInfinity(scip, -lb) && !SCIPisInfinity(scip, ub) )
4343  {
4344  SCIP_Bool fixed;
4345  fixed = FALSE;
4346 
4347  if( SCIPisEQ(scip, lb, ub) )
4348  fixed = TRUE;
4349 
4350  if( v < ndiscretevars )
4351  {
4352  assert( SCIPisFeasIntegral(scip, lb) && SCIPisFeasIntegral(scip, ub) );
4353 
4354  if( fixed )
4355  SCIPinfoMessage(scip, file, "var int: %s = %.f;\n", varname, lb);
4356  else
4357  SCIPinfoMessage(scip, file, "var %.f..%.f: %s;\n", lb, ub, varname);
4358  }
4359  else
4360  {
4361  /* Real valued bounds have to be made type conform */
4362  if( fixed )
4363  {
4364  flattenFloat(scip, lb, buffy);
4365  SCIPinfoMessage(scip, file, "var float: %s = %s;\n", varname, buffy);
4366  }
4367  else
4368  {
4369  char buffy2[FZN_BUFFERLEN];
4370 
4371  flattenFloat(scip, lb, buffy);
4372  flattenFloat(scip, ub, buffy2);
4373  SCIPinfoMessage(scip, file, "var %s..%s: %s;\n", buffy, buffy2, varname);
4374  }
4375  }
4376  }
4377  else
4378  {
4379  assert(SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
4380  assert( v >= nbinvars );
4381 
4382  /* declare the variable without any bound */
4383  if( v < ndiscretevars )
4384  SCIPinfoMessage(scip, file, "var int: %s;\n", varname);
4385  else
4386  SCIPinfoMessage(scip, file, "var float: %s;\n", varname);
4387 
4388  /* if there is a bound, store the variable and its boundtype for adding a corresponding constraint later-on */
4389  if( ! SCIPisInfinity(scip, ub) )
4390  {
4391  boundedvars[nboundedvars] = v;
4392  boundtypes[nboundedvars] = SCIP_BOUNDTYPE_UPPER;
4393  nboundedvars++;
4394  }
4395  if( ! SCIPisInfinity(scip, -lb) )
4396  {
4397  boundedvars[nboundedvars] = v;
4398  boundtypes[nboundedvars] = SCIP_BOUNDTYPE_LOWER;
4399  nboundedvars++;
4400  }
4401  }
4402  }
4403 
4404  /* set up the datastructures for the auxiliary int2float variables, the casting constraints and the problem constraints */
4405  fznoutput.ndiscretevars = ndiscretevars;
4406  fznoutput.varbufferpos = 0;
4407  fznoutput.consbufferpos = 0;
4408  fznoutput.castbufferpos = 0;
4409 
4410  SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.varhasfloat, ndiscretevars) );
4411  SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.varbuffer, FZN_BUFFERLEN) );
4412  SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.castbuffer, FZN_BUFFERLEN) );
4413  SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.consbuffer, FZN_BUFFERLEN) );
4414  fznoutput.consbufferlen = FZN_BUFFERLEN;
4415  fznoutput.varbufferlen = FZN_BUFFERLEN;
4416  fznoutput.castbufferlen = FZN_BUFFERLEN;
4417 
4418  for( v = 0; v < ndiscretevars; v++ )
4419  fznoutput.varhasfloat[v] = FALSE;
4420  fznoutput.varbuffer[0] = '\0';
4421  fznoutput.consbuffer[0] = '\0';
4422  fznoutput.castbuffer[0] = '\0';
4423 
4424  /* output all problem constraints */
4425  for( c = 0; c < nconss; c++ )
4426  {
4427  cons = conss[c];
4428  assert( cons != NULL);
4429 
4430  /* in case the transformed is written only constraint are posted which are enabled in the current node */
4431  assert(!transformed || SCIPconsIsEnabled(cons));
4432 
4433  conshdlr = SCIPconsGetHdlr(cons);
4434  assert( conshdlr != NULL );
4435 
4436  conshdlrname = SCIPconshdlrGetName(conshdlr);
4437  assert( transformed == SCIPconsIsTransformed(cons) );
4438 
4439  /* By now, only linear, setppc, logicor, knapsack, and varbound constraints can be written.
4440  * Since they are all linearizable, a linear representation of them is written.
4441  */
4442  if( strcmp(conshdlrname, "linear") == 0 )
4443  {
4444  SCIP_CALL( printLinearCons(scip, &fznoutput,
4445  SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
4446  SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), transformed, TRUE) );
4447  }
4448  else if( strcmp(conshdlrname, "setppc") == 0 )
4449  {
4450  consvars = SCIPgetVarsSetppc(scip, cons);
4451  nconsvars = SCIPgetNVarsSetppc(scip, cons);
4452 
4453  /* Setppc constraints only differ in their lhs/rhs (+- INF or 1) */
4454  switch( SCIPgetTypeSetppc(scip, cons) )
4455  {
4457  SCIP_CALL( printLinearCons(scip, &fznoutput,
4458  consvars, NULL, nconsvars, 1.0, 1.0, transformed, FALSE) );
4459  break;
4461  SCIP_CALL( printLinearCons(scip, &fznoutput,
4462  consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, transformed, FALSE) );
4463  break;
4465  SCIP_CALL( printLinearCons(scip, &fznoutput,
4466  consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), transformed, FALSE) );
4467  break;
4468  }
4469  }
4470  else if( strcmp(conshdlrname, "logicor") == 0 )
4471  {
4472  SCIP_CALL( printLinearCons(scip, &fznoutput,
4473  SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons),
4474  1.0, SCIPinfinity(scip), transformed, FALSE) );
4475  }
4476  else if( strcmp(conshdlrname, "knapsack") == 0 )
4477  {
4478  SCIP_Longint* weights;
4479 
4480  consvars = SCIPgetVarsKnapsack(scip, cons);
4481  nconsvars = SCIPgetNVarsKnapsack(scip, cons);
4482 
4483  /* copy Longint array to SCIP_Real array */
4484  weights = SCIPgetWeightsKnapsack(scip, cons);
4485  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
4486  for( v = 0; v < nconsvars; ++v )
4487  consvals[v] = (SCIP_Real)weights[v];
4488 
4489  SCIP_CALL( printLinearCons(scip, &fznoutput, consvars, consvals, nconsvars, -SCIPinfinity(scip),
4490  (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), transformed, FALSE) );
4491 
4492  SCIPfreeBufferArray(scip, &consvals);
4493  }
4494  else if( strcmp(conshdlrname, "varbound") == 0 )
4495  {
4496  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
4497  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
4498 
4499  consvars[0] = SCIPgetVarVarbound(scip, cons);
4500  consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
4501 
4502  consvals[0] = 1.0;
4503  consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
4504 
4505  /* Varbound constraints always consist of exactly two variables */
4506  SCIP_CALL( printLinearCons(scip, &fznoutput,
4507  consvars, consvals, 2,
4508  SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons), transformed, TRUE) );
4509 
4510  SCIPfreeBufferArray(scip, &consvars);
4511  SCIPfreeBufferArray(scip, &consvals);
4512  }
4513  else if( strcmp(conshdlrname, "cumulative") == 0 )
4514  {
4515  int* intvals;
4516 
4517  consvars = SCIPgetVarsCumulative(scip, cons);
4518  nconsvars = SCIPgetNVarsCumulative(scip, cons);
4519 
4520  SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), "cumulative([") );
4521 
4522  for( v = 0; v < nconsvars; ++v )
4523  {
4524  if( v < nconsvars - 1)
4525  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s, ", SCIPvarGetName(consvars[v]) );
4526  else
4527  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s", SCIPvarGetName(consvars[v]) );
4528 
4529  SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), varname) );
4530  }
4531 
4532  SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), "], [") );
4533 
4534  intvals = SCIPgetDurationsCumulative(scip, cons);
4535 
4536  for( v = 0; v < nconsvars; ++v )
4537  {
4538  if( v < nconsvars - 1)
4539  (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d, ", intvals[v] );
4540  else
4541  (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d", intvals[v] );
4542 
4543  SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), buffy) );
4544  }
4545 
4546  SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), "], [") );
4547 
4548  intvals = SCIPgetDemandsCumulative(scip, cons);
4549 
4550  for( v = 0; v < nconsvars; ++v )
4551  {
4552  if( v < nconsvars - 1)
4553  (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d, ", intvals[v] );
4554  else
4555  (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d", intvals[v] );
4556 
4557  SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), buffy) );
4558  }
4559  (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "], %d);\n", SCIPgetCapacityCumulative(scip, cons) );
4560 
4561  SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), buffy) );
4562  }
4563  else
4564  {
4565  SCIPwarningMessage(scip, "constraint handler <%s> cannot print flatzinc format\n", conshdlrname );
4566  }
4567  }
4568 
4569  SCIP_CALL( SCIPallocBufferArray(scip,&intobjvars,ndiscretevars) );
4570  SCIP_CALL( SCIPallocBufferArray(scip,&floatobjvars,nvars) );
4571  nintobjvars = 0;
4572  nfloatobjvars = 0;
4573 
4574  /* scan objective function: Which variables have to be put to the float part, which to the int part? */
4575  for( v = 0; v < nvars; v++ )
4576  {
4577  SCIP_Real obj;
4578 
4579  var = vars[v];
4580  obj = SCIPvarGetObj(var);
4581 
4582  if( !SCIPisZero(scip,obj) )
4583  {
4584  /* only discrete variables with integral objective coefficient will be put to the int part of the objective */
4585  if( v < ndiscretevars && SCIPisIntegral(scip, objscale*obj) )
4586  {
4587  intobjvars[nintobjvars] = v;
4588  SCIPdebugMsg(scip, "variable <%s> at pos <%d,%d> has an integral obj: %f=%f*%f\n",
4589  SCIPvarGetName(var), nintobjvars, v, obj, objscale, SCIPvarGetObj(var));
4590  nintobjvars++;
4591  }
4592  else
4593  {
4594  /* if not happened yet, introduce an auxiliary variable for discrete variables with fractional coefficients */
4595  if( v < ndiscretevars && !fznoutput.varhasfloat[v] )
4596  {
4598 
4599  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "var float: %s_float;\n", SCIPvarGetName(var));
4600  SCIP_CALL( appendBuffer(scip, &(fznoutput.varbuffer), &(fznoutput.varbufferlen), &(fznoutput.varbufferpos),buffer) );
4601 
4602  (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "constraint int2float(%s, %s_float);\n", SCIPvarGetName(var), SCIPvarGetName(var));
4603  SCIP_CALL( appendBuffer(scip, &(fznoutput.castbuffer), &(fznoutput.castbufferlen), &(fznoutput.castbufferpos),buffer) );
4604 
4605  fznoutput.varhasfloat[v] = TRUE;
4606  }
4607 
4608  floatobjvars[nfloatobjvars] = v;
4609  nfloatobjvars++;
4610  }
4611  }
4612  }
4613 
4614  /* output all created auxiliary variables (float equivalents of discrete variables) */
4615  if( fznoutput.varbufferpos > 0 )
4616  {
4617  SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Auxiliary variables %%%%%%%%%%%%\n");
4618  writeBuffer(scip, file, fznoutput.varbuffer, fznoutput.varbufferpos );
4619  }
4620 
4621  /* output all int2float casting/conversion constraints */
4622  if( fznoutput.castbufferpos > 0 )
4623  {
4624  SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Variable conversions %%%%%%%%%%%%\n");
4625  writeBuffer(scip, file, fznoutput.castbuffer, fznoutput.castbufferpos );
4626  }
4627 
4628  if( nboundedvars > 0 )
4629  SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Variable bounds %%%%%%%%%%%%\n");
4630 
4631  /* output all bounds of variables with exactly one bound*/
4632  for( v = 0; v < nboundedvars; v++ )
4633  {
4634  var = vars[boundedvars[v]];
4635 
4636  if( SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER )
4637  {
4638  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
4639  SCIPinfoMessage(scip, file,"constraint int_ge(%s, %.f);\n",SCIPvarGetName(var),
4640  transformed ? SCIPvarGetLbLocal(var) : SCIPvarGetLbOriginal(var));
4641  else
4642  {
4643  assert( boundtypes[v] == SCIP_BOUNDTYPE_UPPER );
4644  SCIPinfoMessage(scip, file,"constraint int_le(%s, %.f);\n",SCIPvarGetName(var),
4645  transformed ? SCIPvarGetUbLocal(var) : SCIPvarGetUbOriginal(var));
4646  }
4647  }
4648  else
4649  {
4651 
4652  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
4653  {
4654  flattenFloat(scip, transformed ? SCIPvarGetLbLocal(var) : SCIPvarGetLbOriginal(var), buffy);
4655  SCIPinfoMessage(scip, file,"constraint float_ge(%s, %s);\n", SCIPvarGetName(var), buffy);
4656  }
4657  else
4658  {
4659  assert( boundtypes[v] == SCIP_BOUNDTYPE_UPPER );
4660  flattenFloat(scip, transformed ? SCIPvarGetUbLocal(var) : SCIPvarGetUbOriginal(var), buffy);
4661  SCIPinfoMessage(scip, file,"constraint float_le(%s, %s);\n",SCIPvarGetName(var), buffy);
4662  }
4663  }
4664  }
4665 
4666  /* output all problem constraints */
4667  if( fznoutput.consbufferpos > 0 )
4668  {
4669  SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Problem constraints %%%%%%%%%%%%\n");
4670  writeBuffer(scip, file, fznoutput.consbuffer, fznoutput.consbufferpos );
4671  }
4672 
4673  SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Objective function %%%%%%%%%%%%\n");
4674 
4675  /* If there is at least one variable in the objective function write down the optimization problem, else declare it to be a satisfiability problem */
4676  if( nintobjvars > 0 || nfloatobjvars > 0 )
4677  {
4678  SCIPinfoMessage(scip, file, "solve %s int_float_lin([", objsense == SCIP_OBJSENSE_MINIMIZE ? "minimize" : "maximize" );
4679 
4680  /* first array: coefficients (in float representation) of discrete variables with integral objective coefficient */
4681  for( v = 0; v < nintobjvars; v++ )
4682  {
4683  SCIP_Real obj;
4684  var = vars[intobjvars[v]];
4685  obj = objscale * SCIPvarGetObj(var);
4686  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));
4687 
4688  assert( SCIPisIntegral(scip, obj) );
4689  flattenFloat(scip, obj, buffy);
4690  SCIPinfoMessage(scip, file, "%s%s", buffy, v < nintobjvars-1 ? ", " : "" );
4691  }
4692 
4693  /* second array: all other objective coefficients */
4694  SCIPinfoMessage(scip, file, "], [");
4695  for( v = 0; v < nfloatobjvars; v++ )
4696  {
4697  SCIP_Real obj;
4698  obj = objscale * SCIPvarGetObj(vars[floatobjvars[v]]);
4699  flattenFloat(scip, obj, buffy);
4700  assert( !SCIPisIntegral(scip, obj) || SCIPvarGetType(vars[floatobjvars[v]]) == SCIP_VARTYPE_CONTINUOUS
4701  || SCIPvarGetType(vars[floatobjvars[v]]) == SCIP_VARTYPE_IMPLINT);
4702  SCIPinfoMessage(scip, file, "%s%s", buffy, v < nfloatobjvars-1 ? ", " : "" );
4703  }
4704 
4705  /* potentially add an objective offset */
4706  if( !SCIPisZero(scip, objoffset) )
4707  {
4708  flattenFloat(scip, objscale * objoffset, buffy);
4709  SCIPinfoMessage(scip, file, "%s%s", nfloatobjvars == 0 ? "" : ", ", buffy );
4710  }
4711 
4712  /* third array: all discrete variables with integral objective coefficient */
4713  SCIPinfoMessage(scip, file, "], [");
4714  for( v = 0; v < nintobjvars; v++ )
4715  SCIPinfoMessage(scip, file, "%s%s", SCIPvarGetName(vars[intobjvars[v]]), v < nintobjvars-1 ? ", " : "" );
4716 
4717  /* fourth array: all other variables with nonzero objective coefficient */
4718  SCIPinfoMessage(scip, file, "], [");
4719  for( v = 0; v < nfloatobjvars; v++ )
4720  SCIPinfoMessage(scip, file, "%s%s%s", SCIPvarGetName(vars[floatobjvars[v]]), floatobjvars[v] < ndiscretevars ? "_float" : "", v < nfloatobjvars-1 ? ", " : "" );
4721 
4722  /* potentially add a 1.0 for the objective offset */
4723  if( !SCIPisZero(scip, objoffset) )
4724  SCIPinfoMessage(scip, file, "%s%.1f", nfloatobjvars == 0 ? "" : ", ", 1.0 );
4725  SCIPinfoMessage(scip, file, "]);\n");
4726  }
4727  else
4728  SCIPinfoMessage(scip, file, "solve satisfy;\n");
4729 
4730  /* free all memory */
4731  SCIPfreeBufferArray(scip, &fznoutput.castbuffer);
4732  SCIPfreeBufferArray(scip, &fznoutput.consbuffer);
4733  SCIPfreeBufferArray(scip, &fznoutput.varbuffer);
4734 
4735  SCIPfreeBufferArray(scip, &boundtypes);
4736  SCIPfreeBufferArray(scip, &boundedvars);
4737  SCIPfreeBufferArray(scip, &floatobjvars);
4738  SCIPfreeBufferArray(scip, &intobjvars);
4739  SCIPfreeBufferArray(scip, &fznoutput.varhasfloat);
4740 
4741  *result = SCIP_SUCCESS;
4742  return SCIP_OKAY;
4743 }
4744 
4745 /*
4746  * Callback methods of reader
4747  */
4748 
4749 /** copy method for reader plugins (called when SCIP copies plugins) */
4750 static
4751 SCIP_DECL_READERCOPY(readerCopyFzn)
4752 { /*lint --e{715}*/
4753  assert(scip != NULL);
4754  assert(reader != NULL);
4755  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4756 
4757  /* call inclusion method of reader */
4759 
4760  return SCIP_OKAY;
4761 }
4762 
4763 
4764 /** destructor of reader to free user data (called when SCIP is exiting) */
4765 static
4766 SCIP_DECL_READERFREE(readerFreeFzn)
4767 {
4768  SCIP_READERDATA* readerdata;
4769  int v;
4770 
4771  readerdata = SCIPreaderGetData(reader);
4772  assert(readerdata != NULL);
4773 
4774  /* free all variable array elements */
4775  for( v = 0; v < readerdata->nvararrays; ++v )
4776  {
4777  freeVararray(scip, &readerdata->vararrays[v]);
4778  }
4779 
4780  SCIPfreeBlockMemoryArrayNull(scip, &readerdata->vararrays, readerdata->vararrayssize);
4781 
4782  /* free reader data */
4783  SCIPfreeBlockMemory(scip, &readerdata);
4784 
4785  return SCIP_OKAY;
4786 }
4787 
4788 
4789 /** problem reading method of reader */
4790 static
4791 SCIP_DECL_READERREAD(readerReadFzn)
4792 { /*lint --e{715}*/
4793  FZNINPUT fzninput;
4794  int i;
4795 
4796  /* initialize FZN input data */
4797  fzninput.file = NULL;
4798  fzninput.linebuf[0] = '\0';
4799  SCIP_CALL( SCIPallocBufferArray(scip, &fzninput.token, FZN_BUFFERLEN) );
4800  fzninput.token[0] = '\0';
4801 
4802  for( i = 0; i < FZN_MAX_PUSHEDTOKENS; ++i )
4803  {
4804  SCIP_CALL( SCIPallocBufferArray(scip, &(fzninput.pushedtokens[i]), FZN_BUFFERLEN) ); /*lint !e866*/
4805  }
4806 
4807  fzninput.npushedtokens = 0;
4808  fzninput.linenumber = 1;
4809  fzninput.bufpos = 0;
4810  fzninput.linepos = 0;
4811  fzninput.objsense = SCIP_OBJSENSE_MINIMIZE;
4812  fzninput.endline = FALSE;
4813  fzninput.comment = FALSE;
4814  fzninput.haserror = FALSE;
4815  fzninput.valid = TRUE;
4816  fzninput.vararrays = NULL;
4817  fzninput.nvararrays = 0;
4818  fzninput.vararrayssize = 0;
4819  fzninput.constarrays = NULL;
4820  fzninput.nconstarrays = 0;
4821  fzninput.constarrayssize = 0;
4822 
4823  SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &(fzninput.initialconss)) );
4824  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &(fzninput.dynamicconss)) );
4825  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &(fzninput.dynamiccols)) );
4826  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &(fzninput.dynamicrows)) );
4827 
4829  hashGetKeyVar, SCIPhashKeyEqString, SCIPhashKeyValString, NULL) );
4830 
4831  SCIP_CALL( SCIPhashtableCreate(&fzninput.constantHashtable, SCIPblkmem(scip), SCIP_HASHSIZE_NAMES,
4832  hashGetKeyConstant, SCIPhashKeyEqString, SCIPhashKeyValString, NULL) );
4833  SCIP_CALL( SCIPallocBufferArray(scip, &fzninput.constants, 10) );
4834 
4835  fzninput.nconstants = 0;
4836  fzninput.sconstants = 10;
4837 
4838  /* read the file */
4839  SCIP_CALL( readFZNFile(scip, SCIPreaderGetData(reader), &fzninput, filename) );
4840 
4841  /* free dynamically allocated memory */
4842  for( i = fzninput.nconstants - 1; i >= 0; --i )
4843  {
4844  SCIPfreeBufferArray(scip, &fzninput.constants[i]->name);
4845  SCIPfreeBuffer(scip, &fzninput.constants[i]);
4846  }
4847  SCIPfreeBufferArray(scip, &fzninput.constants);
4848 
4849  for( i = FZN_MAX_PUSHEDTOKENS - 1; i >= 0; --i ) /*lint !e778*/
4850  {
4851  SCIPfreeBufferArrayNull(scip, &fzninput.pushedtokens[i]);
4852  }
4853  SCIPfreeBufferArrayNull(scip, &fzninput.token);
4854 
4855  /* free memory */
4856  SCIPhashtableFree(&fzninput.varHashtable);
4857  SCIPhashtableFree(&fzninput.constantHashtable);
4858 
4859  /* free variable arrays */
4860  for( i = 0; i < fzninput.nvararrays; ++i )
4861  {
4862  freeVararray(scip, &fzninput.vararrays[i]);
4863  }
4864  SCIPfreeBlockMemoryArrayNull(scip, &(fzninput.vararrays), fzninput.vararrayssize);
4865 
4866  /* free constant arrays */
4867  for( i = 0; i < fzninput.nconstarrays; ++i )
4868  {
4869  freeConstarray(scip, &(fzninput.constarrays[i]));
4870  }
4871  SCIPfreeBlockMemoryArrayNull(scip, &fzninput.constarrays, fzninput.constarrayssize);
4872 
4873  /* evaluate the result */
4874  if( fzninput.haserror || ! fzninput.valid )
4875  return SCIP_READERROR;
4876 
4877  *result = SCIP_SUCCESS;
4878 
4879  return SCIP_OKAY;
4880 }
4881 
4882 
4883 /** problem writing method of reader */
4884 static
4885 SCIP_DECL_READERWRITE(readerWriteFzn)
4886 { /*lint --e{715}*/
4887  if( genericnames )
4888  {
4889  SCIP_CALL( writeFzn(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4890  nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
4891  }
4892  else
4893  {
4894  int i;
4895  SCIP_Bool legal;
4896 
4897  legal = TRUE;
4898 
4899  /* Scan whether all variable names are flatzinc conform */
4900  for( i = 0; i < nvars; i++ )
4901  {
4902  const char* varname;
4903  size_t length;
4904 
4905  varname = SCIPvarGetName(vars[i]);
4906  length = strlen(varname);
4907  legal = isIdentifier(varname);
4908  if( !legal )
4909  {
4910  SCIPwarningMessage(scip, "The name of variable <%d>: \"%s\" is not conform to the fzn standard.\n", i, varname);
4911  break;
4912  }
4913 
4914  if( length >= 7 )
4915  legal = (strncmp(&varname[length-6],"_float",6) != 0);
4916  if( !legal )
4917  {
4918  SCIPwarningMessage(scip, "The name of variable <%d>: \"%s\" ends with \"_float\" which is not supported.\n", i, varname);
4919  break;
4920  }
4921  }
4922 
4923  /* If there is at least one name, which is not conform, use generic names */
4924  if( legal )
4925  {
4926  SCIP_CALL( writeFzn(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4927  nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
4928  }
4929  else if( transformed )
4930  {
4931  SCIPwarningMessage(scip, "Write transformed problem with generic variable names.\n");
4932  SCIP_CALL( SCIPprintTransProblem(scip, file, "fzn", TRUE) );
4933  }
4934  else
4935  {
4936  SCIPwarningMessage(scip, "Write original problem with generic variable names.\n");
4937  SCIP_CALL( SCIPprintOrigProblem(scip, file, "fzn", TRUE) );
4938  }
4939  }
4940 
4941  *result = SCIP_SUCCESS;
4942 
4943  return SCIP_OKAY;
4944 }
4945 
4946 /*
4947  * reader specific interface methods
4948  */
4949 
4950 /** includes the fzn file reader in SCIP */
4952  SCIP* scip /**< SCIP data structure */
4953  )
4954 {
4955  SCIP_READERDATA* readerdata;
4956  SCIP_READER* reader;
4957 
4958  /* create fzn reader data */
4959  SCIP_CALL( readerdataCreate(scip, &readerdata) );
4960 
4961  /* include reader */
4962  SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) );
4963 
4964  /* set non fundamental callbacks via setter functions */
4965  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyFzn) );
4966  SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeFzn) );
4967  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadFzn) );
4968  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteFzn) );
4969 
4970  return SCIP_OKAY;
4971 }
4972 
4973 /** print given solution in Flatzinc format w.r.t. the output annotation */
4975  SCIP* scip, /**< SCIP data structure */
4976  SCIP_SOL* sol, /**< primal solution, or NULL for current LP/pseudo solution */
4977  FILE* file /**< output file (or NULL for standard output) */
4978  )
4979 {
4980  SCIP_READER* reader;
4981  SCIP_READERDATA* readerdata;
4982  SCIP_VAR** vars;
4983  VARARRAY** vararrays;
4984  DIMENSIONS* info;
4985  VARARRAY* vararray;
4986  FZNNUMBERTYPE type;
4987  SCIP_Real solvalue;
4988  int nvararrays;
4989  int nvars;
4990  int i;
4991  int v;
4992 
4993  reader = SCIPfindReader(scip, READER_NAME);
4994  assert(reader != NULL);
4995 
4996  readerdata = SCIPreaderGetData(reader);
4997  assert(readerdata != NULL);
4998 
4999  vararrays = readerdata->vararrays;
5000  nvararrays = readerdata->nvararrays;
5001 
5002  /* sort variable arrays */
5003  SCIPsortPtr((void**)vararrays, vararraysComp, nvararrays);
5004 
5005  for( i = 0; i < nvararrays; ++i )
5006  {
5007  vararray = vararrays[i];
5008  info = vararray->info;
5009  vars = vararray->vars;
5010  nvars = vararray->nvars;
5011  type = vararray->type;
5012 
5013  if( info->ndims == 0 )
5014  {
5015  solvalue = SCIPgetSolVal(scip, sol, vars[0]);
5016 
5017  SCIPinfoMessage(scip, file, "%s = ", vararray->name);
5018 
5019  printValue(scip, file, solvalue, type);
5020 
5021  SCIPinfoMessage(scip, file, ";\n");
5022  }
5023  else
5024  {
5025  SCIPinfoMessage(scip, file, "%s = array%dd(", vararray->name, info->ndims);
5026 
5027  for( v = 0; v < info->ndims; ++v )
5028  {
5029  SCIPinfoMessage(scip, file, "%d..%d, ", info->lbs[v], info->ubs[v]);
5030  }
5031 
5032  SCIPinfoMessage(scip, file, "[");
5033 
5034  for( v = 0; v < nvars; ++v )
5035  {
5036  if( v > 0)
5037  SCIPinfoMessage(scip, file, ", ");
5038 
5039  solvalue = SCIPgetSolVal(scip, sol, vars[v]);
5040  printValue(scip, file, solvalue, type);
5041  }
5042 
5043  SCIPinfoMessage(scip, file, "]);\n");
5044  }
5045  }
5046 
5047  SCIPinfoMessage(scip, file, "----------\n");
5048 
5049  return SCIP_OKAY;
5050 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPincludeReaderFzn(SCIP *scip)
Definition: reader_fzn.c:4951
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:97
FznNumberType
Definition: reader_fzn.c:81
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_EXPORT const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:548
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:86
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPcreateConsAnd(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_and.c:5007
static SCIP_RETCODE parseAggregation(SCIP *scip, FZNINPUT *fzninput, const char *name, const char *type)
Definition: reader_fzn.c:2733
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:8174
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:80
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2487
static SCIP_DECL_READERCOPY(readerCopyFzn)
Definition: reader_fzn.c:4751
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:1557
public methods for SCIP parameter handling
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
static void parseRange(SCIP *scip, FZNINPUT *fzninput, FZNNUMBERTYPE *type, SCIP_Real *lb, SCIP_Real *ub)
Definition: reader_fzn.c:1506
static SCIP_RETCODE parseConstantArrayAssignment(SCIP *scip, FZNINPUT *fzninput, SCIP_Real **vals, int *nvals, int sizevals)
Definition: reader_fzn.c: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:4255
static void writeBuffer(SCIP *scip, FILE *file, char *buffer, int bufferpos)
Definition: reader_fzn.c:3942
public methods for memory management
static SCIP_RETCODE readerdataAddOutputvararray(SCIP *scip, SCIP_READERDATA *readerdata, const char *name, SCIP_VAR **vars, int nvars, FZNNUMBERTYPE type, DIMENSIONS *info)
Definition: reader_fzn.c:1092
static SCIP_Bool isValueChar(char c, char nextc, SCIP_Bool firstchar, SCIP_Bool *hasdot, FZNEXPTYPE *exptype)
Definition: reader_fzn.c:358
static SCIP_RETCODE parseArrayAssignment(SCIP *scip, FZNINPUT *fzninput, char ***elements, int *nelements, int selements)
Definition: reader_fzn.c:1892
SCIP_EXPORT SCIP_READERDATA * SCIPreaderGetData(SCIP_READER *reader)
Definition: reader.c:483
SCIP_RETCODE SCIPprintVar(SCIP *scip, SCIP_VAR *var, FILE *file)
Definition: scip_var.c:9813
enum FznExpType FZNEXPTYPE
Definition: reader_fzn.c:96
#define SCIP_MAXSTRLEN
Definition: def.h:279
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip_prob.c:1240
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:123
static SCIP_Bool hasError(FZNINPUT *fzninput)
Definition: reader_fzn.c:701
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2548
static SCIP_RETCODE ensureVararrySizeFznInput(SCIP *scip, FZNINPUT *fzninput)
Definition: reader_fzn.c:760
SCIP_VAR ** SCIPgetVarsCumulative(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1353
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:241
static void computeLinearConsSides(SCIP *scip, FZNINPUT *fzninput, const char *name, SCIP_Real sidevalue, SCIP_Real *lhs, SCIP_Real *rhs)
Definition: reader_fzn.c:1411
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:70
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE parseConstantArray(SCIP *scip, FZNINPUT *fzninput, const char *name, int nconstants, FZNNUMBERTYPE type)
Definition: reader_fzn.c:2101
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip_reader.c:186
#define FALSE
Definition: def.h:73
SCIP_EXPORT SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17515
static SCIP_RETCODE fzninputAddVararray(SCIP *scip, FZNINPUT *fzninput, const char *name, SCIP_VAR **vars, int nvars, FZNNUMBERTYPE type, DIMENSIONS *info)
Definition: reader_fzn.c:1121
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip_reader.c:138
SCIP_EXPORT SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17182
#define TRUE
Definition: def.h:72
#define SCIPdebug(x)
Definition: pub_message.h:84
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
static SCIP_Bool isIdentifier(const char *name)
Definition: reader_fzn.c:335
static SCIP_RETCODE appendBuffer(SCIP *scip, char **buffer, int *bufferlen, int *bufferpos, const char *extension)
Definition: reader_fzn.c:3962
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9273
static SCIP_RETCODE readerdataAddOutputvar(SCIP *scip, SCIP_READERDATA *readerdata, SCIP_VAR *var, FZNNUMBERTYPE type)
Definition: reader_fzn.c:1045
public methods for problem variables
static SCIP_Bool isTokenChar(char c)
Definition: reader_fzn.c:278
static SCIP_RETCODE parseArray(SCIP *scip, SCIP_READERDATA *readerdata, FZNINPUT *fzninput)
Definition: reader_fzn.c:2162
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:95
struct FznConstant FZNCONSTANT
Definition: reader_fzn.c:115
Constraint handler for AND constraints, .
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:119
static void parseValue(SCIP *scip, FZNINPUT *fzninput, SCIP_Real *value, const char *assignment)
Definition: reader_fzn.c:2325
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:10562
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:123
Constraint handler for the set partitioning / packing / covering constraints .
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:78
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:93
static SCIP_RETCODE copyDimensions(SCIP *scip, DIMENSIONS **target, DIMENSIONS *source)
Definition: reader_fzn.c:868
public methods for SCIP variables
#define READER_DESC
Definition: reader_fzn.c:69
int SCIPfseek(SCIP_FILE *stream, long offset, int whence)
Definition: fileio.c:203
#define SCIPdebugMsgPrint
Definition: scip_message.h:70
#define SCIPdebugMsg
Definition: scip_message.h:69
static void printValue(SCIP *scip, FILE *file, SCIP_Real value, FZNNUMBERTYPE type)
Definition: reader_fzn.c:824
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
enum FznNumberType FZNNUMBERTYPE
Definition: reader_fzn.c:87
#define FZN_BUFFERLEN
Definition: reader_fzn.c:73
struct ConstArray CONSTARRAY
Definition: reader_fzn.c:125
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE readerdataCreate(SCIP *scip, SCIP_READERDATA **readerdata)
Definition: reader_fzn.c:712
static SCIP_RETCODE createConstarray(SCIP *scip, CONSTARRAY **constarray, const char *name, FZNCONSTANT **constants, int nconstants, FZNNUMBERTYPE type)
Definition: reader_fzn.c:976
static void flattenAssignment(SCIP *scip, FZNINPUT *fzninput, char *assignment)
Definition: reader_fzn.c:1350
static SCIP_RETCODE createVararray(SCIP *scip, VARARRAY **vararray, const char *name, SCIP_VAR **vars, int nvars, FZNNUMBERTYPE type, DIMENSIONS *info)
Definition: reader_fzn.c:891
public methods for numerical tolerances
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2236
SCIP_RETCODE SCIPfreeProb(SCIP *scip)
Definition: scip_prob.c:692
public methods for querying solving statistics
static SCIP_RETCODE parseQuadratic(SCIP *scip, FZNINPUT *fzninput, const char *name)
Definition: reader_fzn.c:2604
int SCIPgetNVarsCumulative(SCIP *scip, SCIP_CONS *cons)
Constraint handler for "or" constraints, .
SCIP_RETCODE SCIPsetReaderWrite(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERWRITE((*readerwrite)))
Definition: scip_reader.c:210
static void parseArrayType(SCIP *scip, FZNINPUT *fzninput, SCIP_Bool *isvararray, FZNNUMBERTYPE *type, SCIP_Real *lb, SCIP_Real *ub)
Definition: reader_fzn.c:1855
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:144
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:92
static CONSTARRAY * findConstarray(FZNINPUT *fzninput, const char *name)
Definition: reader_fzn.c:1023
public methods for managing constraints
Constraint handler for knapsack constraints of the form , x binary and .
#define CREATE_CONSTRAINT(x)
Definition: reader_fzn.c:158
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: scip_var.c:1735
static SCIP_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:1307
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_EXPORT const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17017
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10647
static SCIP_RETCODE parsePredicate(SCIP *scip, FZNINPUT *fzninput)
Definition: reader_fzn.c:2147
#define SCIPerrorMessage
Definition: pub_message.h:55
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
#define SCIPallocBuffer(scip, ptr)
Definition: scip_mem.h:109
static SCIP_RETCODE applyVariableAssignment(SCIP *scip, FZNINPUT *fzninput, SCIP_VAR *var, FZNNUMBERTYPE type, const char *assignment)
Definition: reader_fzn.c:1731
struct Dimensions DIMENSIONS
Definition: reader_fzn.c:106
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
static const char delimchars[]
Definition: reader_fzn.c:215
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip_mem.h:124
int SCIPfeof(SCIP_FILE *stream)
Definition: fileio.c:218
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:48
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:34
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:191
static SCIP_RETCODE readFZNFile(SCIP *scip, SCIP_READERDATA *readerdata, FZNINPUT *fzninput, const char *filename)
Definition: reader_fzn.c:3721
static SCIP_RETCODE parseName(SCIP *scip, FZNINPUT *fzninput, char *name, SCIP_Bool *output, DIMENSIONS **info)
Definition: reader_fzn.c:1618
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
constraint handler for quadratic constraints
static SCIP_DECL_SORTPTRCOMP(vararraysComp)
Definition: reader_fzn.c:245
#define NULL
Definition: lpi_spx1.cpp:155
SCIP_RETCODE SCIPsetReaderFree(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERFREE((*readerfree)))
Definition: scip_reader.c:162
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPprintOrigProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
static SCIP_Bool isEndStatement(FZNINPUT *fzninput)
Definition: reader_fzn.c:647
#define SCIP_CALL(x)
Definition: def.h:370
static void parseArrayDimension(SCIP *scip, FZNINPUT *fzninput, int *nelements)
Definition: reader_fzn.c:1926
SCIP_Longint SCIPconvertRealToLongint(SCIP *scip, SCIP_Real real)
static SCIP_RETCODE createQuadraticCons(SCIP *scip, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadterms, SCIP_VAR **quadvars1, SCIP_VAR **quadvars2, SCIP_Real *quadcoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initialconss, SCIP_Bool dynamicconss, SCIP_Bool dynamicrows)
Definition: reader_fzn.c:1178
static SCIP_Bool isDelimChar(char c)
Definition: reader_fzn.c: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:1965
static const int nconstypes
Definition: reader_fzn.c:3448
SCIP_EXPORT void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
static SCIP_RETCODE getActiveVariables(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
Definition: reader_fzn.c:3889
public methods for constraint handler plugins and constraints
wrapper functions to map file i/o to standard or zlib file i/o
static SCIP_RETCODE fzninputAddConstarray(SCIP *scip, FZNINPUT *fzninput, const char *name, FZNCONSTANT **constants, int nconstants, FZNNUMBERTYPE type)
Definition: reader_fzn.c:1150
static void syntaxError(SCIP *scip, FZNINPUT *fzninput, const char *msg)
Definition: reader_fzn.c:684
SCIP_READER * SCIPfindReader(SCIP *scip, const char *name)
Definition: scip_reader.c:226
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
struct FznOutput FZNOUTPUT
Definition: reader_fzn.c:213
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:111
struct SCIP_ReaderData SCIP_READERDATA
Definition: type_reader.h:44
SCIP_Real SCIPinfinity(SCIP *scip)
public data structures and miscellaneous methods
static SCIP_Bool isChar(const char *token, char c)
Definition: reader_fzn.c:287
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2286
#define SCIP_Bool
Definition: def.h:70
static const char commentchars[]
Definition: reader_fzn.c:217
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
static SCIP_Bool equalTokens(const char *token1, const char *token2)
Definition: reader_fzn.c:402
SCIP_RETCODE SCIPcreateConsOr(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_or.c:2091
#define MAX(x, y)
Definition: tclique_def.h:83
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip_var.c:105
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8386
static void flattenFloat(SCIP *scip, SCIP_Real val, char *buffer)
Definition: reader_fzn.c:3998
SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
static SCIP_Bool getNextLine(SCIP *scip, FZNINPUT *fzninput)
Definition: reader_fzn.c:420
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip_reader.c:100
static SCIP_DECL_HASHGETKEY(hashGetKeyVar)
Definition: reader_fzn.c:225
static SCIP_RETCODE ensureConstarrySizeFznInput(SCIP *scip, FZNINPUT *fzninput)
Definition: reader_fzn.c:792
static void pushToken(FZNINPUT *fzninput)
Definition: reader_fzn.c:634
static SCIP_RETCODE parseConstant(SCIP *scip, FZNINPUT *fzninput, FZNNUMBERTYPE type)
Definition: reader_fzn.c:2286
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip_prob.c:107
int * SCIPgetDurationsCumulative(SCIP *scip, SCIP_CONS *cons)
Constraint handler for linear constraints in their most general form, .
SCIP_EXPORT SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17613
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1666
SCIP_RETCODE SCIPprintTransProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
SCIP_EXPORT SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17723
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10232
static void freeVararray(SCIP *scip, VARARRAY **vararray)
Definition: reader_fzn.c:935
static VARARRAY * findVararray(FZNINPUT *fzninput, const char *name)
Definition: reader_fzn.c:950
#define SCIP_HASHSIZE_NAMES
Definition: def.h:289
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:4115
SCIP_EXPORT SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17733
methods for sorting joint arrays of various types
Constraint handler for XOR constraints, .
#define SCIPfreeBuffer(scip, ptr)
Definition: scip_mem.h:121
int SCIPgetCapacityCumulative(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsXor(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_Bool rhs, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_xor.c:5842
public methods for solutions
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:4507
static const SCIP_Real scalars[]
Definition: lp.c:5731
FznExpType
Definition: reader_fzn.c:90
static SCIP_RETCODE parseVariableArrayAssignment(SCIP *scip, FZNINPUT *fzninput, SCIP_VAR ***vars, int *nvars, int sizevars)
Definition: reader_fzn.c: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:1238
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
FlatZinc file reader.
static SCIP_RETCODE parseVariableArray(SCIP *scip, SCIP_READERDATA *readerdata, FZNINPUT *fzninput, const char *name, int nvars, FZNNUMBERTYPE type, SCIP_Real lb, SCIP_Real ub, DIMENSIONS *info)
Definition: reader_fzn.c:2024
static SCIP_DECL_READERWRITE(readerWriteFzn)
Definition: reader_fzn.c:4885
public methods for message output
static SCIP_DECL_READERREAD(readerReadFzn)
Definition: reader_fzn.c:4791
static void parseType(SCIP *scip, FZNINPUT *fzninput, FZNNUMBERTYPE *type, SCIP_Real *lb, SCIP_Real *ub)
Definition: reader_fzn.c:1678
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10604
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9250
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1245
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:163
static const char tokenchars[]
Definition: reader_fzn.c:216
public methods for input file readers
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8097
static SCIP_RETCODE parseSolveItem(SCIP *scip, FZNINPUT *fzninput)
Definition: reader_fzn.c:3557
public methods for message handling
SCIP_EXPORT SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12545
#define SCIP_INVALID
Definition: def.h:183
void SCIPprintSysError(const char *message)
Definition: misc.c:10513
struct FznInput FZNINPUT
Definition: reader_fzn.c:196
static SCIP_RETCODE parseList(SCIP *scip, FZNINPUT *fzninput, char ***elements, int *nelements, int selements)
Definition: reader_fzn.c:1454
#define SCIP_Longint
Definition: def.h:148
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4167
SCIP_RETCODE SCIPprintSolReaderFzn(SCIP *scip, SCIP_SOL *sol, FILE *file)
Definition: reader_fzn.c:4974
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9296
SCIP_EXPORT int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17360
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2764
static SCIP_Bool getNextToken(SCIP *scip, FZNINPUT *fzninput)
Definition: reader_fzn.c:515
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
SCIP_RETCODE SCIPcreateConsCumulative(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, int *durations, int *demands, int capacity, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
static SCIP_DECL_READERFREE(readerFreeFzn)
Definition: reader_fzn.c:4766
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:98
static void freeStringBufferArray(SCIP *scip, char **array, int nelements)
Definition: reader_fzn.c:253
static SCIP_RETCODE createConstantAssignment(SCIP *scip, FZNCONSTANT **constant, FZNINPUT *fzninput, const char *name, FZNNUMBERTYPE type, const char *assignment)
Definition: reader_fzn.c:1787
static void freeConstarray(SCIP *scip, CONSTARRAY **constarray)
Definition: reader_fzn.c:1004
SCIP_RETCODE SCIPcreateConsQuadratic(SCIP *scip, SCIP_CONS **cons, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadterms, SCIP_VAR **quadvars1, SCIP_VAR **quadvars2, SCIP_Real *quadcoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable)
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:122
SCIP_EXPORT SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17633
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:199
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:223
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1110
static SCIP_RETCODE createLinearCons(SCIP *scip, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initialconss, SCIP_Bool dynamicconss, SCIP_Bool dynamicrows)
Definition: reader_fzn.c:1210
struct VarArray VARARRAY
Definition: reader_fzn.c:136
public methods for reader plugins
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIPABORT()
Definition: def.h:342
public methods for global and local (sub)problems
static SCIP_RETCODE ensureVararrySize(SCIP *scip, SCIP_READERDATA *readerdata)
Definition: reader_fzn.c:728
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
#define READER_NAME
Definition: reader_fzn.c:68
#define FZN_MAX_PUSHEDTOKENS
Definition: reader_fzn.c:74
static void freeDimensions(SCIP *scip, DIMENSIONS **dim)
Definition: reader_fzn.c:920
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:4012
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
static SCIP_Bool isValue(const char *token, SCIP_Real *value)
Definition: reader_fzn.c:658
memory allocation routines