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