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