Scippy

SCIP

Solving Constraint Integer Programs

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