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-2025 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
    41#include <ctype.h>
    42#include "scip/cons_nonlinear.h"
    43#include "scip/cons_and.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"
    69#include "scip/scip_var.h"
    70#include <stdlib.h>
    71#include <string.h>
    72
    73#ifdef ALLDIFFERENT
    74#include "scip/cons_alldifferent.h" /* cppcheck-suppress missingInclude */
    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{
    107
    108/* structures to store the dimension information */
    109struct 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};
    116typedef struct Dimensions DIMENSIONS;
    117
    118/** FlatZinc constant */
    119struct FznConstant
    120{
    121 const char* name; /**< constant name */
    122 FZNNUMBERTYPE type; /**< constant type */
    123 SCIP_Real value; /**< constant value */
    124};
    125typedef struct FznConstant FZNCONSTANT;
    126
    127/** structure to store information for an array variable */
    128struct 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};
    135typedef struct ConstArray CONSTARRAY;
    136
    137/** structure to store information for an array variable */
    138struct 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};
    146typedef struct VarArray VARARRAY;
    147
    148/** data for FlatZinc reader */
    149struct 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 */
    172struct 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};
    206typedef struct FznInput FZNINPUT;
    207
    208/** FlatZinc writing data */
    209struct 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 SCIP_Bool* vardiscrete; /* array that indicates if a variable is discrete */
    221 SCIP_Bool* varhasfloat; /* array which indicates, whether a discrete variable already has a float representative */
    222};
    223typedef struct FznOutput FZNOUTPUT;
    224
    225static const char delimchars[] = " \f\n\r\t\v";
    226static const char tokenchars[] = ":<>=;{}[],()";
    227static const char commentchars[] = "%";
    228
    229/*
    230 * Hash functions
    231 */
    232
    233/** gets the key (i.e. the name) of the given variable */
    234static
    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 */
    244static
    245SCIP_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 */
    254static
    256{
    257 return strcmp( ((VARARRAY*)elem1)->name, ((VARARRAY*)elem2)->name );
    258}
    259
    260
    261/** frees a given buffer char* array */
    262static
    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 */
    278static
    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 */
    287static
    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 */
    296static
    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 */
    309static
    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_]* */
    344static
    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 */
    367static
    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 */
    411static
    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 */
    429static
    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 while( 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 */
    487static
    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() */
    608static
    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 */
    621static
    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 */
    632static
    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 */
    658static
    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 */
    675static
    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 */
    686static
    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 */
    702static
    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 */
    734static
    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 */
    766static
    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 */
    798static
    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 */
    842static
    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 {
    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 */
    865static
    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 */
    894static
    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);
    905 }
    906}
    907
    908/** free variable array data structure */
    909static
    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 */
    924static
    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 */
    950static
    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 */
    978static
    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 */
    997static
    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 */
    1019static
    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
    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 */
    1066static
    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 */
    1095static
    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
    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 */
    1124static
    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
    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 */
    1152static
    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
    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 */
    1185static
    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
    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 */
    1213static
    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 */
    1282static
    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 */
    1325static
    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 */
    1386static
    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 */
    1429static
    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 */
    1481static
    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 */
    1532static
    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 = FZN_INT; /* init for scan-build */
    1540 SCIP_Real lb = SCIP_INVALID; /* init for scan-build */
    1541 SCIP_Real ub = SCIP_INVALID; /* init for scan-build */
    1542 int nelements;
    1543 int size;
    1544
    1545 nelements = 0;
    1546 size = 100;
    1547
    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 */
    1593static
    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) */
    1653static
    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 */
    1706static
    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 */
    1762static
    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) */
    1830static
    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 */
    1867static
    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 */
    1901static
    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 */
    1940static
    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,
    1976 NULL, NULL, NULL, NULL, NULL) );
    1977 SCIP_CALL( SCIPaddVar(scip, varcopy) );
    1978
    1979 SCIPdebugMsg(scip, "created variable\n");
    1980 SCIPdebug( SCIP_CALL( SCIPprintVar(scip, varcopy, NULL) ) );
    1981
    1982 /* variable name should not exist before */
    1983 assert(SCIPhashtableRetrieve(fzninput->varHashtable, varcopy) == NULL);
    1984
    1985 /* insert variable into the hashmap for later use in the constraint section */
    1986 SCIP_CALL( SCIPhashtableInsert(fzninput->varHashtable, varcopy) );
    1987
    1988 /* copy variable pointer before releasing the variable to keep the pointer to the variable */
    1989 if( var != NULL )
    1990 *var = varcopy;
    1991
    1992 /* release variable */
    1993 SCIP_CALL( SCIPreleaseVar(scip, &varcopy) );
    1994
    1995 return SCIP_OKAY;
    1996}
    1997
    1998
    1999/** parse variable array assignment and create the variables */
    2000static
    2002 SCIP* scip, /**< SCIP data structure */
    2003 SCIP_READERDATA* readerdata, /**< reader data */
    2004 FZNINPUT* fzninput, /**< FZN reading data */
    2005 const char* name, /**< array name */
    2006 int nvars, /**< number of variables */
    2007 FZNNUMBERTYPE type, /**< number type */
    2008 SCIP_Real lb, /**< lower bound of the variables */
    2009 SCIP_Real ub, /**< lower bound of the variables */
    2010 DIMENSIONS* info /**< dimension information */
    2011 )
    2012{
    2013 SCIP_VAR** vars;
    2014 char varname[FZN_BUFFERLEN];
    2015 int v;
    2016
    2017 /* create variables and add them to the problem */
    2018 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    2019
    2020 for( v = 0; v < nvars; ++v )
    2021 {
    2022 (void) SCIPsnprintf(varname, FZN_BUFFERLEN, "%s[%d]", name, v + 1);
    2023
    2024 /* create variable */
    2025 SCIP_CALL( createVariable(scip, fzninput, &vars[v], varname, lb, ub, type) );
    2026 }
    2027
    2028 if( !getNextToken(scip, fzninput) )
    2029 {
    2030 syntaxError(scip, fzninput, "expected semicolon");
    2031 }
    2032 else
    2033 {
    2034 if( isChar(fzninput->token, '=') )
    2035 {
    2036 char** assigns;
    2037 int nassigns;
    2038
    2039 SCIP_CALL( SCIPallocBufferArray(scip, &assigns, nvars) );
    2040 nassigns = 0;
    2041
    2042 SCIP_CALL( parseArrayAssignment(scip, fzninput, &assigns, &nassigns, nvars) );
    2043
    2044 if(!hasError(fzninput) )
    2045 {
    2046 for( v = 0; v < nvars && !hasError(fzninput); ++v )
    2047 {
    2048 /* parse and apply assignment */
    2049 SCIP_CALL( applyVariableAssignment(scip, fzninput, vars[v], type, assigns[v]) );
    2050 }
    2051 }
    2052
    2053 freeStringBufferArray(scip, assigns, nassigns);
    2054 }
    2055 else
    2056 {
    2057 /* push back the ';' */
    2058 assert( isEndStatement(fzninput) );
    2059 pushToken(fzninput);
    2060 }
    2061
    2062 if( info != NULL )
    2063 {
    2064 SCIP_CALL( readerdataAddOutputvararray(scip, readerdata, name, vars, nvars, type, info) );
    2065 }
    2066
    2067 /* add variable information to fzninput since this array name might be used later in the fzn file */
    2068 SCIP_CALL( fzninputAddVararray(scip, fzninput, name, vars, nvars, type, info) );
    2069 }
    2070
    2071 SCIPfreeBufferArray(scip, &vars);
    2072
    2073 return SCIP_OKAY;
    2074}
    2075
    2076/** parse constant array assignment and create the constants */
    2077static
    2079 SCIP* scip, /**< SCIP data structure */
    2080 FZNINPUT* fzninput, /**< FZN reading data */
    2081 const char* name, /**< array name */
    2082 int nconstants, /**< number of constants */
    2083 FZNNUMBERTYPE type /**< number type */
    2084 )
    2085{
    2086 FZNCONSTANT** constants;
    2087 char** assigns;
    2088 char constantname[FZN_BUFFERLEN];
    2089 int nassigns;
    2090 int c;
    2091
    2092 if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '=') )
    2093 {
    2094 syntaxError(scip, fzninput, "expected token <=>");
    2095 return SCIP_OKAY;
    2096 }
    2097
    2098 SCIP_CALL( SCIPallocBufferArray(scip, &assigns, nconstants) );
    2099 SCIP_CALL( SCIPallocBufferArray(scip, &constants, nconstants) );
    2100 nassigns = 0;
    2101
    2102 SCIP_CALL( parseArrayAssignment(scip, fzninput, &assigns, &nassigns, nconstants) );
    2103
    2104 if( !hasError(fzninput) )
    2105 {
    2106 for( c = 0; c < nconstants; ++c )
    2107 {
    2108 (void) SCIPsnprintf(constantname, FZN_BUFFERLEN, "%s[%d]", name, c + 1);
    2109 SCIP_CALL( createConstantAssignment(scip, &constants[c], fzninput, constantname, type, assigns[c]) );
    2110 }
    2111
    2112 /* add variable information to fzninput since this array name might be used later in the fzn file */
    2113 SCIP_CALL( fzninputAddConstarray(scip, fzninput, name, constants, nconstants, type) );
    2114 }
    2115
    2116 SCIPfreeBufferArray(scip, &constants);
    2117 freeStringBufferArray(scip, assigns, nassigns);
    2118
    2119 return SCIP_OKAY;
    2120}
    2121
    2122/** parse predicate expression */
    2123static
    2125 SCIP* scip, /**< SCIP data structure */
    2126 FZNINPUT* fzninput /**< FZN reading data */
    2127 )
    2128{
    2129 assert(scip != NULL);
    2130
    2131 /* mark predicate expression as comment such that it gets skipped */
    2132 fzninput->comment = TRUE;
    2133
    2134 return SCIP_OKAY;
    2135}
    2136
    2137/** parse array expression */
    2138static
    2140 SCIP* scip, /**< SCIP data structure */
    2141 SCIP_READERDATA* readerdata, /**< reader data */
    2142 FZNINPUT* fzninput /**< FZN reading data */
    2143 )
    2144{
    2145 FZNNUMBERTYPE type;
    2146 DIMENSIONS* info;
    2147 int nelements;
    2148 SCIP_Real lb;
    2149 SCIP_Real ub;
    2150 SCIP_Bool isvararray;
    2151 SCIP_Bool output;
    2152 char name[FZN_BUFFERLEN];
    2153
    2154 assert(scip != NULL);
    2155 assert(fzninput != NULL);
    2156
    2157 info = NULL;
    2158 isvararray = FALSE;
    2159 nelements = -1;
    2160
    2161 SCIPdebugMsg(scip, "parse array expression\n");
    2162
    2163 /* parse array dimension */
    2164 parseArrayDimension(scip, fzninput, &nelements);
    2165 assert(hasError(fzninput) || nelements > 0);
    2166
    2167 if( hasError(fzninput) )
    2168 return SCIP_OKAY;
    2169
    2170 /* parse array type ( (i) variable or constant; (ii) integer, float, bool, or set) */
    2171 parseArrayType(scip, fzninput, &isvararray, &type, &lb, &ub);
    2172
    2173 if( hasError(fzninput) )
    2174 return SCIP_OKAY;
    2175
    2176 /* parse array name */
    2177 SCIP_CALL( parseName(scip, fzninput, name, &output, &info) );
    2178 assert(!output || info != NULL);
    2179
    2180 if( hasError(fzninput) )
    2181 return SCIP_OKAY;
    2182
    2183 SCIPdebugMsg(scip, "found <%s> array named <%s> of type <%s> and size <%d> with bounds [%g,%g] (output %u)\n",
    2184 isvararray ? "variable" : "constant", name,
    2185 type == FZN_BOOL ? "bool" : type == FZN_INT ? "integer" : "float", nelements, lb, ub, output);
    2186
    2187 if( isvararray )
    2188 SCIP_CALL( parseVariableArray(scip, readerdata, fzninput, name, nelements, type, lb, ub, info) );
    2189 else
    2190 SCIP_CALL( parseConstantArray(scip, fzninput, name, nelements, type) );
    2191
    2192 freeDimensions(scip, &info);
    2193
    2194 return SCIP_OKAY;
    2195}
    2196
    2197/** parse variable expression */
    2198static
    2200 SCIP* scip, /**< SCIP data structure */
    2201 SCIP_READERDATA* readerdata, /**< reader data */
    2202 FZNINPUT* fzninput /**< FZN reading data */
    2203 )
    2204{
    2205 SCIP_VAR* var;
    2206 FZNNUMBERTYPE type;
    2207 SCIP_Real lb;
    2208 SCIP_Real ub;
    2209 SCIP_Bool output;
    2210 char assignment[FZN_BUFFERLEN];
    2211 char name[FZN_BUFFERLEN];
    2212
    2213 assert(scip != NULL);
    2214 assert(fzninput != NULL);
    2215
    2216 SCIPdebugMsg(scip, "parse variable expression\n");
    2217
    2218 /* pares variable type and range */
    2219 parseType(scip, fzninput, &type, &lb, &ub);
    2220
    2221 if( hasError(fzninput) )
    2222 return SCIP_OKAY;
    2223
    2224 /* parse variable name without annotations */
    2225 SCIP_CALL( parseName(scip, fzninput, name, &output, NULL) );
    2226
    2227 if( hasError(fzninput) )
    2228 return SCIP_OKAY;
    2229
    2230 assert(type == FZN_BOOL || type == FZN_INT || type == FZN_FLOAT);
    2231
    2232 /* create variable */
    2233 SCIP_CALL( createVariable(scip, fzninput, &var, name, lb, ub, type) );
    2234
    2235 /* check if the variable should be part of the output */
    2236 if( output )
    2237 {
    2238 SCIP_CALL( readerdataAddOutputvar(scip, readerdata, var, type) );
    2239 }
    2240
    2241 if( !getNextToken(scip, fzninput) )
    2242 {
    2243 syntaxError(scip, fzninput, "expected semicolon");
    2244 return SCIP_OKAY;
    2245 }
    2246
    2247 if( isChar(fzninput->token, '=') )
    2248 {
    2249 /* parse and flatten assignment */
    2250 flattenAssignment(scip, fzninput, assignment);
    2251
    2252 /* apply assignment */
    2253 SCIP_CALL( applyVariableAssignment(scip, fzninput, var, type, assignment) );
    2254 }
    2255 else
    2256 pushToken(fzninput);
    2257
    2258 return SCIP_OKAY;
    2259}
    2260
    2261/** parse constant expression */
    2262static
    2264 SCIP* scip, /**< SCIP data structure */
    2265 FZNINPUT* fzninput, /**< FZN reading data */
    2266 FZNNUMBERTYPE type /**< constant type */
    2267 )
    2268{
    2269 FZNCONSTANT* constant;
    2270 char name[FZN_BUFFERLEN];
    2271 char assignment[FZN_BUFFERLEN];
    2272
    2273 assert(scip != NULL);
    2274 assert(fzninput != NULL);
    2275 assert(type == FZN_INT || type == FZN_FLOAT || type == FZN_BOOL);
    2276
    2277 SCIPdebugMsg(scip, "parse constant expression\n");
    2278
    2279 /* parse name of the constant */
    2280 SCIP_CALL( parseName(scip, fzninput, name, NULL, NULL) );
    2281
    2282 if( hasError(fzninput) )
    2283 return SCIP_OKAY;
    2284
    2285 if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '=') )
    2286 {
    2287 syntaxError(scip, fzninput, "expected token <=>");
    2288 return SCIP_OKAY;
    2289 }
    2290
    2291 /* the assignment has to be an other constant or a suitable value */
    2292 flattenAssignment(scip, fzninput, assignment);
    2293
    2294 /* applies constant assignment and creates constant */
    2295 SCIP_CALL( createConstantAssignment(scip, &constant, fzninput, name, type, assignment) );
    2296
    2297 return SCIP_OKAY;
    2298}
    2299
    2300/** evaluates current token as constant */
    2301static
    2303 SCIP* scip, /**< SCIP data structure */
    2304 FZNINPUT* fzninput, /**< FZN reading data */
    2305 SCIP_Real* value, /**< pointer to store value */
    2306 const char* assignment /**< assignment to parse a value */
    2307 )
    2308{
    2309 if( isValue(assignment, value) )
    2310 return;
    2311
    2312 /* if it is an identifier name, it has to belong to a constant or fixed variable */
    2313 if( isIdentifier(assignment) )
    2314 {
    2315 FZNCONSTANT* constant;
    2316
    2317 /* identifier has to be one of a constant */
    2318 constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) assignment);
    2319
    2320 if( constant == NULL )
    2321 {
    2322 SCIP_VAR* var;
    2323
    2324 var = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) assignment);
    2325
    2326 if( var == NULL )
    2327 syntaxError(scip, fzninput, "unknown constant name");
    2328 else
    2329 {
    2331 (*value) = SCIPvarGetLbOriginal(var);
    2332 else
    2333 syntaxError(scip, fzninput, "expected fixed variable");
    2334 }
    2335 }
    2336 else
    2337 (*value) = constant->value;
    2338 }
    2339 else
    2340 syntaxError(scip, fzninput, "expected constant expression");
    2341}
    2342
    2343/** parse array expression containing constants */
    2344static
    2346 SCIP* scip, /**< SCIP data structure */
    2347 FZNINPUT* fzninput, /**< FZN reading data */
    2348 SCIP_Real** vals, /**< pointer to value array */
    2349 int* nvals, /**< pointer to store the number if values */
    2350 int sizevals /**< size of the vals array */
    2351 )
    2352{
    2353 int c;
    2354
    2355 assert(*nvals <= sizevals);
    2356
    2357 /* check for next token */
    2358 if( !getNextToken(scip, fzninput) )
    2359 {
    2360 syntaxError(scip, fzninput, "expected constant array");
    2361 return SCIP_OKAY;
    2362 }
    2363
    2364 /* check if an array is given explicitly */
    2365 if( isChar(fzninput->token, '[') )
    2366 {
    2367 char** elements;
    2368 SCIP_Real value;
    2369 int nelements;
    2370
    2371 SCIP_CALL( SCIPallocBufferArray(scip, &elements, sizevals) );
    2372 nelements = 0;
    2373
    2374 value = 0.0;
    2375
    2376 /* push back '[' which closes the list */
    2377 pushToken(fzninput);
    2378
    2379 /* pares array assignment */
    2380 SCIP_CALL( parseArrayAssignment(scip, fzninput, &elements, &nelements, sizevals) );
    2381
    2382 if( sizevals <= *nvals + nelements )
    2383 {
    2384 SCIP_CALL( SCIPreallocBufferArray(scip, vals, *nvals + nelements) );
    2385 }
    2386
    2387 for( c = 0; c < nelements && !hasError(fzninput); ++c )
    2388 {
    2389 parseValue(scip, fzninput, &value, elements[c]);
    2390 assert(!hasError(fzninput));
    2391
    2392 (*vals)[(*nvals)] = value;
    2393 (*nvals)++;
    2394 }
    2395
    2396 freeStringBufferArray(scip, elements, nelements);
    2397 }
    2398 else
    2399 {
    2400 /* array is not given explicitly; therefore, check constant array data base if the given constant array name was
    2401 * parsed before
    2402 */
    2403
    2404 CONSTARRAY* constarray;
    2405
    2406 constarray = findConstarray(fzninput, fzninput->token);
    2407
    2408 if( constarray != NULL )
    2409 {
    2410 /* ensure variable array size */
    2411 if( sizevals <= *nvals + constarray->nconstants )
    2412 {
    2413 SCIP_CALL( SCIPreallocBufferArray(scip, vals, *nvals + constarray->nconstants) );
    2414 }
    2415
    2416 for( c = 0; c < constarray->nconstants; ++c )
    2417 {
    2418 (*vals)[(*nvals)] = constarray->constants[c]->value;
    2419 (*nvals)++;
    2420 }
    2421 }
    2422 else
    2423 {
    2424 /* there is no constant array with the given name; therefore check the variable array data base if such an
    2425 * array exist with fixed variables
    2426 */
    2427
    2428 VARARRAY* vararray;
    2429
    2430 vararray = findVararray(fzninput, fzninput->token);
    2431
    2432 if( vararray == NULL )
    2433 {
    2434 syntaxError(scip, fzninput, "unknown constants array name");
    2435 }
    2436 else
    2437 {
    2438 /* ensure variable array size */
    2439 if( sizevals <= *nvals + vararray->nvars )
    2440 {
    2441 SCIP_CALL( SCIPreallocBufferArray(scip, vals, *nvals + vararray->nvars) );
    2442 }
    2443
    2444 for( c = 0; c < vararray->nvars; ++c )
    2445 {
    2446 SCIP_VAR* var;
    2447
    2448 var = vararray->vars[c];
    2449 assert(var != NULL);
    2450
    2452 {
    2453 (*vals)[(*nvals)] = SCIPvarGetLbOriginal(var);
    2454 (*nvals)++;
    2455 }
    2456 else
    2457 {
    2458 syntaxError(scip, fzninput, "variable array contains unfixed variable");
    2459 break;
    2460 }
    2461 }
    2462 }
    2463 }
    2464 }
    2465
    2466 return SCIP_OKAY;
    2467}
    2468
    2469/** parse array expression containing variables */
    2470static
    2472 SCIP* scip, /**< SCIP data structure */
    2473 FZNINPUT* fzninput, /**< FZN reading data */
    2474 SCIP_VAR*** vars, /**< pointer to variable array */
    2475 int* nvars, /**< pointer to store the number if variable */
    2476 int sizevars /**< size of the variable array */
    2477 )
    2478{
    2479 int v;
    2480
    2481 assert(*nvars <= sizevars);
    2482
    2483 /* check for next token */
    2484 if( !getNextToken(scip, fzninput) )
    2485 {
    2486 syntaxError(scip, fzninput, "expected constant array");
    2487 return SCIP_OKAY;
    2488 }
    2489
    2490 if( isChar(fzninput->token, '[') )
    2491 {
    2492 char** elements;
    2493 int nelements;
    2494
    2495 SCIP_CALL( SCIPallocBufferArray(scip, &elements, sizevars) );
    2496 nelements = 0;
    2497
    2498 /* push back '[' which closes the list */
    2499 pushToken(fzninput);
    2500
    2501 SCIP_CALL( parseArrayAssignment(scip, fzninput, &elements, &nelements, sizevars) );
    2502
    2503 if( sizevars <= *nvars + nelements )
    2504 {
    2505 SCIP_CALL( SCIPreallocBufferArray(scip, vars, *nvars + nelements) );
    2506 }
    2507
    2508 for( v = 0; v < nelements; ++v )
    2509 {
    2510 (*vars)[(*nvars)] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, elements[v]);
    2511
    2512 if( (*vars)[(*nvars)] == NULL )
    2513 {
    2514 /* since the given element does not correspond to a variable name
    2515 * it might be the case that it is a constant which can be seen as
    2516 * as a fixed variable
    2517 */
    2518
    2519 FZNCONSTANT* constant;
    2520 SCIP_Real value;
    2521
    2522 constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) elements[v]);
    2523
    2524 if( constant != NULL )
    2525 {
    2526 assert(constant->type == FZN_FLOAT);
    2527 value = constant->value;
    2528 }
    2529 else if(!isValue(elements[v], &value) )
    2530 {
    2531 char* tmptoken;
    2532
    2533 tmptoken = fzninput->token;
    2534 fzninput->token = elements[v];
    2535 syntaxError(scip, fzninput, "expected variable name or constant");
    2536
    2537 fzninput->token = tmptoken;
    2538 break;
    2539 }
    2540
    2541 /* create a fixed variable */
    2542 SCIP_CALL( createVariable(scip, fzninput, &(*vars)[*nvars], elements[v], value, value, FZN_FLOAT) );
    2543 }
    2544
    2545 (*nvars)++;
    2546 }
    2547
    2548 freeStringBufferArray(scip, elements, nelements);
    2549 }
    2550 else
    2551 {
    2552 VARARRAY* vararray;
    2553
    2554 vararray = findVararray(fzninput, fzninput->token);
    2555
    2556 if( vararray != NULL )
    2557 {
    2558 assert(vararray != NULL);
    2559
    2560 /* ensure variable array size */
    2561 if( sizevars <= *nvars + vararray->nvars )
    2562 {
    2563 SCIP_CALL( SCIPreallocBufferArray(scip, vars, *nvars + vararray->nvars) );
    2564 }
    2565
    2566 for( v = 0; v < vararray->nvars; ++v )
    2567 {
    2568 (*vars)[(*nvars)] = vararray->vars[v];
    2569 (*nvars)++;
    2570 }
    2571 }
    2572 else
    2573 syntaxError(scip, fzninput, "unknown variable array name");
    2574 }
    2575
    2576 return SCIP_OKAY;
    2577}
    2578
    2579/** parse linking statement */
    2580static
    2582 SCIP* scip, /**< SCIP data structure */
    2583 FZNINPUT* fzninput, /**< FZN reading data */
    2584 const char* name /**< name of constraint */
    2585 )
    2586{
    2587 char** elements;
    2588 int nelements;
    2589
    2590 SCIP_CALL( SCIPallocBufferArray(scip, &elements, 3) );
    2591 nelements = 0;
    2592
    2593 /* parse the list of three elements */
    2594 SCIP_CALL( parseList(scip, fzninput, &elements, &nelements, 3) );
    2595 assert(nelements == 3);
    2596
    2597 if( !hasError(fzninput) )
    2598 {
    2599 SCIP_VAR** vars;
    2600 SCIP_Real* vals;
    2601 SCIP_Real rhs;
    2602 int v;
    2603
    2604 rhs = 0.0;
    2605
    2606 SCIP_CALL( SCIPallocBufferArray(scip, &vars, 3) );
    2607 SCIP_CALL( SCIPallocBufferArray(scip, &vals, 3) );
    2608
    2609 for( v = 0; v < 3; ++v )
    2610 {
    2611 /* collect variable if constraint identifier is a variable */
    2612 vars[v] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[v]);
    2613
    2614 /* parse the numeric value otherwise */
    2615 if( vars[v] == NULL )
    2616 {
    2617 parseValue(scip, fzninput, &vals[v], elements[v]);
    2618 assert(!hasError(fzninput));
    2619 }
    2620 else
    2621 vals[v] = SCIP_INVALID;
    2622 }
    2623
    2624 /* the first two identifiers are proper variables => the constraints is indeed quadratic */
    2625 if( vars[0] != NULL && vars[1] != NULL )
    2626 {
    2627 SCIP_Real quadval;
    2628 quadval = 1.0;
    2629
    2630 /* we might have an additional linear term or just a constant */
    2631 if( vars[2] != NULL )
    2632 {
    2633 SCIP_Real linval;
    2634 linval = -1.0;
    2635
    2636 SCIP_CALL( createQuadraticCons(scip, name, 1, &vars[2], &linval, 1, &vars[0], &vars[1], &quadval, rhs, rhs,
    2637 fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
    2638 }
    2639 else
    2640 {
    2641 rhs += vals[2];
    2642 SCIP_CALL( createQuadraticCons(scip, name, 0, NULL, NULL, 1, &vars[0], &vars[1], &quadval, rhs, rhs,
    2643 fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows));
    2644 }
    2645 }
    2646 else if( vars[0] != NULL || vars[1] != NULL )
    2647 {
    2648 int nvars;
    2649 nvars = 1;
    2650
    2651 /* the left hand side of x*y = z is linear (but not constant) */
    2652 if( vars[0] == NULL )
    2653 SCIPswapPointers((void**)&vars[0], (void**)&vars[1]);
    2654 else
    2655 SCIPswapPointers((void**)&vals[0], (void**)&vals[1]);
    2656
    2657 /* after swapping, the variable and the coefficient should stand in front */
    2658 assert(vars[0] != NULL && vals[0] != SCIP_INVALID ); /*lint !e777*/
    2659
    2660 /* the right hand side might be a variable or a constant */
    2661 if( vars[2] != NULL )
    2662 {
    2663 SCIPswapPointers((void**)&vars[1], (void**)&vars[2]);
    2664 vals[1] = -1.0;
    2665 nvars++;
    2666 }
    2667 else
    2668 {
    2669 assert(vals[2] != SCIP_INVALID); /*lint !e777*/
    2670 rhs += vals[2];
    2671 }
    2672
    2673 SCIP_CALL( createLinearCons(scip, name, nvars, vars, vals, rhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
    2674 }
    2675 else
    2676 {
    2677 /* the left hand side of x*y = z is constant */
    2678 assert(vals[0] != SCIP_INVALID && vals[1] != SCIP_INVALID); /*lint !e777*/
    2679
    2680 rhs = rhs - vals[0]*vals[1];
    2681
    2682 /* the right hand side might be a variable or a constant */
    2683 if( vars[2] != NULL )
    2684 {
    2685 SCIP_Real val;
    2686 val = -1.0;
    2687 SCIP_CALL( createLinearCons(scip, name, 1, &vars[2], &val, rhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
    2688 }
    2689 else
    2690 {
    2691 assert(vals[2] != SCIP_INVALID); /*lint !e777*/
    2692 rhs += vals[2];
    2693 SCIP_CALL( createLinearCons(scip, name, 0, NULL, NULL, rhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
    2694 }
    2695 }
    2696
    2697 /* free buffer arrays */
    2698 SCIPfreeBufferArray(scip, &vals);
    2699 SCIPfreeBufferArray(scip, &vars);
    2700 }
    2701
    2702 /* free elements array */
    2703 freeStringBufferArray(scip, elements, nelements);
    2704
    2705 return SCIP_OKAY;
    2706}
    2707
    2708/** parse aggregation statement (plus, minus, negate) */
    2709static
    2711 SCIP* scip, /**< SCIP data structure */
    2712 FZNINPUT* fzninput, /**< FZN reading data */
    2713 const char* name, /**< name of constraint */
    2714 const char* type /**< linear constraint type */
    2715 )
    2716{
    2717 /* here we take care of the three expression
    2718 *
    2719 * - int_plus(x1,x2,x3) -> x1 + x2 == x3
    2720 * - int_minus(x1,x2,x3) -> x1 - x2 == x3
    2721 * - int_negate(x1,x2) -> x1 + x2 == 0
    2722 */
    2723 char** elements;
    2724 int nelements;
    2725
    2726 SCIP_CALL( SCIPallocBufferArray(scip, &elements, 3) );
    2727 nelements = 0;
    2728
    2729 /* parse the list of three elements */
    2730 SCIP_CALL( parseList(scip, fzninput, &elements, &nelements, 3) );
    2731 assert(nelements == 3 || nelements == 2);
    2732
    2733 if( !hasError(fzninput) )
    2734 {
    2735 SCIP_VAR** vars;
    2736 SCIP_Real* vals;
    2737 SCIP_Real value;
    2738 SCIP_Real rhs;
    2739 int nvars;
    2740
    2741 nvars = 0;
    2742 rhs = 0.0;
    2743
    2744 SCIP_CALL( SCIPallocBufferArray(scip, &vars, 3) );
    2745 SCIP_CALL( SCIPallocBufferArray(scip, &vals, 3) );
    2746
    2747 /* parse first element */
    2748 vars[nvars] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[0]);
    2749 if( vars[nvars] == NULL )
    2750 {
    2751 parseValue(scip, fzninput, &value, elements[0]);
    2752 assert(!hasError(fzninput));
    2753
    2754 rhs -= value;
    2755 }
    2756 else
    2757 {
    2758 vals[nvars] = 1.0;
    2759 nvars++;
    2760 }
    2761
    2762 /* parse second element */
    2763 vars[nvars] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[1]);
    2764 if( vars[nvars] == NULL )
    2765 {
    2766 parseValue(scip, fzninput, &value, elements[1]);
    2767 assert(!hasError(fzninput));
    2768
    2769 if( equalTokens(type, "minus") )
    2770 rhs += value;
    2771 else
    2772 rhs -= value;
    2773 }
    2774 else
    2775 {
    2776 if( equalTokens(type, "minus") )
    2777 {
    2778 /* in case of minus the second element get a -1.0 as coefficient */
    2779 vals[nvars] = -1.0;
    2780 }
    2781 else
    2782 vals[nvars] = 1.0;
    2783
    2784 nvars++;
    2785 }
    2786
    2787 if( !equalTokens(type, "negate") )
    2788 {
    2789 /* parse third element in case of "minus" or "plus" */
    2790 vars[nvars] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[2]);
    2791 if( vars[nvars] == NULL )
    2792 {
    2793 parseValue(scip, fzninput, &value, elements[2]);
    2794 assert(!hasError(fzninput));
    2795
    2796 rhs += value;
    2797 }
    2798 else
    2799 {
    2800 vals[nvars] = -1.0;
    2801 nvars++;
    2802 }
    2803 }
    2804
    2805 SCIP_CALL( createLinearCons(scip, name, nvars, vars, vals, rhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
    2806
    2807 /* free buffer arrays */
    2808 SCIPfreeBufferArray(scip, &vals);
    2809 SCIPfreeBufferArray(scip, &vars);
    2810 }
    2811
    2812 /* free elements array */
    2813 freeStringBufferArray(scip, elements, nelements);
    2814 return SCIP_OKAY;
    2815}
    2816
    2817/** parse linking statement */
    2818static
    2820 SCIP* scip, /**< SCIP data structure */
    2821 FZNINPUT* fzninput, /**< FZN reading data */
    2822 const char* name, /**< name of constraint */
    2823 const char* type, /**< linear constraint type */
    2824 SCIP_Real sidevalue /**< side value of constraint */
    2825 )
    2826{
    2827 char** names;
    2828 SCIP_Real lhs = SCIP_INVALID;
    2829 SCIP_Real rhs = SCIP_INVALID;
    2830 int nnames;
    2831
    2832 nnames = 0;
    2833 SCIP_CALL( SCIPallocBufferArray(scip, &names, 2) );
    2834
    2835 SCIP_CALL( parseList(scip, fzninput, &names, &nnames, 2) );
    2836 assert(nnames == 2);
    2837
    2838 if( hasError(fzninput) )
    2839 goto TERMINATE;
    2840
    2841 /* compute left and right side */
    2842 computeLinearConsSides(scip, fzninput, type, sidevalue, &lhs, &rhs);
    2843
    2844 if( hasError(fzninput) )
    2845 goto TERMINATE;
    2846
    2847 SCIP_CALL( createLinking(scip, fzninput, name, names[0], names[1], lhs, rhs) );
    2848
    2849 TERMINATE:
    2850 freeStringBufferArray(scip, names, nnames);
    2851
    2852 return SCIP_OKAY;
    2853}
    2854
    2855/** creates a linear constraint for an array operation */
    2856static
    2857CREATE_CONSTRAINT(createCoercionOpCons)
    2858{ /*lint --e{715}*/
    2859 assert(scip != NULL);
    2860 assert(fzninput != NULL);
    2861
    2862 /* check if the function identifier name is array operation */
    2863 if( !equalTokens(fname, "int2float") && !equalTokens(fname, "bool2int") )
    2864 return SCIP_OKAY;
    2865
    2866 SCIP_CALL( parseLinking(scip, fzninput, fname, "eq", 0.0) );
    2867
    2868 *created = TRUE;
    2869
    2870 return SCIP_OKAY;
    2871}
    2872
    2873/** creates a linear constraint for an array operation */
    2874static
    2875CREATE_CONSTRAINT(createSetOpCons)
    2876{ /*lint --e{715}*/
    2877 assert(scip != NULL);
    2878 assert(fzninput != NULL);
    2879
    2880 /* check if the function identifier name is array operation */
    2881 if( !equalTokens(ftokens[0], "set") )
    2882 return SCIP_OKAY;
    2883
    2884 fzninput->valid = FALSE;
    2885 SCIPwarningMessage(scip, "Line %d: set operations are not supported yet.\n", fzninput->linenumber);
    2886
    2887 return SCIP_OKAY;
    2888}
    2889
    2890/** creates linear constraint for an array operation */
    2891static
    2892CREATE_CONSTRAINT(createArrayOpCons)
    2893{ /*lint --e{715}*/
    2894 assert(scip != NULL);
    2895 assert(fzninput != NULL);
    2896
    2897 /* check if the function identifier name is array operation */
    2898 if( !equalTokens(ftokens[0], "array") )
    2899 return SCIP_OKAY;
    2900
    2901 fzninput->valid = FALSE;
    2902 SCIPwarningMessage(scip, "Line %d: array operations are not supported yet.\n", fzninput->linenumber);
    2903
    2904 return SCIP_OKAY;
    2905}
    2906
    2907/** creates a linear constraint for a logical operation */
    2908static
    2909CREATE_CONSTRAINT(createLogicalOpCons)
    2910{ /*lint --e{715}*/
    2911 assert(scip != NULL);
    2912 assert(fzninput != NULL);
    2913
    2914 /* check if the function identifier name is array operation */
    2915 if(nftokens < 2)
    2916 return SCIP_OKAY;
    2917
    2918 if(equalTokens(ftokens[0], "bool") && nftokens == 2 )
    2919 {
    2920 char** elements;
    2921 int nelements;
    2922
    2923 /* the bool_eq constraint is processed in createComparisonOpCons() */
    2924 if( equalTokens(ftokens[1], "eq") || equalTokens(ftokens[1], "ge") || equalTokens(ftokens[1], "le")
    2925 || equalTokens(ftokens[1], "lt") || equalTokens(ftokens[1], "gt") )
    2926 return SCIP_OKAY;
    2927
    2928 SCIP_CALL( SCIPallocBufferArray(scip, &elements, 3) );
    2929 nelements = 0;
    2930
    2931 SCIP_CALL( parseList(scip, fzninput, &elements, &nelements, 3) );
    2932
    2933 if( !hasError(fzninput) )
    2934 {
    2935 SCIP_CONS* cons;
    2936 SCIP_VAR** vars;
    2937 int v;
    2938 int nvars;
    2939
    2940 if( equalTokens(ftokens[1], "ne") || equalTokens(ftokens[1], "not") )
    2941 nvars = 2;
    2942 else
    2943 nvars = 3;
    2944
    2945 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    2946
    2947 /* collect variable if constraint identifier is a variable */
    2948 for( v = 0; v < nvars; ++v )
    2949 {
    2950 vars[v] = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[v]);
    2951
    2952 if( vars[v] == NULL )
    2953 {
    2954 syntaxError(scip, fzninput, "unknown variable identifier name");
    2955 goto TERMINATE;
    2956 }
    2957 }
    2958
    2959 if( equalTokens(ftokens[1], "ne" ) || equalTokens(ftokens[1], "not") )
    2960 {
    2961 SCIP_Real vals[] = {1.0, 1.0};
    2962
    2963 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, fname, 2, vars, vals, 1.0, 1.0,
    2964 fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
    2965
    2966 *created = TRUE;
    2967 }
    2968 else if( equalTokens(ftokens[1], "or" ) )
    2969 {
    2970 SCIP_CALL( SCIPcreateConsOr(scip, &cons, fname, vars[2], 2, vars,
    2971 fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
    2972
    2973 *created = TRUE;
    2974 }
    2975 else if( equalTokens(ftokens[1], "and") )
    2976 {
    2977 SCIP_CALL( SCIPcreateConsAnd(scip, &cons, fname, vars[2], 2, vars,
    2978 fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
    2979
    2980 *created = TRUE;
    2981 }
    2982 else if( equalTokens(ftokens[1], "xor") )
    2983 {
    2984 /* swap resultant to front */
    2985 SCIPswapPointers((void**)&vars[0], (void**)&vars[2]);
    2986
    2987 SCIP_CALL( SCIPcreateConsXor(scip, &cons, fname, FALSE, 3, vars,
    2988 fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
    2989
    2990 *created = TRUE;
    2991 }
    2992 else
    2993 {
    2994 fzninput->valid = FALSE;
    2995 SCIPwarningMessage(scip, "logical operation <%s> is not supported yet\n", fname);
    2996 goto TERMINATE;
    2997 }
    2998
    3000
    3001 SCIP_CALL( SCIPaddCons(scip, cons) );
    3002 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    3003
    3004 TERMINATE:
    3005 SCIPfreeBufferArray(scip, &vars);
    3006 }
    3007
    3008 /* free elements array */
    3009 freeStringBufferArray(scip, elements, nelements);
    3010 }
    3011 else if(equalTokens(ftokens[1], "bool") && nftokens == 3 )
    3012 {
    3013 SCIP_CONS* cons;
    3014 SCIP_VAR** vars;
    3015 SCIP_VAR* resvar;
    3016 int nvars;
    3017 char** elements;
    3018 int nelements;
    3019 int size;
    3020
    3021 if( !equalTokens(ftokens[2], "or" ) && !equalTokens(ftokens[2], "and" ) )
    3022 {
    3023 fzninput->valid = FALSE;
    3024 SCIPwarningMessage(scip, "logical operation <%s> is not supported yet\n", fname);
    3025 return SCIP_OKAY;
    3026 }
    3027
    3028 size = 10;
    3029 nvars = 0;
    3030
    3031 SCIP_CALL( SCIPallocBufferArray(scip, &vars, size) );
    3032 SCIP_CALL( SCIPallocBufferArray(scip, &elements, 1) );
    3033 nelements = 0;
    3034
    3035 SCIPdebugMsg(scip, "found and constraint <%s>\n", fname);
    3036
    3037 /* parse operand variable array */
    3038 SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, size) );
    3039
    3040 /* check error and for the comma between the variable array and side value */
    3041 if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
    3042 {
    3043 if( hasError(fzninput) )
    3044 syntaxError(scip, fzninput, "unexpected error in fzn input");
    3045 else
    3046 syntaxError(scip, fzninput, "expected token <,>");
    3047
    3048 goto TERMINATE2;
    3049 }
    3050
    3051 /* parse resultant variable array */
    3052 SCIP_CALL( parseList(scip, fzninput, &elements, &nelements, 1) );
    3053 resvar = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) elements[0]);
    3054
    3055 /* check error and for the comma between the variable array and side value */
    3056 if( hasError(fzninput) || resvar == NULL )
    3057 {
    3058 if( hasError(fzninput) )
    3059 syntaxError(scip, fzninput, "unexpected error in fzn input");
    3060 else
    3061 syntaxError(scip, fzninput, "unknown variable identifier name");
    3062 goto TERMINATE2;
    3063 }
    3064
    3065 /* create the constraint */
    3066 if( equalTokens(ftokens[2], "or" ) )
    3067 {
    3068 SCIP_CALL( SCIPcreateConsOr(scip, &cons, fname, resvar, nvars, vars,
    3069 fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
    3070 }
    3071 else
    3072 {
    3073 assert( equalTokens(ftokens[2], "and") );
    3074
    3075 SCIP_CALL( SCIPcreateConsAnd(scip, &cons, fname, resvar, nvars, vars,
    3076 fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
    3077 }
    3078
    3080 *created = TRUE;
    3081
    3082 SCIP_CALL( SCIPaddCons(scip, cons) );
    3083 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    3084
    3085 TERMINATE2:
    3086 /* free elements array */
    3087 freeStringBufferArray(scip, elements, nelements);
    3088 SCIPfreeBufferArray(scip, &vars);
    3089 }
    3090 else if( equalTokens(ftokens[1], "bool") )
    3091 {
    3092 fzninput->valid = FALSE;
    3093 SCIPwarningMessage(scip, "logical operation <%s> is not supported yet\n", fname);
    3094 return SCIP_OKAY;
    3095 }
    3096
    3097 return SCIP_OKAY;
    3098}
    3099
    3100/** creates a linear constraint for a comparison operation */
    3101static
    3102CREATE_CONSTRAINT(createComparisonOpCons)
    3103{ /*lint --e{715}*/
    3104 char assignment[FZN_BUFFERLEN];
    3105
    3106 assert(scip != NULL);
    3107 assert(fzninput != NULL);
    3108
    3109 /* check if the function name ends of "reif" (reified constraint) which SCIP does not support yet */
    3110 if( equalTokens(ftokens[nftokens - 1], "reif") )
    3111 {
    3112 SCIPwarningMessage(scip, "Line %d: reified constraints are not supported.\n", fzninput->linenumber);
    3113 fzninput->valid = FALSE;
    3114 return SCIP_OKAY;
    3115 }
    3116
    3117 /* the last token can be
    3118 * 'eq' -- equal
    3119 * 'ne' -- not equal
    3120 * 'lt' -- less than
    3121 * 'gt' -- greater than
    3122 * 'le' -- less or equal than
    3123 * 'ge' -- greater or equal than
    3124 * => these are comparison constraints
    3125 * 'plus' -- addition
    3126 * 'minus' -- subtraction
    3127 * 'negate' -- negation
    3128 * => these are aggregation constraints
    3129 * 'times' -- multiplication
    3130 * => this is a nonlinear constraint
    3131 */
    3132 if( strlen(ftokens[nftokens - 1]) != 2 && nftokens != 2 )
    3133 return SCIP_OKAY;
    3134
    3135 /* check if any sets are involved in the constraint */
    3136 if( equalTokens(ftokens[0], "set") )
    3137 {
    3138 SCIPwarningMessage(scip, "constraints using sets are not supported\n");
    3139 fzninput->valid = FALSE;
    3140 return SCIP_OKAY;
    3141 }
    3142
    3143 /* check if the constraint is a 'not equal' one */
    3144 if( equalTokens(ftokens[nftokens - 1], "ne") )
    3145 {
    3146 SCIPwarningMessage(scip, "constraints with 'not equal' relation are not supported\n");
    3147 fzninput->valid = FALSE;
    3148 return SCIP_OKAY;
    3149 }
    3150
    3151 /* check if the constraint contains float variable and coefficients and '<' or '>' relation */
    3152 if( equalTokens(ftokens[0], "float") &&
    3153 (equalTokens(ftokens[nftokens - 1], "lt") || equalTokens(ftokens[nftokens - 1], "gt") ) )
    3154 {
    3155 SCIPwarningMessage(scip, "constraints with '<' or '>' relation and continuous variables are not supported\n");
    3156 fzninput->valid = FALSE;
    3157 return SCIP_OKAY;
    3158 }
    3159
    3160 if( equalTokens(ftokens[1], "lin") )
    3161 {
    3162 SCIP_VAR** vars;
    3163 SCIP_Real* vals;
    3164 SCIP_Real sidevalue;
    3165 int nvars;
    3166 int nvals;
    3167 int size;
    3168
    3169 assert(nftokens == 3);
    3170
    3171 size = 10;
    3172 nvars = 0;
    3173 nvals = 0;
    3174 sidevalue = SCIP_INVALID;
    3175
    3176 SCIP_CALL( SCIPallocBufferArray(scip, &vars, size) );
    3177 SCIP_CALL( SCIPallocBufferArray(scip, &vals, size) );
    3178
    3179 SCIPdebugMsg(scip, "found linear constraint <%s>\n", fname);
    3180
    3181 /* pares coefficients array */
    3182 SCIP_CALL( parseConstantArrayAssignment(scip, fzninput, &vals, &nvals, size) );
    3183
    3184 /* check error and for the comma between the coefficient and variable array */
    3185 if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
    3186 {
    3187 if( !hasError(fzninput) )
    3188 syntaxError(scip, fzninput, "expected token <,>");
    3189
    3190 goto TERMINATE;
    3191 }
    3192
    3193 /* pares variable array */
    3194 SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, size) );
    3195
    3196 /* check error and for the comma between the variable array and side value */
    3197 if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
    3198 {
    3199 if( !hasError(fzninput) )
    3200 syntaxError(scip, fzninput, "expected token <,>");
    3201
    3202 goto TERMINATE;
    3203 }
    3204
    3205 /* pares sidevalue */
    3206 flattenAssignment(scip, fzninput, assignment);
    3207 parseValue(scip, fzninput, &sidevalue, assignment);
    3208
    3209 if( !hasError(fzninput) )
    3210 {
    3211 SCIP_Real lhs = -SCIPinfinity(scip);
    3213
    3214 assert(sidevalue != SCIP_INVALID); /*lint !e777*/
    3215
    3216 /* compute left and right side */
    3217 computeLinearConsSides(scip, fzninput, ftokens[2], sidevalue, &lhs, &rhs);
    3218
    3219 if( hasError(fzninput) )
    3220 goto TERMINATE;
    3221
    3222 SCIP_CALL( createLinearCons(scip, fname, nvars, vars, vals, lhs, rhs, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
    3223 }
    3224
    3225 TERMINATE:
    3226 SCIPfreeBufferArray(scip, &vals);
    3227 SCIPfreeBufferArray(scip, &vars);
    3228 }
    3229 else if( equalTokens(ftokens[1], "minus") || equalTokens(ftokens[1], "plus") || equalTokens(ftokens[1], "negate") )
    3230 {
    3231 assert(nftokens == 2);
    3232 SCIP_CALL( parseAggregation(scip, fzninput, fname, ftokens[1]) );
    3233 }
    3234 else if( equalTokens(ftokens[1], "eq") || equalTokens(ftokens[1], "le") || equalTokens(ftokens[1], "ge")
    3235 || equalTokens(ftokens[1], "lt") || equalTokens(ftokens[1], "gt") )
    3236 {
    3237 assert(nftokens == 2);
    3238 SCIP_CALL( parseLinking(scip, fzninput, fname, ftokens[1], 0.0) );
    3239 }
    3240 else if( equalTokens(ftokens[1], "times") )
    3241 {
    3242 assert(nftokens == 2);
    3243 SCIP_CALL( parseQuadratic(scip, fzninput, fname) );
    3244 }
    3245 else
    3246 {
    3247 syntaxError(scip, fzninput, "unknown constraint type");
    3248 }
    3249
    3250 *created = TRUE;
    3251
    3252 return SCIP_OKAY;
    3253}
    3254
    3255/** creates an alldifferent constraint */
    3256static
    3257CREATE_CONSTRAINT(createAlldifferentOpCons)
    3258{ /*lint --e{715}*/
    3259 SCIP_VAR** vars;
    3260#ifdef ALLDIFFERENT
    3261 SCIP_CONS* cons;
    3262#endif
    3263 int nvars;
    3264 int size;
    3265
    3266 assert(scip != NULL);
    3267 assert(fzninput != NULL);
    3268
    3269 /* check if the function identifier name is array operation */
    3270 if( !equalTokens(ftokens[0], "all") || !equalTokens(ftokens[1], "different") )
    3271 return SCIP_OKAY;
    3272
    3273 size = 10;
    3274 nvars = 0;
    3275 SCIP_CALL( SCIPallocBufferArray(scip, &vars, size) );
    3276
    3277 SCIPdebugMsg(scip, "parse alldifferent expression\n");
    3278
    3279 /* pares variable array */
    3280 SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, size) );
    3281
    3282#ifdef ALLDIFFERENT
    3283 /* create alldifferent constraint */
    3284 SCIP_CALL( SCIPcreateConsAlldifferent(scip, &cons, fname, nvars, vars,
    3285 fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
    3286
    3288
    3289 /* add and release the constraint to the problem */
    3290 SCIP_CALL( SCIPaddCons(scip, cons) );
    3291 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    3292
    3293 *created = TRUE;
    3294#endif
    3295
    3296 SCIPfreeBufferArray(scip, &vars);
    3297
    3298 return SCIP_OKAY;
    3299}
    3300
    3301/** creates an alldifferent constraint */
    3302static
    3303CREATE_CONSTRAINT(createCumulativeOpCons)
    3304{ /*lint --e{715}*/
    3305 SCIP_CONS* cons;
    3306 SCIP_VAR** vars;
    3307 SCIP_Real* vals = NULL;
    3308 int* durations = NULL;
    3309 int* demands = NULL;
    3310 SCIP_Real val;
    3311 int capacity;
    3312 char assignment[FZN_BUFFERLEN];
    3313
    3314 int nvars;
    3315 int ndurations;
    3316 int ndemads;
    3317 int size;
    3318 int i;
    3319
    3320 assert(scip != NULL);
    3321 assert(fzninput != NULL);
    3322
    3323 /* check if the function identifier name is array operation */
    3324 if( !equalTokens(ftokens[0], "cumulative") )
    3325 return SCIP_OKAY;
    3326
    3327 size = 10;
    3328 nvars = 0;
    3329 ndurations = 0;
    3330 ndemads = 0;
    3331
    3332 SCIPdebugMsg(scip, "parse cumulative expression\n");
    3333
    3334 /* pares start time variable array */
    3335 SCIP_CALL( SCIPallocBufferArray(scip, &vars, size) );
    3336 SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, size) );
    3337
    3338 /* check error and for the comma between the variable array and side value */
    3339 if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
    3340 {
    3341 if( !hasError(fzninput) )
    3342 syntaxError(scip, fzninput, "expected token <,>");
    3343
    3344 goto TERMINATE;
    3345 }
    3346
    3347 /* pares job duration array */
    3348 SCIP_CALL( SCIPallocBufferArray(scip, &vals, size) );
    3349 SCIP_CALL( parseConstantArrayAssignment(scip, fzninput, &vals, &ndurations, size) );
    3350
    3351 SCIP_CALL( SCIPallocBufferArray(scip, &durations, ndurations) );
    3352 for( i = 0; i < ndurations; ++i )
    3353 durations[i] = (int)vals[i];
    3354
    3355 /* check error and for the comma between the variable array and side value */
    3356 if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
    3357 {
    3358 if( !hasError(fzninput) )
    3359 syntaxError(scip, fzninput, "expected token <,>");
    3360
    3361 goto TERMINATE;
    3362 }
    3363
    3364 /* pares job demand array */
    3365 SCIP_CALL( parseConstantArrayAssignment(scip, fzninput, &vals, &ndemads, size) );
    3366
    3367 SCIP_CALL( SCIPallocBufferArray(scip, &demands, ndemads) );
    3368 for( i = 0; i < ndemads; ++i )
    3369 demands[i] = (int)vals[i];
    3370
    3371 /* check error and for the comma between the variable array and side value */
    3372 if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
    3373 {
    3374 if( !hasError(fzninput) )
    3375 syntaxError(scip, fzninput, "expected token <,>");
    3376
    3377 goto TERMINATE;
    3378 }
    3379
    3380 /* parse cumulative capacity */
    3381 flattenAssignment(scip, fzninput, assignment);
    3382 parseValue(scip, fzninput, &val, assignment);
    3383 assert(!hasError(fzninput));
    3384
    3385 capacity = (int)val;
    3386
    3387 assert(nvars == ndurations);
    3388 assert(nvars == ndemads);
    3389
    3390 /* create cumulative constraint */
    3391 SCIP_CALL( SCIPcreateConsCumulative(scip, &cons, fname, nvars, vars, durations, demands, capacity,
    3392 fzninput->initialconss, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, fzninput->dynamicconss, fzninput->dynamicrows, FALSE) );
    3393
    3395
    3396 /* add and release the constraint to the problem */
    3397 SCIP_CALL( SCIPaddCons(scip, cons) );
    3398 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    3399
    3400 assert(!hasError(fzninput));
    3401 *created = TRUE;
    3402
    3403 TERMINATE:
    3404 /* free buffers */
    3405 SCIPfreeBufferArrayNull(scip, &demands);
    3406 SCIPfreeBufferArrayNull(scip, &durations);
    3408 SCIPfreeBufferArray(scip, &vars);
    3409
    3410 return SCIP_OKAY;
    3411}
    3412
    3413/* function pointer array containing all function which can create a constraint */
    3414static CREATE_CONSTRAINT((*constypes[])) = {
    3415 createCoercionOpCons,
    3416 createSetOpCons,
    3417 createLogicalOpCons,
    3418 createArrayOpCons,
    3419 createComparisonOpCons,
    3420 createAlldifferentOpCons,
    3421 createCumulativeOpCons
    3422};
    3423
    3424/** size of the function pointer array */
    3425static const int nconstypes = 7;
    3426
    3427
    3428/** parse constraint expression */
    3429static
    3431 SCIP* scip, /**< SCIP data structure */
    3432 FZNINPUT* fzninput /**< FZN reading data */
    3433 )
    3434{
    3435 SCIP_VAR* var;
    3436 char* tokens[4];
    3437 char* token;
    3438 char* nexttoken;
    3439 char name[FZN_BUFFERLEN];
    3440 char fname[FZN_BUFFERLEN];
    3441 SCIP_Bool created;
    3442 int ntokens;
    3443 int i;
    3444 int c;
    3445
    3446 assert(scip != NULL);
    3447 assert(fzninput != NULL);
    3448
    3449 SCIPdebugMsg(scip, "parse constraint expression\n");
    3450
    3451 /* get next token already flatten */
    3452 flattenAssignment(scip, fzninput, name);
    3453
    3454 /* check if constraint identifier is a variable */
    3455 var = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) name);
    3456
    3457 if( var != NULL )
    3458 {
    3459 SCIP_Real vals[] = {1.0};
    3460
    3461 /* create fixing constraint */
    3462 SCIP_CALL( createLinearCons(scip, "fixing", 1, &var, vals, 1.0, 1.0, fzninput->initialconss, fzninput->dynamicconss, fzninput->dynamicrows) );
    3463 return SCIP_OKAY;
    3464 }
    3465
    3466 /* check constraint identifier name */
    3467 if( !isIdentifier(name) )
    3468 {
    3469 syntaxError(scip, fzninput, "expected constraint identifier name");
    3470 return SCIP_OKAY;
    3471 }
    3472
    3473 /* check if we have a opening parenthesis */
    3474 if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '(') )
    3475 {
    3476 syntaxError(scip, fzninput, "expected token <(>");
    3477 return SCIP_OKAY;
    3478 }
    3479
    3480 /* copy function name */
    3481 (void) SCIPsnprintf(fname, FZN_BUFFERLEN, "%s", name);
    3482
    3483 /* truncate the function identifier name in separate tokens */
    3484 token = SCIPstrtok(name, "_", &nexttoken);
    3485 ntokens = 0;
    3486 while( token != NULL )
    3487 {
    3488 if( ntokens == 4 )
    3489 break;
    3490
    3491 SCIP_CALL( SCIPduplicateBufferArray(scip, &(tokens[ntokens]), token, (int) strlen(token) + 1) ); /*lint !e866*/
    3492 ntokens++;
    3493
    3494 token = SCIPstrtok(NULL, "_", &nexttoken);
    3495 }
    3496
    3497 assert(token == NULL || tokens[0] != NULL); /*lint !e771*/
    3498 for( i = 0; i < ntokens; ++i )
    3499 {
    3500 SCIPdebugMsgPrint(scip, "%s ", tokens[i]);
    3501 }
    3502 SCIPdebugMsgPrint(scip, "\n");
    3503
    3504 created = FALSE;
    3505
    3506 /* loop over all methods which can create a constraint */
    3507 for( c = 0; c < nconstypes && !created && !hasError(fzninput); ++c )
    3508 {
    3509 SCIP_CALL( constypes[c](scip, fzninput, fname, tokens, ntokens, &created) );
    3510 }
    3511
    3512 /* check if a constraint was created */
    3513 if( !hasError(fzninput) && !created )
    3514 {
    3515 fzninput->valid = FALSE;
    3516 SCIPwarningMessage(scip, "Line %d: Constraint <%s> is not supported yet.\n", fzninput->linenumber, fname);
    3517 }
    3518
    3519 /* free memory */
    3520 for( i = ntokens - 1; i >= 0 ; --i )
    3521 {
    3522 SCIPfreeBufferArray(scip, &tokens[i]);
    3523 }
    3524
    3525 /* check for the closing parenthesis */
    3526 if( !hasError(fzninput) && ( !getNextToken(scip, fzninput) || !isChar(fzninput->token, ')')) )
    3527 syntaxError(scip, fzninput, "expected token <)>");
    3528
    3529 return SCIP_OKAY;
    3530}
    3531
    3532/** parse solve item expression */
    3533static
    3535 SCIP* scip, /**< SCIP data structure */
    3536 FZNINPUT* fzninput /**< FZN reading data */
    3537 )
    3538{
    3539 assert(scip != NULL);
    3540 assert(fzninput != NULL);
    3541
    3542 SCIPdebugMsg(scip, "parse solve item expression\n");
    3543
    3544 if( !getNextToken(scip, fzninput) )
    3545 {
    3546 syntaxError(scip, fzninput, "expected solving specification");
    3547 return SCIP_OKAY;
    3548 }
    3549
    3550 /* check for annotations */
    3551 if( equalTokens(fzninput->token, "::") )
    3552 {
    3553 /* skip the annotation */
    3554 do
    3555 {
    3556 if( !getNextToken(scip, fzninput) )
    3557 syntaxError(scip, fzninput, "expected more tokens");
    3558 }
    3559 while( !equalTokens(fzninput->token, "satisfy")
    3560 && !equalTokens(fzninput->token, "minimize")
    3561 && !equalTokens(fzninput->token, "maximize") );
    3562 }
    3563
    3564 if( equalTokens(fzninput->token, "satisfy") )
    3565 {
    3566 SCIPdebugMsg(scip, "detected a satisfiability problem\n");
    3567 }
    3568 else
    3569 {
    3570 SCIP_VAR* var;
    3571 FZNCONSTANT* constant;
    3572 char name[FZN_BUFFERLEN];
    3573
    3574 if( equalTokens(fzninput->token, "minimize") )
    3575 {
    3576 fzninput->objsense = SCIP_OBJSENSE_MINIMIZE;
    3577 SCIPdebugMsg(scip, "detected a minimization problem\n");
    3578 }
    3579 else
    3580 {
    3581 assert(equalTokens(fzninput->token, "maximize"));
    3582 fzninput->objsense = SCIP_OBJSENSE_MAXIMIZE;
    3583 SCIPdebugMsg(scip, "detected a maximization problem\n");
    3584 }
    3585
    3586 /* parse objective coefficients */
    3587
    3588 /* parse and flatten assignment */
    3589 flattenAssignment(scip, fzninput, name);
    3590
    3591 var = (SCIP_VAR*) SCIPhashtableRetrieve(fzninput->varHashtable, (char*) name);
    3592 constant = (FZNCONSTANT*) SCIPhashtableRetrieve(fzninput->constantHashtable, (char*) name);
    3593
    3594 if( var != NULL )
    3595 {
    3596 SCIP_CALL( SCIPchgVarObj(scip, var, 1.0) );
    3597 }
    3598 else if( constant != NULL )
    3599 {
    3600 SCIPdebugMsg(scip, "optimizing a constant is equal to a satisfiability problem!\n");
    3601 }
    3602 else if( equalTokens(name, "int_float_lin") )
    3603 {
    3604 SCIP_VAR** vars;
    3605 SCIP_Real* vals;
    3606 int nvars;
    3607 int nvals;
    3608 int size;
    3609 int v;
    3610
    3611 nvars = 0;
    3612 nvals = 0;
    3613 size = 10;
    3614
    3615 SCIP_CALL( SCIPallocBufferArray(scip, &vars, size) );
    3616 SCIP_CALL( SCIPallocBufferArray(scip, &vals, size) );
    3617
    3618 SCIPdebugMsg(scip, "found linear objective\n");
    3619
    3620 if( !getNextToken(scip, fzninput) || !isChar(fzninput->token, '(') )
    3621 {
    3622 syntaxError(scip, fzninput, "expected token <(>");
    3623 goto TERMINATE;
    3624 }
    3625
    3626 /* pares coefficients array for integer variables */
    3627 SCIP_CALL( parseConstantArrayAssignment(scip, fzninput, &vals, &nvals, size) );
    3628
    3629 /* check error and for the comma between the coefficient and variable array */
    3630 if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
    3631 {
    3632 if( !hasError(fzninput) )
    3633 syntaxError(scip, fzninput, "expected token <,>");
    3634
    3635 goto TERMINATE;
    3636 }
    3637
    3638 /* pares coefficients array for continuous variables */
    3639 SCIP_CALL( parseConstantArrayAssignment(scip, fzninput, &vals, &nvals, MAX(size, nvals)) );
    3640
    3641 /* check error and for the comma between the coefficient and variable array */
    3642 if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
    3643 {
    3644 if( !hasError(fzninput) )
    3645 syntaxError(scip, fzninput, "expected token <,>");
    3646
    3647 goto TERMINATE;
    3648 }
    3649
    3650 /* pares integer variable array */
    3651 SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, size) );
    3652
    3653 /* check error and for the comma between the variable array and side value */
    3654 if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ',') )
    3655 {
    3656 if( !hasError(fzninput) )
    3657 syntaxError(scip, fzninput, "expected token <,>");
    3658
    3659 goto TERMINATE;
    3660 }
    3661
    3662 assert(nvars <= nvals);
    3663
    3664 /* pares continuous variable array */
    3665 SCIP_CALL( parseVariableArrayAssignment(scip, fzninput, &vars, &nvars, MAX(size, nvars)) );
    3666
    3667 /* check error and for the ')' */
    3668 if( hasError(fzninput) || !getNextToken(scip, fzninput) || !isChar(fzninput->token, ')') )
    3669 {
    3670 if( !hasError(fzninput) )
    3671 syntaxError(scip, fzninput, "expected token <)>");
    3672
    3673 goto TERMINATE;
    3674 }
    3675
    3676 assert( nvars == nvals );
    3677
    3678 for( v = 0; v < nvars; ++v )
    3679 {
    3680 SCIP_CALL( SCIPchgVarObj(scip, vars[v], vals[v]) );
    3681 }
    3682
    3683 TERMINATE:
    3684 SCIPfreeBufferArray(scip, &vals);
    3685 SCIPfreeBufferArray(scip, &vars);
    3686 }
    3687 else
    3688 {
    3689 syntaxError(scip, fzninput, "unknown identifier expression for a objective function");
    3690 }
    3691 }
    3692
    3693 return SCIP_OKAY;
    3694}
    3695
    3696/** reads a FlatZinc model */
    3697static
    3699 SCIP* scip, /**< SCIP data structure */
    3700 SCIP_READERDATA* readerdata, /**< reader data */
    3701 FZNINPUT* fzninput, /**< FZN reading data */
    3702 const char* filename /**< name of the input file */
    3703 )
    3704{
    3705 assert(scip != NULL);
    3706 assert(readerdata != NULL);
    3707 assert(fzninput != NULL);
    3708
    3709 /* open file */
    3710 fzninput->file = SCIPfopen(filename, "r");
    3711 if( fzninput->file == NULL )
    3712 {
    3713 SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
    3714 SCIPprintSysError(filename);
    3715 return SCIP_NOFILE;
    3716 }
    3717
    3718 /* create problem */
    3719 SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
    3720
    3721 /* create two auxiliary variable for true and false values */
    3722 SCIP_CALL( createVariable(scip, fzninput, NULL, "true", 1.0, 1.0, FZN_BOOL) );
    3723 SCIP_CALL( createVariable(scip, fzninput, NULL, "false", 0.0, 0.0, FZN_BOOL) );
    3724
    3725 /* parse through statements one-by-one */
    3726 while( !SCIPfeof( fzninput->file ) && !hasError(fzninput) )
    3727 {
    3728 /* read the first token (keyword) of a new statement */
    3729 if( getNextToken(scip, fzninput) )
    3730 {
    3731 if( equalTokens(fzninput->token, "predicate") )
    3732 {
    3733 /* parse array expression containing constants or variables */
    3734 SCIP_CALL( parsePredicate(scip, fzninput) );
    3735 }
    3736 else if( equalTokens(fzninput->token, "array") )
    3737 {
    3738 /* parse array expression containing constants or variables */
    3739 SCIP_CALL( parseArray(scip, readerdata, fzninput) );
    3740 }
    3741 else if( equalTokens(fzninput->token, "constraint") )
    3742 {
    3743 /* parse a constraint */
    3744 SCIP_CALL( parseConstraint(scip, fzninput) );
    3745 }
    3746 else if( equalTokens(fzninput->token, "int") )
    3747 {
    3748 /* parse an integer constant */
    3749 SCIP_CALL( parseConstant(scip, fzninput, FZN_INT) );
    3750 }
    3751 else if( equalTokens(fzninput->token, "float") )
    3752 {
    3753 /* parse a float constant */
    3754 SCIP_CALL( parseConstant(scip, fzninput, FZN_FLOAT) );
    3755 }
    3756 else if( equalTokens(fzninput->token, "bool") )
    3757 {
    3758 /* parse a bool constant */
    3759 SCIP_CALL( parseConstant(scip, fzninput, FZN_BOOL) );
    3760 }
    3761 else if( equalTokens(fzninput->token, "set") )
    3762 {
    3763 /* deal with sets */
    3764 SCIPwarningMessage(scip, "sets are not supported yet\n");
    3765 fzninput->valid = FALSE;
    3766 break;
    3767 }
    3768 else if( equalTokens(fzninput->token, "solve") )
    3769 {
    3770 /* parse solve item (objective sense and objective function) */
    3771 SCIP_CALL( parseSolveItem(scip, fzninput) );
    3772 }
    3773 else if( equalTokens(fzninput->token, "var") )
    3774 {
    3775 /* parse variables */
    3776 SCIP_CALL( parseVariable(scip, readerdata, fzninput) );
    3777 }
    3778 else if( equalTokens(fzninput->token, "output") )
    3779 {
    3780 /* the output section is the last section in the flatzinc model and can be skipped */
    3781 SCIPdebugMsg(scip, "skip output section\n");
    3782 break;
    3783 }
    3784 else
    3785 {
    3786 FZNNUMBERTYPE type;
    3787 SCIP_Real lb;
    3788 SCIP_Real ub;
    3789
    3790 /* check if the new statement starts with a range expression
    3791 * which indicates a constant; therefore, push back the current token
    3792 * since it belongs to the range expression */
    3793 pushToken(fzninput);
    3794
    3795 /* parse range to detect constant type */
    3796 parseRange(scip, fzninput, &type, &lb, &ub);
    3797
    3798 if( hasError(fzninput) )
    3799 break;
    3800
    3801 /* parse the remaining constant statement */
    3802 SCIP_CALL( parseConstant(scip, fzninput, type) );
    3803
    3804 if( hasError(fzninput) )
    3805 {
    3806 SCIPwarningMessage(scip, "unknown keyword <%s> skip statement\n", fzninput->token);
    3807 SCIPABORT();
    3808 return SCIP_OKAY; /*lint !e527*/
    3809 }
    3810 }
    3811
    3812 if( hasError(fzninput) )
    3813 break;
    3814
    3815 /* if the current statement got marked as comment continue with the next line */
    3816 if( fzninput->comment )
    3817 continue;
    3818
    3819 /* each statement should be closed with a semicolon */
    3820 if( !getNextToken(scip, fzninput) )
    3821 syntaxError(scip, fzninput, "expected semicolon");
    3822
    3823 /* check for annotations */
    3824 if( equalTokens(fzninput->token, "::") )
    3825 {
    3826 /* skip the annotation */
    3827 do
    3828 {
    3829 if( !getNextToken(scip, fzninput) )
    3830 syntaxError(scip, fzninput, "expected more tokens");
    3831 }
    3832 while( !isEndStatement(fzninput) );
    3833 }
    3834
    3835 if( !isEndStatement(fzninput) )
    3836 syntaxError(scip, fzninput, "expected semicolon");
    3837 }
    3838 }
    3839
    3840 /* close file */
    3841 SCIPfclose(fzninput->file);
    3842
    3843 if( hasError(fzninput) )
    3844 {
    3846
    3847 /* create empty problem */
    3848 SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
    3849 }
    3850 else
    3851 {
    3852 SCIP_CALL( SCIPsetObjsense(scip, fzninput->objsense) );
    3853 }
    3854
    3855 return SCIP_OKAY;
    3856}
    3857
    3858
    3859/*
    3860 * Local methods (for writing)
    3861 */
    3862
    3863/** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
    3864static
    3866 SCIP* scip, /**< SCIP data structure */
    3867 SCIP_VAR*** vars, /**< pointer to vars array to get active variables for */
    3868 SCIP_Real** scalars, /**< pointer to scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
    3869 int* nvars, /**< pointer to number of variables and values in vars and vals array */
    3870 SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
    3871 SCIP_Bool transformed /**< transformed constraint? */
    3872 )
    3873{
    3874 int requiredsize;
    3875 int v;
    3876
    3877 assert(scip != NULL);
    3878 assert(vars != NULL);
    3879 assert(scalars != NULL);
    3880 assert(nvars != NULL);
    3881 assert(*vars != NULL || *nvars == 0);
    3882 assert(*scalars != NULL || *nvars == 0);
    3883 assert(constant != NULL);
    3884
    3885 if( transformed )
    3886 {
    3887 SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize) );
    3888
    3889 if( requiredsize > *nvars )
    3890 {
    3891 SCIP_CALL( SCIPreallocBufferArray(scip, vars, requiredsize) );
    3892 SCIP_CALL( SCIPreallocBufferArray(scip, scalars, requiredsize) );
    3893
    3894 SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize) );
    3895 }
    3896 assert( requiredsize == *nvars );
    3897 }
    3898 else
    3899 {
    3900 if( *nvars > 0 && ( *vars == NULL || *scalars == NULL ) ) /*lint !e774 !e845*/
    3901 {
    3902 SCIPerrorMessage("Null pointer in FZN reader\n"); /* should not happen */
    3903 SCIPABORT();
    3904 return SCIP_INVALIDDATA; /*lint !e527*/
    3905 }
    3906
    3907 for( v = 0; v < *nvars; ++v )
    3908 {
    3909 SCIP_CALL( SCIPvarGetOrigvarSum(&(*vars)[v], &(*scalars)[v], constant) );
    3910
    3911 /* negated variables with an original counterpart may also be returned by SCIPvarGetOrigvarSum();
    3912 * make sure we get the original variable in that case
    3913 */
    3914 if( SCIPvarGetStatus((*vars)[v]) == SCIP_VARSTATUS_NEGATED )
    3915 {
    3916 (*vars)[v] = SCIPvarGetNegatedVar((*vars)[v]);
    3917 *constant += (*scalars)[v];
    3918 (*scalars)[v] *= -1.0;
    3919 }
    3920 }
    3921 }
    3922 return SCIP_OKAY;
    3923}
    3924
    3925/** ends the given line with '\\0' and prints it to the given file stream */
    3926static
    3928 SCIP* scip, /**< SCIP data structure */
    3929 FILE* file, /**< output file (or NULL for standard output) */
    3930 char* buffer, /**< line */
    3931 int bufferpos /**< number of characters in buffer */
    3932 )
    3933{
    3934 assert( scip != NULL );
    3935 assert( buffer != NULL );
    3936
    3937 if( bufferpos > 0 )
    3938 {
    3939 buffer[bufferpos] = '\0';
    3940
    3941 SCIPinfoMessage(scip, file, "%s", buffer);
    3942 }
    3943}
    3944
    3945/** appends extension to line and prints it to the give file stream if the line buffer get full */
    3946static
    3948 SCIP* scip, /**< SCIP data structure */
    3949 char** buffer, /**< buffer which should be extended */
    3950 int* bufferlen, /**< length of the buffer */
    3951 int* bufferpos, /**< current position in the buffer */
    3952 const char* extension /**< string to extend the line */
    3953 )
    3954{
    3955 int newpos;
    3956 int extlen;
    3957
    3958 assert( scip != NULL );
    3959 assert( buffer != NULL );
    3960 assert( bufferlen != NULL );
    3961 assert( bufferpos != NULL );
    3962 assert( extension != NULL );
    3963
    3964 /* avoid overflow by reallocation */
    3965 extlen = (int)strlen(extension);
    3966 newpos = (*bufferpos) + extlen;
    3967 if( newpos >= (*bufferlen) )
    3968 {
    3969 *bufferlen = MAX( newpos, 2 * (*bufferlen) );
    3970
    3971 SCIP_CALL( SCIPreallocBufferArray(scip, buffer, (*bufferlen)) );
    3972 }
    3973
    3974 /* append extension to linebuffer (+1 because of '\0') */
    3975 (void)SCIPstrncpy((*buffer) + (*bufferpos), extension, extlen + 1);
    3976 *bufferpos = newpos;
    3977
    3978 return SCIP_OKAY;
    3979}
    3980
    3981/* Writes a real value to a string with full precision, if fractional and adds a ".0" if integral */
    3982static
    3984 SCIP* scip, /**< SCIP data structure */
    3985 SCIP_Real val, /**< value to flatten */
    3986 char* buffer /**< string buffer to print in */
    3987 )
    3988{
    3989 if( SCIPisIntegral(scip, val) )
    3990 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.1f", SCIPround(scip, val));
    3991 else
    3992 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%+.15g", val);
    3993}
    3994
    3995/* print row in FZN format to file stream */
    3996static
    3998 SCIP* scip, /**< SCIP data structure */
    3999 FZNOUTPUT* fznoutput, /**< output data structure containing the buffers to write to */
    4000 const char* type, /**< row type ("eq", "le" or "ge") */
    4001 SCIP_VAR** vars, /**< array of variables */
    4002 SCIP_Real* vals, /**< array of values */
    4003 int nvars, /**< number of variables */
    4004 SCIP_Real rhs, /**< right hand side */
    4005 SCIP_Bool hasfloats /**< are there continuous variables or coefficients in the constraint? */
    4006 )
    4007{
    4008 SCIP_VAR* var; /* some variable */
    4009 int v; /* variable counter */
    4010 char buffer[FZN_BUFFERLEN];
    4011 char buffy[FZN_BUFFERLEN];
    4012
    4013 assert( scip != NULL );
    4014 assert( vars != NULL || nvars == 0 );
    4015 assert( strcmp(type, "eq") == 0 || strcmp(type, "le") == 0 || strcmp(type, "ge") == 0 );
    4016
    4017 /* Add a constraint of type float_lin or int_lin, depending on whether there are continuous variables or coefficients */
    4018 SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), "constraint ") );
    4019 if( hasfloats )
    4020 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "float_lin_%s([", type);
    4021 else
    4022 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "int_lin_%s([", type);
    4023 SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
    4024
    4025 /* print all coefficients but the last one */
    4026 for( v = 0; v < nvars-1; ++v )
    4027 {
    4028 if( hasfloats )
    4029 {
    4030 flattenFloat(scip, vals[v], buffy);
    4031 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s, ", buffy);
    4032 }
    4033 else
    4034 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.f, ", vals[v]);
    4035 SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
    4036 }
    4037
    4038 /* print last coefficient */
    4039 if( nvars > 0 )
    4040 {
    4041 if( hasfloats )
    4042 {
    4043 flattenFloat(scip, vals[nvars-1], buffy);
    4044 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s", buffy);
    4045 }
    4046 else
    4047 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.f", vals[nvars-1]);
    4048
    4049 SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
    4050 }
    4051
    4052 SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), "], [") );
    4053
    4054 /* print all variables but the last one */
    4055 for( v = 0; v < nvars-1; ++v )
    4056 {
    4057 var = vars[v]; /*lint !e613*/
    4058 assert( var != NULL );
    4059
    4060 if( hasfloats )
    4061 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s%s, ", SCIPvarGetName(var), fznoutput->vardiscrete[SCIPvarGetProbindex(var)] ? "_float" : "");
    4062 else
    4063 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s, ", SCIPvarGetName(var) );
    4064 SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), buffer) );
    4065 }
    4066
    4067 /* print last variable */
    4068 if( nvars > 0 )
    4069 {
    4070 assert(vars != NULL); /* for lint */
    4071 if( hasfloats )
    4072 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s%s",SCIPvarGetName(vars[nvars-1]),
    4073 fznoutput->vardiscrete[SCIPvarGetProbindex(vars[nvars-1])] ? "_float" : ""); /*lint !e613*/
    4074 else
    4075 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s", SCIPvarGetName(vars[nvars-1])); /*lint !e613*/
    4076
    4077 SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos),buffer) );
    4078 }
    4079
    4080 SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos), "], ") );
    4081
    4082 /* print right hand side */
    4083 if( SCIPisZero(scip, rhs) )
    4084 rhs = 0.0;
    4085
    4086 if( hasfloats )
    4087 {
    4088 flattenFloat(scip, rhs, buffy);
    4089 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%s);\n", buffy);
    4090 }
    4091 else
    4092 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "%.f);\n", rhs);
    4093 SCIP_CALL( appendBuffer(scip, &(fznoutput->consbuffer), &(fznoutput->consbufferlen), &(fznoutput->consbufferpos),buffer) );
    4094
    4095 return SCIP_OKAY;
    4096}
    4097
    4098/** prints given linear constraint information in FZN format to file stream */
    4099static
    4101 SCIP* scip, /**< SCIP data structure */
    4102 FZNOUTPUT* fznoutput, /**< output data structure containing the buffers to write to */
    4103 SCIP_VAR** vars, /**< array of variables */
    4104 SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
    4105 int nvars, /**< number of variables */
    4106 SCIP_Real lhs, /**< left hand side */
    4107 SCIP_Real rhs, /**< right hand side */
    4108 SCIP_Bool transformed /**< transformed 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 /* fractional sides trigger a constraint to be of float type */
    4155 if( !SCIPisInfinity(scip, -lhs) )
    4156 hasfloats = hasfloats || !SCIPisIntegral(scip, lhs-activeconstant);
    4157 if( !SCIPisInfinity(scip, rhs) )
    4158 hasfloats = hasfloats || !SCIPisIntegral(scip, rhs-activeconstant);
    4159
    4160 /* any continuous variable or fractional variable coefficient triggers a constraint to be of float type */
    4161 for( v = 0; v < nactivevars && !hasfloats; v++ )
    4162 {
    4163 SCIP_VAR* var;
    4164
    4165 assert(activevars != 0);
    4166 var = activevars[v];
    4167
    4168 hasfloats = hasfloats || !fznoutput->vardiscrete[SCIPvarGetProbindex(var)] || !SCIPisIntegral(scip, activevals[v]);
    4169 }
    4170
    4171 /* If the constraint has to be written as float type, all discrete variables need to have a float counterpart */
    4172 if( hasfloats )
    4173 {
    4174 for( v = 0; v < nactivevars; v++ )
    4175 {
    4176 SCIP_VAR* var;
    4177 int idx;
    4178
    4179 assert(activevars != 0);
    4180 var = activevars[v];
    4181 idx = SCIPvarGetProbindex(var);
    4182 assert( idx >= 0);
    4183
    4184 /* If there was no float representation of the variable before, add an auxiliary variable and a conversion constraint */
    4185 if( fznoutput->vardiscrete[idx] && !fznoutput->varhasfloat[idx] )
    4186 {
    4187 assert(SCIPvarIsIntegral(var));
    4188
    4189 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "var float: %s_float;\n", SCIPvarGetName(var));
    4190 SCIP_CALL( appendBuffer(scip, &(fznoutput->varbuffer), &(fznoutput->varbufferlen), &(fznoutput->varbufferpos),buffer) );
    4191
    4192 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "constraint int2float(%s, %s_float);\n", SCIPvarGetName(var), SCIPvarGetName(var));
    4193 SCIP_CALL( appendBuffer(scip, &(fznoutput->castbuffer), &(fznoutput->castbufferlen), &(fznoutput->castbufferpos),buffer) );
    4194
    4195 fznoutput->varhasfloat[idx] = TRUE;
    4196 }
    4197 }
    4198 }
    4199
    4200 if( SCIPisEQ(scip, lhs, rhs) )
    4201 {
    4202 assert( !SCIPisInfinity(scip, rhs) );
    4203
    4204 /* equality constraint */
    4205 SCIP_CALL( printRow(scip, fznoutput, "eq", activevars, activevals, nactivevars, rhs - activeconstant, hasfloats) );
    4206 }
    4207 else
    4208 {
    4209 if( !SCIPisInfinity(scip, -lhs) )
    4210 {
    4211 /* print inequality ">=" */
    4212 SCIP_CALL( printRow(scip, fznoutput, "ge", activevars, activevals, nactivevars, lhs - activeconstant, hasfloats) );
    4213 }
    4214
    4215 if( !SCIPisInfinity(scip, rhs) )
    4216 {
    4217 /* print inequality "<=" */
    4218 SCIP_CALL( printRow(scip, fznoutput, "le", activevars, activevals, nactivevars, rhs - activeconstant, hasfloats) );
    4219 }
    4220 }
    4221
    4222 /* free buffer arrays */
    4223 SCIPfreeBufferArrayNull(scip, &activevars);
    4224 SCIPfreeBufferArrayNull(scip, &activevals);
    4225
    4226 return SCIP_OKAY;
    4227}
    4228
    4229/** writes problem to a flatzinc conforming file, including introduction of several auxiliary variables and constraints */
    4230static
    4232 SCIP* scip, /**< SCIP data structure */
    4233 FILE* file, /**< output file, or NULL if standard output should be used */
    4234 const char* name, /**< problem name */
    4235 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
    4236 SCIP_OBJSENSE objsense, /**< objective sense */
    4237 SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
    4238 * extobj = objsense * objscale * (intobj + objoffset) */
    4239 SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
    4240 SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
    4241 int nvars, /**< number of active variables in the problem */
    4242 int nbinvars, /**< number of binary variables */
    4243 int nintvars, /**< number of general integer variables */
    4244 int nimplvars, /**< number of implicit integer variables */
    4245 int ncontvars, /**< number of continuous variables */
    4246 SCIP_CONS** conss, /**< array with constraints of the problem */
    4247 int nconss, /**< number of constraints in the problem */
    4248 SCIP_RESULT* result /**< pointer to store the result of the file writing call */
    4249 )
    4250{
    4251 FZNOUTPUT fznoutput; /* data structure for writing in fzn format */
    4252
    4253 SCIP_CONSHDLR* conshdlr;
    4254 SCIP_CONS* cons;
    4255 const char* conshdlrname;
    4256 SCIP_VAR** consvars; /* variables of a specific constraint */
    4257 SCIP_VAR* var;
    4258 SCIP_BOUNDTYPE* boundtypes; /* indicates whether to which side the variables are bounded */
    4259 SCIP_Real* consvals; /* coefficients of a specific constraint */
    4260
    4261 int* boundedvars; /* variables which are bounded to exactly one side */
    4262 int* floatobjvars; /* discrete variables which have a fractional objective coefficient */
    4263 int* intobjvars; /* discrete variables which have an integral objective coefficient */
    4264
    4265 SCIP_Real lb; /* lower bound of some variable */
    4266 SCIP_Real ub; /* upper bound of some variable */
    4267
    4268 int implintlevel; /* implied integral level */
    4269 int ndiscretevars; /* number of discrete variables */
    4270 int nboundedvars; /* number of variables which are bounded to exactly one side */
    4271 int nconsvars; /* number of variables appearing in a specific constraint */
    4272 int nfloatobjvars; /* number of discrete variables which have a fractional objective coefficient */
    4273 int nintobjvars; /* number of discrete variables which have an integral objective coefficient */
    4274 int c; /* counter for the constraints */
    4275 int v; /* counter for the variables */
    4276
    4277 char varname[SCIP_MAXSTRLEN]; /* buffer for storing variable names */
    4278 char buffer[FZN_BUFFERLEN]; /* buffer for storing auxiliary variables and constraints */
    4279 char buffy[FZN_BUFFERLEN];
    4280
    4281 SCIP_CALL( SCIPgetIntParam(scip, "write/implintlevel", &implintlevel) );
    4282 assert(implintlevel >= -2);
    4283 assert(implintlevel <= 2);
    4284
    4285 /* print problem statistics as comment to file */
    4286 SCIPinfoMessage(scip, file, "%% SCIP STATISTICS\n");
    4287 SCIPinfoMessage(scip, file, "%% Problem name : %s\n", name);
    4288 SCIPinfoMessage(scip, file, "%% Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
    4289 nvars, nbinvars, nintvars, nimplvars, ncontvars);
    4290 SCIPinfoMessage(scip, file, "%% Constraints : %d\n", nconss);
    4291
    4292 SCIP_CALL( SCIPallocBufferArray(scip, &boundedvars, nvars) );
    4293 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nvars) );
    4294 nboundedvars = 0;
    4295
    4296 SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.vardiscrete, nvars) );
    4297 ndiscretevars = 0;
    4298
    4299 if( nvars > 0 )
    4300 SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Problem variables %%%%%%%%%%%%\n");
    4301
    4302 /* write all (active) problem variables */
    4303 for( v = 0; v < nvars; v++ )
    4304 {
    4305 var = vars[v];
    4306 assert( var != NULL );
    4307 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s", SCIPvarGetName(var) );
    4308
    4309 if( transformed )
    4310 {
    4311 /* in case the transformed is written only local bounds are posted which are valid in the current node */
    4312 lb = SCIPvarGetLbLocal(var);
    4313 ub = SCIPvarGetUbLocal(var);
    4314 }
    4315 else
    4316 {
    4317 lb = SCIPvarGetLbOriginal(var);
    4318 ub = SCIPvarGetUbOriginal(var);
    4319 }
    4320
    4321 /* save whether variable is written as integer */
    4323 fznoutput.vardiscrete[v] = (int)SCIPvarGetImplType(var) > 2 - implintlevel;
    4324 else
    4325 fznoutput.vardiscrete[v] = (int)SCIPvarGetImplType(var) <= 2 + implintlevel;
    4326
    4327 if( fznoutput.vardiscrete[v] )
    4328 ++ndiscretevars;
    4329
    4330 /* if a variable is bounded to both sides, the bounds are added to the declaration,
    4331 * for variables bounded to exactly one side, an auxiliary constraint will be added later-on.
    4332 */
    4333 if( !SCIPisInfinity(scip, -lb) && !SCIPisInfinity(scip, ub) )
    4334 {
    4335 SCIP_Bool fixed;
    4336 fixed = FALSE;
    4337
    4338 if( SCIPisEQ(scip, lb, ub) )
    4339 fixed = TRUE;
    4340
    4341 if( fznoutput.vardiscrete[v] )
    4342 {
    4343 assert( SCIPisFeasIntegral(scip, lb) && SCIPisFeasIntegral(scip, ub) );
    4344
    4345 if( fixed )
    4346 SCIPinfoMessage(scip, file, "var int: %s = %.f;\n", varname, lb);
    4347 else
    4348 SCIPinfoMessage(scip, file, "var %.f..%.f: %s;\n", lb, ub, varname);
    4349 }
    4350 else
    4351 {
    4352 /* real valued bounds have to be made type conforming */
    4353 if( fixed )
    4354 {
    4355 flattenFloat(scip, lb, buffy);
    4356 SCIPinfoMessage(scip, file, "var float: %s = %s;\n", varname, buffy);
    4357 }
    4358 else
    4359 {
    4360 char buffy2[FZN_BUFFERLEN];
    4361
    4362 flattenFloat(scip, lb, buffy);
    4363 flattenFloat(scip, ub, buffy2);
    4364 SCIPinfoMessage(scip, file, "var %s..%s: %s;\n", buffy, buffy2, varname);
    4365 }
    4366 }
    4367 }
    4368 else
    4369 {
    4370 assert(SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
    4371 assert(v >= nbinvars);
    4372
    4373 /* declare the variable without any bound */
    4374 if( fznoutput.vardiscrete[v] )
    4375 SCIPinfoMessage(scip, file, "var int: %s;\n", varname);
    4376 else
    4377 SCIPinfoMessage(scip, file, "var float: %s;\n", varname);
    4378
    4379 /* if there is a bound, store the variable and its boundtype for adding a corresponding constraint later-on */
    4380 if( ! SCIPisInfinity(scip, ub) )
    4381 {
    4382 boundedvars[nboundedvars] = v;
    4383 boundtypes[nboundedvars] = SCIP_BOUNDTYPE_UPPER;
    4384 nboundedvars++;
    4385 }
    4386 if( ! SCIPisInfinity(scip, -lb) )
    4387 {
    4388 boundedvars[nboundedvars] = v;
    4389 boundtypes[nboundedvars] = SCIP_BOUNDTYPE_LOWER;
    4390 nboundedvars++;
    4391 }
    4392 }
    4393 }
    4394
    4395 /* set up the datastructures for the auxiliary int2float variables, the casting constraints and the problem constraints */
    4396 fznoutput.varbufferpos = 0;
    4397 fznoutput.consbufferpos = 0;
    4398 fznoutput.castbufferpos = 0;
    4399
    4400 SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.varhasfloat, nvars) );
    4401 SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.varbuffer, FZN_BUFFERLEN) );
    4402 SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.castbuffer, FZN_BUFFERLEN) );
    4403 SCIP_CALL( SCIPallocBufferArray(scip, &fznoutput.consbuffer, FZN_BUFFERLEN) );
    4404 fznoutput.consbufferlen = FZN_BUFFERLEN;
    4405 fznoutput.varbufferlen = FZN_BUFFERLEN;
    4406 fznoutput.castbufferlen = FZN_BUFFERLEN;
    4407
    4408 for( v = 0; v < nvars; v++ )
    4409 fznoutput.varhasfloat[v] = FALSE;
    4410 fznoutput.varbuffer[0] = '\0';
    4411 fznoutput.consbuffer[0] = '\0';
    4412 fznoutput.castbuffer[0] = '\0';
    4413
    4414 /* output all problem constraints */
    4415 for( c = 0; c < nconss; c++ )
    4416 {
    4417 cons = conss[c];
    4418 assert( cons != NULL);
    4419
    4420 /* in case the transformed is written only constraint are posted which are enabled in the current node */
    4421 assert(!transformed || SCIPconsIsEnabled(cons));
    4422
    4423 conshdlr = SCIPconsGetHdlr(cons);
    4424 assert( conshdlr != NULL );
    4425
    4426 conshdlrname = SCIPconshdlrGetName(conshdlr);
    4427 assert( transformed == SCIPconsIsTransformed(cons) );
    4428
    4429 /* By now, only linear, setppc, logicor, knapsack, and varbound constraints can be written.
    4430 * Since they are all linearizable, a linear representation of them is written.
    4431 */
    4432 if( strcmp(conshdlrname, "linear") == 0 )
    4433 {
    4434 SCIP_CALL( printLinearCons(scip, &fznoutput,
    4436 SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), transformed) );
    4437 }
    4438 else if( strcmp(conshdlrname, "setppc") == 0 )
    4439 {
    4440 consvars = SCIPgetVarsSetppc(scip, cons);
    4441 nconsvars = SCIPgetNVarsSetppc(scip, cons);
    4442
    4443 /* Setppc constraints only differ in their lhs/rhs (+- INF or 1) */
    4444 switch( SCIPgetTypeSetppc(scip, cons) )
    4445 {
    4447 SCIP_CALL( printLinearCons(scip, &fznoutput,
    4448 consvars, NULL, nconsvars, 1.0, 1.0, transformed) );
    4449 break;
    4451 SCIP_CALL( printLinearCons(scip, &fznoutput,
    4452 consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, transformed) );
    4453 break;
    4455 SCIP_CALL( printLinearCons(scip, &fznoutput,
    4456 consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), transformed) );
    4457 break;
    4458 }
    4459 }
    4460 else if( strcmp(conshdlrname, "logicor") == 0 )
    4461 {
    4462 SCIP_CALL( printLinearCons(scip, &fznoutput,
    4464 1.0, SCIPinfinity(scip), transformed) );
    4465 }
    4466 else if( strcmp(conshdlrname, "knapsack") == 0 )
    4467 {
    4468 SCIP_Longint* weights;
    4469
    4470 consvars = SCIPgetVarsKnapsack(scip, cons);
    4471 nconsvars = SCIPgetNVarsKnapsack(scip, cons);
    4472
    4473 /* copy Longint array to SCIP_Real array */
    4474 weights = SCIPgetWeightsKnapsack(scip, cons);
    4475 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
    4476 for( v = 0; v < nconsvars; ++v )
    4477 consvals[v] = (SCIP_Real)weights[v];
    4478
    4479 SCIP_CALL( printLinearCons(scip, &fznoutput, consvars, consvals, nconsvars, -SCIPinfinity(scip),
    4480 (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), transformed) );
    4481
    4482 SCIPfreeBufferArray(scip, &consvals);
    4483 }
    4484 else if( strcmp(conshdlrname, "varbound") == 0 )
    4485 {
    4486 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
    4487 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
    4488
    4489 consvars[0] = SCIPgetVarVarbound(scip, cons);
    4490 consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
    4491
    4492 consvals[0] = 1.0;
    4493 consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
    4494
    4495 /* Varbound constraints always consist of exactly two variables */
    4496 SCIP_CALL( printLinearCons(scip, &fznoutput,
    4497 consvars, consvals, 2,
    4498 SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons), transformed) );
    4499
    4500 SCIPfreeBufferArray(scip, &consvars);
    4501 SCIPfreeBufferArray(scip, &consvals);
    4502 }
    4503 else if( strcmp(conshdlrname, "cumulative") == 0 )
    4504 {
    4505 int* intvals;
    4506
    4507 consvars = SCIPgetVarsCumulative(scip, cons);
    4508 nconsvars = SCIPgetNVarsCumulative(scip, cons);
    4509
    4510 SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), "cumulative([") );
    4511
    4512 for( v = 0; v < nconsvars; ++v )
    4513 {
    4514 if( v < nconsvars - 1)
    4515 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s, ", SCIPvarGetName(consvars[v]) );
    4516 else
    4517 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s", SCIPvarGetName(consvars[v]) );
    4518
    4519 SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), varname) );
    4520 }
    4521
    4522 SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), "], [") );
    4523
    4524 intvals = SCIPgetDurationsCumulative(scip, cons);
    4525
    4526 for( v = 0; v < nconsvars; ++v )
    4527 {
    4528 if( v < nconsvars - 1)
    4529 (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d, ", intvals[v] );
    4530 else
    4531 (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d", intvals[v] );
    4532
    4533 SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), buffy) );
    4534 }
    4535
    4536 SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), "], [") );
    4537
    4538 intvals = SCIPgetDemandsCumulative(scip, cons);
    4539
    4540 for( v = 0; v < nconsvars; ++v )
    4541 {
    4542 if( v < nconsvars - 1)
    4543 (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d, ", intvals[v] );
    4544 else
    4545 (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "%d", intvals[v] );
    4546
    4547 SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), buffy) );
    4548 }
    4549 (void) SCIPsnprintf(buffy, SCIP_MAXSTRLEN, "], %d);\n", SCIPgetCapacityCumulative(scip, cons) );
    4550
    4551 SCIP_CALL( appendBuffer(scip, &(fznoutput.consbuffer), &(fznoutput.consbufferlen), &(fznoutput.consbufferpos), buffy) );
    4552 }
    4553 else
    4554 {
    4555 SCIPwarningMessage(scip, "constraint handler <%s> cannot print flatzinc format\n", conshdlrname );
    4556 }
    4557 }
    4558
    4559 SCIP_CALL( SCIPallocBufferArray(scip, &intobjvars, ndiscretevars) );
    4560 SCIP_CALL( SCIPallocBufferArray(scip, &floatobjvars, nvars) );
    4561 nintobjvars = 0;
    4562 nfloatobjvars = 0;
    4563
    4564 /* scan objective function: Which variables have to be put to the float part, which to the int part? */
    4565 for( v = 0; v < nvars; v++ )
    4566 {
    4567 SCIP_Real obj;
    4568
    4569 var = vars[v];
    4570 obj = SCIPvarGetObj(var);
    4571
    4572 if( !SCIPisZero(scip,obj) )
    4573 {
    4574 /* only discrete variables with integral objective coefficient will be put to the int part of the objective */
    4575 if( fznoutput.vardiscrete[v] && SCIPisIntegral(scip, objscale*obj) )
    4576 {
    4577 assert(SCIPvarIsIntegral(var));
    4578
    4579 intobjvars[nintobjvars] = v;
    4580 SCIPdebugMsg(scip, "variable <%s> at pos <%d,%d> has an integral obj: %f=%f*%f\n",
    4581 SCIPvarGetName(var), nintobjvars, v, obj, objscale, SCIPvarGetObj(var));
    4582 nintobjvars++;
    4583 }
    4584 else
    4585 {
    4586 /* if not happened yet, introduce an auxiliary variable for discrete variables with fractional coefficients */
    4587 if( fznoutput.vardiscrete[v] && !fznoutput.varhasfloat[v] )
    4588 {
    4589 assert(SCIPvarIsIntegral(var));
    4590
    4591 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "var float: %s_float;\n", SCIPvarGetName(var));
    4592 SCIP_CALL( appendBuffer(scip, &(fznoutput.varbuffer), &(fznoutput.varbufferlen), &(fznoutput.varbufferpos),buffer) );
    4593
    4594 (void) SCIPsnprintf(buffer, FZN_BUFFERLEN, "constraint int2float(%s, %s_float);\n", SCIPvarGetName(var), SCIPvarGetName(var));
    4595 SCIP_CALL( appendBuffer(scip, &(fznoutput.castbuffer), &(fznoutput.castbufferlen), &(fznoutput.castbufferpos),buffer) );
    4596
    4597 fznoutput.varhasfloat[v] = TRUE;
    4598 }
    4599
    4600 floatobjvars[nfloatobjvars] = v;
    4601 nfloatobjvars++;
    4602 }
    4603 }
    4604 }
    4605
    4606 /* output all created auxiliary variables (float equivalents of discrete variables) */
    4607 if( fznoutput.varbufferpos > 0 )
    4608 {
    4609 SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Auxiliary variables %%%%%%%%%%%%\n");
    4610 writeBuffer(scip, file, fznoutput.varbuffer, fznoutput.varbufferpos );
    4611 }
    4612
    4613 /* output all int2float casting/conversion constraints */
    4614 if( fznoutput.castbufferpos > 0 )
    4615 {
    4616 SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Variable conversions %%%%%%%%%%%%\n");
    4617 writeBuffer(scip, file, fznoutput.castbuffer, fznoutput.castbufferpos );
    4618 }
    4619
    4620 if( nboundedvars > 0 )
    4621 SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Variable bounds %%%%%%%%%%%%\n");
    4622
    4623 /* output all bounds of variables with exactly one bound*/
    4624 for( v = 0; v < nboundedvars; v++ )
    4625 {
    4626 var = vars[boundedvars[v]];
    4627
    4628 if( fznoutput.vardiscrete[boundedvars[v]] )
    4629 {
    4630 assert(SCIPvarIsIntegral(var));
    4631
    4632 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
    4633 SCIPinfoMessage(scip, file,"constraint int_ge(%s, %.f);\n",SCIPvarGetName(var),
    4634 transformed ? SCIPvarGetLbLocal(var) : SCIPvarGetLbOriginal(var));
    4635 else
    4636 {
    4637 assert( boundtypes[v] == SCIP_BOUNDTYPE_UPPER );
    4638 SCIPinfoMessage(scip, file,"constraint int_le(%s, %.f);\n",SCIPvarGetName(var),
    4639 transformed ? SCIPvarGetUbLocal(var) : SCIPvarGetUbOriginal(var));
    4640 }
    4641 }
    4642 else
    4643 {
    4644 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
    4645 {
    4646 flattenFloat(scip, transformed ? SCIPvarGetLbLocal(var) : SCIPvarGetLbOriginal(var), buffy);
    4647 SCIPinfoMessage(scip, file,"constraint float_ge(%s, %s);\n", SCIPvarGetName(var), buffy);
    4648 }
    4649 else
    4650 {
    4651 assert( boundtypes[v] == SCIP_BOUNDTYPE_UPPER );
    4652 flattenFloat(scip, transformed ? SCIPvarGetUbLocal(var) : SCIPvarGetUbOriginal(var), buffy);
    4653 SCIPinfoMessage(scip, file,"constraint float_le(%s, %s);\n",SCIPvarGetName(var), buffy);
    4654 }
    4655 }
    4656 }
    4657
    4658 /* output all problem constraints */
    4659 if( fznoutput.consbufferpos > 0 )
    4660 {
    4661 SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Problem constraints %%%%%%%%%%%%\n");
    4662 writeBuffer(scip, file, fznoutput.consbuffer, fznoutput.consbufferpos );
    4663 }
    4664
    4665 SCIPinfoMessage(scip, file, "\n%%%%%%%%%%%% Objective function %%%%%%%%%%%%\n");
    4666
    4667 /* If there is at least one variable in the objective function write down the optimization problem, else declare it to be a satisfiability problem */
    4668 if( nintobjvars > 0 || nfloatobjvars > 0 || !SCIPisZero(scip, objoffset) )
    4669 {
    4670 SCIPinfoMessage(scip, file, "solve %s int_float_lin([", objsense == SCIP_OBJSENSE_MINIMIZE ? "minimize" : "maximize" );
    4671
    4672 /* first array: coefficients (in float representation) of discrete variables with integral objective coefficient */
    4673 for( v = 0; v < nintobjvars; v++ )
    4674 {
    4675 SCIP_Real obj;
    4676 var = vars[intobjvars[v]];
    4677 obj = objscale * SCIPvarGetObj(var);
    4678 SCIPdebugMsg(scip, "variable <%s> at pos <%d,%d> has an integral obj: %f=%f*%f\n", SCIPvarGetName(var), v, intobjvars[v], obj, objscale, SCIPvarGetObj(var));
    4679
    4680 assert( SCIPisIntegral(scip, obj) );
    4681 flattenFloat(scip, obj, buffy);
    4682 SCIPinfoMessage(scip, file, "%s%s", buffy, v < nintobjvars-1 ? ", " : "" );
    4683 }
    4684
    4685 /* second array: all other objective coefficients */
    4686 SCIPinfoMessage(scip, file, "], [");
    4687 for( v = 0; v < nfloatobjvars; v++ )
    4688 {
    4689 SCIP_Real obj;
    4690 obj = objscale * SCIPvarGetObj(vars[floatobjvars[v]]);
    4691 flattenFloat(scip, obj, buffy);
    4692 assert(SCIPvarGetType(vars[floatobjvars[v]]) == SCIP_VARTYPE_CONTINUOUS || !SCIPisIntegral(scip, obj));
    4693 SCIPinfoMessage(scip, file, "%s%s", buffy, v < nfloatobjvars-1 ? ", " : "" );
    4694 }
    4695
    4696 /* potentially add an objective offset */
    4697 if( !SCIPisZero(scip, objoffset) )
    4698 {
    4699 flattenFloat(scip, objscale * objoffset, buffy);
    4700 SCIPinfoMessage(scip, file, "%s%s", nfloatobjvars == 0 ? "" : ", ", buffy );
    4701 }
    4702
    4703 /* third array: all discrete variables with integral objective coefficient */
    4704 SCIPinfoMessage(scip, file, "], [");
    4705 for( v = 0; v < nintobjvars; v++ )
    4706 SCIPinfoMessage(scip, file, "%s%s", SCIPvarGetName(vars[intobjvars[v]]), v < nintobjvars-1 ? ", " : "" );
    4707
    4708 /* fourth array: all other variables with nonzero objective coefficient */
    4709 SCIPinfoMessage(scip, file, "], [");
    4710 for( v = 0; v < nfloatobjvars; v++ )
    4711 SCIPinfoMessage(scip, file, "%s%s%s", SCIPvarGetName(vars[floatobjvars[v]]), fznoutput.vardiscrete[floatobjvars[v]] ? "_float" : "", v < nfloatobjvars-1 ? ", " : "" );
    4712
    4713 /* potentially add a 1.0 for the objective offset */
    4714 if( !SCIPisZero(scip, objoffset) )
    4715 SCIPinfoMessage(scip, file, "%s%.1f", nfloatobjvars == 0 ? "" : ", ", 1.0 );
    4716 SCIPinfoMessage(scip, file, "]);\n");
    4717 }
    4718 else
    4719 SCIPinfoMessage(scip, file, "solve satisfy;\n");
    4720
    4721 /* free all memory */
    4722 SCIPfreeBufferArray(scip, &fznoutput.castbuffer);
    4723 SCIPfreeBufferArray(scip, &fznoutput.consbuffer);
    4724 SCIPfreeBufferArray(scip, &fznoutput.varbuffer);
    4725
    4726 SCIPfreeBufferArray(scip, &boundtypes);
    4727 SCIPfreeBufferArray(scip, &boundedvars);
    4728 SCIPfreeBufferArray(scip, &floatobjvars);
    4729 SCIPfreeBufferArray(scip, &intobjvars);
    4730 SCIPfreeBufferArray(scip, &fznoutput.varhasfloat);
    4731 SCIPfreeBufferArray(scip, &fznoutput.vardiscrete);
    4732
    4733 *result = SCIP_SUCCESS;
    4734 return SCIP_OKAY;
    4735}
    4736
    4737/*
    4738 * Callback methods of reader
    4739 */
    4740
    4741/** copy method for reader plugins (called when SCIP copies plugins) */
    4742static
    4744{ /*lint --e{715}*/
    4745 assert(scip != NULL);
    4746 assert(reader != NULL);
    4747 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
    4748
    4749 /* call inclusion method of reader */
    4751
    4752 return SCIP_OKAY;
    4753}
    4754
    4755
    4756/** destructor of reader to free user data (called when SCIP is exiting) */
    4757static
    4759{
    4760 SCIP_READERDATA* readerdata;
    4761 int v;
    4762
    4763 readerdata = SCIPreaderGetData(reader);
    4764 assert(readerdata != NULL);
    4765
    4766 /* free all variable array elements */
    4767 for( v = 0; v < readerdata->nvararrays; ++v )
    4768 {
    4769 freeVararray(scip, &readerdata->vararrays[v]);
    4770 }
    4771
    4772 SCIPfreeBlockMemoryArrayNull(scip, &readerdata->vararrays, readerdata->vararrayssize);
    4773
    4774 /* free reader data */
    4775 SCIPfreeBlockMemory(scip, &readerdata);
    4776
    4777 return SCIP_OKAY;
    4778}
    4779
    4780
    4781/** problem reading method of reader */
    4782static
    4784{ /*lint --e{715}*/
    4785 FZNINPUT fzninput;
    4786 int i;
    4787
    4788 assert(reader != NULL);
    4789 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
    4790 assert(result != NULL);
    4791
    4792 *result = SCIP_DIDNOTRUN;
    4793
    4794 /* initialize FZN input data */
    4795 fzninput.file = NULL;
    4797 fzninput.linebuf[0] = '\0';
    4798 fzninput.linebufsize = FZN_INIT_LINELEN;
    4799 SCIP_CALL( SCIPallocBufferArray(scip, &fzninput.token, FZN_BUFFERLEN) );
    4800 fzninput.token[0] = '\0';
    4801
    4802 for( i = 0; i < FZN_MAX_PUSHEDTOKENS; ++i )
    4803 {
    4804 SCIP_CALL( SCIPallocBufferArray(scip, &(fzninput.pushedtokens[i]), FZN_BUFFERLEN) ); /*lint !e866*/
    4805 }
    4806
    4807 fzninput.npushedtokens = 0;
    4808 fzninput.linenumber = 1;
    4809 fzninput.bufpos = 0;
    4810 fzninput.linepos = 0;
    4811 fzninput.objsense = SCIP_OBJSENSE_MINIMIZE;
    4812 fzninput.comment = FALSE;
    4813 fzninput.haserror = FALSE;
    4814 fzninput.valid = TRUE;
    4815 fzninput.vararrays = NULL;
    4816 fzninput.nvararrays = 0;
    4817 fzninput.vararrayssize = 0;
    4818 fzninput.constarrays = NULL;
    4819 fzninput.nconstarrays = 0;
    4820 fzninput.constarrayssize = 0;
    4821
    4822 SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &(fzninput.initialconss)) );
    4823 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &(fzninput.dynamicconss)) );
    4824 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &(fzninput.dynamiccols)) );
    4825 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &(fzninput.dynamicrows)) );
    4826
    4828 hashGetKeyVar, SCIPhashKeyEqString, SCIPhashKeyValString, NULL) );
    4829
    4830 SCIP_CALL( SCIPhashtableCreate(&fzninput.constantHashtable, SCIPblkmem(scip), SCIP_HASHSIZE_NAMES,
    4831 hashGetKeyConstant, SCIPhashKeyEqString, SCIPhashKeyValString, NULL) );
    4832 SCIP_CALL( SCIPallocBufferArray(scip, &fzninput.constants, 10) );
    4833
    4834 fzninput.nconstants = 0;
    4835 fzninput.sconstants = 10;
    4836
    4837 /* read the file */
    4838 SCIP_CALL( readFZNFile(scip, SCIPreaderGetData(reader), &fzninput, filename) );
    4839
    4840 /* free dynamically allocated memory */
    4841 for( i = fzninput.nconstants - 1; i >= 0; --i )
    4842 {
    4843 SCIPfreeBufferArray(scip, &fzninput.constants[i]->name);
    4844 SCIPfreeBuffer(scip, &fzninput.constants[i]);
    4845 }
    4846 SCIPfreeBufferArray(scip, &fzninput.constants);
    4847
    4848 for( i = FZN_MAX_PUSHEDTOKENS - 1; i >= 0; --i ) /*lint !e778*/
    4849 {
    4850 SCIPfreeBufferArrayNull(scip, &fzninput.pushedtokens[i]);
    4851 }
    4852 SCIPfreeBufferArrayNull(scip, &fzninput.token);
    4853
    4854 /* free memory */
    4855 SCIPhashtableFree(&fzninput.varHashtable);
    4856 SCIPhashtableFree(&fzninput.constantHashtable);
    4857
    4858 /* free variable arrays */
    4859 for( i = 0; i < fzninput.nvararrays; ++i )
    4860 {
    4861 freeVararray(scip, &fzninput.vararrays[i]);
    4862 }
    4863 SCIPfreeBlockMemoryArrayNull(scip, &(fzninput.vararrays), fzninput.vararrayssize);
    4864
    4865 /* free constant arrays */
    4866 for( i = 0; i < fzninput.nconstarrays; ++i )
    4867 {
    4868 freeConstarray(scip, &(fzninput.constarrays[i]));
    4869 }
    4870 SCIPfreeBlockMemoryArrayNull(scip, &fzninput.constarrays, fzninput.constarrayssize);
    4871
    4872 SCIPfreeBlockMemoryArray(scip, &fzninput.linebuf, fzninput.linebufsize);
    4873
    4874 /* evaluate the result */
    4875 if( fzninput.haserror || ! fzninput.valid )
    4876 return SCIP_READERROR;
    4877
    4878 *result = SCIP_SUCCESS;
    4879
    4880 return SCIP_OKAY;
    4881}
    4882
    4883
    4884/** problem writing method of reader */
    4885static
    4887{ /*lint --e{715}*/
    4888 if( genericnames )
    4889 {
    4890 SCIP_CALL( writeFzn(scip, file, name, transformed, objsense, objscale, objoffset, vars,
    4891 nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
    4892 }
    4893 else
    4894 {
    4895 int i;
    4896 SCIP_Bool legal;
    4897
    4898 legal = TRUE;
    4899
    4900 /* scan whether all variable names are flatzinc conforming */
    4901 for( i = 0; i < nvars; i++ )
    4902 {
    4903 const char* varname;
    4904 size_t length;
    4905
    4906 varname = SCIPvarGetName(vars[i]);
    4907 length = strlen(varname);
    4908 legal = isIdentifier(varname);
    4909 if( !legal )
    4910 {
    4911 SCIPwarningMessage(scip, "The name of variable <%d>: \"%s\" does not conform to the fzn standard.\n", i, varname);
    4912 break;
    4913 }
    4914
    4915 if( length >= 7 )
    4916 legal = (strncmp(&varname[length-6],"_float",6) != 0);
    4917 if( !legal )
    4918 {
    4919 SCIPwarningMessage(scip, "The name of variable <%d>: \"%s\" ends with \"_float\" which is not supported.\n", i, varname);
    4920 break;
    4921 }
    4922 }
    4923
    4924 /* if there is at least one name, which does not conform, use generic names */
    4925 if( legal )
    4926 {
    4927 SCIP_CALL( writeFzn(scip, file, name, transformed, objsense, objscale, objoffset, vars,
    4928 nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
    4929 }
    4930 else if( transformed )
    4931 {
    4932 SCIPwarningMessage(scip, "Write transformed problem with generic variable names.\n");
    4933 SCIP_CALL( SCIPprintTransProblem(scip, file, "fzn", TRUE) );
    4934 }
    4935 else
    4936 {
    4937 SCIPwarningMessage(scip, "Write original problem with generic variable names.\n");
    4938 SCIP_CALL( SCIPprintOrigProblem(scip, file, "fzn", TRUE) );
    4939 }
    4940 }
    4941
    4942 *result = SCIP_SUCCESS;
    4943
    4944 return SCIP_OKAY;
    4945}
    4946
    4947/*
    4948 * reader specific interface methods
    4949 */
    4950
    4951/** includes the fzn file reader in SCIP */
    4953 SCIP* scip /**< SCIP data structure */
    4954 )
    4955{
    4956 SCIP_READERDATA* readerdata;
    4957 SCIP_READER* reader;
    4958
    4959 /* create fzn reader data */
    4960 SCIP_CALL( readerdataCreate(scip, &readerdata) );
    4961
    4962 /* include reader */
    4964
    4965 /* set non fundamental callbacks via setter functions */
    4966 SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyFzn) );
    4967 SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeFzn) );
    4968 SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadFzn) );
    4969 SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteFzn) );
    4970
    4971 return SCIP_OKAY;
    4972}
    4973
    4974/** print given solution in Flatzinc format w.r.t. the output annotation */
    4976 SCIP* scip, /**< SCIP data structure */
    4977 SCIP_SOL* sol, /**< primal solution, or NULL for current LP/pseudo solution */
    4978 FILE* file /**< output file (or NULL for standard output) */
    4979 )
    4980{
    4981 SCIP_READER* reader;
    4982 SCIP_READERDATA* readerdata;
    4983 SCIP_VAR** vars;
    4984 VARARRAY** vararrays;
    4985 DIMENSIONS* info;
    4986 VARARRAY* vararray;
    4987 FZNNUMBERTYPE type;
    4988 SCIP_Real solvalue;
    4989 int nvararrays;
    4990 int nvars;
    4991 int i;
    4992 int v;
    4993
    4994 reader = SCIPfindReader(scip, READER_NAME);
    4995 assert(reader != NULL);
    4996
    4997 readerdata = SCIPreaderGetData(reader);
    4998 assert(readerdata != NULL);
    4999
    5000 vararrays = readerdata->vararrays;
    5001 nvararrays = readerdata->nvararrays;
    5002
    5003 /* sort variable arrays */
    5004 SCIPsortPtr((void**)vararrays, vararraysComp, nvararrays);
    5005
    5006 for( i = 0; i < nvararrays; ++i )
    5007 {
    5008 vararray = vararrays[i];
    5009 info = vararray->info;
    5010 vars = vararray->vars;
    5011 nvars = vararray->nvars;
    5012 type = vararray->type;
    5013
    5014 if( info->ndims == 0 )
    5015 {
    5016 solvalue = SCIPgetSolVal(scip, sol, vars[0]);
    5017
    5018 SCIPinfoMessage(scip, file, "%s = ", vararray->name);
    5019
    5020 printValue(scip, file, solvalue, type);
    5021
    5022 SCIPinfoMessage(scip, file, ";\n");
    5023 }
    5024 else
    5025 {
    5026 SCIPinfoMessage(scip, file, "%s = array%dd(", vararray->name, info->ndims);
    5027
    5028 for( v = 0; v < info->ndims; ++v )
    5029 {
    5030 SCIPinfoMessage(scip, file, "%d..%d, ", info->lbs[v], info->ubs[v]);
    5031 }
    5032
    5033 SCIPinfoMessage(scip, file, "[");
    5034
    5035 for( v = 0; v < nvars; ++v )
    5036 {
    5037 if( v > 0)
    5038 SCIPinfoMessage(scip, file, ", ");
    5039
    5040 solvalue = SCIPgetSolVal(scip, sol, vars[v]);
    5041 printValue(scip, file, solvalue, type);
    5042 }
    5043
    5044 SCIPinfoMessage(scip, file, "]);\n");
    5045 }
    5046 }
    5047
    5048 SCIPinfoMessage(scip, file, "----------\n");
    5049
    5050 return SCIP_OKAY;
    5051}
    Constraint handler for AND constraints, .
    constraint handler for cumulative constraints
    Constraint handler for knapsack constraints of the form , x binary and .
    Constraint handler for linear constraints in their most general form, .
    Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
    constraint handler for nonlinear constraints specified by algebraic expressions
    Constraint handler for "or" constraints, .
    Constraint handler for the set partitioning / packing / covering constraints .
    Constraint handler for variable bound constraints .
    Constraint handler for XOR constraints, .
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_Real
    Definition: def.h:156
    #define SCIP_HASHSIZE_NAMES
    Definition: def.h:280
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:334
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define SCIPABORT()
    Definition: def.h:327
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_FILE * SCIPfopen(const char *path, const char *mode)
    Definition: fileio.c:153
    int SCIPfeof(SCIP_FILE *stream)
    Definition: fileio.c:227
    int SCIPfclose(SCIP_FILE *fp)
    Definition: fileio.c:232
    char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
    Definition: fileio.c:200
    int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
    int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
    int * SCIPgetDurationsCumulative(SCIP *scip, SCIP_CONS *cons)
    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:5059
    SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
    int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
    int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9596
    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:6014
    SCIP_VAR ** SCIPgetVarsCumulative(SCIP *scip, SCIP_CONS *cons)
    SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9619
    int * SCIPgetDemandsCumulative(SCIP *scip, SCIP_CONS *cons)
    SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
    SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
    int SCIPgetCapacityCumulative(SCIP *scip, SCIP_CONS *cons)
    SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
    SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9642
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
    SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
    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_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
    int SCIPgetNVarsCumulative(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsCumulative(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, int *durations, int *demands, int capacity, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    @ SCIP_SETPPCTYPE_PARTITIONING
    Definition: cons_setppc.h:87
    @ SCIP_SETPPCTYPE_COVERING
    Definition: cons_setppc.h:89
    @ SCIP_SETPPCTYPE_PACKING
    Definition: cons_setppc.h:88
    SCIP_RETCODE SCIPprintSolReaderFzn(SCIP *scip, SCIP_SOL *sol, FILE *file)
    Definition: reader_fzn.c:4975
    SCIP_RETCODE SCIPincludeReaderFzn(SCIP *scip)
    Definition: reader_fzn.c:4952
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_RETCODE SCIPfreeProb(SCIP *scip)
    Definition: scip_prob.c:835
    SCIP_RETCODE SCIPprintTransProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
    Definition: scip_prob.c:696
    SCIP_RETCODE SCIPprintOrigProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
    Definition: scip_prob.c:652
    SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
    Definition: scip_prob.c:1417
    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:119
    void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
    Definition: misc.c:2348
    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:2298
    void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
    Definition: misc.c:2596
    SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2535
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsgPrint
    Definition: scip_message.h:79
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
    Definition: scip_param.c:250
    SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
    Definition: scip_param.c:269
    void SCIPswapPointers(void **pointer1, void **pointer2)
    Definition: misc.c:10511
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4316
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8409
    SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
    Definition: cons.c:8698
    SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
    Definition: cons.c:8486
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    #define SCIPfreeBuffer(scip, ptr)
    Definition: scip_mem.h:134
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPduplicateBufferArray(scip, ptr, source, num)
    Definition: scip_mem.h:132
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPallocBuffer(scip, ptr)
    Definition: scip_mem.h:122
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    #define SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    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
    SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
    Definition: scip_reader.c:147
    SCIP_READERDATA * SCIPreaderGetData(SCIP_READER *reader)
    Definition: reader.c:605
    SCIP_READER * SCIPfindReader(SCIP *scip, const char *name)
    Definition: scip_reader.c:235
    SCIP_RETCODE SCIPsetReaderFree(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERFREE((*readerfree)))
    Definition: scip_reader.c:171
    const char * SCIPreaderGetName(SCIP_READER *reader)
    Definition: reader.c:680
    SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
    Definition: scip_reader.c:195
    SCIP_RETCODE SCIPsetReaderWrite(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERWRITE((*readerwrite)))
    Definition: scip_reader.c:219
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Longint SCIPconvertRealToLongint(SCIP *scip, SCIP_Real real)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
    Definition: var.c:18320
    SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
    Definition: var.c:23868
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
    Definition: var.c:24020
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
    Definition: var.c:24063
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
    Definition: scip_var.c:2378
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    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:120
    SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
    Definition: var.c:23463
    SCIP_RETCODE SCIPprintVar(SCIP *scip, SCIP_VAR *var, FILE *file)
    Definition: scip_var.c:12465
    SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
    Definition: scip_var.c:5372
    void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    void SCIPprintSysError(const char *message)
    Definition: misc.c:10719
    int SCIPstrncpy(char *t, const char *s, int size)
    Definition: misc.c:10897
    char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
    Definition: misc.c:10768
    static const SCIP_Real scalars[]
    Definition: lp.c:5959
    memory allocation routines
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    public methods for managing constraints
    wrapper functions to map file i/o to standard or zlib file i/o
    struct SCIP_File SCIP_FILE
    Definition: pub_fileio.h:43
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    #define SCIPdebugPrintCons(x, y, z)
    Definition: pub_message.h:102
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for input file readers
    public methods for problem variables
    static SCIP_RETCODE parseArrayAssignment(SCIP *scip, FZNINPUT *fzninput, char ***elements, int *nelements, int selements)
    Definition: reader_fzn.c:1868
    static SCIP_Bool equalTokens(const char *token1, const char *token2)
    Definition: reader_fzn.c:412
    #define FZN_INIT_LINELEN
    Definition: reader_fzn.c:83
    static void freeVararray(SCIP *scip, VARARRAY **vararray)
    Definition: reader_fzn.c:910
    static void parseRange(SCIP *scip, FZNINPUT *fzninput, FZNNUMBERTYPE *type, SCIP_Real *lb, SCIP_Real *ub)
    Definition: reader_fzn.c:1482
    static SCIP_RETCODE getActiveVariables(SCIP *scip, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
    Definition: reader_fzn.c:3865
    static SCIP_DECL_READERWRITE(readerWriteFzn)
    Definition: reader_fzn.c:4886
    static SCIP_RETCODE parseConstantArray(SCIP *scip, FZNINPUT *fzninput, const char *name, int nconstants, FZNNUMBERTYPE type)
    Definition: reader_fzn.c:2078
    static SCIP_RETCODE parseLinking(SCIP *scip, FZNINPUT *fzninput, const char *name, const char *type, SCIP_Real sidevalue)
    Definition: reader_fzn.c:2819
    static void flattenAssignment(SCIP *scip, FZNINPUT *fzninput, char *assignment)
    Definition: reader_fzn.c:1326
    static SCIP_RETCODE parseName(SCIP *scip, FZNINPUT *fzninput, char *name, SCIP_Bool *output, DIMENSIONS **info)
    Definition: reader_fzn.c:1594
    static void freeConstarray(SCIP *scip, CONSTARRAY **constarray)
    Definition: reader_fzn.c:979
    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_RETCODE parseAggregation(SCIP *scip, FZNINPUT *fzninput, const char *name, const char *type)
    Definition: reader_fzn.c:2710
    static SCIP_RETCODE copyDimensions(SCIP *scip, DIMENSIONS **target, DIMENSIONS *source)
    Definition: reader_fzn.c:843
    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:4231
    static void parseValue(SCIP *scip, FZNINPUT *fzninput, SCIP_Real *value, const char *assignment)
    Definition: reader_fzn.c:2302
    static SCIP_RETCODE parseQuadratic(SCIP *scip, FZNINPUT *fzninput, const char *name)
    Definition: reader_fzn.c:2581
    static void freeStringBufferArray(SCIP *scip, char **array, int nelements)
    Definition: reader_fzn.c:263
    static SCIP_RETCODE parseSolveItem(SCIP *scip, FZNINPUT *fzninput)
    Definition: reader_fzn.c:3534
    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 readFZNFile(SCIP *scip, SCIP_READERDATA *readerdata, FZNINPUT *fzninput, const char *filename)
    Definition: reader_fzn.c:3698
    static SCIP_DECL_HASHGETKEY(hashGetKeyVar)
    Definition: reader_fzn.c:235
    static SCIP_DECL_READERCOPY(readerCopyFzn)
    Definition: reader_fzn.c:4743
    struct FznConstant FZNCONSTANT
    Definition: reader_fzn.c:125
    static const char tokenchars[]
    Definition: reader_fzn.c:226
    static SCIP_RETCODE parseConstantArrayAssignment(SCIP *scip, FZNINPUT *fzninput, SCIP_Real **vals, int *nvals, int sizevals)
    Definition: reader_fzn.c:2345
    static const int nconstypes
    Definition: reader_fzn.c:3425
    FznExpType
    Definition: reader_fzn.c:101
    @ FZN_EXP_UNSIGNED
    Definition: reader_fzn.c:103
    @ FZN_EXP_NONE
    Definition: reader_fzn.c:102
    @ FZN_EXP_SIGNED
    Definition: reader_fzn.c:104
    struct FznOutput FZNOUTPUT
    Definition: reader_fzn.c:223
    static void writeBuffer(SCIP *scip, FILE *file, char *buffer, int bufferpos)
    Definition: reader_fzn.c:3927
    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
    static SCIP_Bool getNextLine(SCIP *scip, FZNINPUT *fzninput)
    Definition: reader_fzn.c:430
    static SCIP_RETCODE fzninputAddConstarray(SCIP *scip, FZNINPUT *fzninput, const char *name, FZNCONSTANT **constants, int nconstants, FZNNUMBERTYPE type)
    Definition: reader_fzn.c:1125
    static const char commentchars[]
    Definition: reader_fzn.c:227
    static void parseArrayType(SCIP *scip, FZNINPUT *fzninput, SCIP_Bool *isvararray, FZNNUMBERTYPE *type, SCIP_Real *lb, SCIP_Real *ub)
    Definition: reader_fzn.c:1831
    static SCIP_Bool isValue(const char *token, SCIP_Real *value)
    Definition: reader_fzn.c:633
    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)
    Definition: reader_fzn.c:4100
    #define FZN_BUFFERLEN
    Definition: reader_fzn.c:82
    #define READER_DESC
    Definition: reader_fzn.c:78
    static SCIP_RETCODE ensureConstarrySizeFznInput(SCIP *scip, FZNINPUT *fzninput)
    Definition: reader_fzn.c:767
    static void parseArrayIndex(SCIP *scip, FZNINPUT *fzninput, int *idx)
    Definition: reader_fzn.c:1283
    static void flattenFloat(SCIP *scip, SCIP_Real val, char *buffer)
    Definition: reader_fzn.c:3983
    struct ConstArray CONSTARRAY
    Definition: reader_fzn.c:135
    static SCIP_Bool isBoolExp(const char *name, SCIP_Bool *value)
    Definition: reader_fzn.c:310
    enum FznNumberType FZNNUMBERTYPE
    Definition: reader_fzn.c:97
    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:2001
    enum FznExpType FZNEXPTYPE
    Definition: reader_fzn.c:106
    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:3997
    static SCIP_RETCODE parseList(SCIP *scip, FZNINPUT *fzninput, char ***elements, int *nelements, int selements)
    Definition: reader_fzn.c:1430
    static SCIP_RETCODE ensureVararrySizeFznInput(SCIP *scip, FZNINPUT *fzninput)
    Definition: reader_fzn.c:735
    static void freeDimensions(SCIP *scip, DIMENSIONS **dim)
    Definition: reader_fzn.c:895
    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 void parseArrayDimension(SCIP *scip, FZNINPUT *fzninput, int *nelements)
    Definition: reader_fzn.c:1902
    #define READER_EXTENSION
    Definition: reader_fzn.c:79
    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 SCIP_RETCODE parseConstraint(SCIP *scip, FZNINPUT *fzninput)
    Definition: reader_fzn.c:3430
    static SCIP_RETCODE parseConstant(SCIP *scip, FZNINPUT *fzninput, FZNNUMBERTYPE type)
    Definition: reader_fzn.c:2263
    struct FznInput FZNINPUT
    Definition: reader_fzn.c:206
    static SCIP_Bool isValueChar(char c, char nextc, SCIP_Bool firstchar, SCIP_Bool *hasdot, FZNEXPTYPE *exptype)
    Definition: reader_fzn.c:368
    #define CREATE_CONSTRAINT(x)
    Definition: reader_fzn.c:168
    static void pushToken(FZNINPUT *fzninput)
    Definition: reader_fzn.c:609
    struct VarArray VARARRAY
    Definition: reader_fzn.c:146
    static SCIP_RETCODE parsePredicate(SCIP *scip, FZNINPUT *fzninput)
    Definition: reader_fzn.c:2124
    static SCIP_RETCODE createConstantAssignment(SCIP *scip, FZNCONSTANT **constant, FZNINPUT *fzninput, const char *name, FZNNUMBERTYPE type, const char *assignment)
    Definition: reader_fzn.c:1763
    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
    #define READER_NAME
    Definition: reader_fzn.c:77
    static SCIP_Bool isEndStatement(FZNINPUT *fzninput)
    Definition: reader_fzn.c:622
    static SCIP_RETCODE readerdataAddOutputvar(SCIP *scip, SCIP_READERDATA *readerdata, SCIP_VAR *var, FZNNUMBERTYPE type)
    Definition: reader_fzn.c:1020
    static SCIP_RETCODE appendBuffer(SCIP *scip, char **buffer, int *bufferlen, int *bufferpos, const char *extension)
    Definition: reader_fzn.c:3947
    static SCIP_RETCODE readerdataCreate(SCIP *scip, SCIP_READERDATA **readerdata)
    Definition: reader_fzn.c:687
    static VARARRAY * findVararray(FZNINPUT *fzninput, const char *name)
    Definition: reader_fzn.c:925
    static SCIP_Bool isDelimChar(char c)
    Definition: reader_fzn.c:279
    static SCIP_DECL_READERFREE(readerFreeFzn)
    Definition: reader_fzn.c:4758
    FznNumberType
    Definition: reader_fzn.c:92
    @ FZN_BOOL
    Definition: reader_fzn.c:93
    @ FZN_FLOAT
    Definition: reader_fzn.c:95
    @ FZN_INT
    Definition: reader_fzn.c:94
    static SCIP_DECL_SORTPTRCOMP(vararraysComp)
    Definition: reader_fzn.c:255
    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
    static SCIP_Bool isChar(const char *token, char c)
    Definition: reader_fzn.c:297
    struct Dimensions DIMENSIONS
    Definition: reader_fzn.c:116
    static SCIP_Bool isIdentifier(const char *name)
    Definition: reader_fzn.c:345
    static SCIP_RETCODE applyVariableAssignment(SCIP *scip, FZNINPUT *fzninput, SCIP_VAR *var, FZNNUMBERTYPE type, const char *assignment)
    Definition: reader_fzn.c:1707
    static void parseType(SCIP *scip, FZNINPUT *fzninput, FZNNUMBERTYPE *type, SCIP_Real *lb, SCIP_Real *ub)
    Definition: reader_fzn.c:1654
    static CONSTARRAY * findConstarray(FZNINPUT *fzninput, const char *name)
    Definition: reader_fzn.c:998
    static void syntaxError(SCIP *scip, FZNINPUT *fzninput, const char *msg)
    Definition: reader_fzn.c:659
    static SCIP_RETCODE ensureVararrySize(SCIP *scip, SCIP_READERDATA *readerdata)
    Definition: reader_fzn.c:703
    static SCIP_DECL_READERREAD(readerReadFzn)
    Definition: reader_fzn.c:4783
    #define FZN_MAX_PUSHEDTOKENS
    Definition: reader_fzn.c:84
    static SCIP_RETCODE parseVariableArrayAssignment(SCIP *scip, FZNINPUT *fzninput, SCIP_VAR ***vars, int *nvars, int sizevars)
    Definition: reader_fzn.c:2471
    static const char delimchars[]
    Definition: reader_fzn.c:225
    static void printValue(SCIP *scip, FILE *file, SCIP_Real value, FZNNUMBERTYPE type)
    Definition: reader_fzn.c:799
    static SCIP_RETCODE parseVariable(SCIP *scip, SCIP_READERDATA *readerdata, FZNINPUT *fzninput)
    Definition: reader_fzn.c:2199
    static SCIP_Bool hasError(FZNINPUT *fzninput)
    Definition: reader_fzn.c:676
    static SCIP_Bool isTokenChar(char c)
    Definition: reader_fzn.c:288
    static SCIP_RETCODE createConstarray(SCIP *scip, CONSTARRAY **constarray, const char *name, FZNCONSTANT **constants, int nconstants, FZNNUMBERTYPE type)
    Definition: reader_fzn.c:951
    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
    static SCIP_RETCODE parseOutputDimensioninfo(SCIP *scip, FZNINPUT *fzninput, DIMENSIONS **info)
    Definition: reader_fzn.c:1533
    static SCIP_RETCODE parseArray(SCIP *scip, SCIP_READERDATA *readerdata, FZNINPUT *fzninput)
    Definition: reader_fzn.c:2139
    static SCIP_Bool getNextToken(SCIP *scip, FZNINPUT *fzninput)
    Definition: reader_fzn.c:488
    FlatZinc file reader.
    public methods for constraint handler plugins and constraints
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for reader plugins
    public methods for solutions
    public methods for querying solving statistics
    public methods for SCIP variables
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    @ SCIP_BOUNDTYPE_LOWER
    Definition: type_lp.h:57
    enum SCIP_BoundType SCIP_BOUNDTYPE
    Definition: type_lp.h:60
    @ SCIP_OBJSENSE_MAXIMIZE
    Definition: type_prob.h:47
    @ SCIP_OBJSENSE_MINIMIZE
    Definition: type_prob.h:48
    enum SCIP_Objsense SCIP_OBJSENSE
    Definition: type_prob.h:50
    struct SCIP_ReaderData SCIP_READERDATA
    Definition: type_reader.h:54
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_NOFILE
    Definition: type_retcode.h:47
    @ SCIP_READERROR
    Definition: type_retcode.h:45
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    @ SCIP_VARSTATUS_NEGATED
    Definition: type_var.h:57
    enum SCIP_Vartype SCIP_VARTYPE
    Definition: type_var.h:73