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