Scippy

SCIP

Solving Constraint Integer Programs

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