Scippy

SCIP

Solving Constraint Integer Programs

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