Scippy

SCIP

Solving Constraint Integer Programs

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