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