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