Scippy

SCIP

Solving Constraint Integer Programs

reader_opb.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_opb.c
26 * @ingroup DEFPLUGINS_READER
27 * @brief pseudo-Boolean file reader (opb format)
28 * @author Stefan Heinz
29 * @author Michael Winkler
30 * @author Dominik Kamp
31 *
32 * This file reader parses the @a opb format and is also used by the @a wbo reader for the @a wbo format. For a
33 * detailed description of this format see
34 *
35 * - http://www.cril.univ-artois.fr/PB07/solver_req.html
36 * - http://www.cril.univ-artois.fr/PB10/format.pdf
37 *
38 * The syntax of the input file format can be described by a simple Backus-Naur
39 * form. <formula> is the start symbol of this grammar.
40 *
41 * <formula>::= <sequence_of_comments>
42 * [<objective>] | [<softheader>]
43 * <sequence_of_comments_or_constraints>
44 *
45 * <sequence_of_comments>::= <comment> [<sequence_of_comments>]
46 * <comment>::= "*" <any_sequence_of_characters_other_than_EOL> <EOL>
47 * <sequence_of_comments_or_constraints>::=<comment_or_constraint> [<sequence_of_comments_or_constraints>]
48 * <comment_or_constraint>::=<comment>|<constraint>
49 *
50 * <objective>::= "min:" <zeroOrMoreSpace> <sum> ";"
51 * <constraint>::= <sum> <relational_operator> <zeroOrMoreSpace> <integer> <zeroOrMoreSpace> ";"
52 *
53 * <sum>::= <weightedterm> | <weightedterm> <sum>
54 * <weightedterm>::= <integer> <oneOrMoreSpace> <term> <oneOrMoreSpace>
55 *
56 * <integer>::= <unsigned_integer> | "+" <unsigned_integer> | "-" <unsigned_integer>
57 * <unsigned_integer>::= <digit> | <digit><unsigned_integer>
58 *
59 * <relational_operator>::= ">=" | "="
60 *
61 * <variablename>::= "x" <unsigned_integer>
62 *
63 * <oneOrMoreSpace>::= " " [<oneOrMoreSpace>]
64 * <zeroOrMoreSpace>::= [" " <zeroOrMoreSpace>]
65 *
66 * For linear pseudo-Boolean instances, <term> is defined as
67 *
68 * <term>::=<variablename>
69 *
70 * For non-linear instances, <term> is defined as
71 *
72 * <term>::= <oneOrMoreLiterals>
73 * <oneOrMoreLiterals>::= <literal> | <literal> <oneOrMoreSpace> <oneOrMoreLiterals>
74 * <literal>::= <variablename> | "~"<variablename>
75 *
76 * For wbo-files are the following additional/changed things possible.
77 *
78 * <softheader>::= "soft:" [<unsigned integer>] ";"
79 *
80 * <comment_or_constraint>::=<comment>|<constraint>|<softconstraint>
81 *
82 * <softconstraint>::= "[" <zeroOrMoreSpace> <unsigned integer> <zeroOrMoreSpace> "]" <constraint>
83 *
84 */
85
86/* Our parser should also be lax by handling variable names and it's possible to read doubles instead of integer and
87 * possible some more :). */
88
89/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
90
92#include <ctype.h>
93#include "scip/cons_and.h"
94#include "scip/cons_indicator.h"
95#include "scip/cons_knapsack.h"
96#include "scip/cons_linear.h"
98#include "scip/cons_logicor.h"
100#include "scip/cons_setppc.h"
101#include "scip/cons_varbound.h"
102#include "scip/debug.h"
103#include "scip/pub_cons.h"
104#include "scip/pub_fileio.h"
105#include "scip/pub_message.h"
106#include "scip/pub_misc.h"
107#include "scip/pub_misc_sort.h"
108#include "scip/pub_reader.h"
109#include "scip/pub_var.h"
110#include "scip/reader_opb.h"
111#include "scip/rational.h"
112#include "scip/scip_cons.h"
113#include "scip/scip_exact.h"
114#include "scip/scip_mem.h"
115#include "scip/scip_message.h"
116#include "scip/scip_numerics.h"
117#include "scip/scip_param.h"
118#include "scip/scip_prob.h"
119#include "scip/scip_reader.h"
121#include "scip/scip_var.h"
122#include <stdlib.h>
123#include <string.h>
124
125#define READER_NAME "opbreader"
126#define READER_DESC "file reader for pseudo-Boolean problem in opb format"
127#define READER_EXTENSION "opb"
128
129#define GENCONSNAMES TRUE /* remove if no constraint names should be generated */
130#define INDICATORVARNAME "indicatorvar" /* standard part of name for all indicator variables */
131#define INDICATORSLACKVARNAME "indslack" /* standard part of name for all indicator slack variables; should be the same in cons_indicator */
132#define TOPCOSTCONSNAME "topcostcons" /* standard name for artificial topcost constraint in wbo problems */
133
134/*
135 * Data structures
136 */
137#define OPB_MAX_LINELEN 65536 /**< size of the line buffer for reading or writing */
138#define OPB_MAX_PUSHEDTOKENS 2
139#define OPB_INIT_COEFSSIZE 8192
140#define OPB_MAX_INTSIZE -1 /**< maximum allowed "intsize" (i.e. the number of bits required to represent the
141 * sum of absolute values of all integers that appear in a constraint or objective
142 * function) or -1 for unlimited */
143
144/** OPB reader data */
145struct SCIP_ReaderData
146{
147 int maxintsize; /**< maximum allowed "intsize" (i.e., the number of bits required
148 * to represent the sum of absolute values of all integers that
149 * appear in a constraint or objective function) or -1 for
150 * unlimited */
151};
152
153/** Section in OPB File */
155{
161
163{
169typedef enum OpbSense OPBSENSE;
170
171/** OPB reading data */
172struct OpbInput
173{
174 SCIP_FILE* file;
175 char* linebuf;
176 char* token;
177 char* tokenbuf;
178 char* pushedtokens[OPB_MAX_PUSHEDTOKENS];
179 int npushedtokens;
180 int linenumber;
181 int linepos;
182 int linebufsize;
183 int intsize;
184 SCIP_OBJSENSE objsense;
185 SCIP_Bool eof;
186 SCIP_Bool haserror;
187 int nproblemcoeffs;
188 SCIP_Bool wbo;
189 SCIP_Real topcost;
190 int nindvars;
191#if GENCONSNAMES == TRUE
192 int consnumber;
193#endif
194};
195
196typedef struct OpbInput OPBINPUT;
197
198static const char commentchars[] = "*";
199/*
200 * Local methods (for reading)
201 */
202
203/** issues an error message and marks the OPB data to have errors */
204static
206 SCIP* scip, /**< SCIP data structure */
207 OPBINPUT* opbinput, /**< OPB reading data */
208 const char* msg /**< error message */
209 )
210{
211 assert(scip != NULL);
212 assert(opbinput != NULL);
213
214 SCIPerrorMessage("Syntax error in line %d: %s found <%s>\n", opbinput->linenumber, msg, opbinput->token);
215 if( opbinput->linebuf[opbinput->linebufsize - 1] == '\n' )
216 {
217 SCIPerrorMessage(" input: %s", opbinput->linebuf);
218 }
219 else
220 {
221 SCIPerrorMessage(" input: %s\n", opbinput->linebuf);
222 }
223
224 opbinput->haserror = TRUE;
225}
226
227/** returns whether a syntax error was detected */
228static
230 OPBINPUT* opbinput /**< OPB reading data */
231 )
232{
233 assert(opbinput != NULL);
234
235 return opbinput->haserror;
236}
237
238/** returns whether the given character is a token delimiter */
239static
241 char c /**< input character */
242 )
243{
244 switch (c)
245 {
246 case ' ':
247 case '\f':
248 case '\n':
249 case '\r':
250 case '\t':
251 case '\v':
252 case '\0':
253 return TRUE;
254 default:
255 return FALSE;
256 }
257}
258
259/** returns whether the given character is a single token */
260static
262 char c /**< input character */
263 )
264{
265 switch (c)
266 {
267 case '-':
268 case '+':
269 case ':':
270 case '<':
271 case '>':
272 case '=':
273 case '[':
274 case ']':
275 case ';':
276 return TRUE;
277 default:
278 return FALSE;
279 }
280}
281
282/** returns whether the current character is member of a value string */
283static
285 char c, /**< input character */
286 char nextc, /**< next input character */
287 SCIP_Bool firstchar, /**< is the given character the first char of the token? */
288 SCIP_Bool* hasdot, /**< pointer to update the dot flag */
289 OPBEXPTYPE* exptype /**< pointer to update the exponent type */
290 )
291{
292 assert(hasdot != NULL);
293 assert(exptype != NULL);
294
295 if( isdigit((unsigned char)c) )
296 return TRUE;
297 else if( (*exptype == OPB_EXP_NONE) && !(*hasdot) && (c == '.') )
298 {
299 *hasdot = TRUE;
300 return TRUE;
301 }
302 else if( !firstchar && (*exptype == OPB_EXP_NONE) && (c == 'e' || c == 'E') )
303 {
304 if( nextc == '+' || nextc == '-' )
305 {
306 *exptype = OPB_EXP_SIGNED;
307 return TRUE;
308 }
309 else if( isdigit((unsigned char)nextc) )
310 {
311 *exptype = OPB_EXP_UNSIGNED;
312 return TRUE;
313 }
314 }
315 else if( (*exptype == OPB_EXP_SIGNED) && (c == '+' || c == '-') )
316 {
317 *exptype = OPB_EXP_UNSIGNED;
318 return TRUE;
319 }
320
321 return FALSE;
322}
323
324/** reads the next line from the input file into the line buffer; skips comments;
325 * returns whether a line could be read
326 */
327static
329 SCIP* scip, /**< SCIP data structure */
330 OPBINPUT* opbinput /**< OPB reading data */
331 )
332{
333 int i;
334
335 assert(opbinput != NULL);
336
337 /* read next line */
338 opbinput->linepos = 0;
339 opbinput->linebuf[opbinput->linebufsize - 2] = '\0';
340
341 if( SCIPfgets(opbinput->linebuf, opbinput->linebufsize, opbinput->file) == NULL )
342 return FALSE;
343
344 opbinput->linenumber++;
345
346 /* if line is too long for our buffer reallocate buffer */
347 while( opbinput->linebuf[opbinput->linebufsize - 2] != '\0' )
348 {
349 int newsize;
350
351 newsize = SCIPcalcMemGrowSize(scip, opbinput->linebufsize + 1);
352 SCIP_CALL_ABORT( SCIPreallocBlockMemoryArray(scip, &opbinput->linebuf, opbinput->linebufsize, newsize) );
353
354 opbinput->linebuf[newsize-2] = '\0';
355 if ( SCIPfgets(opbinput->linebuf + opbinput->linebufsize - 1, newsize - opbinput->linebufsize + 1, opbinput->file) == NULL )
356 return FALSE;
357 opbinput->linebufsize = newsize;
358 }
359
360 opbinput->linebuf[opbinput->linebufsize - 1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
361
362 /* skip characters after comment symbol */
363 for( i = 0; commentchars[i] != '\0'; ++i )
364 {
365 char* commentstart;
366
367 commentstart = strchr(opbinput->linebuf, commentchars[i]);
368 if( commentstart != NULL )
369 {
370 *commentstart = '\0';
371 *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
372 break;
373 }
374 }
375
376 SCIPdebugMsg(scip, "%s\n", opbinput->linebuf);
377
378 return TRUE;
379}
380
381/** swaps the addresses of two pointers */
382static
384 char** pointer1, /**< first pointer */
385 char** pointer2 /**< second pointer */
386 )
387{
388 char* tmp;
389
390 tmp = *pointer1;
391 *pointer1 = *pointer2;
392 *pointer2 = tmp;
393}
394
395/** reads the next token from the input file into the token buffer; returns whether a token was read */
396static
398 SCIP* scip, /**< SCIP data structure */
399 OPBINPUT* opbinput /**< OPB reading data */
400 )
401{
402 SCIP_Bool hasdot;
403 OPBEXPTYPE exptype;
404 char* buf;
405 int tokenlen;
406
407 assert(opbinput != NULL);
408 assert(opbinput->linepos < opbinput->linebufsize);
409
410 /* check the token stack */
411 if( opbinput->npushedtokens > 0 )
412 {
413 swapPointers(&opbinput->token, &opbinput->pushedtokens[opbinput->npushedtokens-1]);
414 opbinput->npushedtokens--;
415 SCIPdebugMsg(scip, "(line %d) read token again: '%s'\n", opbinput->linenumber, opbinput->token);
416 return TRUE;
417 }
418
419 /* skip delimiters */
420 buf = opbinput->linebuf;
421 while( isDelimChar(buf[opbinput->linepos]) )
422 {
423 if( buf[opbinput->linepos] == '\0' )
424 {
425 if( !getNextLine(scip, opbinput) )
426 {
427 SCIPdebugMsg(scip, "(line %d) end of file\n", opbinput->linenumber);
428 return FALSE;
429 }
430 assert(opbinput->linepos == 0);
431 /* update buf, because the linebuffer may have been reallocated */
432 buf = opbinput->linebuf;
433 }
434 else
435 opbinput->linepos++;
436 }
437 assert(opbinput->linepos < opbinput->linebufsize);
438 assert(!isDelimChar(buf[opbinput->linepos]));
439
440 /* check if the token is a value */
441 hasdot = FALSE;
442 exptype = OPB_EXP_NONE;
443 if( isValueChar(buf[opbinput->linepos], buf[opbinput->linepos+1], TRUE, &hasdot, &exptype) )
444 {
445 /* read value token */
446 tokenlen = 0;
447 do
448 {
449 assert(tokenlen < OPB_MAX_LINELEN);
450 assert(!isDelimChar(buf[opbinput->linepos]));
451 opbinput->token[tokenlen] = buf[opbinput->linepos];
452 tokenlen++;
453 opbinput->linepos++;
454 }
455 while( isValueChar(buf[opbinput->linepos], buf[opbinput->linepos+1], FALSE, &hasdot, &exptype) );
456 }
457 else
458 {
459 /* read non-value token */
460 tokenlen = 0;
461 do
462 {
463 assert(tokenlen < OPB_MAX_LINELEN);
464 opbinput->token[tokenlen] = buf[opbinput->linepos];
465 tokenlen++;
466 opbinput->linepos++;
467 if( tokenlen == 1 && isTokenChar(opbinput->token[0]) )
468 break;
469 }
470 while( !isDelimChar(buf[opbinput->linepos]) && !isTokenChar(buf[opbinput->linepos]) );
471
472 /* if the token is an equation sense '<', '>', or '=', skip a following '='
473 * if the token is an equality token '=' and the next character is a '<' or '>',
474 * replace the token by the inequality sense
475 */
476 if( tokenlen >= 1
477 && (opbinput->token[tokenlen-1] == '<' || opbinput->token[tokenlen-1] == '>' || opbinput->token[tokenlen-1] == '=')
478 && buf[opbinput->linepos] == '=' )
479 {
480 opbinput->linepos++;
481 }
482 else if( opbinput->token[tokenlen-1] == '=' && (buf[opbinput->linepos] == '<' || buf[opbinput->linepos] == '>') )
483 {
484 opbinput->token[tokenlen-1] = buf[opbinput->linepos];
485 opbinput->linepos++;
486 }
487 }
488 assert(tokenlen < OPB_MAX_LINELEN);
489 opbinput->token[tokenlen] = '\0';
490
491 SCIPdebugMsg(scip, "(line %d) read token: '%s'\n", opbinput->linenumber, opbinput->token);
492
493 return TRUE;
494}
495
496/** puts the current token on the token stack, such that it is read at the next call to getNextToken() */
497static
499 OPBINPUT* opbinput /**< OPB reading data */
500 )
501{
502 assert(opbinput != NULL);
503 assert(opbinput->npushedtokens < OPB_MAX_PUSHEDTOKENS);
504
505 swapPointers(&opbinput->pushedtokens[opbinput->npushedtokens], &opbinput->token);
506 opbinput->npushedtokens++;
507}
508
509/** puts the buffered token on the token stack, such that it is read at the next call to getNextToken() */
510static
512 OPBINPUT* opbinput /**< OPB reading data */
513 )
514{
515 assert(opbinput != NULL);
516 assert(opbinput->npushedtokens < OPB_MAX_PUSHEDTOKENS);
517
518 swapPointers(&opbinput->pushedtokens[opbinput->npushedtokens], &opbinput->tokenbuf);
519 opbinput->npushedtokens++;
520}
521
522/** swaps the current token with the token buffer */
523static
525 OPBINPUT* opbinput /**< OPB reading data */
526 )
527{
528 assert(opbinput != NULL);
529
530 swapPointers(&opbinput->token, &opbinput->tokenbuf);
531}
532
533/** checks whether the current token is a section identifier, and if yes, switches to the corresponding section */
534static
536 OPBINPUT* opbinput /**< OPB reading data */
537 )
538{
539 assert(opbinput != NULL);
540
541 if( *(opbinput->token) == ';')
542 return TRUE;
543
544 return FALSE;
545}
546
547/** returns whether the current token is a sign */
548static
550 OPBINPUT* opbinput, /**< OPB reading data */
551 int* sign /**< pointer to update the sign */
552 )
553{
554 assert(opbinput != NULL);
555 assert(sign != NULL);
556 assert(*sign == +1 || *sign == -1);
557
558 if( strlen(opbinput->token) == 1 )
559 {
560 assert(opbinput->token[1] == '\0');
561
562 if( *opbinput->token == '+' )
563 return TRUE;
564 else if( *opbinput->token == '-' )
565 {
566 *sign *= -1;
567 return TRUE;
568 }
569 }
570
571 return FALSE;
572}
573
574/** returns whether the current token is a value */
575static
577 SCIP* scip, /**< SCIP data structure */
578 OPBINPUT* opbinput, /**< OPB reading data */
579 SCIP_Real* value /**< pointer to store the value (unchanged, if token is no value) */
580 )
581{
582 assert(opbinput != NULL);
583 assert(value != NULL);
584
585 if( SCIPstrcasecmp(opbinput->token, "INFINITY") == 0 || SCIPstrcasecmp(opbinput->token, "INF") == 0 )
586 {
587 *value = SCIPinfinity(scip);
588 return TRUE;
589 }
590 else
591 {
592 double val;
593 char* endptr;
594
595 val = strtod(opbinput->token, &endptr);
596 if( endptr != opbinput->token && *endptr == '\0' )
597 {
598 *value = val;
599 if( strlen(opbinput->token) > 18 )
600 opbinput->nproblemcoeffs++;
601 return TRUE;
602 }
603 }
604
605 return FALSE;
606}
607
608/** returns whether the current token is an equation sense */
609static
611 OPBINPUT* opbinput, /**< OPB reading data */
612 OPBSENSE* sense /**< pointer to store the equation sense, or NULL */
613 )
614{
615 assert(opbinput != NULL);
616
617 if( strcmp(opbinput->token, "<") == 0 )
618 {
619 if( sense != NULL )
620 *sense = OPB_SENSE_LE;
621 return TRUE;
622 }
623 else if( strcmp(opbinput->token, ">") == 0 )
624 {
625 if( sense != NULL )
626 *sense = OPB_SENSE_GE;
627 return TRUE;
628 }
629 else if( strcmp(opbinput->token, "=") == 0 )
630 {
631 if( sense != NULL )
632 *sense = OPB_SENSE_EQ;
633 return TRUE;
634 }
635
636 return FALSE;
637}
638
639/** returns whether the current token is a value */
640static
642 SCIP* scip, /**< SCIP data structure */
643 OPBINPUT* opbinput /**< OPB reading data */
644 )
645{
646 assert(scip != NULL);
647 assert(opbinput != NULL);
648
649 if( strcmp(opbinput->token, "[") == 0 )
650 return TRUE;
651
652 return FALSE;
653}
654
655/** returns whether the current token is a value */
656static
658 SCIP* scip, /**< SCIP data structure */
659 OPBINPUT* opbinput /**< OPB reading data */
660 )
661{
662 assert(scip != NULL);
663 assert(opbinput != NULL);
664
665 if( strcmp(opbinput->token, "]") == 0 )
666 return TRUE;
667
668 return FALSE;
669}
670
671/** create binary variable with given name */
672static
674 SCIP* scip, /**< SCIP data structure */
675 SCIP_VAR** var, /**< pointer to store the variable */
676 char* name /**< name for the variable */
677 )
678{
679 SCIP_VAR* newvar;
680 SCIP_Bool dynamiccols;
681 SCIP_Bool initial;
682 SCIP_Bool removable;
683
684 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &dynamiccols) );
685 initial = !dynamiccols;
686 removable = dynamiccols;
687
688 /* create new variable of the given name */
689 SCIPdebugMsg(scip, "creating new variable: <%s>\n", name);
690
691 SCIP_CALL( SCIPcreateVar(scip, &newvar, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY,
692 initial, removable, NULL, NULL, NULL, NULL, NULL) );
693 if( SCIPisExact(scip) )
694 {
696 }
697 SCIP_CALL( SCIPaddVar(scip, newvar) );
698 *var = newvar;
699
700 /* because the variable was added to the problem, it is captured by SCIP and we
701 * can safely release it right now without making the returned *var invalid */
702 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
703
704 return SCIP_OKAY;
705}
706
707/** returns the variable with the given name, or creates a new variable if it does not exist */
708static
710 SCIP* scip, /**< SCIP data structure */
711 OPBINPUT* opbinput, /**< OPB reading data */
712 SCIP_VAR*** vars, /**< pointer to store the variables */
713 int* nvars, /**< pointer to store the number of variables */
714 int* varssize /**< pointer to store the varsize, if changed (should already be initialized) */
715 )
716{
717 SCIP_Bool negated;
718 char* name;
719
720 assert(scip != NULL);
721 assert(opbinput != NULL);
722 assert(vars != NULL);
723 assert(nvars != NULL);
724 assert(varssize != NULL);
725 assert(*varssize >= 0);
726
727 *nvars = 0;
728
729 name = opbinput->token;
730 assert(name != NULL);
731
732 /* parse AND terms */
733 while(!isdigit((unsigned char) *name ) && !isTokenChar(*name) && !opbinput->haserror )
734 {
735 SCIP_VAR* var;
736
737 negated = FALSE;
738 if( *name == '~' )
739 {
740 negated = TRUE;
741 ++name;
742 }
743
744 var = SCIPfindVar(scip, name);
745 if( var == NULL )
746 {
747 SCIP_CALL( createVariable(scip, &var, name) );
748 }
749
750 if( negated )
751 {
752 SCIP_VAR* negvar;
753 SCIP_CALL( SCIPgetNegatedVar(scip, var, &negvar) );
754
755 var = negvar;
756 }
757
758 /* reallocated memory */
759 if( *nvars == *varssize )
760 {
761 *varssize = SCIPcalcMemGrowSize(scip, *varssize + 1);
762 SCIP_CALL( SCIPreallocBufferArray(scip, vars, *varssize) );
763 }
764
765 (*vars)[*nvars] = var;
766 ++(*nvars);
767
768 if( !getNextToken(scip, opbinput) )
769 opbinput->haserror = TRUE;
770
771 name = opbinput->token;
772 }
773
774 /* check if we found at least on variable */
775 if( *nvars == 0 )
776 syntaxError(scip, opbinput, "expected a variable name");
777
778 pushToken(opbinput);
779
780 return SCIP_OKAY;
781}
782
783/** reads an objective or constraint with name and coefficients */
784static
786 SCIP*const scip, /**< SCIP data structure */
787 OPBINPUT*const opbinput, /**< OPB reading data */
788 char*const name, /**< pointer to store the name of the line; must be at least of size
789 * OPB_MAX_LINELEN */
790 SCIP_VAR*** linvars, /**< pointer to store the array with linear variables (must be freed by caller) */
791 SCIP_Real** lincoefs, /**< pointer to store the array with linear coefficients (must be freed by caller) */
792 int*const nlincoefs, /**< pointer to store the number of linear coefficients */
793 int* lincoefssize, /**< pointer to store the size of linvars/lincoefs arrays */
794 SCIP_VAR**** terms, /**< pointer to store the array with nonlinear variables (must be freed by caller) */
795 SCIP_Real** termcoefs, /**< pointer to store the array with nonlinear coefficients (must be freed by caller) */
796 int** ntermvars, /**< pointer to store the number of nonlinear variables in the terms (must be freed by caller) */
797 int* termcoefssize, /**< pointer to store the size of terms/termcoefs */
798 int*const ntermcoefs, /**< pointer to store the number of nonlinear coefficients */
799 SCIP_Bool*const newsection, /**< pointer to store whether a new section was encountered */
800 SCIP_Bool*const isNonlinear, /**< pointer to store if we have a nonlinear constraint */
801 SCIP_Bool*const issoftcons, /**< pointer to store whether it is a soft constraint (for wbo files) */
802 SCIP_Real*const weight /**< pointer to store the weight of the soft constraint */
803 )
804{
805 SCIP_VAR** tmpvars;
806 SCIP_Real* tmpcoefs;
807 SCIP_Bool havesign;
808 SCIP_Bool havevalue;
809 SCIP_Bool haveweightstart;
810 SCIP_Bool haveweightend;
811 SCIP_Real coef;
812 int coefsign;
813 int tmpvarssize;
814 int ntmpcoefs;
815 int ntmpvars;
816
817 assert(opbinput != NULL);
818 assert(name != NULL);
819 assert(linvars != NULL);
820 assert(lincoefs != NULL);
821 assert(lincoefssize != NULL);
822 assert(nlincoefs != NULL);
823 assert(terms != NULL);
824 assert(termcoefs != NULL);
825 assert(ntermvars != NULL);
826 assert(termcoefssize != NULL);
827 assert(ntermcoefs != NULL);
828 assert(newsection != NULL);
829
830 *linvars = NULL;
831 *lincoefs = NULL;
832 *lincoefssize = 0;
833 *terms = NULL;
834 *termcoefs = NULL;
835 *ntermvars = NULL;
836 *termcoefssize = 0;
837 *name = '\0';
838 *nlincoefs = 0;
839 *ntermcoefs = 0;
840 *newsection = FALSE;
841 *isNonlinear = FALSE;
842 *issoftcons = FALSE;
843
844 SCIPdebugMsg(scip, "read coefficients\n");
845
846 /* read the first token, which may be the name of the line */
847 if( getNextToken(scip, opbinput) )
848 {
849 /* remember the token in the token buffer */
850 swapTokenBuffer(opbinput);
851
852 /* get the next token and check, whether it is a colon */
853 if( getNextToken(scip, opbinput) )
854 {
855 if( strcmp(opbinput->token, ":") == 0 )
856 {
857 /* the second token was a colon ':' the first token is a constraint name */
858 (void)SCIPmemccpy(name, opbinput->tokenbuf, '\0', SCIP_MAXSTRLEN);
859
860 name[SCIP_MAXSTRLEN-1] = '\0';
861 SCIPdebugMsg(scip, "(line %d) read constraint name: '%s'\n", opbinput->linenumber, name);
862
863 /* all but the first coefficient need a sign */
864 if( strcmp(name, "soft") == 0 && (SCIPgetNVars(scip) > 0 || SCIPgetNConss(scip) > 0) )
865 {
866 syntaxError(scip, opbinput, "Soft top cost line needs to be the first non-comment line, and without any objective function.\n");
867 return SCIP_OKAY;
868 }
869 }
870 else
871 {
872 /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */
873 SCIPdebugMsg(scip, "(line %d) constraint has no name\n", opbinput->linenumber);
874 pushToken(opbinput);
875 pushBufferToken(opbinput);
876 }
877 }
878 else
879 {
880 /* there was only one token left: push it back onto the token stack and parse it as coefficient */
881 pushBufferToken(opbinput);
882 }
883 }
884 else
885 {
886 assert(SCIPfeof( opbinput->file ) );
887 opbinput->eof = TRUE;
888 return SCIP_OKAY;
889 }
890
891 /* initialize buffers for storing the coefficients */
892 *lincoefssize = OPB_INIT_COEFSSIZE;
893 *termcoefssize = OPB_INIT_COEFSSIZE;
894 tmpvarssize = OPB_INIT_COEFSSIZE;
895 SCIP_CALL( SCIPallocBlockMemoryArray(scip, linvars, *lincoefssize) );
896 SCIP_CALL( SCIPallocBlockMemoryArray(scip, lincoefs, *lincoefssize) );
897 SCIP_CALL( SCIPallocBlockMemoryArray(scip, terms, *termcoefssize) );
898 SCIP_CALL( SCIPallocBlockMemoryArray(scip, termcoefs, *termcoefssize) );
899 SCIP_CALL( SCIPallocBlockMemoryArray(scip, ntermvars, *termcoefssize) );
900
901 SCIP_CALL( SCIPallocBufferArray(scip, &tmpvars, tmpvarssize) );
902 SCIP_CALL( SCIPallocBufferArray(scip, &tmpcoefs, tmpvarssize) );
903
904 /* read the coefficients */
905 coefsign = +1;
906 coef = 1.0;
907 havesign = FALSE;
908 havevalue = FALSE;
909 haveweightstart = FALSE;
910 haveweightend = FALSE;
911 ntmpcoefs = 0;
912 ntmpvars = 0;
913
914 while( getNextToken(scip, opbinput) && !hasError(opbinput) )
915 {
916 if( isEndLine(opbinput) )
917 {
918 *newsection = TRUE;
919 goto TERMINATE;
920 }
921
922 /* check if we reached an equation sense */
923 if( isSense(opbinput, NULL) )
924 {
925 /* put the sense back onto the token stack */
926 pushToken(opbinput);
927 goto TERMINATE;
928 }
929
930 /* check if we read a sign */
931 if( isSign(opbinput, &coefsign) )
932 {
933 SCIPdebugMsg(scip, "(line %d) read coefficient sign: %+d\n", opbinput->linenumber, coefsign);
934 havesign = TRUE;
935 continue;
936 }
937
938 /* check if we read a value */
939 if( isValue(scip, opbinput, &coef) )
940 {
941 /* coefficients without a sign are treated as "+" */
942 if( (*nlincoefs > 0 || *ntermcoefs > 0 || ntmpcoefs > 0) && !havesign )
943 {
944 coefsign = 1;
945 havesign = TRUE;
946 }
947
948 SCIPdebugMsg(scip, "(line %d) read coefficient value: %g with sign %+d\n", opbinput->linenumber, coef, coefsign);
949 if( havevalue )
950 {
951 syntaxError(scip, opbinput, "two consecutive values");
952 goto TERMINATE;
953 }
954 havevalue = TRUE;
955
956 /* if we read a wbo file, the first line should be something like "soft: <weight>;", where weight is a value or nothing */
957 if( strcmp(name, "soft") == 0 )
958 {
959 assert(ntmpcoefs == 0);
960
961 tmpcoefs[ntmpcoefs] = coefsign * coef;
962 ++ntmpcoefs;
963 }
964
965 continue;
966 }
967
968 /* check if we are reading a soft constraint line, it start with "[<weight>]", where weight is a value */
969 if( *nlincoefs == 0 && *ntermcoefs == 0 && ntmpcoefs == 0 && !havesign && !havevalue && strcmp(name, "soft") != 0 && isStartingSoftConstraintWeight(scip, opbinput) )
970 {
971 if( !opbinput->wbo )
972 {
973 SCIPwarningMessage(scip, "Found in line %d a soft constraint, without having read a starting top-cost line.\n", opbinput->linenumber);
974 }
975 haveweightstart = TRUE;
976
977 continue;
978 }
979 if( *nlincoefs == 0 && *ntermcoefs == 0 && ntmpcoefs == 0 && havevalue && haveweightstart && isEndingSoftConstraintWeight(scip, opbinput) )
980 {
981 *weight = coefsign * coef;
982 SCIPdebugMsg(scip, "(line %d) found soft constraint weight: %g\n", opbinput->linenumber, *weight);
983
984 coefsign = +1;
985 havesign = FALSE;
986 havevalue = FALSE;
987 haveweightend = TRUE;
988 *issoftcons = TRUE;
989
990 continue;
991 }
992
993 /* if we read a '[' we should already read a ']', which indicates that we read a soft constraint,
994 * we have a parsing error */
995 if( haveweightstart != haveweightend )
996 {
997 syntaxError(scip, opbinput, "Wrong soft constraint.");
998 goto TERMINATE;
999 }
1000
1001 /* if we read the first non-comment line of a wbo file we should never be here */
1002 if( strcmp(name, "soft") == 0 )
1003 {
1004 syntaxError(scip, opbinput, "Wrong soft top cost line.");
1005 goto TERMINATE;
1006 }
1007
1008 /* the token is a variable name: get the corresponding variables (or create a new ones) */
1009 SCIP_CALL( getVariableOrTerm(scip, opbinput, &tmpvars, &ntmpvars, &tmpvarssize) );
1010
1011 if( ntmpvars > 1 )
1012 {
1013 /* insert non-linear term */
1014 *isNonlinear = TRUE;
1015
1016 SCIPdebugMsg(scip, "(line %d) found linear term: %+g", opbinput->linenumber, coefsign * coef);
1017#ifndef NDEBUG
1018 {
1019 int v;
1020 for( v = 0; v < ntmpvars; ++v )
1021 {
1022 SCIPdebugMsgPrint(scip, " %s * ", SCIPvarGetName(tmpvars[v]));
1023 }
1024 SCIPdebugMsgPrint(scip, "\n");
1025 }
1026#endif
1027 if( !SCIPisZero(scip, coef) )
1028 {
1029 assert(*ntermcoefs <= *termcoefssize);
1030 /* resize the terms, ntermvars, and termcoefs array if needed */
1031 if( *ntermcoefs >= *termcoefssize )
1032 {
1033 int newsize;
1034
1035 newsize = SCIPcalcMemGrowSize(scip, *ntermcoefs + 1);
1036 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, terms, *termcoefssize, newsize) );
1037 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, termcoefs, *termcoefssize, newsize) );
1038 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, ntermvars, *termcoefssize, newsize) );
1039 *termcoefssize = newsize;
1040 }
1041 assert(*ntermcoefs < *termcoefssize);
1042
1043 /* get memory for the last term */
1044 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*terms)[*ntermcoefs]), ntmpvars) ); /*lint !e866 */
1045
1046 /* set the number of variable in this term */
1047 (*ntermvars)[*ntermcoefs] = ntmpvars;
1048
1049 /* add all variables */
1050 for( --ntmpvars; ntmpvars >= 0; --ntmpvars )
1051 {
1052 (*terms)[*ntermcoefs][ntmpvars] = tmpvars[ntmpvars];
1053 }
1054 /* add coefficient */
1055 (*termcoefs)[*ntermcoefs] = coefsign * coef;
1056
1057 /***********************/
1058 if( !SCIPisIntegral(scip, (*termcoefs)[*ntermcoefs]) )
1059 {
1060 SCIPwarningMessage(scip, "coefficient %g in line %d not integral.\n", (*termcoefs)[*ntermcoefs], opbinput->linenumber);
1061 }
1062
1063 ++(*ntermcoefs);
1064 }
1065
1066 /* reset the flags and coefficient value for the next coefficient */
1067 coefsign = +1;
1068 coef = 1.0;
1069 havesign = FALSE;
1070 havevalue = FALSE;
1071 ntmpvars = 0;
1072 }
1073 else
1074 {
1075 assert(ntmpvars == 1);
1076 /* insert linear term */
1077 SCIPdebugMsg(scip, "(line %d) found linear term: %+g<%s>\n", opbinput->linenumber, coefsign * coef, SCIPvarGetName(tmpvars[0]));
1078 if( !SCIPisZero(scip, coef) )
1079 {
1080 assert(*nlincoefs <= *lincoefssize);
1081 /* resize the vars and coefs array if needed */
1082 if( *nlincoefs >= *lincoefssize )
1083 {
1084 int newsize;
1085
1086 newsize = SCIPcalcMemGrowSize(scip, *nlincoefs + 1);
1087 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, linvars, *lincoefssize, newsize) );
1088 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, lincoefs, *lincoefssize, newsize) );
1089 *lincoefssize = newsize;
1090 }
1091 assert(*nlincoefs < *lincoefssize);
1092
1093 /* add coefficient */
1094 (*linvars)[*nlincoefs] = tmpvars[0];
1095 (*lincoefs)[*nlincoefs] = coefsign * coef;
1096
1097 /***********************/
1098 if( !SCIPisIntegral(scip, (*lincoefs)[*nlincoefs]) )
1099 {
1100 SCIPwarningMessage(scip, "coefficient %g in line %d not integral.\n", (*lincoefs)[*nlincoefs], opbinput->linenumber);
1101 }
1102
1103 ++(*nlincoefs);
1104 }
1105
1106 /* reset the flags and coefficient value for the next coefficient */
1107 coefsign = +1;
1108 coef = 1.0;
1109 havesign = FALSE;
1110 havevalue = FALSE;
1111 ntmpvars = 0;
1112 }
1113 }
1114
1115 TERMINATE:
1116 if( !opbinput->haserror )
1117 {
1118 /* all variables should be in the right arrays */
1119 assert(ntmpvars == 0);
1120 /* the following is only the case if we read topcost's of a wbo file, we need to move this topcost value to the
1121 * right array */
1122 if( ntmpcoefs > 0 )
1123 {
1124 /* maximal one topcost value is possible */
1125 assert(ntmpcoefs == 1);
1126 /* no other coefficient should be found here */
1127 assert(*nlincoefs == 0 && *ntermcoefs == 0);
1128
1129 /* copy value */
1130 (*lincoefs)[*nlincoefs] = tmpcoefs[0];
1131
1132 /***********************/
1133 if( !SCIPisIntegral(scip, (*lincoefs)[*nlincoefs]) )
1134 {
1135 SCIPwarningMessage(scip, "topcost not integral.\n");
1136 }
1137
1138 *nlincoefs = 1;
1139 }
1140 }
1141 /* clear memory */
1142 SCIPfreeBufferArray(scip, &tmpcoefs);
1143 SCIPfreeBufferArray(scip, &tmpvars);
1144
1145 return SCIP_OKAY;
1146}
1147
1148/** set the objective section */
1149static
1151 SCIP*const scip, /**< SCIP data structure */
1152 OPBINPUT*const opbinput, /**< OPB reading data */
1153 const char* sense, /**< objective sense */
1154 SCIP_Real const scale, /**< objective scale */
1155 SCIP_VAR**const linvars, /**< array of linear variables */
1156 SCIP_Real*const coefs, /**< array of objective values for linear variables */
1157 int const ncoefs, /**< number of coefficients for linear part */
1158 SCIP_VAR***const terms, /**< array with nonlinear variables */
1159 SCIP_Real*const termcoefs, /**< array of objective values for nonlinear variables */
1160 int*const ntermvars, /**< number of nonlinear variables in the terms */
1161 int const ntermcoefs /**< number of nonlinear coefficients */
1162 )
1163{
1164 assert(scip != NULL);
1165 assert(opbinput != NULL);
1166 assert(isEndLine(opbinput));
1167 assert(ncoefs == 0 || (linvars != NULL && coefs != NULL));
1168 assert(ntermcoefs == 0 || (terms != NULL && ntermvars != NULL && termcoefs != NULL));
1169
1170 if( !hasError(opbinput) )
1171 {
1172 SCIP_VAR* var;
1173 char name[SCIP_MAXSTRLEN];
1174 int v;
1175
1176#ifndef NDEBUG
1177 /* check intsize validity for small int instances */
1178 if( opbinput->intsize >= 0 && opbinput->intsize <= CHAR_BIT * (int)sizeof(unsigned long long) )
1179 {
1181 summand = SCIPceil(scip, ABS(summand));
1182 assert(summand <= (SCIP_Real)ULLONG_MAX);
1183 unsigned long long presum;
1184 unsigned long long intsum = (unsigned long long)summand;
1185
1186 for( v = 0; v < ncoefs; ++v )
1187 {
1188 summand = scale * coefs[v];
1189 summand = SCIPceil(scip, ABS(summand));
1190 assert(summand <= (SCIP_Real)ULLONG_MAX);
1191 presum = intsum;
1192 intsum += (unsigned long long)summand;
1193 assert(intsum > presum);
1194 }
1195
1196 for( v = 0; v < ntermcoefs; ++v )
1197 {
1198 summand = scale * termcoefs[v];
1199 summand = SCIPceil(scip, ABS(summand));
1200 assert(summand <= (SCIP_Real)ULLONG_MAX);
1201 presum = intsum;
1202 intsum += (unsigned long long)summand;
1203 assert(intsum > presum);
1204 }
1205
1206 intsum >>= opbinput->intsize;
1207 assert(intsum == 0);
1208 }
1209#endif
1210
1211 if( strcmp(sense, "max" ) == 0 )
1212 opbinput->objsense = SCIP_OBJSENSE_MAXIMIZE;
1213
1214 /* handle non-linear terms by and-constraints */
1215 if( ntermcoefs > 0 )
1216 {
1217 if( SCIPisExact(scip) )
1218 {
1219 SCIPerrorMessage("Non-linear objectives are not supported in exact solving mode.\n");
1220 return SCIP_READERROR;
1221 }
1222
1223 SCIP_VAR** vars;
1224 int nvars;
1225 int t;
1226 SCIP_CONS* andcons;
1227
1228 for( t = 0; t < ntermcoefs; ++t )
1229 {
1230 assert(terms != NULL); /* for lint */
1231 assert(ntermvars != NULL);
1232 assert(termcoefs != NULL);
1233
1234 vars = terms[t];
1235 nvars = ntermvars[t];
1236 assert(vars != NULL);
1237 assert(nvars > 1);
1238
1239 /* @todo: reuse equivalent terms */
1240 /* create auxiliary variable */
1241 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, ARTIFICIALVARNAMEPREFIX"obj_%d", t);
1242 SCIP_CALL( SCIPcreateVarImpl(scip, &var, name, 0.0, 1.0, scale * termcoefs[t],
1244
1245 /* add auxiliary variable to the problem */
1246 SCIP_CALL( SCIPaddVar(scip, var) );
1247
1248#ifdef WITH_DEBUG_SOLUTION
1249 if( SCIPdebugIsMainscip(scip) )
1250 {
1251 SCIP_Real val = 0.0;
1252
1253 for( v = nvars - 1; v >= 0; --v )
1254 {
1255 SCIP_CALL( SCIPdebugGetSolVal(scip, vars[v], &val) );
1256 assert(SCIPisFeasZero(scip, val) || SCIPisFeasEQ(scip, val, 1.0));
1257
1258 if( val < 0.5 )
1259 break;
1260 }
1261 SCIP_CALL( SCIPdebugAddSolVal(scip, var, (val < 0.5) ? 0.0 : 1.0) );
1262 }
1263#endif
1264
1265 /* @todo: check whether all constraint creation flags are the best option */
1266 /* create and-constraint */
1267 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "obj_andcons_%d", t);
1268 SCIP_CALL( SCIPcreateConsAnd(scip, &andcons, name, var, nvars, vars,
1269 TRUE, TRUE, TRUE, TRUE, TRUE,
1270 FALSE, FALSE, FALSE, FALSE, FALSE) );
1271 SCIP_CALL( SCIPaddCons(scip, andcons) );
1272 SCIPdebugPrintCons(scip, andcons, NULL);
1273 SCIP_CALL( SCIPreleaseCons(scip, &andcons) );
1274
1275 SCIP_CALL( SCIPreleaseVar(scip, &var) );
1276 }
1277 }
1278 /* set the objective values */
1279 for( v = 0; v < ncoefs; ++v )
1280 {
1281 assert(linvars != NULL); /* for lint */
1282 assert(coefs != NULL);
1283
1284 if( SCIPisExact(scip) )
1285 {
1286 SCIP_RETCODE retcode = SCIP_OKAY;
1287 SCIP_RATIONAL* obj;
1288
1290
1291 if( SCIPvarIsNegated(linvars[v]) )
1292 {
1293 SCIP_VAR* negvar = SCIPvarGetNegationVar(linvars[v]);
1294
1295 SCIPrationalSetReal(obj, coefs[v]);
1296 SCIP_CALL_TERMINATE( retcode, SCIPaddOrigObjoffsetExact(scip, obj), TERMINATE );
1297
1298 SCIPrationalMultReal(obj, obj, -scale);
1299 SCIPrationalAdd(obj, obj, SCIPvarGetObjExact(negvar));
1300 SCIP_CALL_TERMINATE( retcode, SCIPchgVarObjExact(scip, negvar, obj), TERMINATE );
1301 }
1302 else
1303 {
1304 SCIPrationalSetReal(obj, coefs[v]);
1305 SCIPrationalMultReal(obj, obj, scale);
1306 SCIPrationalAdd(obj, obj, SCIPvarGetObjExact(linvars[v]));
1307 SCIP_CALL_TERMINATE( retcode, SCIPchgVarObjExact(scip, linvars[v], obj), TERMINATE );
1308 }
1309
1310 TERMINATE:
1312 SCIP_CALL( retcode );
1313 }
1314 else
1315 {
1316 if( SCIPvarIsNegated(linvars[v]) )
1317 {
1318 SCIP_VAR* negvar = SCIPvarGetNegationVar(linvars[v]);
1319
1320 SCIP_CALL( SCIPaddOrigObjoffset(scip, coefs[v]) );
1321 SCIP_CALL( SCIPaddVarObj(scip, negvar, -scale * coefs[v]) );
1322 }
1323 else
1324 {
1325 SCIP_CALL( SCIPaddVarObj(scip, linvars[v], scale * coefs[v]) );
1326 }
1327 }
1328 }
1329 }
1330
1331 return SCIP_OKAY;
1332}
1333
1334/** reads the constraints section */
1335static
1337 SCIP* scip, /**< SCIP data structure */
1338 OPBINPUT* opbinput, /**< OPB reading data */
1339 SCIP_Real objscale, /**< objective scale */
1340 int* nNonlinearConss /**< pointer to store number of nonlinear constraints */
1341 )
1342{
1343 char name[OPB_MAX_LINELEN];
1344 SCIP_CONS* cons;
1345 SCIP_VAR** linvars;
1346 SCIP_Real* lincoefs;
1347 int lincoefssize;
1348 int nlincoefs;
1349 SCIP_VAR*** terms;
1350 SCIP_Real* termcoefs;
1351 int* ntermvars;
1352 int termcoefssize;
1353 int ntermcoefs;
1354 OPBSENSE sense;
1355 SCIP_RETCODE retcode;
1356 SCIP_Real sidevalue;
1357 SCIP_Real lhs;
1358 SCIP_Real rhs;
1359 SCIP_Bool newsection;
1360 SCIP_Bool initialconss;
1361 SCIP_Bool dynamicconss;
1362 SCIP_Bool dynamicrows;
1363 SCIP_Bool initial;
1365 SCIP_Bool enforce;
1366 SCIP_Bool check;
1367 SCIP_Bool propagate;
1368 SCIP_Bool local;
1369 SCIP_Bool modifiable;
1370 SCIP_Bool dynamic;
1371 SCIP_Bool removable;
1372 SCIP_Bool isNonlinear;
1373 int sidesign;
1374 SCIP_Bool issoftcons;
1375 SCIP_Real weight;
1376 SCIP_VAR* indvar;
1377 char indname[SCIP_MAXSTRLEN];
1378 int t;
1379
1380 assert(scip != NULL);
1381 assert(opbinput != NULL);
1382 assert(nNonlinearConss != NULL);
1383
1384 weight = -SCIPinfinity(scip);
1385 retcode = SCIP_OKAY;
1386
1387 /* read the objective coefficients */
1388 SCIP_CALL( readCoefficients(scip, opbinput, name, &linvars, &lincoefs, &nlincoefs, &lincoefssize, &terms, &termcoefs, &ntermvars, &termcoefssize,
1389 &ntermcoefs, &newsection, &isNonlinear, &issoftcons, &weight) );
1390
1391 if( hasError(opbinput) || opbinput->eof )
1392 goto TERMINATE;
1393 if( newsection )
1394 {
1395 if( strcmp(name, "min") == 0 || strcmp(name, "max") == 0 )
1396 {
1397 if( opbinput->wbo )
1398 {
1399 syntaxError(scip, opbinput, "Cannot have an objective function when having soft constraints.\n");
1400 goto TERMINATE;
1401 }
1402
1403 /* set objective function */
1404 SCIP_CALL_TERMINATE( retcode, setObjective(scip, opbinput, name, objscale, linvars, lincoefs, nlincoefs, terms, termcoefs, ntermvars, ntermcoefs), TERMINATE );
1405 }
1406 else if( strcmp(name, "soft") == 0 )
1407 {
1408 /* we have a "weighted boolean optimization"-file(wbo) */
1409 opbinput->wbo = TRUE;
1410 if( nlincoefs == 0 )
1411 opbinput->topcost = SCIPinfinity(scip);
1412 else
1413 {
1414 assert(nlincoefs == 1);
1415 assert(lincoefs != NULL);
1416 opbinput->topcost = lincoefs[0];
1417 }
1418 SCIPdebugMsg(scip, "Weighted Boolean Optimization problem has topcost of %g\n", opbinput->topcost);
1419 }
1420 else if( nlincoefs > 0 )
1421 syntaxError(scip, opbinput, "expected constraint sense '=' or '>='");
1422 goto TERMINATE;
1423 }
1424
1425 /* read the constraint sense */
1426 if( !getNextToken(scip, opbinput) )
1427 {
1428 syntaxError(scip, opbinput, "expected constraint sense.");
1429 goto TERMINATE;
1430 }
1431 if( !isSense(opbinput, &sense) )
1432 {
1433 syntaxError(scip, opbinput, "expected constraint sense '=' or '>='.");
1434 goto TERMINATE;
1435 }
1436
1437 /* read the right hand side */
1438 sidesign = +1;
1439 if( !getNextToken(scip, opbinput) )
1440 {
1441 syntaxError(scip, opbinput, "missing right hand side");
1442 goto TERMINATE;
1443 }
1444 if( isSign(opbinput, &sidesign) )
1445 {
1446 if( !getNextToken(scip, opbinput) )
1447 {
1448 syntaxError(scip, opbinput, "missing value of right hand side");
1449 goto TERMINATE;
1450 }
1451 }
1452 if( !isValue(scip, opbinput, &sidevalue) )
1453 {
1454 syntaxError(scip, opbinput, "expected value as right hand side");
1455 goto TERMINATE;
1456 }
1457 sidevalue *= sidesign;
1458
1459 /* check if we reached the line end */
1460 if( !getNextToken(scip, opbinput) || !isEndLine(opbinput) )
1461 {
1462 syntaxError(scip, opbinput, "expected endline character ';'");
1463 goto TERMINATE;
1464 }
1465
1466 /* assign the left and right hand side, depending on the constraint sense */
1467 switch( sense ) /*lint !e530*/
1468 {
1469 case OPB_SENSE_GE:
1470 lhs = sidevalue;
1471 rhs = SCIPinfinity(scip);
1472 break;
1473 case OPB_SENSE_LE:
1474 lhs = -SCIPinfinity(scip);
1475 rhs = sidevalue;
1476 break;
1477 case OPB_SENSE_EQ:
1478 lhs = sidevalue;
1479 rhs = sidevalue;
1480 break;
1481 case OPB_SENSE_NOTHING:
1482 default:
1483 SCIPerrorMessage("invalid constraint sense <%d>\n", sense);
1484 retcode = SCIP_INVALIDDATA;
1485 goto TERMINATE;
1486 }
1487
1488#ifndef NDEBUG
1489 /* check intsize validity for small int instances */
1490 if( opbinput->intsize >= 0 && opbinput->intsize <= CHAR_BIT * (int)sizeof(unsigned long long) )
1491 {
1492 SCIP_Real summand = SCIPceil(scip, ABS(sidevalue));
1493 assert(summand <= (SCIP_Real)ULLONG_MAX);
1494 unsigned long long presum;
1495 unsigned long long intsum = (unsigned long long)summand;
1496
1497 for( t = 0; t < nlincoefs; ++t )
1498 {
1499 summand = SCIPceil(scip, ABS(lincoefs[t]));
1500 assert(summand <= (SCIP_Real)ULLONG_MAX);
1501 presum = intsum;
1502 intsum += (unsigned long long)summand;
1503 assert(intsum > presum);
1504 }
1505
1506 for( t = 0; t < ntermcoefs; ++t )
1507 {
1508 summand = SCIPceil(scip, ABS(termcoefs[t]));
1509 assert(summand <= (SCIP_Real)ULLONG_MAX);
1510 presum = intsum;
1511 intsum += (unsigned long long)summand;
1512 assert(intsum > presum);
1513 }
1514
1515 intsum >>= opbinput->intsize;
1516 assert(intsum == 0);
1517 }
1518#endif
1519
1520 /* create and add the linear constraint */
1521 SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &initialconss) );
1522 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &dynamicrows) );
1523 SCIP_CALL( SCIPgetBoolParam(scip, "reading/" READER_NAME "/dynamicconss", &dynamicconss) );
1524
1525 initial = initialconss;
1526 separate = TRUE;
1527 enforce = TRUE;
1528 check = TRUE;
1529 propagate = TRUE;
1530 local = FALSE;
1531 modifiable = FALSE;
1532 dynamic = FALSE;/*dynamicconss;*/
1533 removable = dynamicrows;
1534
1535 /* create corresponding constraint */
1536 if( issoftcons )
1537 {
1538 (void) SCIPsnprintf(indname, SCIP_MAXSTRLEN, INDICATORVARNAME"%d", opbinput->nindvars);
1539 ++(opbinput->nindvars);
1540 SCIP_CALL( createVariable(scip, &indvar, indname) );
1541
1542 assert(!SCIPisInfinity(scip, -weight));
1543 SCIP_CALL( SCIPchgVarObj(scip, indvar, objscale * weight) );
1544 }
1545 else
1546 indvar = NULL;
1547
1548 if( ntermcoefs > 0 || issoftcons )
1549 {
1550 if( SCIPisExact(scip) )
1551 {
1552 SCIPerrorMessage("Non-linear constraints are not supported in exact solving mode.\n");
1553 retcode = SCIP_READERROR;
1554 goto TERMINATE;
1555 }
1556#if GENCONSNAMES == TRUE
1557 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "pseudoboolean%d", opbinput->consnumber);
1558 ++(opbinput->consnumber);
1559#else
1560 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "pseudoboolean");
1561#endif
1562 retcode = SCIPcreateConsPseudoboolean(scip, &cons, name, linvars, nlincoefs, lincoefs, terms, ntermcoefs,
1563 ntermvars, termcoefs, indvar, weight, issoftcons, lhs, rhs, initial, separate, enforce, check, propagate, /*lint !e644*/
1564 local, modifiable, dynamic, removable, FALSE);
1565 if( retcode != SCIP_OKAY )
1566 goto TERMINATE;
1567 }
1568 else
1569 {
1570#if GENCONSNAMES == TRUE
1571 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "linear%d", opbinput->consnumber);
1572 ++(opbinput->consnumber);
1573#else
1574 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "linear");
1575#endif
1576 if( !SCIPisExact(scip) )
1577 {
1578 retcode = SCIPcreateConsLinear(scip, &cons, name, nlincoefs, linvars, lincoefs, lhs, rhs, /*lint !e644*/
1579 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE);
1580 }
1581 else
1582 {
1583 SCIP_RATIONAL** lincoefsrat;
1584 SCIP_RATIONAL* lhsrat;
1585 SCIP_RATIONAL* rhsrat;
1586
1587 SCIP_CALL( SCIPrationalCreateBufferArray(SCIPbuffer(scip), &lincoefsrat, nlincoefs) );
1590 SCIPrationalSetReal(lhsrat, lhs); /*lint !e644*/
1591 SCIPrationalSetReal(rhsrat, rhs); /*lint !e644*/
1592 for( int i = 0; i < nlincoefs; ++i )
1593 SCIPrationalSetReal(lincoefsrat[i], lincoefs[i]);
1594 retcode = SCIPcreateConsExactLinear(scip, &cons, name, nlincoefs, linvars, lincoefsrat, lhsrat, rhsrat,
1595 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE);
1598 SCIPrationalFreeBufferArray(SCIPbuffer(scip), &lincoefsrat, nlincoefs);
1599 }
1600
1601 if( retcode != SCIP_OKAY )
1602 goto TERMINATE;
1603 }
1604
1605 SCIP_CALL( SCIPaddCons(scip, cons) );
1606 SCIPdebugMsg(scip, "(line %d) created constraint: ", opbinput->linenumber);
1608 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1609
1610 if( isNonlinear )
1611 ++(*nNonlinearConss);
1612
1613 TERMINATE:
1614
1615 /* free memory */
1616 for( t = ntermcoefs - 1; t >= 0; --t )
1617 {
1618 assert(terms != NULL); /* for lint */
1619 SCIPfreeBlockMemoryArray(scip, &(terms[t]), ntermvars[t]);
1620 }
1621
1622 SCIPfreeBlockMemoryArrayNull(scip, &ntermvars, termcoefssize);
1623 SCIPfreeBlockMemoryArrayNull(scip, &termcoefs, termcoefssize);
1624 SCIPfreeBlockMemoryArrayNull(scip, &terms, termcoefssize);
1625 SCIPfreeBlockMemoryArrayNull(scip, &lincoefs, lincoefssize);
1626 SCIPfreeBlockMemoryArrayNull(scip, &linvars, lincoefssize);
1627
1628 SCIP_CALL( retcode );
1629
1630 return SCIP_OKAY;
1631}
1632
1633/** read the first comment line which usually contains information about (1) the max size of "and" products and (2) the
1634 * "intsize" which represents the number of bits required to represent the sum of the absolute values of all integers
1635 * that appear in any constraint or the objective */
1636static
1638 SCIP* scip, /**< SCIP data structure */
1639 OPBINPUT* opbinput, /**< OPB reading data */
1640 SCIP_Real* objscale, /**< pointer to store objective scale */
1641 SCIP_Real* objoffset /**< pointer to store objective offset */
1642 )
1643{
1644 assert(scip != NULL);
1645 assert(opbinput != NULL);
1646 assert(objoffset != NULL);
1647
1648 *objscale = 1.0;
1649 *objoffset = 0.0;
1650 opbinput->linebuf[opbinput->linebufsize - 2] = '\0';
1651 opbinput->intsize = -1;
1652
1653 while( SCIPfgets(opbinput->linebuf, opbinput->linebufsize, opbinput->file) != NULL )
1654 {
1655 char* commentstart;
1656 char* str;
1657
1658 /* if line is too long for our buffer reallocate buffer */
1659 while( opbinput->linebuf[opbinput->linebufsize - 2] != '\0' )
1660 {
1661 int newsize;
1662
1663 newsize = SCIPcalcMemGrowSize(scip, opbinput->linebufsize + 1);
1664 SCIP_CALL_ABORT( SCIPreallocBlockMemoryArray(scip, &opbinput->linebuf, opbinput->linebufsize, newsize) );
1665
1666 opbinput->linebuf[newsize-2] = '\0';
1667 if ( SCIPfgets(opbinput->linebuf + opbinput->linebufsize - 1, newsize - opbinput->linebufsize + 1, opbinput->file) == NULL )
1668 return SCIP_READERROR;
1669 opbinput->linebufsize = newsize;
1670 }
1671 opbinput->linebuf[opbinput->linebufsize - 1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
1672
1673 /* locate comment character */
1674 commentstart = strpbrk(opbinput->linebuf, commentchars);
1675
1676 /* no comment line */
1677 if( commentstart == NULL )
1678 break;
1679
1680#ifdef SCIP_DISABLED_CODE
1681 /* search for "#product= xyz" in comment line, where xyz represents the number of and constraints */
1682 str = strstr(opbinput->linebuf, "#product= ");
1683 if( str != NULL )
1684 {
1685 const char delimchars[] = " \t";
1686 char* pos;
1687
1688 str += strlen("#product= ");
1689
1690 pos = strtok(str, delimchars);
1691
1692 if( pos != NULL )
1693 {
1694 SCIPdebugMsg(scip, "%d products supposed to be in file.\n", atoi(pos));
1695 }
1696
1697 pos = strtok (NULL, delimchars);
1698
1699 if( pos != NULL && strcmp(pos, "sizeproduct=") == 0 )
1700 {
1701 pos = strtok (NULL, delimchars);
1702 if( pos != NULL )
1703 {
1704 SCIPdebugMsg(scip, "sizeproducts = %d\n", atoi(pos));
1705 }
1706 }
1707 }
1708#endif
1709
1710 /* search for "intsize= xyz" in comment line */
1711 str = strstr(opbinput->linebuf, "intsize= ");
1712 if( str != NULL )
1713 {
1714 const char delimchars[] = " \t";
1715 char* pos;
1716
1717 str += strlen("intsize= ");
1718
1719 pos = strtok(str, delimchars);
1720
1721 if( pos != NULL )
1722 {
1723 opbinput->intsize = atoi(pos);
1724 SCIPdebugMsg(scip, "number of bits required to represent sum of the absolute values of all integers appearing in a constraint or objective function = %d\n", opbinput->intsize);
1725 }
1726 }
1727
1728 /* search for "Obj. scale : <number>" in comment line */
1729 str = strstr(opbinput->linebuf, "Obj. scale : ");
1730 if( str != NULL )
1731 {
1732 str += strlen("Obj. scale : ");
1733 *objscale = atof(str);
1734 }
1735
1736 /* search for "Obj. offset : <number>" in comment line */
1737 str = strstr(opbinput->linebuf, "Obj. offset : ");
1738 if( str != NULL )
1739 {
1740 str += strlen("Obj. offset : ");
1741 *objoffset = atof(str);
1742 }
1743
1744 /* make sure that comment vanishes */
1745 *commentstart = '\0';
1746 }
1747
1748 return SCIP_OKAY;
1749}
1750
1751/** reads an OPB file */
1752static
1754 SCIP* scip, /**< SCIP data structure */
1755 SCIP_READER* reader, /**< the file reader itself */
1756 OPBINPUT* opbinput, /**< OPB reading data */
1757 const char* filename /**< name of the input file */
1758 )
1759{
1760 SCIP_READERDATA* readerdata = SCIPreaderGetData(reader);
1761 SCIP_RETCODE retcode = SCIP_OKAY;
1762 SCIP_Real objscale;
1763 SCIP_Real objoffset;
1764 int nNonlinearConss;
1765 int i;
1766
1767 assert(scip != NULL);
1768 assert(readerdata != NULL);
1769 assert(opbinput != NULL);
1770
1771 /* open file */
1772 opbinput->file = SCIPfopen(filename, "r");
1773 if( opbinput->file == NULL )
1774 {
1775 SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
1776 SCIPprintSysError(filename);
1777 return SCIP_NOFILE;
1778 }
1779
1780 /* @todo: reading additional information about the number of and constraints in comments to avoid reallocating
1781 * "opbinput.andconss"
1782 */
1783
1784 /* read the first comment line which contains information about size of products and coefficients */
1785 SCIP_CALL_TERMINATE( retcode, getCommentLineData(scip, opbinput, &objscale, &objoffset), TERMINATE2 );
1786
1787 if( readerdata->maxintsize >= 0 && opbinput->intsize > readerdata->maxintsize )
1788 {
1789 SCIPinfoMessage(scip, NULL, "Intsize %d exceeds %d maximum.\n", opbinput->intsize, readerdata->maxintsize);
1790 retcode = SCIP_INVALIDDATA;
1791 goto TERMINATE2;
1792 }
1793
1794 /* create problem */
1795 SCIP_CALL_TERMINATE( retcode, SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL), TERMINATE2 );
1796
1797 /* opb format supports only minimization; therefore, flip objective sense for negative objective scale */
1798 if( objscale < 0.0 )
1799 opbinput->objsense = (SCIP_OBJSENSE)(-1 * (int)(opbinput->objsense));
1800
1801 if( ! SCIPisZero(scip, objoffset) )
1802 {
1803 SCIP_CALL_TERMINATE( retcode, SCIPaddOrigObjoffset(scip, objscale * objoffset), TERMINATE2 );
1804 }
1805
1806 nNonlinearConss = 0;
1807
1808 while( !SCIPfeof( opbinput->file ) && !hasError(opbinput) )
1809 {
1810 SCIP_CALL_TERMINATE( retcode, readConstraints(scip, opbinput, objscale, &nNonlinearConss), TERMINATE2 );
1811 }
1812
1813 /* if we read a wbo file we need to make sure that the top cost won't be exceeded */
1814 if( opbinput->wbo )
1815 {
1816 SCIP_VAR** vars;
1817 SCIP_VAR** topcostvars;
1818 SCIP_CONS* topcostcons;
1819 SCIP_Real* topcosts;
1820 SCIP_Real topcostrhs;
1821 int nvars;
1822 int ntopcostvars;
1823
1824 nvars = SCIPgetNVars(scip);
1825 vars = SCIPgetVars(scip);
1826 assert(nvars > 0 || vars != NULL);
1827
1828 SCIP_CALL( SCIPallocBufferArray(scip, &topcostvars, nvars) );
1829 SCIP_CALL( SCIPallocBufferArray(scip, &topcosts, nvars) );
1830
1831 ntopcostvars = 0;
1832 for( i = nvars - 1; i >= 0; --i )
1833 {
1834 if( !SCIPisZero(scip, SCIPvarGetObj(vars[i])) )
1835 {
1836 topcostvars[ntopcostvars] = vars[i];
1837 topcosts[ntopcostvars] = SCIPvarGetObj(vars[i]);
1838 ++ntopcostvars;
1839 }
1840 }
1841 topcostrhs = SCIPceil(scip, opbinput->topcost - 1.0);
1842
1843 if( !SCIPisExact(scip) )
1844 {
1845 SCIP_CALL_TERMINATE( retcode, SCIPcreateConsLinear(scip, &topcostcons, TOPCOSTCONSNAME, ntopcostvars, topcostvars, topcosts,
1846 -SCIPinfinity(scip), topcostrhs, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE), TERMINATE1 );
1847 }
1848 else
1849 {
1850 SCIP_RATIONAL** topcostsrat;
1851 SCIP_RATIONAL* lhs;
1852 SCIP_RATIONAL* rhs;
1853
1854 SCIP_CALL( SCIPrationalCreateBufferArray(SCIPbuffer(scip), &topcostsrat, ntopcostvars) );
1858 SCIPrationalSetReal(rhs, topcostrhs);
1859 for( int j = 0; j < ntopcostvars; ++j )
1860 SCIPrationalSetReal(topcostsrat[j], topcosts[j]);
1861 retcode = SCIPcreateConsExactLinear(scip, &topcostcons, TOPCOSTCONSNAME, ntopcostvars, topcostvars,
1862 topcostsrat, lhs, rhs, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE);
1865 SCIPrationalFreeBufferArray(SCIPbuffer(scip), &topcostsrat, ntopcostvars);
1866 if( retcode != SCIP_OKAY )
1867 goto TERMINATE1;
1868 }
1869
1870 SCIP_CALL_TERMINATE( retcode, SCIPaddCons(scip, topcostcons), TERMINATE1 );
1871 SCIPdebugPrintCons(scip, topcostcons, NULL);
1872 SCIP_CALL_TERMINATE( retcode, SCIPreleaseCons(scip, &topcostcons), TERMINATE1 );
1873
1874 TERMINATE1:
1875 SCIPfreeBufferArray(scip, &topcosts);
1876 SCIPfreeBufferArray(scip, &topcostvars);
1877 }
1878
1879 TERMINATE2:
1880 /* close file */
1881 SCIPfclose(opbinput->file);
1882
1883 return retcode;
1884}
1885
1886
1887/*
1888 * Local methods (for writing)
1889 */
1890
1891/** transforms given and constraint variables to the corresponding active or negated variables */
1892static
1894 SCIP*const scip, /**< SCIP data structure */
1895 SCIP_VAR**const vars, /**< vars array to get active variables for */
1896 int const nvars, /**< pointer to number of variables and values in vars and vals array */
1897 SCIP_Bool const transformed /**< transformed constraint? */
1898 )
1899{
1900 SCIP_Bool negated;
1901 int v;
1902
1903 assert( scip != NULL );
1904 assert( vars != NULL );
1905 assert( nvars > 0 );
1906
1907 if( transformed )
1908 {
1909 for( v = nvars - 1; v >= 0; --v )
1910 {
1911 /* gets a binary variable that is equal to the given binary variable, and that is either active, fixed, or
1912 * multi-aggregated, or the negated variable of an active, fixed, or multi-aggregated variable
1913 */
1914 SCIP_CALL( SCIPgetBinvarRepresentative( scip, vars[v], &vars[v], &negated) );
1915 }
1916 }
1917 else
1918 {
1919 SCIP_Real scalar;
1920 SCIP_Real constant;
1921
1922 for( v = nvars - 1; v >= 0; --v )
1923 {
1924 scalar = 1.0;
1925 constant = 0.0;
1926
1927 /* retransforms given variable, scalar and constant to the corresponding original variable, scalar and constant,
1928 * if possible; if the retransformation is impossible, NULL is returned as variable
1929 */
1930 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalar, &constant) );
1931
1932 if( vars[v] == NULL )
1933 {
1934 SCIPdebugMsg(scip, "A variable couldn't retransformed to an original variable.\n");
1935 return SCIP_INVALIDDATA;
1936 }
1937 if( SCIPisEQ(scip, scalar, -1.0) && SCIPisEQ(scip, constant, 1.0) )
1938 {
1939 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &vars[v]) );
1940 }
1941 else
1942 {
1943 if( !SCIPisEQ(scip, scalar, 1.0) || !SCIPisZero(scip, constant) )
1944 {
1945 SCIPdebugMsg(scip, "A variable couldn't retransformed to an original variable or a negated variable of an original variable (scalar = %g, constant = %g).\n", scalar, constant);
1946 return SCIP_INVALIDDATA;
1947 }
1948 }
1949 }
1950 }
1951
1952 return SCIP_OKAY;
1953}
1954
1955/** transforms given variables, real scalars, and real constant to the corresponding active variables, real scalars, and real constant */
1956static
1958 SCIP* scip, /**< SCIP data structure */
1959 SCIP_VAR*** vars, /**< vars array to get active variables for */
1960 SCIP_Real** scalars, /**< real scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
1961 int* nvars, /**< pointer to number of variables and values in vars and vals array */
1962 int* varssize, /**< pointer to size of variable array */
1963 SCIP_Real* constant, /**< pointer to real constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
1964 SCIP_Bool transformed /**< transformed constraint? */
1965 )
1966{
1967 int requiredsize;
1968 int v;
1969
1970 assert(scip != NULL);
1971 assert(vars != NULL);
1972 assert(scalars != NULL);
1973 assert(nvars != NULL);
1974 assert(varssize != NULL);
1975 assert(constant != NULL);
1976
1977 if( transformed )
1978 {
1979 SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *varssize, constant, &requiredsize) );
1980
1981 if( requiredsize > *varssize )
1982 {
1983 SCIP_CALL( SCIPreallocBufferArray(scip, vars, requiredsize) );
1984 SCIP_CALL( SCIPreallocBufferArray(scip, scalars, requiredsize) );
1985 *varssize = requiredsize;
1986 SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *varssize, constant, &requiredsize) );
1987 }
1988 assert(requiredsize == *nvars);
1989 }
1990 else
1991 {
1992 for( v = 0; v < *nvars; ++v )
1993 {
1994 SCIP_CALL( SCIPvarGetOrigvarSum(*vars + v, *scalars + v, constant) );
1995
1996 if( (*vars)[v] == NULL )
1997 return SCIP_INVALIDDATA;
1998 }
1999 }
2000
2001 return SCIP_OKAY;
2002}
2003
2004/** transforms given variables, exact scalars, and exact constant to the corresponding active variables, exact scalars, and exact constant */
2005static
2007 SCIP* scip, /**< SCIP data structure */
2008 SCIP_VAR*** vars, /**< vars array to get active variables for */
2009 SCIP_RATIONAL*** scalars, /**< exact scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
2010 int* nvars, /**< pointer to number of variables and values in vars and vals array */
2011 int* varssize, /**< pointer to size of variable array */
2012 SCIP_RATIONAL* constant, /**< pointer to exact constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
2013 SCIP_Bool transformed /**< transformed constraint? */
2014 )
2015{
2016 int requiredsize;
2017 int v;
2018
2019 assert(scip != NULL);
2020 assert(vars != NULL);
2021 assert(scalars != NULL);
2022 assert(nvars != NULL);
2023 assert(varssize != NULL);
2024 assert(constant != NULL);
2025
2026 if( transformed )
2027 {
2028 SCIP_CALL( SCIPgetProbvarLinearSumExact(scip, *vars, *scalars, nvars, *varssize, constant, &requiredsize, TRUE) );
2029
2030 if( requiredsize > *varssize )
2031 {
2032 SCIP_CALL( SCIPreallocBufferArray(scip, vars, requiredsize) );
2033 SCIP_CALL( SCIPrationalReallocBufferArray(SCIPbuffer(scip), scalars, *varssize, requiredsize) );
2034 *varssize = requiredsize;
2035 SCIP_CALL( SCIPgetProbvarLinearSumExact(scip, *vars, *scalars, nvars, *varssize, constant, &requiredsize, TRUE) );
2036 }
2037 assert(requiredsize == *nvars);
2038 }
2039 else
2040 {
2041 for( v = 0; v < *nvars; ++v )
2042 {
2043 SCIP_CALL( SCIPvarGetOrigvarSumExact(*vars + v, (*scalars)[v], constant) );
2044
2045 if( (*vars)[v] == NULL )
2046 return SCIP_INVALIDDATA;
2047 }
2048 }
2049
2050 return SCIP_OKAY;
2051}
2052
2053/* computes all and-resultants and their corresponding constraint variables */
2054static
2056 SCIP*const scip, /**< SCIP data structure */
2057 SCIP_Bool const transformed, /**< transformed problem? */
2058 SCIP_VAR*** resvars, /**< pointer to store all resultant variables */
2059 int* nresvars, /**< pointer to store the number of all resultant variables */
2060 SCIP_VAR**** andvars, /**< pointer to store to all resultant variables their corresponding active( or negated) and-constraint variables */
2061 int** nandvars, /**< pointer to store the number of all corresponding and-variables to their corresponding resultant variable */
2062 SCIP_Bool*const existandconshdlr, /**< pointer to store whether the and-constrainthandler exists*/
2063 SCIP_Bool*const existands /**< pointer to store if their exists some and-constraints */
2064 )
2065{
2066 SCIP_CONSHDLR* conshdlr;
2067
2068 assert(scip != NULL);
2069 assert(resvars != NULL);
2070 assert(nresvars != NULL);
2071 assert(andvars != NULL);
2072 assert(nandvars != NULL);
2073 assert(existandconshdlr != NULL);
2074 assert(existands != NULL);
2075
2076 *resvars = NULL;
2077 *nandvars = NULL;
2078 *andvars = NULL;
2079 *nresvars = 0;
2080
2081 /* detect all and-resultants */
2082 conshdlr = SCIPfindConshdlr(scip, "and");
2083 if( conshdlr != NULL )
2084 {
2085 SCIP_CONS** andconss;
2086 int nandconss;
2087 int* shouldnotbeinand;
2088 int a;
2089 int c;
2090 int r;
2091 int v;
2092 int pos;
2093 int ncontainedands;
2094
2095 andconss = NULL;
2096 nandconss = 0;
2097 *existandconshdlr = TRUE;
2098
2099 /* if we write the original problem we need to get the original and constraints */
2100 if( !transformed )
2101 {
2102 SCIP_CONS** origconss;
2103 int norigconss;
2104
2105 origconss = SCIPgetOrigConss(scip);
2106 norigconss = SCIPgetNOrigConss(scip);
2107
2108 /* allocate memory for all possible and-constraints */
2109 SCIP_CALL( SCIPallocBufferArray(scip, &andconss, norigconss) );
2110
2111 /* collect all original and-constraints */
2112 for( c = norigconss - 1; c >= 0; --c )
2113 {
2114 conshdlr = SCIPconsGetHdlr(origconss[c]);
2115 assert( conshdlr != NULL );
2116
2117 if( strcmp(SCIPconshdlrGetName(conshdlr), "and") == 0 )
2118 {
2119 andconss[nandconss] = origconss[c];
2120 ++nandconss;
2121 }
2122 }
2123 }
2124 else
2125 {
2126 nandconss = SCIPconshdlrGetNConss(conshdlr);
2127 andconss = SCIPconshdlrGetConss(conshdlr);
2128 }
2129
2130 assert(andconss != NULL || nandconss == 0);
2131
2132 *nresvars = nandconss;
2133
2134 if( nandconss > 0 )
2135 {
2136 *existands = TRUE;
2137
2138 assert(andconss != NULL);
2139
2140 SCIP_CALL( SCIPallocMemoryArray(scip, resvars, *nresvars) );
2141 SCIP_CALL( SCIPallocMemoryArray(scip, andvars, *nresvars) );
2142 SCIP_CALL( SCIPallocMemoryArray(scip, nandvars, *nresvars) );
2143
2144 /* collect all and-constraint variables */
2145 for( c = nandconss - 1; c >= 0; --c )
2146 {
2147 SCIP_VAR** scipandvars;
2148
2149 assert(andconss[c] != NULL);
2150
2151 scipandvars = SCIPgetVarsAnd(scip, andconss[c]);
2152 (*nandvars)[c] = SCIPgetNVarsAnd(scip, andconss[c]);
2153 SCIP_CALL( SCIPduplicateMemoryArray(scip, &((*andvars)[c]), scipandvars, (*nandvars)[c]) ); /*lint !e866 */
2154 SCIP_CALL( getBinVarsRepresentatives(scip, (*andvars)[c], (*nandvars)[c], transformed) );
2155
2156 (*resvars)[c] = SCIPgetResultantAnd(scip, andconss[c]);
2157
2158 assert((*andvars)[c] != NULL && (*nandvars)[c] > 0);
2159 assert((*resvars)[c] != NULL);
2160 }
2161
2162 /* sorted the array */
2163 SCIPsortPtrPtrInt((void**)(*resvars), (void**)(*andvars), (*nandvars), SCIPvarComp, (*nresvars));
2164 }
2165 else
2166 *existands = FALSE;
2167
2168 SCIP_CALL( SCIPallocBufferArray(scip, &shouldnotbeinand, *nresvars) );
2169
2170 /* check that all and-constraints doesn't contain any and-resultants, if they do try to resolve this */
2171 /* attention: if resolving leads to x = x*y*... , we can't do anything here ( this only means (... >=x and) y >= x, so normally the and-constraint needs to be
2172 deleted and the inequality from before needs to be added ) */
2173 assert(*nandvars != NULL || *nresvars == 0);
2174 for( r = *nresvars - 1; r >= 0; --r )
2175 {
2176 ncontainedands = 0;
2177 shouldnotbeinand[ncontainedands] = r;
2178 ++ncontainedands;
2179 v = 0;
2180
2181 assert(*nandvars != NULL);
2182 while( v < (*nandvars)[r] )
2183 {
2184 assert(*andvars != NULL);
2185 assert(*resvars != NULL);
2186 if( SCIPsortedvecFindPtr((void**)(*resvars), SCIPvarComp, (*andvars)[r][v], *nresvars, &pos) )
2187 {
2188 /* check if the found position "pos" is equal to an already visited and resultant in this constraint,
2189 * than here could exist a directed cycle
2190 */
2191 /* better use tarjan's algorithm
2192 * <http://algowiki.net/wiki/index.php?title=Tarjan%27s_algorithm>,
2193 * <http://en.wikipedia.org/wiki/Tarjan%E2%80%99s_strongly_connected_components_algorithm>
2194 * because it could be that the same resultant is part of this and-constraint and than it would fail
2195 * without no cycle
2196 * Note1: tarjans standard algorithm doesn't find cycle from one node to the same;
2197 * Note2: when tarjan's algorithm find a cycle, it's still possible that this cycle is not "real" e.g.
2198 * y = y ~y z (z can also be a product) where y = 0 follows and therefor only "0 = z" is necessary
2199 */
2200 for( a = ncontainedands - 1; a >= 0; --a )
2201 if( shouldnotbeinand[a] == pos )
2202 {
2203 SCIPwarningMessage(scip, "This should not happen here. The and-constraint with resultant variable: ");
2204 SCIP_CALL( SCIPprintVar(scip, (*resvars)[r], NULL) );
2205 SCIPwarningMessage(scip, "possible contains a loop with and-resultant:");
2206 SCIP_CALL( SCIPprintVar(scip, (*resvars)[pos], NULL) );
2207
2208 /* free memory iff necessary */
2209 SCIPfreeBufferArray(scip, &shouldnotbeinand);
2210 if( !transformed )
2211 {
2212 SCIPfreeBufferArray(scip, &andconss);
2213 }
2214 return SCIP_INVALIDDATA;
2215 }
2216 SCIPdebugMsg(scip, "Another and-constraint contains and-resultant:");
2217 SCIPdebug( SCIP_CALL( SCIPprintVar(scip, (*resvars)[pos], NULL) ) );
2218 SCIPdebugMsg(scip, "Trying to resolve.\n");
2219
2220 shouldnotbeinand[ncontainedands] = pos;
2221 ++ncontainedands;
2222
2223 /* try to resolve containing ands */
2224
2225 /* resize array and number of variables */
2226 (*nandvars)[r] = (*nandvars)[r] + (*nandvars)[pos] - 1;
2227 SCIP_CALL( SCIPreallocMemoryArray(scip, &((*andvars)[r]), (*nandvars)[r]) ); /*lint !e866 */
2228
2229 /* copy all variables */
2230 for( a = (*nandvars)[pos] - 1; a >= 0; --a )
2231 (*andvars)[r][(*nandvars)[r] - a - 1] = (*andvars)[pos][a];
2232
2233 /* check same position with new variable, so we do not increase v */
2234 }
2235 else
2236 ++v;
2237 }
2238 }
2239 SCIPfreeBufferArray(scip, &shouldnotbeinand);
2240
2241 /* free memory iff necessary */
2242 if( !transformed )
2243 {
2244 SCIPfreeBufferArray(scip, &andconss);
2245 }
2246 }
2247 else
2248 {
2249 SCIPdebugMsg(scip, "found no and-constraint-handler\n");
2250 *existands = FALSE;
2251 *existandconshdlr = FALSE;
2252 }
2253
2254 return SCIP_OKAY;
2255}
2256
2257/** clears the given line buffer */
2258static
2260 char* linebuffer, /**< line */
2261 int* linecnt /**< number of characters in line */
2262 )
2263{
2264 assert( linebuffer != NULL );
2265 assert( linecnt != NULL );
2266
2267 (*linecnt) = 0;
2268 linebuffer[0] = '\0';
2269}
2270
2271
2272/** ends the given line with '\\0' and prints it to the given file stream */
2273static
2275 SCIP* scip, /**< SCIP data structure */
2276 FILE* file, /**< output file (or NULL for standard output) */
2277 char* linebuffer, /**< line */
2278 int* linecnt /**< number of characters in line */
2279 )
2280{
2281 assert( scip != NULL );
2282 assert( linebuffer != NULL );
2283 assert( linecnt != NULL );
2284 assert( 0 <= *linecnt && *linecnt < OPB_MAX_LINELEN );
2285
2286 if( (*linecnt) > 0 )
2287 {
2288 linebuffer[(*linecnt)] = '\0';
2289 SCIPinfoMessage(scip, file, "%s", linebuffer);
2290 clearBuffer(linebuffer, linecnt);
2291 }
2292}
2293
2294
2295/** appends extension to line and prints it to the give file stream if the line buffer get full */
2296static
2298 SCIP* scip, /**< SCIP data structure */
2299 FILE* file, /**< output file (or NULL for standard output) */
2300 char* linebuffer, /**< line buffer */
2301 int* linecnt, /**< number of characters in line */
2302 const char* extension /**< string to extent the line */
2303 )
2304{
2305 assert(scip != NULL);
2306 assert(linebuffer != NULL);
2307 assert(linecnt != NULL);
2308 assert(extension != NULL);
2309
2310 if( (*linecnt) + (int) strlen(extension) >= OPB_MAX_LINELEN - 1 )
2311 writeBuffer(scip, file, linebuffer, linecnt);
2312
2313 /* append extension to linebuffer */
2314 (void) strncat(linebuffer, extension, OPB_MAX_LINELEN - (unsigned int)(*linecnt));
2315 (*linecnt) += (int) strlen(extension);
2316}
2317
2318/** write objective function */
2319static
2321 SCIP*const scip, /**< SCIP data structure */
2322 FILE*const file, /**< output file, or NULL if standard output should be used */
2323 SCIP_VAR**const vars, /**< array with active (binary) variables */
2324 int const nvars, /**< number of active variables in the problem */
2325 SCIP_VAR** const resvars, /**< array of resultant variables */
2326 int const nresvars, /**< number of resultant variables */
2327 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2328 int const*const nandvars, /**< array of numbers of corresponding and-variables */
2329 SCIP_OBJSENSE const objsense, /**< objective sense */
2330 SCIP_Real const objoffset, /**< objective offset from bound shifting and fixing */
2331 SCIP_Real const objscale, /**< scalar applied to objective function; external objective value is
2332 * extobj = objsense * objscale * (intobj + objoffset) */
2333 SCIP_RATIONAL*const objoffsetexact, /**< exact objective offset from bound shifting and fixing */
2334 SCIP_RATIONAL*const objscaleexact, /**< exact scalar applied to objective function; external objective value is
2335 * extobjexact = objsense * objscaleexact * (intobjexact + objoffsetexact) */
2336 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
2337 SCIP_Bool const existands, /**< does some and-constraints exist? */
2338 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
2339 )
2340{
2341 SCIP_VAR* var;
2342 char linebuffer[OPB_MAX_LINELEN+1];
2343 char buffer[OPB_MAX_LINELEN];
2344 SCIP_Longint mult;
2345 SCIP_Bool objective;
2346 int v;
2347 int linecnt;
2348 int pos;
2349
2350 assert(scip != NULL);
2351 assert(file != NULL);
2352 assert(vars != NULL || nvars == 0);
2353 assert(resvars != NULL || nresvars == 0);
2354 assert(andvars != NULL || nandvars == NULL);
2355 assert(multisymbol != NULL);
2356
2357 mult = 1;
2358 objective = !SCIPisZero(scip, objoffset);
2359
2360 clearBuffer(linebuffer, &linecnt);
2361
2362 /* check if a objective function exits and compute the multiplier to
2363 * shift the coefficients to integers */
2364 for( v = 0; v < nvars; ++v )
2365 {
2366 var = vars[v]; /*lint !e613 */
2367
2368#ifndef NDEBUG
2369 {
2370 /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
2371 if( !transformed )
2372 assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL ||
2374 }
2375#endif
2376
2377 /* we found a indicator variable so we assume this is a wbo file */
2378 if( strstr(SCIPvarGetName(var), INDICATORVARNAME) != NULL )
2379 {
2380 /* find the topcost linear inequality which gives us the maximal cost which could be violated by our
2381 * solution, which is an artificial constraint and print this at first
2382 *
2383 * @note: only linear constraint handler is enough in problem stage, otherwise it could be any upgraded linear
2384 * constraint which handles pure binary variables
2385 */
2386 SCIP_CONSHDLR* conshdlr;
2387 SCIP_CONS* topcostcons;
2388 const char* conshdlrname;
2389 int written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: ");
2390
2391 topcostcons = SCIPfindCons(scip, TOPCOSTCONSNAME);
2392
2393 if( topcostcons != NULL )
2394 {
2395 conshdlr = SCIPconsGetHdlr(topcostcons);
2396 assert(conshdlr != NULL);
2397 conshdlrname = SCIPconshdlrGetName(conshdlr);
2398 assert(conshdlrname != NULL);
2399
2400 if( strcmp(conshdlrname, "linear") == 0 )
2401 {
2402 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, "%.15g",
2403 SCIPgetRhsLinear(scip, topcostcons));
2404 }
2405 else if( strcmp(conshdlrname, "knapsack") == 0 )
2406 {
2407 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, "%" SCIP_LONGINT_FORMAT,
2408 SCIPgetCapacityKnapsack(scip, topcostcons));
2409 }
2410 else if( strcmp(conshdlrname, "setppc") == 0 )
2411 {
2412 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, "1");
2413 }
2414 else if( strcmp(conshdlrname, "exactlinear") == 0 )
2415 {
2416 assert(SCIPisExact(scip));
2417 written += SCIPrationalToString(SCIPgetRhsExactLinear(scip, topcostcons),
2418 buffer + written, OPB_MAX_LINELEN - written);
2419 }
2420 else
2421 {
2422 SCIPABORT();
2423 return SCIP_INVALIDDATA; /*lint !e527 */
2424 }
2425 }
2426 /* following works only in transformed stage */
2427 else
2428 {
2429 SCIP_Bool topcostfound = FALSE;
2430
2431 /* first try linear constraints */
2432 {
2433 conshdlr = SCIPfindConshdlr(scip, "linear");
2434
2435 if( conshdlr != NULL )
2436 {
2437 SCIP_CONS** conss;
2438 int nconss;
2439 int c;
2440
2441 conss = SCIPconshdlrGetConss(conshdlr);
2442 nconss = SCIPconshdlrGetNConss(conshdlr);
2443 assert(conss != NULL || nconss == 0);
2444
2445 for( c = 0; c < nconss; ++c )
2446 {
2447 SCIP_VAR** consvars;
2448 int nconsvars;
2449 int w;
2450
2451 topcostcons = conss[c]; /*lint !e613 */
2452 assert(topcostcons != NULL);
2453
2454 consvars = SCIPgetVarsLinear(scip, topcostcons);
2455 nconsvars = SCIPgetNVarsLinear(scip, topcostcons);
2456 assert(consvars != NULL || nconsvars == 0);
2457
2458 for( w = 0; w < nconsvars; ++w )
2459 {
2460 if( strstr(SCIPvarGetName(consvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2461 topcostfound = TRUE;
2462 else
2463 {
2464 assert(!topcostfound);
2465 topcostfound = FALSE;
2466 }
2467 }
2468
2469 if( topcostfound )
2470 {
2471 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, "%.15g",
2472 SCIPgetRhsLinear(scip, topcostcons));
2473 break;
2474 }
2475 }
2476 }
2477 }
2478
2479 /* second try knapsack constraints */
2480 if( !topcostfound )
2481 {
2482 conshdlr = SCIPfindConshdlr(scip, "knapsack");
2483
2484 if( conshdlr != NULL )
2485 {
2486 SCIP_CONS** conss;
2487 int nconss;
2488 int c;
2489
2490 conss = SCIPconshdlrGetConss(conshdlr);
2491 nconss = SCIPconshdlrGetNConss(conshdlr);
2492 assert(conss != NULL || nconss == 0);
2493
2494 for( c = 0; c < nconss; ++c )
2495 {
2496 SCIP_VAR** consvars;
2497 int nconsvars;
2498 int w;
2499
2500 topcostcons = conss[c]; /*lint !e613 */
2501 assert(topcostcons != NULL);
2502
2503 consvars = SCIPgetVarsKnapsack(scip, topcostcons);
2504 nconsvars = SCIPgetNVarsKnapsack(scip, topcostcons);
2505 assert(consvars != NULL || nconsvars == 0);
2506
2507 for( w = 0; w < nconsvars; ++w )
2508 {
2509 if( strstr(SCIPvarGetName(consvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2510 topcostfound = TRUE;
2511 else
2512 {
2513 assert(!topcostfound);
2514 topcostfound = FALSE;
2515 }
2516 }
2517
2518 if( topcostfound )
2519 {
2520 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, "%" SCIP_LONGINT_FORMAT,
2521 SCIPgetCapacityKnapsack(scip, topcostcons));
2522 break;
2523 }
2524 }
2525 }
2526 }
2527
2528 /* third try setppc constraints */
2529 if( !topcostfound )
2530 {
2531 conshdlr = SCIPfindConshdlr(scip, "setppc");
2532
2533 if( conshdlr != NULL )
2534 {
2535 SCIP_CONS** conss;
2536 int nconss;
2537 int c;
2538
2539 conss = SCIPconshdlrGetConss(conshdlr);
2540 nconss = SCIPconshdlrGetNConss(conshdlr);
2541 assert(conss != NULL || nconss == 0);
2542
2543 for( c = 0; c < nconss; ++c )
2544 {
2545 SCIP_VAR** consvars;
2546 int nconsvars;
2547 int w;
2548
2549 topcostcons = conss[c]; /*lint !e613 */
2550 assert(topcostcons != NULL);
2551
2552 consvars = SCIPgetVarsSetppc(scip, topcostcons);
2553 nconsvars = SCIPgetNVarsSetppc(scip, topcostcons);
2554 assert(consvars != NULL || nconsvars == 0);
2555
2556 for( w = 0; w < nconsvars; ++w )
2557 {
2558 if( strstr(SCIPvarGetName(consvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2559 topcostfound = TRUE;
2560 else
2561 {
2562 assert(!topcostfound);
2563 topcostfound = FALSE;
2564 }
2565 }
2566
2567 if( topcostfound )
2568 {
2569 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, "1");
2570 break;
2571 }
2572 }
2573 }
2574 }
2575
2576 /* try exactlinear constraints */
2577 if( !topcostfound )
2578 {
2579 conshdlr = SCIPfindConshdlr(scip, "exactlinear");
2580
2581 if( conshdlr != NULL )
2582 {
2583 assert(SCIPisExact(scip));
2584
2585 SCIP_CONS** conss;
2586 int nconss;
2587 int c;
2588
2589 conss = SCIPconshdlrGetConss(conshdlr);
2590 nconss = SCIPconshdlrGetNConss(conshdlr);
2591 assert(conss != NULL || nconss == 0);
2592
2593 for( c = 0; c < nconss; ++c )
2594 {
2595 SCIP_VAR** consvars;
2596 int nconsvars;
2597 int w;
2598
2599 topcostcons = conss[c]; /*lint !e613 */
2600 assert(topcostcons != NULL);
2601
2602 consvars = SCIPgetVarsExactLinear(scip, topcostcons);
2603 nconsvars = SCIPgetNVarsExactLinear(scip, topcostcons);
2604 assert(consvars != NULL || nconsvars == 0);
2605
2606 for( w = 0; w < nconsvars; ++w )
2607 {
2608 if( strstr(SCIPvarGetName(consvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2609 topcostfound = TRUE;
2610 else
2611 {
2612 assert(!topcostfound);
2613 topcostfound = FALSE;
2614 }
2615 }
2616
2617 if( topcostfound )
2618 {
2619 written += SCIPrationalToString(SCIPgetRhsExactLinear(scip, topcostcons),
2620 buffer + written, OPB_MAX_LINELEN - written);
2621 break;
2622 }
2623 }
2624 }
2625 }
2626 }
2627
2628 /* if no topcost constraint found, print empty topcost line, which means there is no upper bound */
2629 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, ";\n");
2630 if( written >= OPB_MAX_LINELEN )
2631 {
2632 SCIPerrorMessage("line bound reached\n");
2633 return SCIP_INVALIDDATA;
2634 }
2635 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2636
2637 writeBuffer(scip, file, linebuffer, &linecnt);
2638
2639 return SCIP_OKAY;
2640 }
2641
2642 /**@todo determine exact multiplier */
2643 if( !SCIPisExact(scip) && !SCIPisZero(scip, SCIPvarGetObj(var)) )
2644 {
2645 objective = TRUE;
2646 while( !SCIPisIntegral(scip, SCIPvarGetObj(var) * mult) )
2647 {
2648 assert(mult * 10 > mult);
2649 mult *= 10;
2650 }
2651 }
2652 }
2653
2654 /* there exists an objective function */
2655 if( objective )
2656 {
2657 /* write exact objective */
2658 if( SCIPisExact(scip) )
2659 {
2660 SCIP_RATIONAL* obj;
2661
2662 /* opb format supports only minimization; therefore, a maximization problem has to be converted */
2663 if( (objsense == SCIP_OBJSENSE_MAXIMIZE) != (SCIPrationalIsNegative(objscaleexact)) )
2664 mult *= -1;
2665 assert(ABS(mult) == 1);
2666
2668
2669 SCIPrationalDivReal(obj, objscaleexact, (SCIP_Real)mult);
2670 SCIPinfoMessage(scip, file, "* Obj. scale : ");
2672 SCIPinfoMessage(scip, file, "\n");
2673 SCIPrationalMultReal(obj, objoffsetexact, (SCIP_Real)mult);
2674 SCIPinfoMessage(scip, file, "* Obj. offset : ");
2676 SCIPinfoMessage(scip, file, "\n");
2677
2679 }
2680 /* write real objective */
2681 else
2682 {
2683 /* opb format supports only minimization; therefore, a maximization problem has to be converted */
2684 if( (objsense == SCIP_OBJSENSE_MAXIMIZE) != (objscale < 0.0) )
2685 mult *= -1;
2686
2687 SCIPinfoMessage(scip, file, "* Obj. scale : %.15g\n", objscale / mult);
2688 SCIPinfoMessage(scip, file, "* Obj. offset : %.15g\n", objoffset * mult);
2689 }
2690
2691 clearBuffer(linebuffer, &linecnt);
2692
2693 SCIPdebugMsg(scip, "print objective function multiplied with %" SCIP_LONGINT_FORMAT "\n", mult);
2694
2695 appendBuffer(scip, file, linebuffer, &linecnt, "min:");
2696
2697#ifndef NDEBUG
2698 if( existands )
2699 {
2700 int c;
2701 /* check that these variables are sorted */
2702 for( c = nresvars - 1; c > 0; --c )
2703 assert(SCIPvarGetIndex(resvars[c]) >= SCIPvarGetIndex(resvars[c - 1])); /*lint !e613 */
2704 }
2705#endif
2706
2707 for( v = 0; v < nvars; ++v )
2708 {
2709 SCIP_Bool negated;
2710 var = vars[v]; /*lint !e613 */
2711
2712 assert(var != NULL);
2713
2714 if( SCIPisZero(scip, SCIPvarGetObj(var)) )
2715 continue;
2716
2717 negated = SCIPvarIsNegated(var);
2718
2719 assert( linecnt != 0 );
2720
2721 if( SCIPvarGetObj(var) * mult > (SCIP_Real)SCIP_LONGINT_MAX )
2722 {
2723 SCIPerrorMessage("Integral objective value to big (mult = %" SCIP_LONGINT_FORMAT ", value = %g, mult*value = %g, printingvalue = %" SCIP_LONGINT_FORMAT ")for printing in opb format.\n", mult, SCIPvarGetObj(var), SCIPvarGetObj(var) * mult, (SCIP_Longint) SCIPround(scip, SCIPvarGetObj(var) * mult));
2724 }
2725
2726 /* replace and-resultant with corresponding variables */
2727 if( existands && SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) )
2728 {
2729 int a;
2730
2731 assert(andvars != NULL);
2732 assert(nandvars != NULL);
2733 assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
2734 assert(andvars[pos][nandvars[pos] - 1] != NULL);
2735
2736 negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2737
2738 /* print and-vars */
2739 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2740 (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "",
2741 strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
2742 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2743
2744 for(a = nandvars[pos] - 2; a >= 0; --a )
2745 {
2746 negated = SCIPvarIsNegated(andvars[pos][a]);
2747
2748 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2749 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2750 }
2751 }
2752 else
2753 {
2754 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2755 (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2756 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2757 }
2758 }
2759
2760 /* and objective function line ends with a ';' */
2761 appendBuffer(scip, file, linebuffer, &linecnt, ";\n");
2762 writeBuffer(scip, file, linebuffer, &linecnt);
2763 }
2764
2765 return SCIP_OKAY;
2766}
2767
2768/* print real non-linear row in OPB format to file stream */
2769static
2771 SCIP*const scip, /**< SCIP data structure */
2772 FILE*const file, /**< output file (or NULL for standard output) */
2773 const char*const type, /**< row type ("=" or ">=") */
2774 SCIP_VAR**const vars, /**< array of variables */
2775 SCIP_Real*const vals, /**< array of real values */
2776 int nvars, /**< number of variables */
2777 SCIP_Real lhs, /**< real left hand side */
2778 SCIP_VAR**const resvars, /**< array of resultant variables */
2779 int nresvars, /**< number of resultant variables */
2780 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2781 const int*const nandvars, /**< array of numbers of corresponding and-variables */
2782 SCIP_Longint weight, /**< if we found a soft constraint this is the integral weight, otherwise 0 */
2783 SCIP_Longint*const mult, /**< integral multiplier for the coefficients */
2784 const char*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2785 )
2786{
2787 SCIP_VAR* var;
2788 SCIP_Real val;
2789 SCIP_Bool negated;
2790 char buffer[OPB_MAX_LINELEN];
2791 char linebuffer[OPB_MAX_LINELEN + 1];
2792 int linecnt;
2793 int pos;
2794 int written;
2795 int v;
2796
2797 assert(scip != NULL);
2798 assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2799 assert(vars != NULL);
2800 assert(vals != NULL);
2801 assert(mult != NULL);
2802 assert(resvars != NULL);
2803 assert(nresvars >= 1);
2804 assert(andvars != NULL);
2805 assert(nandvars != NULL);
2806
2807 clearBuffer(linebuffer, &linecnt);
2808
2809 /* check if all coefficients are internal; if not commentstart multiplier */
2810 for( v = 0; v < nvars; ++v )
2811 {
2812 while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
2813 {
2814 if( ABS(*mult) > ABS(*mult * 10) )
2815 {
2816 SCIPerrorMessage("failed to scale fractional coefficients to integrality because the required multiplier is too large\n");
2817 return SCIP_INVALIDDATA;
2818 }
2819 (*mult) *= 10;
2820 }
2821 }
2822
2823 while( !SCIPisIntegral(scip, lhs * (*mult)) )
2824 {
2825 if( ABS(*mult) > ABS(*mult * 10) )
2826 {
2827 SCIPerrorMessage("failed to scale fractional coefficients to integrality because the required multiplier is too large\n");
2828 return SCIP_INVALIDDATA;
2829 }
2830 (*mult) *= 10;
2831 }
2832
2833 /* print comment line if we have to multiply the coefficients to get integrals */
2834 if( ABS(*mult) != 1 )
2835 {
2836 SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n",
2837 ABS(*mult));
2838 }
2839
2840#ifndef NDEBUG
2841 /* check that these variables are sorted */
2842 for( v = nresvars - 1; v > 0; --v )
2843 assert(SCIPvarGetIndex(resvars[v]) >= SCIPvarGetIndex(resvars[v - 1]));
2844#endif
2845
2846 /* if we have a soft constraint print the weight */
2847 if( weight != 0 )
2848 {
2849 written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "]", weight);
2850 if( written >= OPB_MAX_LINELEN )
2851 {
2852 SCIPerrorMessage("line bound reached\n");
2853 return SCIP_INVALIDDATA;
2854 }
2855 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2856 }
2857
2858 /* print coefficients */
2859 for( v = 0; v < nvars; ++v )
2860 {
2861 var = vars[v];
2862 val = vals[v] * (*mult);
2863 negated = SCIPvarIsNegated(var);
2864
2865 /* replace and-resultant with corresponding variables */
2866 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) )
2867 {
2868 int a;
2869
2870 assert(andvars != NULL);
2871 assert(nandvars != NULL);
2872 assert(pos >= 0);
2873 assert(nandvars[pos] >= 1);
2874 assert(andvars[pos] != NULL);
2875 assert(andvars[pos][nandvars[pos] - 1] != NULL);
2876
2877 negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2878
2879 if( ABS(val) > (SCIP_Real)SCIP_LONGINT_MAX )
2880 {
2881 SCIPerrorMessage("integral coefficient too big (mult = %" SCIP_LONGINT_FORMAT ", mult*value = %g, printingvalue = %" SCIP_LONGINT_FORMAT ") for printing in opb format\n",
2882 *mult, val, (SCIP_Longint)SCIPround(scip, val));
2883 }
2884
2885 written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2886 (SCIP_Longint)SCIPround(scip, val), multisymbol, negated ? "~" : "",
2887 strstr(SCIPvarGetName(negated ? SCIPvarGetNegatedVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
2888 if( written >= OPB_MAX_LINELEN )
2889 {
2890 SCIPerrorMessage("line bound reached\n");
2891 return SCIP_INVALIDDATA;
2892 }
2893 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2894
2895 /* print and-vars */
2896 for( a = nandvars[pos] - 2; a >= 0; --a )
2897 {
2898 negated = SCIPvarIsNegated(andvars[pos][a]);
2899
2900 written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "",
2901 strstr(SCIPvarGetName(negated ? SCIPvarGetNegatedVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2902 if( written >= OPB_MAX_LINELEN )
2903 {
2904 SCIPerrorMessage("line bound reached\n");
2905 return SCIP_INVALIDDATA;
2906 }
2907 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2908 }
2909 }
2910 else
2911 {
2912 written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2913 (SCIP_Longint)SCIPround(scip, val), multisymbol, negated ? "~" : "",
2914 strstr(SCIPvarGetName(negated ? SCIPvarGetNegatedVar(var) : var), "x"));
2915 if( written >= OPB_MAX_LINELEN )
2916 {
2917 SCIPerrorMessage("line bound reached\n");
2918 return SCIP_INVALIDDATA;
2919 }
2920 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2921 }
2922 }
2923
2924 /* print scaled left hand side */
2925 val = lhs * (*mult);
2926
2927 written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %s %+" SCIP_LONGINT_FORMAT ";\n", type,
2928 (SCIP_Longint)SCIPround(scip, val));
2929 if( written >= OPB_MAX_LINELEN )
2930 {
2931 SCIPerrorMessage("line bound reached\n");
2932 return SCIP_INVALIDDATA;
2933 }
2934 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2935
2936 writeBuffer(scip, file, linebuffer, &linecnt);
2937
2938 return SCIP_OKAY;
2939}
2940
2941/** prints given real non-linear constraint information in OPB format to file stream */
2942static
2944 SCIP*const scip, /**< SCIP data structure */
2945 FILE*const file, /**< output file (or NULL for standard output) */
2946 SCIP_VAR**const vars, /**< array of variables */
2947 SCIP_Real*const vals, /**< array of real coefficient values (or NULL if all coefficient values are 1) */
2948 int nvars, /**< number of variables */
2949 SCIP_Real lhs, /**< real left hand side */
2950 SCIP_Real rhs, /**< real right hand side */
2951 SCIP_VAR**const resvars, /**< array of resultant variables */
2952 int nresvars, /**< number of resultant variables */
2953 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2954 const int*const nandvars, /**< array of numbers of corresponding and-variables */
2955 SCIP_Longint weight, /**< if we found a soft constraint this is the integral weight, otherwise 0 */
2956 SCIP_Bool transformed, /**< transformed constraint? */
2957 const char*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2958 )
2959{
2960 SCIP_VAR** activevars;
2961 SCIP_Real* activevals;
2962 SCIP_Real activeconstant;
2963 SCIP_Longint mult;
2964 SCIP_RETCODE retcode;
2965 int varssize;
2966 int v;
2967
2968 assert(scip != NULL);
2969 assert(vars != NULL);
2970 assert(resvars != NULL);
2971 assert(nresvars >= 1);
2972 assert(andvars != NULL);
2973 assert(nandvars != NULL);
2974
2975 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2976 return SCIP_OKAY;
2977
2978 /* duplicate variable and value array */
2979 varssize = nvars;
2980 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, varssize) );
2981 if( vals != NULL )
2982 {
2983 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, varssize) );
2984 }
2985 else
2986 {
2987 SCIP_CALL( SCIPallocBufferArray(scip, &activevals, varssize) );
2988
2989 for( v = 0; v < nvars; ++v )
2990 activevals[v] = 1.0;
2991 }
2992
2993 /* retransform given variables to active variables */
2994 activeconstant = 0.0;
2995 SCIP_CALL( getActiveVariables(scip, &activevars, &activevals, &nvars, &varssize, &activeconstant, transformed) );
2996
2997 /* print row(s) in OPB format */
2998 retcode = SCIP_OKAY;
2999 if( SCIPisEQ(scip, lhs, rhs) )
3000 {
3001 assert(!SCIPisInfinity(scip, rhs));
3002 assert(retcode == SCIP_OKAY);
3003
3004 /* equality constraint */
3005 rhs -= activeconstant;
3006 mult = 1;
3007 retcode = printNLRow(scip, file, "=", activevars, activevals, nvars, rhs, resvars, nresvars, andvars, nandvars,
3008 weight, &mult, multisymbol);
3009 }
3010 else
3011 {
3012 if( !SCIPisInfinity(scip, -lhs) )
3013 {
3014 /* print inequality ">=" */
3015 lhs -= activeconstant;
3016 mult = 1;
3017 retcode = printNLRow(scip, file, ">=", activevars, activevals, nvars, lhs, resvars, nresvars, andvars, nandvars,
3018 weight, &mult, multisymbol);
3019 }
3020
3021 if( !SCIPisInfinity(scip, rhs) )
3022 {
3023 /* print inequality ">=" and multiplying all coefficients by -1 */
3024 rhs -= activeconstant;
3025 mult = -1;
3026 retcode = printNLRow(scip, file, ">=", activevars, activevals, nvars, rhs, resvars, nresvars, andvars, nandvars,
3027 weight, &mult, multisymbol);
3028 }
3029 }
3030
3031 /* free buffer arrays */
3032 SCIPfreeBufferArray(scip, &activevals);
3033 SCIPfreeBufferArray(scip, &activevars);
3034
3035 return retcode;
3036}
3037
3038/* print real row in OPB format to file stream */
3039static
3041 SCIP* scip, /**< SCIP data structure */
3042 FILE* file, /**< output file (or NULL for standard output) */
3043 const char* type, /**< row type ("=" or ">=") */
3044 SCIP_VAR** vars, /**< array of variables */
3045 SCIP_Real* vals, /**< array of real values */
3046 int nvars, /**< number of variables */
3047 SCIP_Real lhs, /**< real left hand side */
3048 SCIP_Longint weight, /**< if we found a soft constraint this is the integral weight, otherwise 0 */
3049 SCIP_Longint* mult, /**< integral multiplier for the coefficients */
3050 const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
3051 )
3052{
3053 SCIP_VAR* var;
3054 SCIP_Real val;
3055 SCIP_Bool negated;
3056 char buffer[OPB_MAX_LINELEN];
3057 char linebuffer[OPB_MAX_LINELEN + 1];
3058 int linecnt;
3059 int written;
3060 int v;
3061
3062 assert(scip != NULL);
3063 assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
3064 assert(vars != NULL || nvars == 0);
3065 assert(vals != NULL || nvars == 0);
3066 assert(mult != NULL);
3067
3068 clearBuffer(linebuffer, &linecnt);
3069
3070 /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution,
3071 * we can stop printing because it is an artificial constraint
3072 */
3073 if( nvars > 0 && strstr(SCIPvarGetName(vars[0]), INDICATORVARNAME) != NULL )
3074 return SCIP_OKAY;
3075
3076 /* check if all coefficients are integral; if not commentstart multiplier */
3077 for( v = 0; v < nvars; ++v )
3078 {
3079 while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
3080 {
3081 if( ABS(*mult) > ABS(*mult * 10) )
3082 {
3083 SCIPerrorMessage("failed to scale fractional coefficients to integrality because the required multiplier is too large\n");
3084 return SCIP_INVALIDDATA;
3085 }
3086 (*mult) *= 10;
3087 }
3088 }
3089
3090 while( !SCIPisIntegral(scip, lhs * (*mult)) )
3091 {
3092 if( ABS(*mult) > ABS(*mult * 10) )
3093 {
3094 SCIPerrorMessage("failed to scale fractional coefficients to integrality because the required multiplier is too large\n");
3095 return SCIP_INVALIDDATA;
3096 }
3097 (*mult) *= 10;
3098 }
3099
3100 /* print comment line if we have to multiply the coefficients to get integrals */
3101 if( ABS(*mult) != 1 )
3102 {
3103 SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n",
3104 ABS(*mult));
3105 }
3106
3107 /* if we have a soft constraint print the weight */
3108 if( weight != 0 )
3109 {
3110 written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "]", weight);
3111 if( written >= OPB_MAX_LINELEN )
3112 {
3113 SCIPerrorMessage("line bound reached\n");
3114 return SCIP_INVALIDDATA;
3115 }
3116 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3117 }
3118
3119 /* print coefficients */
3120 for( v = 0; v < nvars; ++v )
3121 {
3122 var = vars[v];
3123 val = vals[v] * (*mult);
3124 negated = SCIPvarIsNegated(var);
3125
3126 if( ABS(val) > (SCIP_Real)SCIP_LONGINT_MAX )
3127 {
3128 SCIPerrorMessage("integral coefficient too big (mult = %" SCIP_LONGINT_FORMAT ", mult*value = %g, printingvalue = %" SCIP_LONGINT_FORMAT ") for printing in opb format\n",
3129 *mult, val, (SCIP_Longint)SCIPround(scip, val));
3130 }
3131
3132 written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
3133 (SCIP_Longint)SCIPround(scip, val), multisymbol, negated ? "~" : "",
3134 strstr(SCIPvarGetName(negated ? SCIPvarGetNegatedVar(var) : var), "x"));
3135 if( written >= OPB_MAX_LINELEN )
3136 {
3137 SCIPerrorMessage("line bound reached\n");
3138 return SCIP_INVALIDDATA;
3139 }
3140 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3141 }
3142
3143 /* print scaled left hand side */
3144 val = lhs * (*mult);
3145
3146 written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %s %+" SCIP_LONGINT_FORMAT ";\n", type,
3147 (SCIP_Longint)SCIPround(scip, val));
3148 if( written >= OPB_MAX_LINELEN )
3149 {
3150 SCIPerrorMessage("line bound reached\n");
3151 return SCIP_INVALIDDATA;
3152 }
3153 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3154
3155 writeBuffer(scip, file, linebuffer, &linecnt);
3156
3157 return SCIP_OKAY;
3158}
3159
3160/* print exact row in OPB format to file stream */
3161static
3163 SCIP* scip, /**< SCIP data structure */
3164 FILE* file, /**< output file (or NULL for standard output) */
3165 const char* type, /**< row type ("=" or ">=") */
3166 SCIP_VAR** vars, /**< array of variables */
3167 SCIP_RATIONAL** vals, /**< array of exact values */
3168 int nvars, /**< number of variables */
3169 SCIP_RATIONAL* lhs, /**< exact left hand side */
3170 SCIP_RATIONAL* weight, /**< if we found a soft constraint this is the exact weight, otherwise 0 */
3171 SCIP_RATIONAL* mult, /**< exact multiplier for the coefficients */
3172 const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
3173 )
3174{
3175 SCIP_VAR* var;
3176 SCIP_RATIONAL* val;
3177 SCIP_Bool negated;
3178 char buffer[OPB_MAX_LINELEN];
3179 char linebuffer[OPB_MAX_LINELEN + 1];
3180 int linecnt;
3181 int written;
3182 int v;
3183
3184 assert(scip != NULL);
3185 assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
3186 assert(vars != NULL || nvars == 0);
3187 assert(vals != NULL || nvars == 0);
3188 assert(lhs != NULL);
3189 assert(weight != NULL);
3190 assert(mult != NULL);
3191
3192 clearBuffer(linebuffer, &linecnt);
3193
3194 /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution,
3195 * we can stop printing because it is an artificial constraint
3196 */
3197 if( nvars > 0 && strstr(SCIPvarGetName(vars[0]), INDICATORVARNAME) != NULL )
3198 return SCIP_OKAY;
3199
3200 /**@todo check if all values are integral; if not commentstart multiplier */
3201 /**@todo print comment line if we have to multiply the coefficients to get integrals */
3202
3203 /* if we have a soft constraint print the weight */
3204 if( !SCIPrationalIsZero(weight) )
3205 {
3206 written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[");
3207 if( !SCIPrationalIsNegative(weight) )
3208 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, "+");
3209 written += SCIPrationalToString(weight, buffer + written, OPB_MAX_LINELEN - written);
3210 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, "]");
3211 if( written >= OPB_MAX_LINELEN )
3212 {
3213 SCIPerrorMessage("line bound reached\n");
3214 return SCIP_INVALIDDATA;
3215 }
3216 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3217 }
3218
3220
3221 /* print coefficients */
3222 for( v = 0; v < nvars; ++v )
3223 {
3224 var = vars[v];
3225 SCIPrationalMult(val, vals[v], mult);
3226 negated = SCIPvarIsNegated(var);
3227
3228 written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, " ");
3229 if( !SCIPrationalIsNegative(val) )
3230 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, "+");
3231 written += SCIPrationalToString(val, buffer + written, OPB_MAX_LINELEN - written);
3232 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, "%s%s%s", multisymbol, negated ? "~" : "",
3233 strstr(SCIPvarGetName(negated ? SCIPvarGetNegatedVar(var) : var), "x"));
3234 if( written >= OPB_MAX_LINELEN )
3235 {
3237 SCIPerrorMessage("line bound reached\n");
3238 return SCIP_INVALIDDATA;
3239 }
3240 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3241 }
3242
3243 /* print scaled left hand side */
3244 SCIPrationalMult(val, lhs, mult);
3245
3246 written = SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %s ", type);
3247 if( !SCIPrationalIsNegative(val) )
3248 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, "+");
3249 written += SCIPrationalToString(val, buffer + written, OPB_MAX_LINELEN - written);
3250 written += SCIPsnprintf(buffer + written, OPB_MAX_LINELEN - written, ";\n");
3252 if( written >= OPB_MAX_LINELEN )
3253 {
3254 SCIPerrorMessage("line bound reached\n");
3255 return SCIP_INVALIDDATA;
3256 }
3257 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3258
3259 writeBuffer(scip, file, linebuffer, &linecnt);
3260
3261 return SCIP_OKAY;
3262}
3263
3264/** prints given real linear constraint information in OPB format to file stream */
3265static
3267 SCIP* scip, /**< SCIP data structure */
3268 FILE* file, /**< output file (or NULL for standard output) */
3269 SCIP_VAR** vars, /**< array of variables */
3270 SCIP_Real* vals, /**< array of real coefficient values (or NULL if all coefficient values are 1) */
3271 int nvars, /**< number of variables */
3272 SCIP_Real lhs, /**< real left hand side */
3273 SCIP_Real rhs, /**< real right hand side */
3274 SCIP_Longint weight, /**< if we found a soft constraint this is the integral weight, otherwise 0 */
3275 SCIP_Bool transformed, /**< transformed constraint? */
3276 const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
3277 )
3278{
3279 SCIP_VAR** activevars = NULL;
3280 SCIP_Real* activevals = NULL;
3281 SCIP_Real activeconstant;
3282 SCIP_Longint mult;
3283 SCIP_RETCODE retcode;
3284 int varssize;
3285 int v;
3286
3287 assert(scip != NULL);
3288 assert(vars != NULL || nvars == 0);
3289
3290 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
3291 return SCIP_OKAY;
3292
3293 /* duplicate variable and value array */
3294 varssize = nvars;
3295 activeconstant = 0.0;
3296 if( nvars >= 1 )
3297 {
3298 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, varssize) );
3299 if( vals != NULL )
3300 {
3301 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, varssize) );
3302 }
3303 else
3304 {
3305 SCIP_CALL( SCIPallocBufferArray(scip, &activevals, varssize) );
3306
3307 for( v = 0; v < nvars; ++v )
3308 activevals[v] = 1.0;
3309 }
3310
3311 /* retransform given variables to active variables */
3312 SCIP_CALL( getActiveVariables(scip, &activevars, &activevals, &nvars, &varssize, &activeconstant, transformed) );
3313 }
3314
3315 /* print row(s) in OPB format */
3316 retcode = SCIP_OKAY;
3317 if( SCIPisEQ(scip, lhs, rhs) )
3318 {
3319 assert(!SCIPisInfinity(scip, rhs));
3320 assert(retcode == SCIP_OKAY);
3321
3322 /* equality constraint */
3323 rhs -= activeconstant;
3324 mult = 1;
3325 retcode = printRow(scip, file, "=", activevars, activevals, nvars, rhs, weight, &mult, multisymbol);
3326 }
3327 else
3328 {
3329 if( !SCIPisInfinity(scip, -lhs) )
3330 {
3331 assert(retcode == SCIP_OKAY);
3332
3333 /* print inequality ">=" */
3334 lhs -= activeconstant;
3335 mult = 1;
3336 retcode = printRow(scip, file, ">=", activevars, activevals, nvars, lhs, weight, &mult, multisymbol);
3337 }
3338
3339 if( retcode == SCIP_OKAY && !SCIPisInfinity(scip, rhs) )
3340 {
3341 /* print inequality ">=" and multiplying all coefficients by -1 */
3342 rhs -= activeconstant;
3343 mult = -1;
3344 retcode = printRow(scip, file, ">=", activevars, activevals, nvars, rhs, weight, &mult, multisymbol);
3345 }
3346 }
3347
3348 /* free buffer arrays */
3349 SCIPfreeBufferArrayNull(scip, &activevals);
3350 SCIPfreeBufferArrayNull(scip, &activevars);
3351
3352 return retcode;
3353}
3354
3355/** prints given exact linear constraint information in OPB format to file stream */
3356static
3358 SCIP* scip, /**< SCIP data structure */
3359 FILE* file, /**< output file (or NULL for standard output) */
3360 SCIP_VAR** vars, /**< array of variables */
3361 SCIP_RATIONAL** vals, /**< array of exact coefficient values (or NULL if all coefficient values are 1) */
3362 int nvars, /**< number of variables */
3363 SCIP_RATIONAL* lhs, /**< exact left hand side */
3364 SCIP_RATIONAL* rhs, /**< exact right hand side */
3365 SCIP_RATIONAL* weight, /**< if we found a soft constraint this is the exact weight, otherwise 0 */
3366 SCIP_Bool transformed, /**< transformed constraint? */
3367 const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
3368 )
3369{
3370 SCIP_VAR** activevars = NULL;
3371 SCIP_RATIONAL** activevals = NULL;
3372 SCIP_RATIONAL* activeconstant;
3373 SCIP_RATIONAL* activeside;
3374 SCIP_RATIONAL* mult;
3375 SCIP_RETCODE retcode;
3376 int varssize;
3377 int v;
3378
3379 assert(scip != NULL);
3380 assert(vars != NULL || nvars == 0);
3381 assert(lhs != NULL);
3382 assert(rhs != NULL);
3383 assert(weight != NULL);
3384
3386 return SCIP_OKAY;
3387
3388 SCIP_CALL( SCIPrationalCreateBuffer(SCIPbuffer(scip), &activeconstant) );
3391
3392 /* duplicate variable and value array */
3393 varssize = nvars;
3394 SCIPrationalSetReal(activeconstant, 0.0);
3395 if( nvars >= 1 )
3396 {
3397 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, varssize) );
3398 if( vals != NULL )
3399 {
3400 SCIP_CALL( SCIPrationalCopyBufferArray(SCIPbuffer(scip), &activevals, vals, varssize) );
3401 }
3402 else
3403 {
3404 SCIP_CALL( SCIPrationalCreateBufferArray(SCIPbuffer(scip), &activevals, varssize) );
3405
3406 for( v = 0; v < nvars; ++v )
3407 SCIPrationalSetReal(activevals[v], 1.0);
3408 }
3409
3410 /* retransform given variables to active variables */
3411 SCIP_CALL( getActiveVariablesExact(scip, &activevars, &activevals, &nvars, &varssize, activeconstant, transformed) );
3412 }
3413
3414 /* print row(s) in OPB format */
3415 retcode = SCIP_OKAY;
3416 if( SCIPrationalIsEQ(lhs, rhs) )
3417 {
3418 assert(!SCIPrationalIsInfinity(rhs));
3419 assert(retcode == SCIP_OKAY);
3420
3421 /* equality constraint */
3422 SCIPrationalDiff(activeside, rhs, activeconstant);
3423 SCIPrationalSetReal(mult, 1.0);
3424 retcode = printRowExact(scip, file, "=", activevars, activevals, nvars, activeside, weight, mult, multisymbol);
3425 }
3426 else
3427 {
3428 if( !SCIPrationalIsNegInfinity(lhs) )
3429 {
3430 assert(retcode == SCIP_OKAY);
3431
3432 /* print inequality ">=" */
3433 SCIPrationalDiff(activeside, lhs, activeconstant);
3434 SCIPrationalSetReal(mult, 1.0);
3435 retcode = printRowExact(scip, file, ">=", activevars, activevals, nvars, activeside, weight, mult, multisymbol);
3436 }
3437
3438 if( retcode == SCIP_OKAY && !SCIPrationalIsInfinity(rhs) )
3439 {
3440 /* print inequality ">=" and multiplying all coefficients by -1 */
3441 SCIPrationalDiff(activeside, rhs, activeconstant);
3442 SCIPrationalSetReal(mult, -1.0);
3443 retcode = printRowExact(scip, file, ">=", activevars, activevals, nvars, activeside, weight, mult, multisymbol);
3444 }
3445 }
3446
3447 if( activevals != NULL )
3448 SCIPrationalFreeBufferArray(SCIPbuffer(scip), &activevals, varssize);
3449 SCIPfreeBufferArrayNull(scip, &activevars);
3451 SCIPrationalFreeBuffer(SCIPbuffer(scip), &activeside);
3452 SCIPrationalFreeBuffer(SCIPbuffer(scip), &activeconstant);
3453
3454 return retcode;
3455}
3456
3457/** determine total number of split linear and indicator constraints */
3458static
3460 SCIP*const scip, /**< SCIP data structure */
3461 SCIP_CONS**const conss, /**< array with constraints of the problem */
3462 int const nconss, /**< number of constraints in the problem */
3463 int* nlinearconss, /**< pointer to store the total number of split linear constraints */
3464 int* nindicatorconss /**< pointer to store the total number of indicator constraints */
3465 )
3466{
3467 SCIP_CONSHDLR* conshdlr;
3468 const char* conshdlrname;
3469 SCIP_CONS* cons;
3470 int c;
3471
3472 assert(scip != NULL);
3473 assert(conss != NULL || nconss == 0);
3474 assert(nlinearconss != NULL);
3475 assert(nindicatorconss != NULL);
3476
3477 *nlinearconss = 0;
3478 *nindicatorconss = 0;
3479
3480 /* loop over all constraints */
3481 for( c = 0; c < nconss; ++c )
3482 {
3483 SCIP_Bool success;
3484
3485 cons = conss[c];
3486 assert(cons != NULL);
3487 conshdlr = SCIPconsGetHdlr(cons); /*lint !e613*/
3488 assert(conshdlr != NULL);
3489
3490 conshdlrname = SCIPconshdlrGetName(conshdlr);
3491
3492 if( strcmp(conshdlrname, "and") == 0 )
3493 continue;
3494
3495 if( strcmp(conshdlrname, "pseudoboolean") == 0 )
3496 {
3497 if( SCIPgetIndVarPseudoboolean(scip, cons) != NULL )
3498 ++(*nindicatorconss);
3499
3500 continue;
3501 }
3502
3503 if( strcmp(conshdlrname, "indicator") == 0 )
3504 {
3505 ++(*nindicatorconss);
3506
3507 continue;
3508 }
3509
3510 if( SCIPisExact(scip) )
3511 {
3512 SCIP_RATIONAL* lhs;
3513 SCIP_RATIONAL* rhs;
3514
3515 lhs = SCIPconsGetLhsExact(scip, cons, &success);
3516
3517 if( !success )
3518 continue;
3519
3520 rhs = SCIPconsGetRhsExact(scip, cons, &success);
3521
3522 if( !success )
3523 continue;
3524
3525 if( SCIPrationalIsEQ(lhs, rhs) )
3526 ++(*nlinearconss);
3527 else
3528 {
3529 if( !SCIPrationalIsNegInfinity(lhs) )
3530 ++(*nlinearconss);
3531
3532 if( !SCIPrationalIsInfinity(rhs) )
3533 ++(*nlinearconss);
3534 }
3535 }
3536 else
3537 {
3538 SCIP_Real lhs;
3539 SCIP_Real rhs;
3540
3541 lhs = SCIPconsGetLhs(scip, cons, &success);
3542
3543 if( !success )
3544 continue;
3545
3546 rhs = SCIPconsGetRhs(scip, cons, &success);
3547
3548 if( !success )
3549 continue;
3550
3551 if( SCIPisEQ(scip, lhs, rhs) )
3552 ++(*nlinearconss);
3553 else
3554 {
3555 if( !SCIPisInfinity(scip, -lhs) )
3556 ++(*nlinearconss);
3557
3558 if( !SCIPisInfinity(scip, rhs) )
3559 ++(*nlinearconss);
3560 }
3561 }
3562 }
3563}
3564
3565/** write constraints */
3566static
3568 SCIP*const scip, /**< SCIP data structure */
3569 FILE*const file, /**< output file, or NULL if standard output should be used */
3570 SCIP_CONS**const conss, /**< array with constraints of the problem */
3571 int const nconss, /**< number of constraints in the problem */
3572 SCIP_VAR**const vars, /**< array with active (binary) variables */
3573 int const nvars, /**< number of active variables in the problem */
3574 SCIP_VAR** const resvars, /**< array of resultant variables */
3575 int const nresvars, /**< number of resultant variables */
3576 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3577 int const*const nandvars, /**< array of numbers of corresponding and-variables */
3578 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3579 SCIP_Bool const existandconshdlr, /**< does and-constrainthandler exist? */
3580 SCIP_Bool const existands, /**< does some and-constraints exist? */
3581 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3582 )
3583{
3584 SCIP_CONSHDLR* conshdlr;
3585 const char* conshdlrname;
3586 SCIP_CONS* cons = NULL;
3587 SCIP_VAR** consvars;
3588 SCIP_Real* consvals;
3589 SCIP_Bool topcostfound = FALSE;
3590 SCIP_RETCODE retcode = SCIP_OKAY;
3591 int nconsvars;
3592 int v, c;
3593 SCIP_HASHMAP* linconssofindicatorsmap = NULL;
3594 SCIP_HASHMAP* linconssofpbsmap = NULL;
3595 SCIP_RATIONAL* weightexact = NULL;
3596 SCIP_Longint weight = 0LL;
3597
3598 assert(scip != NULL);
3599 assert(file != NULL);
3600 assert(conss != NULL || nconss == 0);
3601 assert(vars != NULL || nvars == 0);
3602 assert(resvars != NULL || nresvars == 0);
3603 assert(andvars != NULL || nandvars == 0);
3604 assert(multisymbol != NULL);
3605
3606 if( SCIPisExact(scip) )
3607 {
3609 }
3610
3611 if( transformed )
3612 {
3613 conshdlr = SCIPfindConshdlr(scip, "indicator");
3614
3615 /* find artificial linear constraints which correspond to indicator constraints to avoid double printing */
3616 if( conshdlr != NULL )
3617 {
3618 SCIP_CONS** indconss;
3619 int nindconss;
3620
3621 indconss = SCIPconshdlrGetConss(conshdlr);
3622 nindconss = SCIPconshdlrGetNConss(conshdlr);
3623 assert(indconss != NULL || nindconss == 0);
3624
3625 if( nindconss > 0 )
3626 {
3627 SCIP_CONS* lincons;
3628
3629 /* create the linear constraint of indicator constraints hash map */
3630 SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nindconss) );
3631 assert(indconss != NULL);
3632
3633 for( c = 0; c < nindconss; ++c )
3634 {
3635 assert(indconss[c] != NULL);
3636 lincons = SCIPgetLinearConsIndicator(indconss[c]);
3637 assert(lincons != NULL);
3638
3639 /* insert constraints into mapping */
3640 SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)indconss[c]) );
3641 }
3642 }
3643 }
3644
3645 conshdlr = SCIPfindConshdlr(scip, "pseudoboolean");
3646
3647 /* find artifical linear constraints which correspond to indicator constraints to avoid double printing */
3648 if( conshdlr != NULL )
3649 {
3650 SCIP_CONS** pbconss;
3651 int npbconss;
3652
3653 pbconss = SCIPconshdlrGetConss(conshdlr);
3654 npbconss = SCIPconshdlrGetNConss(conshdlr);
3655 assert(pbconss != NULL || npbconss == 0);
3656
3657 if( npbconss > 0 )
3658 {
3659 SCIP_CONS* lincons;
3660
3661 /* create the linear constraint of indicator constraints hash map */
3662 SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), npbconss) );
3663
3664 for( c = 0; c < npbconss; ++c )
3665 {
3666 assert(pbconss[c] != NULL); /*lint !e613*/
3667 lincons = SCIPgetLinearConsPseudoboolean(scip, pbconss[c]); /*lint !e613*/
3668 assert(lincons != NULL);
3669
3670 /* insert constraints into mapping */
3671 SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)pbconss[c]) );
3672 }
3673 }
3674 }
3675 }
3676 /* in original space we cannot ask the constraint handler for its constraints, therefore we have to loop over all
3677 * original constraints to check for artificial linear constraints
3678 */
3679 else
3680 {
3681 SCIP_CONS* lincons;
3682 SCIP_Bool pbhashmapcreated = FALSE;
3683 SCIP_Bool indhashmapcreated = FALSE;
3684
3685 /* loop over all constraint for printing */
3686 for( c = 0; c < nconss; ++c )
3687 {
3688 conshdlr = SCIPconsGetHdlr(conss[c]); /*lint !e613*/
3689 assert(conshdlr != NULL);
3690
3691 conshdlrname = SCIPconshdlrGetName(conshdlr);
3692
3693 if( strcmp(conshdlrname, "pseudoboolean") == 0 )
3694 {
3695 if( !pbhashmapcreated )
3696 {
3697 /* create the linear constraint of indicator constraints hash map */
3698 SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), nconss) );
3699 pbhashmapcreated = TRUE;
3700 }
3701
3702 lincons = SCIPgetLinearConsPseudoboolean(scip, conss[c]); /*lint !e613*/
3703 assert(lincons != NULL);
3704
3705 /* insert constraints into mapping */
3706 SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)conss[c]) );
3707 }
3708 else if( strcmp(conshdlrname, "indicator") == 0 )
3709 {
3710 if( !indhashmapcreated )
3711 {
3712 /* create the linear constraint of indicator constraints hash map */
3713 SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nconss) );
3714 indhashmapcreated = TRUE;
3715 }
3716
3717 lincons = SCIPgetLinearConsIndicator(conss[c]); /*lint !e613*/
3718 assert(lincons != NULL);
3719
3720 /* insert constraint into mapping */
3721 SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)conss[c]) );
3722 }
3723 }
3724 }
3725
3726 /* loop over all constraint for printing */
3727 for( c = 0; c < nconss && retcode == SCIP_OKAY; ++c )
3728 {
3729 SCIP_CONS* artcons = NULL;
3730 SCIP_VAR* indvar = NULL;
3731
3732 cons = conss[c]; /*lint !e613 */
3733 assert(cons != NULL);
3734
3735 conshdlr = SCIPconsGetHdlr(cons);
3736 assert(conshdlr != NULL);
3737
3738 conshdlrname = SCIPconshdlrGetName(conshdlr);
3739 assert(transformed == SCIPconsIsTransformed(cons));
3740
3741 /* in case the transformed problem is written only constraints are posted which are enabled in the current node */
3742 assert(!transformed || SCIPconsIsEnabled(cons));
3743
3744 if( linconssofindicatorsmap != NULL )
3745 {
3746 artcons = (SCIP_CONS*)SCIPhashmapGetImage(linconssofindicatorsmap, (void*)cons);
3747
3748 if( artcons != NULL )
3749 continue;
3750 }
3751
3752 if( weightexact != NULL )
3753 SCIPrationalSetReal(weightexact, 0.0);
3754 else
3755 weight = 0LL;
3756
3757 if( linconssofpbsmap != NULL )
3758 {
3759 artcons = (SCIP_CONS*)SCIPhashmapGetImage(linconssofpbsmap, (void*)cons);
3760
3761 if( artcons != NULL )
3762 {
3763 indvar = SCIPgetIndVarPseudoboolean(scip, artcons);
3764
3765 if( indvar != NULL )
3766 {
3767 SCIP_Bool isweightzero;
3768
3769 if( weightexact != NULL )
3770 {
3771 SCIPrationalSetRational(weightexact, SCIPvarGetObjExact(indvar));
3772 isweightzero = SCIPrationalIsZero(weightexact);
3773 }
3774 else
3775 {
3776 weight = (SCIP_Longint)SCIPround(scip, SCIPvarGetObj(indvar));
3777 isweightzero = (weight == 0LL);
3778 }
3779
3780 if( isweightzero )
3781 {
3782 /* pseudoboolean constraint not printed because weight of this soft constraint is zero */
3783 SCIPinfoMessage(scip, file, "* ");
3784 SCIP_CALL( SCIPprintCons(scip, artcons, file) );
3785 SCIPinfoMessage(scip, file, ";\n");
3786 continue;
3787 }
3788 }
3789 }
3790 }
3791
3792 /* if we found the topcost linear inequality which gives us the maximal cost which could be violated,
3793 * we can stop printing because it is an artificial constraint
3794 */
3795 if( strstr(SCIPconsGetName(cons), TOPCOSTCONSNAME) != NULL )
3796 {
3797 if( topcostfound )
3798 SCIPwarningMessage(scip, "further topcost constraint <%s> will be considered as hard constraint\n", SCIPconsGetName(cons));
3799 else
3800 {
3801 topcostfound = TRUE;
3802
3803 continue;
3804 }
3805 }
3806
3807 if( strcmp(conshdlrname, "linear") == 0 )
3808 {
3809 if( existands )
3810 {
3811 retcode = printNonLinearCons(scip, file,
3813 SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), resvars, nresvars, andvars, nandvars,
3814 weight, transformed, multisymbol);
3815 }
3816 else
3817 {
3818 retcode = printLinearCons(scip, file,
3820 SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), weight, transformed, multisymbol);
3821 }
3822 }
3823 else if( strcmp(conshdlrname, "setppc") == 0 )
3824 {
3825 consvars = SCIPgetVarsSetppc(scip, cons);
3826 nconsvars = SCIPgetNVarsSetppc(scip, cons);
3827
3828 switch( SCIPgetTypeSetppc(scip, cons) )
3829 {
3831 if( existands )
3832 {
3833 retcode = printNonLinearCons(scip, file, consvars, NULL, nconsvars, 1.0, 1.0, resvars, nresvars,
3834 andvars, nandvars, weight, transformed, multisymbol);
3835 }
3836 else
3837 {
3838 retcode = printLinearCons(scip, file,
3839 consvars, NULL, nconsvars, 1.0, 1.0, weight, transformed, multisymbol);
3840 }
3841 break;
3843 if( existands )
3844 {
3845 retcode = printNonLinearCons(scip, file,
3846 consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, resvars, nresvars, andvars, nandvars,
3847 weight, transformed, multisymbol);
3848 }
3849 else
3850 {
3851 retcode = printLinearCons(scip, file,
3852 consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, weight, transformed, multisymbol);
3853 }
3854 break;
3856 if( existands )
3857 {
3858 retcode = printNonLinearCons(scip, file,
3859 consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), resvars, nresvars, andvars, nandvars,
3860 weight, transformed, multisymbol);
3861 }
3862 else
3863 {
3864 retcode = printLinearCons(scip, file,
3865 consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), weight, transformed, multisymbol);
3866 }
3867 break;
3868 }
3869 }
3870 else if( strcmp(conshdlrname, "logicor") == 0 )
3871 {
3872 if( existands )
3873 {
3874 retcode = printNonLinearCons(scip, file,
3876 resvars, nresvars, andvars, nandvars, weight, transformed, multisymbol);
3877 }
3878 else
3879 {
3880 retcode = printLinearCons(scip, file,
3882 1.0, SCIPinfinity(scip), weight, transformed, multisymbol);
3883 }
3884 }
3885 else if( strcmp(conshdlrname, "knapsack") == 0 )
3886 {
3887 SCIP_Longint* weights;
3888
3889 consvars = SCIPgetVarsKnapsack(scip, cons);
3890 nconsvars = SCIPgetNVarsKnapsack(scip, cons);
3891
3892 /* copy Longint array to SCIP_Real array */
3893 weights = SCIPgetWeightsKnapsack(scip, cons);
3894 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
3895 for( v = 0; v < nconsvars; ++v )
3896 consvals[v] = (SCIP_Real)weights[v];
3897
3898 if( existands )
3899 {
3900 retcode = printNonLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip),
3901 (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), resvars, nresvars, andvars, nandvars,
3902 weight, transformed, multisymbol);
3903 }
3904 else
3905 {
3906 retcode = printLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip),
3907 (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), weight, transformed, multisymbol);
3908 }
3909
3910 SCIPfreeBufferArray(scip, &consvals);
3911 }
3912 else if( strcmp(conshdlrname, "varbound") == 0 )
3913 {
3914 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
3915 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
3916
3917 consvars[0] = SCIPgetVarVarbound(scip, cons);
3918 consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
3919
3920 consvals[0] = 1.0;
3921 consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
3922
3923 if( existands )
3924 {
3925 retcode = printNonLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons),
3926 SCIPgetRhsVarbound(scip, cons), resvars, nresvars, andvars, nandvars, weight, transformed, multisymbol);
3927 }
3928 else
3929 {
3930 retcode = printLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons),
3931 SCIPgetRhsVarbound(scip, cons), weight, transformed, multisymbol);
3932 }
3933
3934 SCIPfreeBufferArray(scip, &consvals);
3935 SCIPfreeBufferArray(scip, &consvars);
3936 }
3937 else if( strcmp(conshdlrname, "exactlinear") == 0 )
3938 {
3939 assert(SCIPisExact(scip));
3940
3941 /**@todo add printNonLinearConsExact() for printing exact pseudoboolean */
3942 if( existands )
3943 retcode = SCIP_INVALIDDATA;
3944 else
3945 {
3946 retcode = printLinearConsExact(scip, file,
3949 SCIPgetRhsExactLinear(scip, cons), weightexact, transformed, multisymbol);
3950 }
3951 }
3952 else if( strcmp(conshdlrname, "indicator") == 0 )
3953 {
3954 SCIP_CONS* lincons;
3955 SCIP_VAR* slackvar;
3956
3957 /* get artificial binary indicator variables */
3958 indvar = SCIPgetBinaryVarIndicator(cons);
3959 assert(indvar != NULL);
3960
3962 {
3963 indvar = SCIPvarGetNegationVar(indvar);
3964 assert(indvar != NULL);
3966
3967 /* get the soft cost of this constraint */
3968 weight = (SCIP_Longint)SCIPround(scip, SCIPvarGetObj(indvar));
3969 }
3970 else
3971 {
3973
3974 /* get the soft cost of this constraint */
3975 weight = (SCIP_Longint)SCIPround(scip, -SCIPvarGetObj(indvar));
3976 }
3977
3978 /* get artificial slack variable */
3979 slackvar = SCIPgetSlackVarIndicator(cons);
3980 assert(slackvar != NULL);
3981
3982 /* only need to print indicator constraints with weights on their indicator variable */
3983 if( weight != 0 )
3984 {
3985 SCIP_VAR** scipvarslinear;
3986 SCIP_Real* scipvalslinear;
3987 SCIP_Bool cont;
3988 int nonbinarypos;
3989
3990 lincons = SCIPgetLinearConsIndicator(cons);
3991 assert(lincons != NULL);
3992
3993 nconsvars = SCIPgetNVarsLinear(scip, lincons);
3994 scipvarslinear = SCIPgetVarsLinear(scip, lincons);
3995 scipvalslinear = SCIPgetValsLinear(scip, lincons);
3996
3997 /* allocate temporary memory */
3998 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, scipvarslinear, nconsvars) );
3999 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, scipvalslinear, nconsvars) );
4000
4001 nonbinarypos = -1;
4002 cont = FALSE;
4003
4004 /* find non-binary variable */
4005 for( v = 0; v < nconsvars; ++v )
4006 {
4007 if( SCIPvarGetType(consvars[v]) == SCIP_VARTYPE_CONTINUOUS )
4008 {
4009 if( consvars[v] == slackvar )
4010 {
4011 assert(nonbinarypos == -1);
4012 nonbinarypos = v;
4013 }
4014 else
4015 {
4016 SCIPwarningMessage(scip, "cannot print linear constraint <%s> of indicator constraint <%s> because it has more than one non-binary variable\n", SCIPconsGetName(lincons), SCIPconsGetName(cons) );
4017 SCIPinfoMessage(scip, file, "* ");
4018 SCIP_CALL( SCIPprintCons(scip, cons, file) );
4019 SCIPinfoMessage(scip, file, ";\n");
4020 cont = TRUE;
4021 break;
4022 }
4023 }
4024 }
4025
4026 /* if we have not found any non-binary variable we do not print the constraint, maybe we should ??? */
4027 if( nonbinarypos == -1 )
4028 {
4029 SCIPwarningMessage(scip, "cannot print linear constraint <%s> of indicator constraint <%s> because it has no slack variable\n", SCIPconsGetName(lincons), SCIPconsGetName(cons) );
4030 SCIPinfoMessage(scip, file, "* ");
4031 SCIP_CALL( SCIPprintCons(scip, cons, file) );
4032 SCIPinfoMessage(scip, file, ";\n");
4033
4034 /* free temporary memory */
4035 SCIPfreeBufferArray(scip, &consvals);
4036 SCIPfreeBufferArray(scip, &consvars);
4037 continue;
4038 }
4039
4040 /* if the constraint has more than two non-binary variables is not printable and we go to the next */
4041 if( cont )
4042 {
4043 /* free temporary memory */
4044 SCIPfreeBufferArray(scip, &consvals);
4045 SCIPfreeBufferArray(scip, &consvars);
4046 continue;
4047 }
4048
4049 assert(0 <= nonbinarypos && nonbinarypos < nconsvars);
4050
4051 /* remove slackvariable in linear constraint for printing */
4052 --nconsvars;
4053 consvars[nonbinarypos] = consvars[nconsvars];
4054 consvals[nonbinarypos] = consvals[nconsvars];
4055
4056 if( existands )
4057 {
4058 retcode = printNonLinearCons(scip, file,
4059 consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
4060 resvars, nresvars, andvars, nandvars,
4061 weight, transformed, multisymbol);
4062 }
4063 else
4064 {
4065 retcode = printLinearCons(scip, file,
4066 consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
4067 weight, transformed, multisymbol);
4068 }
4069
4070 /* free temporary memory */
4071 SCIPfreeBufferArray(scip, &consvals);
4072 SCIPfreeBufferArray(scip, &consvars);
4073 }
4074 else
4075 {
4076 SCIPwarningMessage(scip, "indicator constraint <%s> will not be printed because the indicator variable has no objective value(= weight of this soft constraint)\n", SCIPconsGetName(cons) );
4077 SCIPinfoMessage(scip, file, "* ");
4078 SCIP_CALL( SCIPprintCons(scip, cons, file) );
4079 SCIPinfoMessage(scip, file, ";\n");
4080 }
4081 }
4082 else if( strcmp(conshdlrname, "and") == 0 )
4083 {
4084 /* all resultants of the and constraint will be replaced by all corresponding variables of this constraint,
4085 * so no and-constraint will be printed directly
4086 */
4087 assert(existandconshdlr);
4088 }
4089 else if( strcmp(conshdlrname, "pseudoboolean") == 0 )
4090 {
4091 /* all and-resultants in linear constraints will be replaced by the corresponding variable products,
4092 * so no pseudoboolean constraint will be printed directly
4093 */
4094 assert(existands);
4095 }
4096 else
4097 {
4098 SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
4099 SCIPinfoMessage(scip, file, "* ");
4100 SCIP_CALL( SCIPprintCons(scip, cons, file) );
4101 SCIPinfoMessage(scip, file, ";\n");
4102 }
4103 }
4104
4105 if( retcode == SCIP_INVALIDDATA )
4106 {
4107 assert(cons != NULL);
4108
4109 SCIPerrorMessage("Cannot print constraint %s with non-integral coefficient or sides in opb-format\n",
4110 SCIPconsGetName(cons));
4111 SCIP_CALL( SCIPprintCons(scip, cons, stderr) );
4112 SCIPinfoMessage(scip, file, ";\n");
4113 }
4114
4115 if( linconssofpbsmap != NULL )
4116 SCIPhashmapFree(&linconssofpbsmap);
4117 if( linconssofindicatorsmap != NULL )
4118 SCIPhashmapFree(&linconssofindicatorsmap);
4119 if( weightexact != NULL )
4120 SCIPrationalFreeBuffer(SCIPbuffer(scip), &weightexact);
4121
4122 return retcode;
4123}
4124
4125/* write fixed variables (unless already done because they are an and resultant or and variable) */
4126static
4128 SCIP*const scip, /**< SCIP data structure */
4129 FILE*const file, /**< output file, or NULL if standard output should be used */
4130 SCIP_VAR** vars, /**< array with active (binary) variables */
4131 int nvars, /**< number of active variables in the problem */
4132 SCIP_HASHTABLE*const printedfixing, /**< hashmap to store if a fixed variable was already printed */
4133 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
4134 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
4135 )
4136{
4137 char linebuffer[OPB_MAX_LINELEN+1];
4138 char buffer[OPB_MAX_LINELEN];
4139 int linecnt;
4140 int v;
4141
4142 assert(scip != NULL);
4143 assert(file != NULL);
4144 assert(vars != NULL || nvars == 0);
4145 assert(printedfixing != NULL);
4146 assert(multisymbol != NULL);
4147
4148 clearBuffer(linebuffer, &linecnt);
4149
4150 /* print variables which are fixed */
4151 for( v = 0; v < nvars; ++v )
4152 {
4153 SCIP_VAR* var;
4154 SCIP_Real lb;
4155 SCIP_Real ub;
4156 SCIP_Bool neg = FALSE;
4157
4158 assert( vars != NULL );
4159 var = vars[v];
4160
4161 if( transformed )
4162 {
4163 /* in case the transformed is written only local bounds are posted which are valid in the current node */
4164 lb = SCIPvarGetLbLocal(var);
4165 ub = SCIPvarGetUbLocal(var);
4166 }
4167 else
4168 {
4169 lb = SCIPvarGetLbOriginal(var);
4170 ub = SCIPvarGetUbOriginal(var);
4171 }
4172 assert(lb > -0.5 && ub < 1.5);
4173 assert(SCIPisFeasIntegral(scip, lb));
4174 assert(SCIPisFeasIntegral(scip, ub));
4175
4176 /* print fixed and-resultants */
4177 if( lb > 0.5 || ub < 0.5 )
4178 {
4179 if( transformed ) {
4180 SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &var, &neg) );
4181 }
4182
4183 if( SCIPhashtableExists(printedfixing, (void*)var) )
4184 continue;
4185
4186 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %.15g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
4187 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4188
4189 /* add variable to the hashmap */
4190 SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
4191 }
4192 }
4193
4194 writeBuffer(scip, file, linebuffer, &linecnt);
4195
4196 return SCIP_OKAY;
4197}
4198
4199/* write and constraints of inactive but relevant and-resultants and and variables which are fixed to one */
4200static
4202 SCIP*const scip, /**< SCIP data structure */
4203 FILE*const file, /**< output file, or NULL if standard output should be used */
4204 SCIP_VAR**const resvars, /**< array of resultant variables */
4205 int const nresvars, /**< number of resultant variables */
4206 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
4207 int const*const nandvars, /**< array of numbers of corresponding and-variables */
4208 SCIP_HASHTABLE*const printedfixing, /**< hashmap to store if a fixed variable was already printed */
4209 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
4210 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
4211 )
4212{
4213 SCIP_VAR* resvar;
4214 SCIP_Longint rhslhs;
4215 char linebuffer[OPB_MAX_LINELEN+1];
4216 char buffer[OPB_MAX_LINELEN];
4217 int linecnt;
4218 int r, v;
4219
4220 assert(scip != NULL);
4221 assert(file != NULL);
4222 assert(resvars != NULL || nresvars == 0);
4223 assert(nandvars != NULL || nresvars == 0);
4224 assert(andvars != NULL || nandvars == NULL);
4225 assert(multisymbol != NULL);
4226
4227 clearBuffer(linebuffer, &linecnt);
4228
4229 /* print and-variables which are fixed */
4230 /* @todo remove this block here and the hashtable and let writeOpbFixedVars() do the job? */
4231 for( r = nresvars - 1; r >= 0; --r )
4232 {
4233 SCIP_VAR* var;
4234 SCIP_Bool neg;
4235 SCIP_Real lb;
4236 SCIP_Real ub;
4237
4238 assert( resvars != NULL );
4239 resvar = resvars[r];
4240
4241 if( transformed )
4242 {
4243 /* in case the transformed is written only local bounds are posted which are valid in the current node */
4244 lb = SCIPvarGetLbLocal(resvar);
4245 ub = SCIPvarGetUbLocal(resvar);
4246 }
4247 else
4248 {
4249 lb = SCIPvarGetLbOriginal(resvar);
4250 ub = SCIPvarGetUbOriginal(resvar);
4251 }
4252
4253 /* print fixed and-resultants */
4254 if( lb > 0.5 || ub < 0.5 )
4255 {
4256 /* coverity[copy_paste_error] */
4257 SCIP_CALL( SCIPgetBinvarRepresentative(scip, resvar, &var, &neg) );
4258
4259 assert(SCIPisFeasIntegral(scip, lb));
4260 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " +1%s%s%s = %.15g;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
4261 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4262
4263 /* add variable to the hashmap */
4264 SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
4265 }
4266
4267 assert( andvars != NULL && nandvars != NULL );
4268 assert( andvars[r] != NULL || nandvars[r] == 0 );
4269
4270 /* print fixed and-variables */
4271 for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
4272 {
4273 assert( andvars[r] != NULL );
4274 assert( andvars[r][v] != NULL );
4275
4276 if( transformed )
4277 {
4278 /* in case the transformed is written only local bounds are posted which are valid in the current node */
4279 lb = SCIPvarGetLbLocal(andvars[r][v]);
4280 ub = SCIPvarGetUbLocal(andvars[r][v]);
4281 }
4282 else
4283 {
4284 lb = SCIPvarGetLbOriginal(andvars[r][v]);
4285 ub = SCIPvarGetUbOriginal(andvars[r][v]);
4286 }
4287
4288 if( lb > 0.5 || ub < 0.5 )
4289 {
4290 SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
4291
4292 assert(SCIPisFeasIntegral(scip, lb));
4293 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " +1%s%s%s = %.15g;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
4294 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4295
4296 /* add variable to the hashmap */
4297 SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
4298 }
4299 }
4300 }
4301
4302 /* print and-constraints with fixed and-resultant to zero and all and-constraints with
4303 * aggregated resultant, otherwise we would loose this information
4304 */
4305 for( r = nresvars - 1; r >= 0; --r )
4306 {
4307 assert( resvars != NULL );
4308 resvar = resvars[r];
4309 rhslhs = (SCIPvarGetUbLocal(resvar) < 0.5) ? 0 : ((SCIPvarGetLbLocal(resvar) > 0.5) ? 1 : -1);
4310
4311 /* if and resultant is fixed to 0 and at least one and-variable is fixed to zero, we don't print this redundant constraint */
4312 if( rhslhs == 0 )
4313 {
4314 SCIP_Bool cont;
4315
4316 cont = FALSE;
4317
4318 assert( andvars != NULL && nandvars != NULL );
4319 assert( andvars[r] != NULL || nandvars[r] == 0 );
4320
4321 /* if resultant variable and one other and variable is already zero, so we did not need to print this and
4322 * constraint because all other variables are free
4323 */
4324 for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
4325 {
4326 assert( andvars[r] != NULL );
4327 assert( andvars[r][v] != NULL );
4328
4329 if( SCIPvarGetUbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
4330 {
4331 cont = TRUE;
4332 break;
4333 }
4334 }
4335
4336 if( cont )
4337 continue;
4338 }
4339 /* if and resultant is fixed to 1 and all and-variable are fixed to 1 too, we don't print this redundant constraint */
4340 else if( rhslhs == 1 )
4341 {
4342 SCIP_Bool cont;
4343
4344 cont = TRUE;
4345
4346 assert( andvars != NULL && nandvars != NULL );
4347 assert( andvars[r] != NULL || nandvars[r] == 0 );
4348
4349 /* if all variables are already fixed to one, we do not need to print this and constraint */
4350 for( v = nandvars[r] - 1; v >= 0; --v )
4351 {
4352 assert( andvars[r] != NULL );
4353 assert( andvars[r][v] != NULL );
4354
4355 if( SCIPvarGetLbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
4356 {
4357 cont = FALSE;
4358 break;
4359 }
4360 }
4361
4362 if( cont )
4363 continue;
4364 }
4365
4366 /* print and with fixed or aggregated and-resultant */
4367 /* rhslhs equals to 0 means the and constraint is relevant due to it's not clear on which values the and variables are
4368 * rhslhs equals to 1 means the and constraint is irrelevant cause all and variables have to be 1 too
4369 * rhslhs equals to -1 means the and constraint is relevant cause the variable is only aggregated */
4370 if( !SCIPvarIsActive(resvar) )
4371 {
4372 SCIP_VAR* var;
4373 SCIP_Bool neg;
4374 SCIP_Bool firstprinted;
4375
4376 firstprinted = FALSE;
4377
4378 assert( andvars != NULL && nandvars != NULL );
4379 assert( andvars[r] != NULL || nandvars[r] == 0 );
4380
4381 for( v = nandvars[r] - 1; v >= 0; --v )
4382 {
4383 assert( andvars[r] != NULL );
4384 assert( andvars[r][v] != NULL );
4385
4386 SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
4387
4388 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", (firstprinted) ? multisymbol : "", neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"));
4389 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4390
4391 firstprinted = TRUE;
4392 }
4393
4394 /* if the resultant is aggregated we need to print his binary representation */
4395 if( rhslhs == -1 )
4396 {
4397 int pos;
4398
4399 assert(transformed);
4400
4401 SCIP_CALL( SCIPgetBinvarRepresentative(scip, resvar, &resvar, &neg) );
4402
4403#ifndef NDEBUG
4404 if( neg )
4405 assert(SCIPvarIsActive(SCIPvarGetNegationVar(resvar)));
4406 else
4407 assert(SCIPvarIsActive(resvar));
4408#endif
4409
4410 /* replace and-resultant with corresponding variables */
4411 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, neg ? SCIPvarGetNegationVar(resvar) : resvar, nresvars, &pos) )
4412 {
4413 SCIP_Bool negated;
4414 int a;
4415
4416 assert(andvars != NULL);
4417 assert(nandvars != NULL);
4418 assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
4419 assert(andvars[pos][nandvars[pos] - 1] != NULL);
4420
4421 negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
4422
4423 /* print and-vars */
4424 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, neg ? " +1%s%s%s" : " -1%s%s%s", multisymbol, negated ? "~" : "",
4425 strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
4426 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4427
4428 for(a = nandvars[pos] - 2; a >= 0; --a )
4429 {
4430 negated = SCIPvarIsNegated(andvars[pos][a]);
4431
4432 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
4433 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4434 }
4435
4436 appendBuffer(scip, file, linebuffer, &linecnt, " ");
4437
4438 if( neg )
4439 rhslhs = 1;
4440 else
4441 rhslhs = 0;
4442 }
4443 else
4444 {
4445 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " -1%s%s%s", multisymbol, neg ? "~" : "",
4446 strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(resvar) : resvar), "x"));
4447 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4448
4449 rhslhs = 0;
4450 }
4451 }
4452
4453 /* print rhslhs */
4454 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " = %+" SCIP_LONGINT_FORMAT ";\n", rhslhs);
4455 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4456
4457 writeBuffer(scip, file, linebuffer, &linecnt);
4458 }
4459 }
4460
4461 return SCIP_OKAY;
4462}
4463
4464/* writes problem to file */
4465static
4467 SCIP* scip, /**< SCIP data structure */
4468 FILE* file, /**< output file, or NULL if standard output should be used */
4469 const char* name, /**< problem name */
4470 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4471 SCIP_OBJSENSE objsense, /**< objective sense */
4472 SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4473 SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4474 * extobj = objsense * objscale * (intobj + objoffset) */
4475 SCIP_RATIONAL* objoffsetexact, /**< exact objective offset from bound shifting and fixing */
4476 SCIP_RATIONAL* objscaleexact, /**< exact scalar applied to objective function; external objective value is
4477 * extobjexact = objsense * objscaleexact * (intobjexact + objoffsetexact) */
4478 SCIP_VAR** vars, /**< array with active (binary) variables */
4479 int nvars, /**< number of active variables in the problem */
4480 SCIP_CONS** conss, /**< array with constraints of the problem */
4481 int nconss, /**< number of constraints in the problem */
4482 SCIP_VAR** const resvars, /**< array of resultant variables */
4483 int const nresvars, /**< number of resultant variables */
4484 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
4485 int const*const nandvars, /**< array of numbers of corresponding and-variables */
4486 SCIP_Bool const existandconshdlr, /**< does and-constrainthandler exist? */
4487 SCIP_Bool const existands, /**< does some and-constraints exist? */
4488 SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4489 )
4490{
4491 char multisymbol[OPB_MAX_LINELEN];
4492 SCIP_HASHTABLE* printedfixing;
4493 SCIP_Bool usesymbol;
4494 SCIP_RETCODE retcode;
4495 int nlinearconss;
4496 int nindicatorconss;
4497
4498 assert( scip != NULL );
4499 assert( vars != NULL || nvars == 0 );
4500 assert( conss != NULL || nconss == 0 );
4501 assert( result != NULL );
4502
4503 /* check if should use a multipliers symbol star '*' between coefficients and variables */
4504 SCIP_CALL( SCIPgetBoolParam(scip, "reading/" READER_NAME "/multisymbol", &usesymbol) );
4505 (void) SCIPsnprintf(multisymbol, OPB_MAX_LINELEN, "%s", usesymbol ? " * " : " ");
4506
4507 /* determine how many split linear and indicator constraints exist */
4508 determineTotalNumberLinearConss(scip, conss, nconss, &nlinearconss, &nindicatorconss);
4509
4510 /* print statistics as comment to file */
4511 SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n");
4512 SCIPinfoMessage(scip, file, "* Problem name : %s\n", name);
4513 SCIPinfoMessage(scip, file, "* Variables : %d\n", nvars - nresvars - nindicatorconss);
4514 SCIPinfoMessage(scip, file, "* Constraints : %d\n", nlinearconss);
4515
4516 /* create a hash table */
4517 SCIP_CALL( SCIPhashtableCreate(&printedfixing, SCIPblkmem(scip), nvars,
4518 SCIPvarGetHashkey, SCIPvarIsHashkeyEq, SCIPvarGetHashkeyVal, NULL) );
4519
4520 /* write objective function */
4521 SCIP_CALL( writeOpbObjective(scip, file, vars, nvars, resvars, nresvars, andvars, nandvars,
4522 objsense, objoffset, objscale, objoffsetexact, objscaleexact, multisymbol, existands, transformed) );
4523
4524 /* write constraints */
4525 retcode = writeOpbConstraints(scip, file, conss, nconss, vars, nvars, resvars, nresvars, andvars, nandvars,
4526 multisymbol, existandconshdlr, existands, transformed);
4527
4528 if( existands && (retcode == SCIP_OKAY) )
4529 {
4530 /* write and constraints of inactive but relevant and-resultants and and-variables which are fixed to one
4531 with no fixed and resultant */
4532 SCIP_CALL( writeOpbRelevantAnds(scip, file, resvars, nresvars, andvars, nandvars, printedfixing, multisymbol, transformed) );
4533 }
4534
4535 /* write fixed variables */
4536 SCIP_CALL( writeOpbFixedVars(scip, file, vars, nvars, printedfixing, multisymbol, transformed) );
4537
4538 SCIPhashtableFree(&printedfixing);
4539
4540 *result = SCIP_SUCCESS;
4541
4542 return retcode;
4543}
4544
4545
4546/*
4547 * extern methods
4548 */
4549
4550/** reads problem from file */
4552 SCIP* scip, /**< SCIP data structure */
4553 SCIP_READER* reader, /**< the file reader itself */
4554 const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
4555 SCIP_RESULT* result /**< pointer to store the result of the file reading call */
4556 )
4557{ /*lint --e{715}*/
4558 OPBINPUT opbinput;
4559 SCIP_RETCODE retcode;
4560 int i;
4561
4562 assert(scip != NULL); /* for lint */
4563 assert(reader != NULL);
4564 assert(result != NULL);
4565
4566 *result = SCIP_DIDNOTRUN;
4567
4568 /* initialize OPB input data (use block memory because order can change during execution) */
4569 opbinput.file = NULL;
4571 opbinput.linebuf[0] = '\0';
4572 opbinput.linebufsize = OPB_MAX_LINELEN;
4574 opbinput.token[0] = '\0';
4576 opbinput.tokenbuf[0] = '\0';
4577 for( i = 0; i < OPB_MAX_PUSHEDTOKENS; ++i )
4578 {
4579 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(opbinput.pushedtokens[i]), OPB_MAX_LINELEN) ); /*lint !e866 */
4580 }
4581
4582 opbinput.npushedtokens = 0;
4583 opbinput.linenumber = 1;
4584 opbinput.linepos = 0;
4585 opbinput.objsense = SCIP_OBJSENSE_MINIMIZE;
4586 opbinput.eof = FALSE;
4587 opbinput.haserror = FALSE;
4588 opbinput.nproblemcoeffs = 0;
4589 opbinput.wbo = FALSE;
4590 opbinput.topcost = -SCIPinfinity(scip);
4591 opbinput.nindvars = 0;
4592#if GENCONSNAMES == TRUE
4593 opbinput.consnumber = 0;
4594#endif
4595
4596 /* read the file */
4597 retcode = readOPBFile(scip, reader, &opbinput, filename);
4598
4599 /* free dynamically allocated memory */
4600 for( i = OPB_MAX_PUSHEDTOKENS - 1; i >= 0; --i )
4601 {
4602 SCIPfreeBlockMemoryArray(scip, &(opbinput.pushedtokens[i]), OPB_MAX_LINELEN);
4603 }
4604 SCIPfreeBlockMemoryArray(scip, &opbinput.tokenbuf, OPB_MAX_LINELEN);
4606 SCIPfreeBlockMemoryArray(scip, &opbinput.linebuf, opbinput.linebufsize);
4607
4608 if( retcode == SCIP_PLUGINNOTFOUND || retcode == SCIP_INVALIDDATA )
4609 retcode = SCIP_READERROR;
4610
4611 SCIP_CALL( retcode );
4612
4613 if( opbinput.nproblemcoeffs > 0 )
4614 {
4615 SCIPwarningMessage(scip, "there might be <%d> coefficients or weight out of range!\n", opbinput.nproblemcoeffs);
4616 }
4617
4618 /* evaluate the result */
4619 if( opbinput.haserror )
4620 return SCIP_READERROR;
4621 else
4622 {
4623 /* set objective sense */
4624 SCIP_CALL( SCIPsetObjsense(scip, opbinput.objsense) );
4625 *result = SCIP_SUCCESS;
4626 }
4627
4628 return SCIP_OKAY;
4629}
4630
4631/** writes problem to file */
4633 SCIP* scip, /**< SCIP data structure */
4634 FILE* file, /**< output file, or NULL if standard output should be used */
4635 const char* name, /**< problem name */
4636 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4637 SCIP_OBJSENSE objsense, /**< objective sense */
4638 SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4639 SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4640 * extobj = objsense * objscale * (intobj + objoffset) */
4641 SCIP_RATIONAL* objoffsetexact, /**< exact objective offset from bound shifting and fixing */
4642 SCIP_RATIONAL* objscaleexact, /**< exact scalar applied to objective function; external objective value is
4643 * extobjexact = objsense * objscaleexact * (intobjexact + objoffsetexact) */
4644 SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
4645 int nvars, /**< number of active variables in the problem */
4646 int nbinvars, /**< number of binary variables */
4647 int nintvars, /**< number of general integer variables */
4648 int nimplvars, /**< number of implicit integer variables */
4649 int ncontvars, /**< number of continuous variables */
4650 SCIP_VAR** fixedvars, /**< array with fixed variables */
4651 int nfixedvars, /**< number of fixed and aggregated variables in the problem */
4652 SCIP_CONS** conss, /**< array with constraints of the problem */
4653 int nconss, /**< number of constraints in the problem */
4654 SCIP_Bool genericnames, /**< should generic variable and constraint names be used */
4655 SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4656 ) /*lint --e{715}*/
4657{ /*lint --e{715}*/
4658 SCIP_VAR*** andvars;
4659 SCIP_VAR** resvars;
4660 SCIP_CONSHDLR* indicatorhdlr = SCIPfindConshdlr(scip, "indicator");
4661 SCIP_Bool existands;
4662 SCIP_Bool existandconshdlr;
4663 SCIP_Bool ispseudoboolean;
4664 SCIP_RETCODE retcode = SCIP_OKAY;
4665 int* nandvars;
4666 int nintegralvars = nvars - ncontvars;
4667 int nindicatorconss = indicatorhdlr != NULL ? SCIPconshdlrGetNConss(indicatorhdlr) : 0;
4668 int nresvars;
4669 int v;
4670
4671 /* check whether problem is pseudoboolean */
4672 ispseudoboolean = (ncontvars <= nindicatorconss);
4673 for( v = nbinvars; v < nintegralvars && ispseudoboolean; ++v )
4674 {
4675 if( !SCIPvarIsBinary(vars[v])
4676 && ( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_INTEGER || ++ncontvars > nindicatorconss ) )
4677 ispseudoboolean = FALSE;
4678 }
4679
4680 if( ispseudoboolean )
4681 {
4682 /* computes all and-resultants and their corresponding constraint variables */
4683 /* coverity[leaked_storage] */
4684 SCIP_CALL( computeAndConstraintInfos(scip, transformed, &resvars, &nresvars, &andvars, &nandvars, &existandconshdlr, &existands) );
4685
4686 if( genericnames )
4687 {
4688#ifndef NDEBUG
4689 /* check for correct names for opb-format */
4690 int idx;
4691 int pos;
4692
4693 for( v = nvars - 1; v >= 0; --v )
4694 {
4695 if( existands )
4696 {
4697 /* and variables are artificial */
4698 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4699 continue;
4700 }
4701
4702 assert(sscanf(SCIPvarGetName(vars[v]), "x%d", &idx) == 1); /* cppcheck-suppress assertWithSideEffect */
4703 }
4704#endif
4705 retcode = writeOpb(scip, file, name, transformed, objsense, objoffset, objscale, objoffsetexact, objscaleexact,
4706 vars, nvars, conss, nconss, resvars, nresvars, andvars, nandvars, existandconshdlr, existands, result);
4707 }
4708 else
4709 {
4710 SCIP_Bool printed;
4711 int idx;
4712 int pos;
4713
4714 printed = FALSE;
4715
4716 /* check if there are already generic names for all (not fixed variables)*/
4717 for( v = nvars - 1; v >= 0; --v )
4718 if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4719 {
4720 if( sscanf(SCIPvarGetName(vars[v]), transformed ? "t_x%d" : "x%d", &idx) != 1 && strstr(SCIPvarGetName(vars[v]), INDICATORVARNAME) == NULL && strstr(SCIPvarGetName(vars[v]), INDICATORSLACKVARNAME) == NULL )
4721 {
4722 SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4723 SCIP_CALL( SCIPprintVar(scip, vars[v], NULL) );
4724 SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4725
4726 if( transformed )
4727 {
4728 SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4729 SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4730 }
4731 else
4732 {
4733 SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4734 SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4735 }
4736 printed = TRUE;
4737 break;
4738 }
4739 }
4740
4741 if( !printed )
4742 {
4743 /* check if there are already generic names for all (fixed variables)*/
4744 for( v = nfixedvars - 1; v >= 0; --v )
4745 if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4746 {
4747 /* coverity[secure_coding] */
4748 if( sscanf(SCIPvarGetName(fixedvars[v]), transformed ? "t_x%d" : "x%d", &idx) != 1 && strstr(SCIPvarGetName(fixedvars[v]), INDICATORVARNAME) == NULL && strstr(SCIPvarGetName(fixedvars[v]), INDICATORSLACKVARNAME) == NULL )
4749 {
4750 SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4751 SCIP_CALL( SCIPprintVar(scip, fixedvars[v], NULL) );
4752 SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4753
4754 if( transformed )
4755 {
4756 SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4757 SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4758 }
4759 else
4760 {
4761 SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4762 SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4763 }
4764 printed = TRUE;
4765 break;
4766 }
4767 }
4768 }
4769
4770 if( !printed )
4771 {
4772#ifndef NDEBUG
4773 for( v = nvars - 1; v >= 0; --v )
4774 {
4775 if( existands )
4776 {
4777 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4778 continue;
4779 }
4780
4781 assert(sscanf(SCIPvarGetName(vars[v]), transformed ? "t_x%d" : "x%d", &idx) == 1 || strstr(SCIPvarGetName(vars[v]), INDICATORVARNAME) != NULL || strstr(SCIPvarGetName(vars[v]), INDICATORSLACKVARNAME) != NULL ); /* cppcheck-suppress assertWithSideEffect */
4782 }
4783#endif
4784 retcode = writeOpb(scip, file, name, transformed, objsense, objoffset, objscale, objoffsetexact, objscaleexact,
4785 vars, nvars, conss, nconss, resvars, nresvars, andvars, nandvars, existandconshdlr, existands, result);
4786 }
4787 }
4788
4789 if( existands )
4790 {
4791 /* free temporary buffers */
4792 assert(resvars != NULL);
4793 assert(andvars != NULL);
4794 assert(nandvars != NULL);
4795
4796 for( v = nresvars - 1; v >= 0; --v )
4797 {
4798 assert(andvars[v] != NULL);
4799 SCIPfreeMemoryArray(scip, &andvars[v]);
4800 }
4801
4802 SCIPfreeMemoryArray(scip, &nandvars);
4803 SCIPfreeMemoryArray(scip, &andvars);
4804 SCIPfreeMemoryArray(scip, &resvars);
4805 }
4806
4807 *result = SCIP_SUCCESS;
4808 }
4809 else
4810 {
4811 SCIPwarningMessage(scip, "only binary problems can be written in OPB format.\n");
4812 *result = SCIP_DIDNOTRUN;
4813 }
4814
4815 if( retcode == SCIP_INVALIDDATA )
4816 return SCIP_WRITEERROR;
4817
4818 return retcode;
4819}
4820
4821/*
4822 * Callback methods of reader
4823 */
4824
4825/** copy method for reader plugins (called when SCIP copies plugins) */
4826static
4828{ /*lint --e{715}*/
4829 assert(scip != NULL);
4830 assert(reader != NULL);
4831 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4832
4833 /* call inclusion method of reader */
4835
4836 return SCIP_OKAY;
4837}
4838
4839
4840/** destructor of reader to free user data (called when SCIP is exiting) */
4841static
4843{
4844 SCIP_READERDATA* readerdata;
4845
4846 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4847 readerdata = SCIPreaderGetData(reader);
4848 SCIPfreeBlockMemory(scip, &readerdata);
4849
4850 return SCIP_OKAY;
4851}
4852
4853
4854/** problem reading method of reader */
4855static
4857{ /*lint --e{715}*/
4858
4859 SCIP_CALL( SCIPreadOpb(scip, reader, filename, result) );
4860
4861 return SCIP_OKAY;
4862}
4863
4864
4865/** problem writing method of reader */
4866static
4868{ /*lint --e{715}*/
4869 assert(reader != NULL);
4870 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4871
4872 if( SCIPisExact(scip) )
4873 {
4874 SCIPerrorMessage("OPB reader cannot yet write problems in exact solving mode\n");
4875 return SCIP_WRITEERROR;
4876 }
4877
4878 SCIP_CALL( SCIPwriteOpb(scip, file, name, transformed, objsense, objoffset, objscale, objoffsetexact, objscaleexact,
4879 vars, nvars, nbinvars, nintvars, nimplvars, ncontvars, fixedvars, nfixedvars, conss, nconss, genericnames, result) );
4880
4881 return SCIP_OKAY;
4882}
4883
4884/*
4885 * reader specific interface methods
4886 */
4887
4888/** includes the opb file reader in SCIP */
4890 SCIP* scip /**< SCIP data structure */
4891 )
4892{
4893 SCIP_READERDATA* readerdata;
4894 SCIP_READER* reader;
4895
4896 /* create reader data */
4897 SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata) );
4898
4899 /* include reader */
4901
4902 /* reader is safe to use in exact solving mode, but exact writing still needs to be implemented */
4903 SCIPreaderMarkExact(reader);
4904
4905 /* set non fundamental callbacks via setter functions */
4906 SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyOpb) );
4907 SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeOpb) );
4908 SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadOpb) );
4909 SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteOpb) );
4910
4911 /* add opb reader parameters */
4913 "reading/" READER_NAME "/dynamicconss", "should model constraints be subject to aging?",
4914 NULL, FALSE, FALSE/*TRUE*/, NULL, NULL) ); /* have to be FALSE, otherwise an error might inccur in restart during branch and bound */
4916 "reading/" READER_NAME "/multisymbol", "use '*' between coefficients and variables by writing to problem?",
4917 NULL, TRUE, FALSE, NULL, NULL) );
4918 SCIP_CALL( SCIPaddIntParam(scip, "reading/" READER_NAME "/maxintsize", "maximum allowed 'intsize' (i.e. the number of "
4919 "bits required to represent the sum of absolute values of all integers that appear in a constraint or "
4920 "objective function) or -1 for unlimited",
4921 &readerdata->maxintsize, TRUE, OPB_MAX_INTSIZE, -1, INT_MAX, NULL, NULL) );
4922
4923 return SCIP_OKAY;
4924}
SCIP_VAR * w
Definition: circlepacking.c:67
SCIP_VAR * a
Definition: circlepacking.c:66
SCIP_Real * r
Definition: circlepacking.c:59
Constraint handler for AND constraints, .
Constraint handler for linear constraints in their most general form, .
constraint handler for indicator 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 pseudoboolean constraints
#define ARTIFICIALVARNAMEPREFIX
Constraint handler for the set partitioning / packing / covering constraints .
Constraint handler for variable bound constraints .
methods for debugging
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:312
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:311
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:156
#define ABS(x)
Definition: def.h:216
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_CALL_ABORT(x)
Definition: def.h:334
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:376
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define SCIPABORT()
Definition: def.h:327
#define SCIP_LONGINT_MAX
Definition: def.h:142
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:153
int SCIPfeof(SCIP_FILE *stream)
Definition: fileio.c:227
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:232
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:200
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RATIONAL * SCIPgetLhsExactLinear(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)
SCIP_RATIONAL * SCIPgetRhsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsExactLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_RATIONAL **vals, SCIP_RATIONAL *lhs, SCIP_RATIONAL *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 ** SCIPgetVarsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsAnd(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_and.c:5059
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5248
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5199
int SCIPgetNVarsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9596
SCIP_VAR * SCIPgetIndVarPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
SCIP_RETCODE SCIPcreateConsPseudoboolean(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR **linvars, int nlinvars, SCIP_Real *linvals, SCIP_VAR ***terms, int nterms, int *ntermvars, SCIP_Real *termvals, SCIP_VAR *indvar, SCIP_Real weight, SCIP_Bool issoftcons, 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 ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9619
SCIP_VAR * SCIPgetBinaryVarIndicator(SCIP_CONS *cons)
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetSlackVarIndicator(SCIP_CONS *cons)
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9642
SCIP_CONS * SCIPgetLinearConsIndicator(SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5223
SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_CONS * SCIPgetLinearConsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
SCIP_RATIONAL ** SCIPgetValsExactLinear(SCIP *scip, SCIP_CONS *cons)
@ 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 SCIPreadOpb(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result)
Definition: reader_opb.c:4551
SCIP_RETCODE SCIPwriteOpb(SCIP *scip, FILE *file, const char *name, SCIP_Bool transformed, SCIP_OBJSENSE objsense, SCIP_Real objoffset, SCIP_Real objscale, SCIP_RATIONAL *objoffsetexact, SCIP_RATIONAL *objscaleexact, SCIP_VAR **vars, int nvars, int nbinvars, int nintvars, int nimplvars, int ncontvars, SCIP_VAR **fixedvars, int nfixedvars, SCIP_CONS **conss, int nconss, SCIP_Bool genericnames, SCIP_RESULT *result)
Definition: reader_opb.c:4632
SCIP_RETCODE SCIPincludeReaderOpb(SCIP *scip)
Definition: reader_opb.c:4889
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1907
int SCIPgetNOrigConss(SCIP *scip)
Definition: scip_prob.c:3712
SCIP_Real SCIPgetOrigObjoffset(SCIP *scip)
Definition: scip_prob.c:1529
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3274
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3620
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:2201
SCIP_RETCODE SCIPprintTransProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
Definition: scip_prob.c:696
SCIP_RETCODE SCIPprintOrigProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
Definition: scip_prob.c:652
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip_prob.c:1417
SCIP_RETCODE SCIPaddOrigObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip_prob.c:1486
SCIP_CONS ** SCIPgetOrigConss(SCIP *scip)
Definition: scip_prob.c:3739
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip_prob.c:119
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip_prob.c:3189
SCIP_CONS * SCIPfindCons(SCIP *scip, const char *name)
Definition: scip_prob.c:3525
SCIP_RETCODE SCIPaddOrigObjoffsetExact(SCIP *scip, SCIP_RATIONAL *addval)
Definition: scip_prob.c:1465
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3095
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3143
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3061
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2348
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2647
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2298
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2535
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
#define SCIPdebugMsgPrint
Definition: scip_message.h:79
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:88
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:250
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:83
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:57
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4778
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4316
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:940
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4735
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8409
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2536
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8698
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:8486
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8389
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_Bool SCIPisExact(SCIP *scip)
Definition: scip_exact.c:193
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
#define SCIPreallocMemoryArray(scip, ptr, newnum)
Definition: scip_mem.h:70
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip_mem.h:64
BMS_BUFMEM * SCIPbuffer(SCIP *scip)
Definition: scip_mem.c:72
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 SCIPduplicateMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:76
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip_mem.h:80
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#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
void SCIPrationalMult(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1066
void SCIPrationalAdd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:935
int SCIPrationalToString(SCIP_RATIONAL *rational, char *str, int strlen)
Definition: rational.cpp:1743
void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
Definition: rational.cpp:603
void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:473
void SCIPrationalDiff(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:983
SCIP_RETCODE SCIPrationalCopyBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***result, SCIP_RATIONAL **src, int len)
Definition: rational.cpp:267
SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:123
SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
Definition: rational.cpp:1624
void SCIPrationalSetRational(SCIP_RATIONAL *res, SCIP_RATIONAL *src)
Definition: rational.cpp:569
void SCIPrationalMessage(SCIP_MESSAGEHDLR *msg, FILE *file, SCIP_RATIONAL *rational)
Definition: rational.cpp:1790
void SCIPrationalSetNegInfinity(SCIP_RATIONAL *res)
Definition: rational.cpp:630
SCIP_Bool SCIPrationalIsNegative(SCIP_RATIONAL *rational)
Definition: rational.cpp:1650
SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1660
SCIP_RETCODE SCIPrationalCreateBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***rational, int size)
Definition: rational.cpp:214
SCIP_Bool SCIPrationalIsNegInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1670
void SCIPrationalDivReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
Definition: rational.cpp:1147
SCIP_Bool SCIPrationalIsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1404
SCIP_RETCODE SCIPrationalReallocBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***result, int oldlen, int newlen)
Definition: rational.cpp:314
void SCIPrationalMultReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
Definition: rational.cpp:1097
void SCIPrationalFreeBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***ratbufarray, int size)
Definition: rational.cpp:518
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip_reader.c:109
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip_reader.c:147
SCIP_READERDATA * SCIPreaderGetData(SCIP_READER *reader)
Definition: reader.c:605
SCIP_RETCODE SCIPsetReaderFree(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERFREE((*readerfree)))
Definition: scip_reader.c:171
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:680
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip_reader.c:195
void SCIPreaderMarkExact(SCIP_READER *reader)
Definition: reader.c:670
SCIP_RETCODE SCIPsetReaderWrite(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERWRITE((*readerwrite)))
Definition: scip_reader.c:219
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(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_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:18320
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:23868
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:23642
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:24020
SCIP_RETCODE SCIPaddVarExactData(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *lb, SCIP_RATIONAL *ub, SCIP_RATIONAL *obj)
Definition: scip_var.c:299
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:23900
SCIP_RETCODE SCIPvarGetOrigvarSumExact(SCIP_VAR **var, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant)
Definition: var.c:18409
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:23652
SCIP_RETCODE SCIPcreateVarImpl(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip_var.c:225
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:24063
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1887
SCIP_RETCODE SCIPgetProbvarLinearSumExact(SCIP *scip, SCIP_VAR **vars, SCIP_RATIONAL **scalars, int *nvars, int varssize, SCIP_RATIONAL *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: scip_var.c:2443
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition: scip_var.c:2378
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip_var.c:2166
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:23443
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:23878
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip_var.c:120
SCIP_RETCODE SCIPprintVar(SCIP *scip, SCIP_VAR *var, FILE *file)
Definition: scip_var.c:12465
SCIP_RETCODE SCIPchgVarObjExact(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *newobj)
Definition: scip_var.c:5420
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:5372
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition: scip_var.c:2236
SCIP_RATIONAL * SCIPvarGetObjExact(SCIP_VAR *var)
Definition: var.c:23910
SCIP_RETCODE SCIPaddVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real addobj)
Definition: scip_var.c:5519
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
void SCIPsortPtrPtrInt(void **ptrarray1, void **ptrarray2, int *intarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPstrcasecmp(const char *s1, const char *s2)
Definition: misc.c:10863
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
void SCIPprintSysError(const char *message)
Definition: misc.c:10719
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition: misc.c:10694
static const SCIP_Real scalars[]
Definition: lp.c:5959
memory allocation routines
SCIP_RATIONAL * SCIPconsGetRhsExact(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: misc_linear.c:176
SCIP_Real SCIPconsGetLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: misc_linear.c:112
SCIP_RATIONAL * SCIPconsGetLhsExact(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: misc_linear.c:213
SCIP_Real SCIPconsGetRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: misc_linear.c:48
public methods for managing constraints
wrapper functions to map file i/o to standard or zlib file i/o
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:43
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:102
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for input file readers
public methods for problem variables
wrapper for rational number arithmetic
static const char delimchars[]
Definition: reader_fzn.c:225
static SCIP_RETCODE writeOpbRelevantAnds(SCIP *const scip, FILE *const file, SCIP_VAR **const resvars, int const nresvars, SCIP_VAR **const *const andvars, int const *const nandvars, SCIP_HASHTABLE *const printedfixing, char const *const multisymbol, SCIP_Bool const transformed)
Definition: reader_opb.c:4201
OpbExpType
Definition: reader_opb.c:155
@ OPB_EXP_SIGNED
Definition: reader_opb.c:158
@ OPB_EXP_UNSIGNED
Definition: reader_opb.c:157
@ OPB_EXP_NONE
Definition: reader_opb.c:156
static SCIP_RETCODE setObjective(SCIP *const scip, OPBINPUT *const opbinput, const char *sense, SCIP_Real const scale, SCIP_VAR **const linvars, SCIP_Real *const coefs, int const ncoefs, SCIP_VAR ***const terms, SCIP_Real *const termcoefs, int *const ntermvars, int const ntermcoefs)
Definition: reader_opb.c:1150
static SCIP_RETCODE writeOpb(SCIP *scip, FILE *file, const char *name, SCIP_Bool transformed, SCIP_OBJSENSE objsense, SCIP_Real objoffset, SCIP_Real objscale, SCIP_RATIONAL *objoffsetexact, SCIP_RATIONAL *objscaleexact, SCIP_VAR **vars, int nvars, SCIP_CONS **conss, int nconss, SCIP_VAR **const resvars, int const nresvars, SCIP_VAR **const *const andvars, int const *const nandvars, SCIP_Bool const existandconshdlr, SCIP_Bool const existands, SCIP_RESULT *result)
Definition: reader_opb.c:4466
static SCIP_RETCODE printRow(SCIP *scip, FILE *file, const char *type, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Real lhs, SCIP_Longint weight, SCIP_Longint *mult, const char *multisymbol)
Definition: reader_opb.c:3040
static void clearBuffer(char *linebuffer, int *linecnt)
Definition: reader_opb.c:2259
static SCIP_Bool isSign(OPBINPUT *opbinput, int *sign)
Definition: reader_opb.c:549
static SCIP_DECL_READERREAD(readerReadOpb)
Definition: reader_opb.c:4856
static SCIP_RETCODE getBinVarsRepresentatives(SCIP *const scip, SCIP_VAR **const vars, int const nvars, SCIP_Bool const transformed)
Definition: reader_opb.c:1893
static SCIP_Bool getNextToken(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:397
static SCIP_Bool isValueChar(char c, char nextc, SCIP_Bool firstchar, SCIP_Bool *hasdot, OPBEXPTYPE *exptype)
Definition: reader_opb.c:284
static SCIP_RETCODE getVariableOrTerm(SCIP *scip, OPBINPUT *opbinput, SCIP_VAR ***vars, int *nvars, int *varssize)
Definition: reader_opb.c:709
static SCIP_RETCODE writeOpbFixedVars(SCIP *const scip, FILE *const file, SCIP_VAR **vars, int nvars, SCIP_HASHTABLE *const printedfixing, char const *const multisymbol, SCIP_Bool const transformed)
Definition: reader_opb.c:4127
#define TOPCOSTCONSNAME
Definition: reader_opb.c:132
static void swapTokenBuffer(OPBINPUT *opbinput)
Definition: reader_opb.c:524
static SCIP_RETCODE printRowExact(SCIP *scip, FILE *file, const char *type, SCIP_VAR **vars, SCIP_RATIONAL **vals, int nvars, SCIP_RATIONAL *lhs, SCIP_RATIONAL *weight, SCIP_RATIONAL *mult, const char *multisymbol)
Definition: reader_opb.c:3162
enum OpbSense OPBSENSE
Definition: reader_opb.c:169
static SCIP_RETCODE writeOpbObjective(SCIP *const scip, FILE *const file, SCIP_VAR **const vars, int const nvars, SCIP_VAR **const resvars, int const nresvars, SCIP_VAR **const *const andvars, int const *const nandvars, SCIP_OBJSENSE const objsense, SCIP_Real const objoffset, SCIP_Real const objscale, SCIP_RATIONAL *const objoffsetexact, SCIP_RATIONAL *const objscaleexact, char const *const multisymbol, SCIP_Bool const existands, SCIP_Bool const transformed)
Definition: reader_opb.c:2320
static SCIP_RETCODE getCommentLineData(SCIP *scip, OPBINPUT *opbinput, SCIP_Real *objscale, SCIP_Real *objoffset)
Definition: reader_opb.c:1637
#define INDICATORVARNAME
Definition: reader_opb.c:130
static SCIP_RETCODE printLinearCons(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Real lhs, SCIP_Real rhs, SCIP_Longint weight, SCIP_Bool transformed, const char *multisymbol)
Definition: reader_opb.c:3266
static const char commentchars[]
Definition: reader_opb.c:198
static SCIP_DECL_READERWRITE(readerWriteOpb)
Definition: reader_opb.c:4867
static void writeBuffer(SCIP *scip, FILE *file, char *linebuffer, int *linecnt)
Definition: reader_opb.c:2274
static void pushToken(OPBINPUT *opbinput)
Definition: reader_opb.c:498
#define READER_DESC
Definition: reader_opb.c:126
static SCIP_RETCODE readOPBFile(SCIP *scip, SCIP_READER *reader, OPBINPUT *opbinput, const char *filename)
Definition: reader_opb.c:1753
static SCIP_RETCODE computeAndConstraintInfos(SCIP *const scip, SCIP_Bool const transformed, SCIP_VAR ***resvars, int *nresvars, SCIP_VAR ****andvars, int **nandvars, SCIP_Bool *const existandconshdlr, SCIP_Bool *const existands)
Definition: reader_opb.c:2055
static SCIP_RETCODE printNonLinearCons(SCIP *const scip, FILE *const file, SCIP_VAR **const vars, SCIP_Real *const vals, int nvars, SCIP_Real lhs, SCIP_Real rhs, SCIP_VAR **const resvars, int nresvars, SCIP_VAR **const *const andvars, const int *const nandvars, SCIP_Longint weight, SCIP_Bool transformed, const char *const multisymbol)
Definition: reader_opb.c:2943
static SCIP_RETCODE printNLRow(SCIP *const scip, FILE *const file, const char *const type, SCIP_VAR **const vars, SCIP_Real *const vals, int nvars, SCIP_Real lhs, SCIP_VAR **const resvars, int nresvars, SCIP_VAR **const *const andvars, const int *const nandvars, SCIP_Longint weight, SCIP_Longint *const mult, const char *const multisymbol)
Definition: reader_opb.c:2770
static SCIP_DECL_READERFREE(readerFreeOpb)
Definition: reader_opb.c:4842
static SCIP_RETCODE writeOpbConstraints(SCIP *const scip, FILE *const file, SCIP_CONS **const conss, int const nconss, SCIP_VAR **const vars, int const nvars, SCIP_VAR **const resvars, int const nresvars, SCIP_VAR **const *const andvars, int const *const nandvars, char const *const multisymbol, SCIP_Bool const existandconshdlr, SCIP_Bool const existands, SCIP_Bool const transformed)
Definition: reader_opb.c:3567
static void determineTotalNumberLinearConss(SCIP *const scip, SCIP_CONS **const conss, int const nconss, int *nlinearconss, int *nindicatorconss)
Definition: reader_opb.c:3459
#define READER_EXTENSION
Definition: reader_opb.c:127
static SCIP_Bool isStartingSoftConstraintWeight(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:641
#define OPB_MAX_PUSHEDTOKENS
Definition: reader_opb.c:138
static void appendBuffer(SCIP *scip, FILE *file, char *linebuffer, int *linecnt, const char *extension)
Definition: reader_opb.c:2297
static SCIP_Bool getNextLine(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:328
static SCIP_RETCODE printLinearConsExact(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_RATIONAL **vals, int nvars, SCIP_RATIONAL *lhs, SCIP_RATIONAL *rhs, SCIP_RATIONAL *weight, SCIP_Bool transformed, const char *multisymbol)
Definition: reader_opb.c:3357
static SCIP_Bool isEndLine(OPBINPUT *opbinput)
Definition: reader_opb.c:535
#define OPB_INIT_COEFSSIZE
Definition: reader_opb.c:139
static SCIP_RETCODE createVariable(SCIP *scip, SCIP_VAR **var, char *name)
Definition: reader_opb.c:673
struct OpbInput OPBINPUT
Definition: reader_opb.c:196
#define READER_NAME
Definition: reader_opb.c:125
static void syntaxError(SCIP *scip, OPBINPUT *opbinput, const char *msg)
Definition: reader_opb.c:205
static SCIP_DECL_READERCOPY(readerCopyOpb)
Definition: reader_opb.c:4827
static SCIP_RETCODE readConstraints(SCIP *scip, OPBINPUT *opbinput, SCIP_Real objscale, int *nNonlinearConss)
Definition: reader_opb.c:1336
static SCIP_Bool isValue(SCIP *scip, OPBINPUT *opbinput, SCIP_Real *value)
Definition: reader_opb.c:576
static SCIP_Bool isDelimChar(char c)
Definition: reader_opb.c:240
static void swapPointers(char **pointer1, char **pointer2)
Definition: reader_opb.c:383
static SCIP_Bool hasError(OPBINPUT *opbinput)
Definition: reader_opb.c:229
static void pushBufferToken(OPBINPUT *opbinput)
Definition: reader_opb.c:511
static SCIP_Bool isSense(OPBINPUT *opbinput, OPBSENSE *sense)
Definition: reader_opb.c:610
static SCIP_RETCODE getActiveVariablesExact(SCIP *scip, SCIP_VAR ***vars, SCIP_RATIONAL ***scalars, int *nvars, int *varssize, SCIP_RATIONAL *constant, SCIP_Bool transformed)
Definition: reader_opb.c:2006
#define OPB_MAX_INTSIZE
Definition: reader_opb.c:140
enum OpbExpType OPBEXPTYPE
Definition: reader_opb.c:160
static SCIP_RETCODE readCoefficients(SCIP *const scip, OPBINPUT *const opbinput, char *const name, SCIP_VAR ***linvars, SCIP_Real **lincoefs, int *const nlincoefs, int *lincoefssize, SCIP_VAR ****terms, SCIP_Real **termcoefs, int **ntermvars, int *termcoefssize, int *const ntermcoefs, SCIP_Bool *const newsection, SCIP_Bool *const isNonlinear, SCIP_Bool *const issoftcons, SCIP_Real *const weight)
Definition: reader_opb.c:785
#define INDICATORSLACKVARNAME
Definition: reader_opb.c:131
static SCIP_RETCODE getActiveVariables(SCIP *scip, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, int *varssize, SCIP_Real *constant, SCIP_Bool transformed)
Definition: reader_opb.c:1957
static SCIP_Bool isEndingSoftConstraintWeight(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:657
static SCIP_Bool isTokenChar(char c)
Definition: reader_opb.c:261
#define OPB_MAX_LINELEN
Definition: reader_opb.c:137
OpbSense
Definition: reader_opb.c:163
@ OPB_SENSE_GE
Definition: reader_opb.c:166
@ OPB_SENSE_NOTHING
Definition: reader_opb.c:164
@ OPB_SENSE_LE
Definition: reader_opb.c:165
@ OPB_SENSE_EQ
Definition: reader_opb.c:167
pseudo-Boolean file reader (opb format)
public methods for constraint handler plugins and constraints
public methods for exact solving
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for reader plugins
public methods for querying solving statistics
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
Definition: sepa_flower.c:1221
@ SCIP_OBJSENSE_MAXIMIZE
Definition: type_prob.h:47
@ SCIP_OBJSENSE_MINIMIZE
Definition: type_prob.h:48
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:50
struct SCIP_ReaderData SCIP_READERDATA
Definition: type_reader.h:54
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_SUCCESS
Definition: type_result.h:58
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_NOFILE
Definition: type_retcode.h:47
@ SCIP_READERROR
Definition: type_retcode.h:45
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_WRITEERROR
Definition: type_retcode.h:46
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_IMPLINTTYPE_STRONG
Definition: type_var.h:106
@ SCIP_VARTYPE_INTEGER
Definition: type_var.h:65
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:64
@ SCIP_VARSTATUS_ORIGINAL
Definition: type_var.h:51
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition: type_var.h:57
@ SCIP_VARSTATUS_AGGREGATED
Definition: type_var.h:55