Scippy

SCIP

Solving Constraint Integer Programs

reader_opb.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file reader_opb.c
26 * @ingroup DEFPLUGINS_READER
27 * @brief pseudo-Boolean file reader (opb format)
28 * @author Stefan Heinz
29 * @author Michael Winkler
30 * @author Dominik Kamp
31 *
32 * This file reader parses the @a opb format and is also used by the @a wbo reader for the @a wbo format. For a
33 * detailed description of this format see
34 *
35 * - http://www.cril.univ-artois.fr/PB07/solver_req.html
36 * - http://www.cril.univ-artois.fr/PB10/format.pdf
37 *
38 * The syntax of the input file format can be described by a simple Backus-Naur
39 * form. <formula> is the start symbol of this grammar.
40 *
41 * <formula>::= <sequence_of_comments>
42 * [<objective>] | [<softheader>]
43 * <sequence_of_comments_or_constraints>
44 *
45 * <sequence_of_comments>::= <comment> [<sequence_of_comments>]
46 * <comment>::= "*" <any_sequence_of_characters_other_than_EOL> <EOL>
47 * <sequence_of_comments_or_constraints>::=<comment_or_constraint> [<sequence_of_comments_or_constraints>]
48 * <comment_or_constraint>::=<comment>|<constraint>
49 *
50 * <objective>::= "min:" <zeroOrMoreSpace> <sum> ";"
51 * <constraint>::= <sum> <relational_operator> <zeroOrMoreSpace> <integer> <zeroOrMoreSpace> ";"
52 *
53 * <sum>::= <weightedterm> | <weightedterm> <sum>
54 * <weightedterm>::= <integer> <oneOrMoreSpace> <term> <oneOrMoreSpace>
55 *
56 * <integer>::= <unsigned_integer> | "+" <unsigned_integer> | "-" <unsigned_integer>
57 * <unsigned_integer>::= <digit> | <digit><unsigned_integer>
58 *
59 * <relational_operator>::= ">=" | "="
60 *
61 * <variablename>::= "x" <unsigned_integer>
62 *
63 * <oneOrMoreSpace>::= " " [<oneOrMoreSpace>]
64 * <zeroOrMoreSpace>::= [" " <zeroOrMoreSpace>]
65 *
66 * For linear pseudo-Boolean instances, <term> is defined as
67 *
68 * <term>::=<variablename>
69 *
70 * For non-linear instances, <term> is defined as
71 *
72 * <term>::= <oneOrMoreLiterals>
73 * <oneOrMoreLiterals>::= <literal> | <literal> <oneOrMoreSpace> <oneOrMoreLiterals>
74 * <literal>::= <variablename> | "~"<variablename>
75 *
76 * For wbo-files are the following additional/changed things possible.
77 *
78 * <softheader>::= "soft:" [<unsigned integer>] ";"
79 *
80 * <comment_or_constraint>::=<comment>|<constraint>|<softconstraint>
81 *
82 * <softconstraint>::= "[" <zeroOrMoreSpace> <unsigned integer> <zeroOrMoreSpace> "]" <constraint>
83 *
84 */
85
86/* Our parser should also be lax by handling variable names and it's possible to read doubles instead of integer and
87 * possible some more :). */
88
89/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
90
92#include <ctype.h>
93#include "scip/cons_and.h"
94#include "scip/cons_indicator.h"
95#include "scip/cons_knapsack.h"
96#include "scip/cons_linear.h"
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, scale * 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** vars;
1751 SCIP_VAR** topcostvars;
1752 SCIP_CONS* topcostcons;
1753 SCIP_Real* topcosts;
1754 SCIP_Real topcostrhs;
1755 int nvars;
1756 int ntopcostvars;
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 {
1768 if( !SCIPisZero(scip, SCIPvarGetObj(vars[i])) )
1769 {
1770 topcostvars[ntopcostvars] = vars[i];
1771 topcosts[ntopcostvars] = SCIPvarGetObj(vars[i]);
1772 ++ntopcostvars;
1773 }
1774 }
1775 topcostrhs = SCIPceil(scip, opbinput->topcost - 1.0);
1776
1777 SCIP_CALL( SCIPcreateConsLinear(scip, &topcostcons, TOPCOSTCONSNAME, ntopcostvars, topcostvars, topcosts,
1778 -SCIPinfinity(scip), topcostrhs, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1779 SCIP_CALL( SCIPaddCons(scip, topcostcons) );
1780 SCIPdebugPrintCons(scip, topcostcons, NULL);
1781 SCIP_CALL( SCIPreleaseCons(scip, &topcostcons) );
1782
1783 SCIPfreeBufferArray(scip, &topcosts);
1784 SCIPfreeBufferArray(scip, &topcostvars);
1785 }
1786
1787 /* close file */
1788 SCIPfclose(opbinput->file);
1789
1790 return SCIP_OKAY;
1791}
1792
1793
1794/*
1795 * Local methods (for writing)
1796 */
1798/** transforms given and constraint variables to the corresponding active or negated variables */
1799static
1801 SCIP*const scip, /**< SCIP data structure */
1802 SCIP_VAR**const vars, /**< vars array to get active variables for */
1803 int const nvars, /**< pointer to number of variables and values in vars and vals array */
1804 SCIP_Bool const transformed /**< transformed constraint? */
1805 )
1806{
1807 SCIP_Bool negated;
1808 int v;
1809
1810 assert( scip != NULL );
1811 assert( vars != NULL );
1812 assert( nvars > 0 );
1813
1814 if( transformed )
1815 {
1816 for( v = nvars - 1; v >= 0; --v )
1817 {
1818 /* gets a binary variable that is equal to the given binary variable, and that is either active, fixed, or
1819 * multi-aggregated, or the negated variable of an active, fixed, or multi-aggregated variable
1820 */
1821 SCIP_CALL( SCIPgetBinvarRepresentative( scip, vars[v], &vars[v], &negated) );
1822 }
1823 }
1824 else
1825 {
1826 SCIP_Real scalar;
1827 SCIP_Real constant;
1828
1829 for( v = nvars - 1; v >= 0; --v )
1830 {
1831 scalar = 1.0;
1832 constant = 0.0;
1833
1834 /* retransforms given variable, scalar and constant to the corresponding original variable, scalar and constant,
1835 * if possible; if the retransformation is impossible, NULL is returned as variable
1836 */
1837 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalar, &constant) );
1838
1839 if( vars[v] == NULL )
1840 {
1841 SCIPdebugMsg(scip, "A variable couldn't retransformed to an original variable.\n");
1842 return SCIP_INVALIDDATA;
1843 }
1844 if( SCIPisEQ(scip, scalar, -1.0) && SCIPisEQ(scip, constant, 1.0) )
1845 {
1846 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &vars[v]) );
1847 }
1848 else
1849 {
1850 if( !SCIPisEQ(scip, scalar, 1.0) || !SCIPisZero(scip, constant) )
1851 {
1852 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);
1853 return SCIP_INVALIDDATA;
1854 }
1855 }
1856 }
1857 }
1858
1859 return SCIP_OKAY;
1860}
1862/** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
1863static
1865 SCIP* scip, /**< SCIP data structure */
1866 SCIP_VAR** vars, /**< vars array to get active variables for */
1867 SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
1868 int* nvars, /**< pointer to number of variables and values in vars and vals array */
1869 SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
1870 SCIP_Bool transformed /**< transformed constraint? */
1871 )
1872{
1873 int requiredsize;
1874 int v;
1875
1876 assert(scip != NULL);
1877 assert(vars != NULL);
1878 assert(scalars != NULL);
1879 assert(nvars != NULL);
1880 assert(constant != NULL);
1881
1882 if( transformed )
1883 {
1884 SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) );
1885
1886 if( requiredsize > *nvars )
1887 {
1888 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
1889 SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) );
1890
1891 SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) );
1892 assert( requiredsize <= *nvars );
1893 }
1894 }
1895 else
1896 for( v = 0; v < *nvars; ++v )
1897 {
1898 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalars[v], constant) );
1899
1900 if( vars[v] == NULL )
1901 return SCIP_INVALIDDATA;
1902 }
1903
1904 return SCIP_OKAY;
1905}
1907/* computes all and-resultants and their corresponding constraint variables */
1908static
1910 SCIP*const scip, /**< SCIP data structure */
1911 SCIP_Bool const transformed, /**< transformed problem? */
1912 SCIP_VAR*** resvars, /**< pointer to store all resultant variables */
1913 int* nresvars, /**< pointer to store the number of all resultant variables */
1914 SCIP_VAR**** andvars, /**< pointer to store to all resultant variables their corresponding active( or negated) and-constraint variables */
1915 int** nandvars, /**< pointer to store the number of all corresponding and-variables to their corresponding resultant variable */
1916 SCIP_Bool*const existandconshdlr, /**< pointer to store whether the and-constrainthandler exists*/
1917 SCIP_Bool*const existands /**< pointer to store if their exists some and-constraints */
1918 )
1919{
1920 SCIP_CONSHDLR* conshdlr;
1921
1922 assert(scip != NULL);
1923 assert(resvars != NULL);
1924 assert(nresvars != NULL);
1925 assert(andvars != NULL);
1926 assert(nandvars != NULL);
1927 assert(existandconshdlr != NULL);
1928 assert(existands != NULL);
1929
1930 *resvars = NULL;
1931 *nandvars = NULL;
1932 *andvars = NULL;
1933 *nresvars = 0;
1934
1935 /* detect all and-resultants */
1936 conshdlr = SCIPfindConshdlr(scip, "and");
1937 if( conshdlr != NULL )
1938 {
1939 SCIP_CONS** andconss;
1940 int nandconss;
1941 int* shouldnotbeinand;
1942 int a;
1943 int c;
1944 int r;
1945 int v;
1946 int pos;
1947 int ncontainedands;
1948
1949 andconss = NULL;
1950 nandconss = 0;
1951 *existandconshdlr = TRUE;
1952
1953 /* if we write the original problem we need to get the original and constraints */
1954 if( !transformed )
1955 {
1956 SCIP_CONS** origconss;
1957 int norigconss;
1958
1959 origconss = SCIPgetOrigConss(scip);
1960 norigconss = SCIPgetNOrigConss(scip);
1961
1962 /* allocate memory for all possible and-constraints */
1963 SCIP_CALL( SCIPallocBufferArray(scip, &andconss, norigconss) );
1964
1965 /* collect all original and-constraints */
1966 for( c = norigconss - 1; c >= 0; --c )
1967 {
1968 conshdlr = SCIPconsGetHdlr(origconss[c]);
1969 assert( conshdlr != NULL );
1970
1971 if( strcmp(SCIPconshdlrGetName(conshdlr), "and") == 0 )
1972 {
1973 andconss[nandconss] = origconss[c];
1974 ++nandconss;
1975 }
1976 }
1977 }
1978 else
1979 {
1980 nandconss = SCIPconshdlrGetNConss(conshdlr);
1981 andconss = SCIPconshdlrGetConss(conshdlr);
1982 }
1983
1984 assert(andconss != NULL || nandconss == 0);
1985
1986 *nresvars = nandconss;
1987
1988 if( nandconss > 0 )
1989 {
1990 *existands = TRUE;
1991
1992 assert(andconss != NULL);
1993
1994 SCIP_CALL( SCIPallocMemoryArray(scip, resvars, *nresvars) );
1995 SCIP_CALL( SCIPallocMemoryArray(scip, andvars, *nresvars) );
1996 SCIP_CALL( SCIPallocMemoryArray(scip, nandvars, *nresvars) );
1997
1998 /* collect all and-constraint variables */
1999 for( c = nandconss - 1; c >= 0; --c )
2000 {
2001 SCIP_VAR** scipandvars;
2002
2003 assert(andconss[c] != NULL);
2004
2005 scipandvars = SCIPgetVarsAnd(scip, andconss[c]);
2006 (*nandvars)[c] = SCIPgetNVarsAnd(scip, andconss[c]);
2007 SCIP_CALL( SCIPduplicateMemoryArray(scip, &((*andvars)[c]), scipandvars, (*nandvars)[c]) ); /*lint !e866 */
2008 SCIP_CALL( getBinVarsRepresentatives(scip, (*andvars)[c], (*nandvars)[c], transformed) );
2009
2010 (*resvars)[c] = SCIPgetResultantAnd(scip, andconss[c]);
2011
2012 assert((*andvars)[c] != NULL && (*nandvars)[c] > 0);
2013 assert((*resvars)[c] != NULL);
2014 }
2015
2016 /* sorted the array */
2017 SCIPsortPtrPtrInt((void**)(*resvars), (void**)(*andvars), (*nandvars), SCIPvarComp, (*nresvars));
2018 }
2019 else
2020 *existands = FALSE;
2021
2022 SCIP_CALL( SCIPallocBufferArray(scip, &shouldnotbeinand, *nresvars) );
2023
2024 /* check that all and-constraints doesn't contain any and-resultants, if they do try to resolve this */
2025 /* 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
2026 deleted and the inequality from before needs to be added ) */
2027 assert(*nandvars != NULL || *nresvars == 0);
2028 for( r = *nresvars - 1; r >= 0; --r )
2029 {
2030 ncontainedands = 0;
2031 shouldnotbeinand[ncontainedands] = r;
2032 ++ncontainedands;
2033 v = 0;
2034
2035 assert(*nandvars != NULL);
2036 while( v < (*nandvars)[r] )
2037 {
2038 assert(*andvars != NULL);
2039 assert(*resvars != NULL);
2040 if( SCIPsortedvecFindPtr((void**)(*resvars), SCIPvarComp, (*andvars)[r][v], *nresvars, &pos) )
2041 {
2042 /* check if the found position "pos" is equal to an already visited and resultant in this constraint,
2043 * than here could exist a directed cycle
2044 */
2045 /* better use tarjan's algorithm
2046 * <http://algowiki.net/wiki/index.php?title=Tarjan%27s_algorithm>,
2047 * <http://en.wikipedia.org/wiki/Tarjan%E2%80%99s_strongly_connected_components_algorithm>
2048 * because it could be that the same resultant is part of this and-constraint and than it would fail
2049 * without no cycle
2050 * Note1: tarjans standard algorithm doesn't find cycle from one node to the same;
2051 * Note2: when tarjan's algorithm find a cycle, it's still possible that this cycle is not "real" e.g.
2052 * y = y ~y z (z can also be a product) where y = 0 follows and therefor only "0 = z" is necessary
2053 */
2054 for( a = ncontainedands - 1; a >= 0; --a )
2055 if( shouldnotbeinand[a] == pos )
2056 {
2057 SCIPwarningMessage(scip, "This should not happen here. The and-constraint with resultant variable: ");
2058 SCIP_CALL( SCIPprintVar(scip, (*resvars)[r], NULL) );
2059 SCIPwarningMessage(scip, "possible contains a loop with and-resultant:");
2060 SCIP_CALL( SCIPprintVar(scip, (*resvars)[pos], NULL) );
2061
2062 /* free memory iff necessary */
2063 SCIPfreeBufferArray(scip, &shouldnotbeinand);
2064 if( !transformed )
2065 {
2066 SCIPfreeBufferArray(scip, &andconss);
2067 }
2068 return SCIP_INVALIDDATA;
2069 }
2070 SCIPdebugMsg(scip, "Another and-constraint contains and-resultant:");
2071 SCIPdebug( SCIP_CALL( SCIPprintVar(scip, (*resvars)[pos], NULL) ) );
2072 SCIPdebugMsg(scip, "Trying to resolve.\n");
2073
2074 shouldnotbeinand[ncontainedands] = pos;
2075 ++ncontainedands;
2076
2077 /* try to resolve containing ands */
2078
2079 /* resize array and number of variables */
2080 (*nandvars)[r] = (*nandvars)[r] + (*nandvars)[pos] - 1;
2081 SCIP_CALL( SCIPreallocMemoryArray(scip, &((*andvars)[r]), (*nandvars)[r]) ); /*lint !e866 */
2082
2083 /* copy all variables */
2084 for( a = (*nandvars)[pos] - 1; a >= 0; --a )
2085 (*andvars)[r][(*nandvars)[r] - a - 1] = (*andvars)[pos][a];
2086
2087 /* check same position with new variable, so we do not increase v */
2088 }
2089 else
2090 ++v;
2091 }
2092 }
2093 SCIPfreeBufferArray(scip, &shouldnotbeinand);
2094
2095 /* free memory iff necessary */
2096 if( !transformed )
2097 {
2098 SCIPfreeBufferArray(scip, &andconss);
2099 }
2100 }
2101 else
2102 {
2103 SCIPdebugMsg(scip, "found no and-constraint-handler\n");
2104 *existands = FALSE;
2105 *existandconshdlr = FALSE;
2106 }
2107
2108 return SCIP_OKAY;
2109}
2111/** clears the given line buffer */
2112static
2113void clearBuffer(
2114 char* linebuffer, /**< line */
2115 int* linecnt /**< number of characters in line */
2116 )
2117{
2118 assert( linebuffer != NULL );
2119 assert( linecnt != NULL );
2120
2121 (*linecnt) = 0;
2122 linebuffer[0] = '\0';
2123}
2124
2126/** ends the given line with '\\0' and prints it to the given file stream */
2127static
2128void writeBuffer(
2129 SCIP* scip, /**< SCIP data structure */
2130 FILE* file, /**< output file (or NULL for standard output) */
2131 char* linebuffer, /**< line */
2132 int* linecnt /**< number of characters in line */
2133 )
2134{
2135 assert( scip != NULL );
2136 assert( linebuffer != NULL );
2137 assert( linecnt != NULL );
2138 assert( 0 <= *linecnt && *linecnt < OPB_MAX_LINELEN );
2139
2140 if( (*linecnt) > 0 )
2141 {
2142 linebuffer[(*linecnt)] = '\0';
2143 SCIPinfoMessage(scip, file, "%s", linebuffer);
2144 clearBuffer(linebuffer, linecnt);
2145 }
2146}
2147
2149/** appends extension to line and prints it to the give file stream if the line buffer get full */
2150static
2151void appendBuffer(
2152 SCIP* scip, /**< SCIP data structure */
2153 FILE* file, /**< output file (or NULL for standard output) */
2154 char* linebuffer, /**< line buffer */
2155 int* linecnt, /**< number of characters in line */
2156 const char* extension /**< string to extent the line */
2157 )
2158{
2159 assert(scip != NULL);
2160 assert(linebuffer != NULL);
2161 assert(linecnt != NULL);
2162 assert(extension != NULL);
2163
2164 if( (*linecnt) + (int) strlen(extension) >= OPB_MAX_LINELEN - 1 )
2165 writeBuffer(scip, file, linebuffer, linecnt);
2166
2167 /* append extension to linebuffer */
2168 (void) strncat(linebuffer, extension, OPB_MAX_LINELEN - (unsigned int)(*linecnt));
2169 (*linecnt) += (int) strlen(extension);
2170}
2172/** write objective function */
2173static
2175 SCIP*const scip, /**< SCIP data structure */
2176 FILE*const file, /**< output file, or NULL if standard output should be used */
2177 SCIP_VAR**const vars, /**< array with active (binary) variables */
2178 int const nvars, /**< number of active variables in the problem */
2179 SCIP_VAR** const resvars, /**< array of resultant variables */
2180 int const nresvars, /**< number of resultant variables */
2181 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2182 int const*const nandvars, /**< array of numbers of corresponding and-variables */
2183 SCIP_OBJSENSE const objsense, /**< objective sense */
2184 SCIP_Real const objscale, /**< scalar applied to objective function; external objective value is
2185 * extobj = objsense * objscale * (intobj + objoffset) */
2186 SCIP_Real const objoffset, /**< objective offset from bound shifting and fixing */
2187 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
2188 SCIP_Bool const existands, /**< does some and-constraints exist? */
2189 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
2190 )
2191{
2192 SCIP_VAR* var;
2193 char linebuffer[OPB_MAX_LINELEN+1];
2194 char buffer[OPB_MAX_LINELEN];
2195 SCIP_Longint mult;
2196 SCIP_Bool objective;
2197 int v;
2198 int linecnt;
2199 int pos;
2200
2201 assert(scip != NULL);
2202 assert(file != NULL);
2203 assert(vars != NULL || nvars == 0);
2204 assert(resvars != NULL || nresvars == 0);
2205 assert(andvars != NULL || nandvars == NULL);
2206 assert(multisymbol != NULL);
2207
2208 mult = 1;
2209 objective = !SCIPisZero(scip, objoffset);
2210
2211 clearBuffer(linebuffer, &linecnt);
2212
2213 /* check if a objective function exits and compute the multiplier to
2214 * shift the coefficients to integers */
2215 for( v = 0; v < nvars; ++v )
2216 {
2217 var = vars[v]; /*lint !e613 */
2218
2219#ifndef NDEBUG
2220 {
2221 /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
2222 if( !transformed )
2223 assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL ||
2225 }
2226#endif
2227
2228 /* we found a indicator variable so we assume this is a wbo file */
2229 if( strstr(SCIPvarGetName(var), INDICATORVARNAME) != NULL )
2230 {
2231 /* find the topcost linear inequality which gives us the maximal cost which could be violated by our
2232 * solution, which is an artificial constraint and print this at first
2233 *
2234 * @note: only linear constraint handler is enough in problem stage, otherwise it could be any upgraded linear
2235 * constraint which handles pure binary variables
2236 */
2237 SCIP_CONSHDLR* conshdlr;
2238 SCIP_CONS* topcostcons;
2239 SCIP_Bool printed;
2240
2241 printed = FALSE;
2242 topcostcons = SCIPfindCons(scip, TOPCOSTCONSNAME);
2243
2244 if( topcostcons != NULL )
2245 {
2246 conshdlr = SCIPconsGetHdlr(topcostcons);
2247 assert(conshdlr != NULL);
2248
2249 if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0 )
2250 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %.15g;\n", SCIPgetRhsLinear(scip, topcostcons));
2251 else if( strcmp(SCIPconshdlrGetName(conshdlr), "knapsack") == 0 )
2252 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %" SCIP_LONGINT_FORMAT ";\n",
2253 SCIPgetCapacityKnapsack(scip, topcostcons));
2254 else if( strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0 )
2255 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: 1;\n");
2256 else
2257 {
2258 SCIPABORT();
2259 return SCIP_INVALIDDATA; /*lint !e527 */
2260 }
2261 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2262 writeBuffer(scip, file, linebuffer, &linecnt);
2263 printed = TRUE;
2264 }
2265 /* following works only in transformed stage */
2266 else
2267 {
2268 /* first try linear constraints */
2269 conshdlr = SCIPfindConshdlr(scip, "linear");
2270
2271 if( conshdlr != NULL )
2272 {
2273 SCIP_CONS** conss;
2274 int nconss;
2275 int c;
2276
2277 conss = SCIPconshdlrGetConss(conshdlr);
2278 nconss = SCIPconshdlrGetNConss(conshdlr);
2279
2280 assert(conss != NULL || nconss == 0);
2281
2282 for( c = 0; c < nconss; ++c )
2283 {
2284 SCIP_VAR** linvars;
2285 int nlinvars;
2286 int w;
2287 SCIP_Bool topcostfound;
2288 SCIP_CONS* cons;
2289
2290 cons = conss[c]; /*lint !e613 */
2291 assert(cons != NULL);
2292
2293 linvars = SCIPgetVarsLinear(scip, cons);
2294 nlinvars = SCIPgetNVarsLinear(scip, cons);
2295
2296 assert(linvars != NULL || nlinvars == 0);
2297 topcostfound = FALSE;
2298
2299 for( w = 0; w < nlinvars; ++w )
2300 {
2301 if( strstr(SCIPvarGetName(linvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2302 topcostfound = TRUE;
2303 else
2304 {
2305 assert(!topcostfound);
2306 topcostfound = FALSE;
2307 }
2308 }
2309
2310 if( topcostfound )
2311 {
2312 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %.15g;\n", SCIPgetRhsLinear(scip, cons));
2313 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2314 writeBuffer(scip, file, linebuffer, &linecnt);
2315 printed = TRUE;
2316 break;
2317 }
2318 }
2319 }
2320
2321 if( !printed )
2322 {
2323 /* second try knapsack constraints */
2324 conshdlr = SCIPfindConshdlr(scip, "knapsack");
2325
2326 if( conshdlr != NULL )
2327 {
2328 SCIP_CONS** conss;
2329 int nconss;
2330 int c;
2331
2332 conss = SCIPconshdlrGetConss(conshdlr);
2333 nconss = SCIPconshdlrGetNConss(conshdlr);
2334
2335 assert(conss != NULL || nconss == 0);
2336
2337 for( c = 0; c < nconss; ++c )
2338 {
2339 SCIP_VAR** topvars;
2340 int ntopvars;
2341 int w;
2342 SCIP_Bool topcostfound;
2343 SCIP_CONS* cons;
2344
2345 cons = conss[c]; /*lint !e613 */
2346 assert(cons != NULL);
2347
2348 topvars = SCIPgetVarsKnapsack(scip, cons);
2349 ntopvars = SCIPgetNVarsKnapsack(scip, cons);
2350
2351 assert(topvars != NULL || ntopvars == 0);
2352 topcostfound = FALSE;
2353
2354 for( w = 0; w < ntopvars; ++w )
2355 {
2356 if( strstr(SCIPvarGetName(topvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2357 topcostfound = TRUE;
2358 else
2359 {
2360 assert(!topcostfound);
2361 topcostfound = FALSE;
2362 }
2363 }
2364
2365 if( topcostfound )
2366 {
2367 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %" SCIP_LONGINT_FORMAT ";\n",
2369 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2370 writeBuffer(scip, file, linebuffer, &linecnt);
2371 printed = TRUE;
2372 break;
2373 }
2374 }
2375 }
2376 }
2377
2378 if( !printed )
2379 {
2380 /* third try setppc constraints */
2381 conshdlr = SCIPfindConshdlr(scip, "setppc");
2382
2383 if( conshdlr != NULL )
2384 {
2385 SCIP_CONS** conss;
2386 int nconss;
2387 int c;
2388
2389 conss = SCIPconshdlrGetConss(conshdlr);
2390 nconss = SCIPconshdlrGetNConss(conshdlr);
2391
2392 assert(conss != NULL || nconss == 0);
2393
2394 for( c = 0; c < nconss; ++c )
2395 {
2396 SCIP_VAR** topvars;
2397 int ntopvars;
2398 int w;
2399 SCIP_Bool topcostfound;
2400 SCIP_CONS* cons;
2401
2402 cons = conss[c]; /*lint !e613 */
2403 assert(cons != NULL);
2404
2405 topvars = SCIPgetVarsSetppc(scip, cons);
2406 ntopvars = SCIPgetNVarsSetppc(scip, cons);
2407
2408 assert(topvars != NULL || ntopvars == 0);
2409 topcostfound = FALSE;
2410
2411 for( w = 0; w < ntopvars; ++w )
2412 {
2413 if( strstr(SCIPvarGetName(topvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2414 topcostfound = TRUE;
2415 else
2416 {
2417 assert(!topcostfound);
2418 topcostfound = FALSE;
2419 }
2420 }
2421
2422 if( topcostfound )
2423 {
2424 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: 1;\n");
2425 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2426 writeBuffer(scip, file, linebuffer, &linecnt);
2427 printed = TRUE;
2428 break;
2429 }
2430 }
2431 }
2432 }
2433 }
2434
2435 /* no topcost constraint found, so print empty topcost line, which means there is no upper bound on violated soft constraints */
2436 if( !printed )
2437 {
2438 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: ;\n");
2439 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2440 writeBuffer(scip, file, linebuffer, &linecnt);
2441 }
2442
2443 return SCIP_OKAY;
2444 }
2445
2446 if( !SCIPisZero(scip, SCIPvarGetObj(var)) )
2447 {
2448 objective = TRUE;
2449 while( !SCIPisIntegral(scip, SCIPvarGetObj(var) * mult) )
2450 {
2451 assert(mult * 10 > mult);
2452 mult *= 10;
2453 }
2454 }
2455 }
2456
2457 if( objective )
2458 {
2459 /* opb format supports only minimization; therefore, a maximization problem has to be converted */
2460 if( ( objsense == SCIP_OBJSENSE_MAXIMIZE ) != ( objscale < 0.0 ) )
2461 mult *= -1;
2462
2463 /* there exist a objective function*/
2464 SCIPinfoMessage(scip, file, "* Obj. scale : %.15g\n", objscale / mult);
2465 SCIPinfoMessage(scip, file, "* Obj. offset : %.15g\n", objoffset * mult);
2466
2467 clearBuffer(linebuffer, &linecnt);
2468
2469 SCIPdebugMsg(scip, "print objective function multiplied with %" SCIP_LONGINT_FORMAT "\n", mult);
2470
2471 appendBuffer(scip, file, linebuffer, &linecnt, "min:");
2472
2473#ifndef NDEBUG
2474 if( existands )
2475 {
2476 int c;
2477 /* check that these variables are sorted */
2478 for( c = nresvars - 1; c > 0; --c )
2479 assert(SCIPvarGetIndex(resvars[c]) >= SCIPvarGetIndex(resvars[c - 1])); /*lint !e613 */
2480 }
2481#endif
2482
2483 for( v = 0; v < nvars; ++v )
2484 {
2485 SCIP_Bool negated;
2486 var = vars[v]; /*lint !e613 */
2487
2488 assert(var != NULL);
2489
2490 if( SCIPisZero(scip, SCIPvarGetObj(var)) )
2491 continue;
2492
2493 negated = SCIPvarIsNegated(var);
2494
2495 assert( linecnt != 0 );
2496
2497 if( SCIPvarGetObj(var) * mult > (SCIP_Real)SCIP_LONGINT_MAX )
2498 {
2499 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));
2500 }
2501
2502 /* replace and-resultant with corresponding variables */
2503 if( existands && SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) )
2504 {
2505 int a;
2506
2507 assert(andvars != NULL);
2508 assert(nandvars != NULL);
2509 assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
2510 assert(andvars[pos][nandvars[pos] - 1] != NULL);
2511
2512 negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2513
2514 /* print and-vars */
2515 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2516 (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "",
2517 strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
2518 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2519
2520 for(a = nandvars[pos] - 2; a >= 0; --a )
2521 {
2522 negated = SCIPvarIsNegated(andvars[pos][a]);
2523
2524 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2525 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2526 }
2527 }
2528 else
2529 {
2530 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2531 (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2532 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2533 }
2534 }
2535
2536 /* and objective function line ends with a ';' */
2537 appendBuffer(scip, file, linebuffer, &linecnt, " ;\n");
2538 writeBuffer(scip, file, linebuffer, &linecnt);
2539 }
2540
2541 return SCIP_OKAY;
2542}
2544/* print maybe non linear row in OPB format to file stream */
2545static
2547 SCIP*const scip, /**< SCIP data structure */
2548 FILE*const file, /**< output file (or NULL for standard output) */
2549 char const*const type, /**< row type ("=" or ">=") */
2550 SCIP_VAR**const vars, /**< array of variables */
2551 SCIP_Real const*const vals, /**< array of values */
2552 int const nvars, /**< number of variables */
2553 SCIP_Real lhs, /**< left hand side */
2554 SCIP_VAR** const resvars, /**< array of resultant variables */
2555 int const nresvars, /**< number of resultant variables */
2556 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2557 int const*const nandvars, /**< array of numbers of corresponding and-variables */
2558 SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2559 SCIP_Longint*const mult, /**< multiplier for the coefficients */
2560 char const*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2561 )
2562{
2563 SCIP_VAR* var;
2564 char buffer[OPB_MAX_LINELEN];
2565 char linebuffer[OPB_MAX_LINELEN + 1];
2566 int v;
2567 int pos;
2568 int linecnt;
2569
2570 assert(scip != NULL);
2571 assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2572 assert(mult != NULL);
2573 assert(resvars != NULL);
2574 assert(nresvars > 0);
2575 assert(andvars != NULL && nandvars != NULL);
2576
2577 clearBuffer(linebuffer, &linecnt);
2578
2579 /* check if all coefficients are internal; if not commentstart multiplier */
2580 for( v = 0; v < nvars; ++v )
2581 {
2582 while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
2583 {
2584 if( ABS(*mult) > ABS(*mult * 10) )
2585 return SCIP_INVALIDDATA;
2586 (*mult) *= 10;
2587 }
2588 }
2589
2590 while( !SCIPisIntegral(scip, lhs * (*mult)) )
2591 {
2592 if( ABS(*mult) > ABS(*mult * 10) )
2593 return SCIP_INVALIDDATA;
2594 (*mult) *= 10;
2595 }
2596
2597 /* print comment line if we have to multiply the coefficients to get integrals */
2598 if( ABS(*mult) != 1 )
2599 SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2600
2601#ifndef NDEBUG
2602 /* check that these variables are sorted */
2603 for( v = nresvars - 1; v > 0; --v )
2604 assert(SCIPvarGetIndex(resvars[v]) >= SCIPvarGetIndex(resvars[v - 1]));
2605#endif
2606
2607 /* if we have a soft constraint print the weight*/
2608 if( weight != 0 )
2609 {
2610 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "] ", weight);
2611 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2612 }
2613
2614 /* print coefficients */
2615 for( v = 0; v < nvars; ++v )
2616 {
2617 SCIP_Bool negated;
2618
2619 var = vars[v];
2620 assert( var != NULL );
2621
2622 negated = SCIPvarIsNegated(var);
2623
2624 /* replace and-resultant with corresponding variables */
2625 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) )
2626 {
2627 int a;
2628
2629 assert(andvars != NULL);
2630 assert(nandvars != NULL);
2631 assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
2632 assert(andvars[pos][nandvars[pos] - 1] != NULL);
2633
2634 negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2635
2636 if( vals[v] * (*mult) > (SCIP_Real)SCIP_LONGINT_MAX )
2637 {
2638 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)));
2639 }
2640
2641 /* print and-vars */
2642 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s",
2643 (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "",
2644 strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x") );
2645 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2646
2647 for(a = nandvars[pos] - 2; a >= 0; --a )
2648 {
2649 negated = SCIPvarIsNegated(andvars[pos][a]);
2650
2651 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2652 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2653 }
2654
2655 appendBuffer(scip, file, linebuffer, &linecnt, " ");
2656 }
2657 else
2658 {
2659 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
2660 (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2661 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2662 }
2663 }
2664
2665 /* print left hand side */
2666 if( SCIPisZero(scip, lhs) )
2667 lhs = 0.0;
2668
2669 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
2670 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2671
2672 writeBuffer(scip, file, linebuffer, &linecnt);
2673
2674 return SCIP_OKAY;
2675}
2676
2678/** prints given maybe non-linear constraint information in OPB format to file stream */
2679static
2681 SCIP*const scip, /**< SCIP data structure */
2682 FILE*const file, /**< output file (or NULL for standard output) */
2683 SCIP_VAR**const vars, /**< array of variables */
2684 SCIP_Real*const vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2685 int const nvars, /**< number of variables */
2686 SCIP_Real const lhs, /**< left hand side */
2687 SCIP_Real const rhs, /**< right hand side */
2688 SCIP_VAR** const resvars, /**< array of resultant variables */
2689 int const nresvars, /**< number of resultant variables */
2690 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2691 int const*const nandvars, /**< array of numbers of corresponding and-variables */
2692 SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2693 SCIP_Bool const transformed, /**< transformed constraint? */
2694 char const*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2695 )
2696{
2697 SCIP_VAR** activevars;
2698 SCIP_Real* activevals;
2699 SCIP_Real activeconstant;
2700 SCIP_Longint mult;
2701 SCIP_RETCODE retcode;
2702 int nactivevars;
2703 int v;
2704
2705 assert(scip != NULL);
2706 assert(vars != NULL || nvars == 0);
2707 assert(resvars != NULL);
2708 assert(nresvars > 0);
2709 assert(andvars != NULL && nandvars != NULL);
2710
2711 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2712 return SCIP_OKAY;
2713
2714 nactivevars = nvars;
2715 activevars = NULL;
2716 activevals = NULL;
2717 activeconstant = 0.0;
2718
2719 /* duplicate variable and value array */
2720 if( vars != NULL )
2721 {
2722 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
2723 if( vals != NULL )
2724 {
2725 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
2726 }
2727 else
2728 {
2729 SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2730
2731 for( v = 0; v < nactivevars; ++v )
2732 activevals[v] = 1.0;
2733 }
2734
2735 /* retransform given variables to active variables */
2736 SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2737 }
2738
2739 mult = 1;
2740 retcode = SCIP_OKAY;
2741
2742 if( activevars != NULL )
2743 {
2744 /* print row(s) in OPB format */
2745 if( SCIPisEQ(scip, lhs, rhs) )
2746 {
2747 assert( !SCIPisInfinity(scip, rhs) );
2748
2749 /* equality constraint */
2750 retcode = printNLRow(scip, file, "=", activevars, activevals, nactivevars, rhs - activeconstant, resvars,
2751 nresvars, andvars, nandvars, weight, &mult, multisymbol);
2752 }
2753 else
2754 {
2755 if( !SCIPisInfinity(scip, -lhs) )
2756 {
2757 /* print inequality ">=" */
2758 retcode = printNLRow(scip, file, ">=", activevars, activevals, nactivevars, lhs - activeconstant, resvars,
2759 nresvars, andvars, nandvars, weight, &mult, multisymbol);
2760 }
2761
2762 if( !SCIPisInfinity(scip, rhs) )
2763 {
2764 mult *= -1;
2765
2766 /* print inequality ">=" and multiplying all coefficients by -1 */
2767 retcode = printNLRow(scip, file, ">=", activevars, activevals, nactivevars, rhs - activeconstant, resvars,
2768 nresvars, andvars, nandvars, weight, &mult, multisymbol);
2769 }
2770 }
2771
2772 /* free buffer arrays */
2773 SCIPfreeBufferArray(scip, &activevals);
2774 SCIPfreeBufferArray(scip, &activevars);
2775 }
2776
2777 return retcode;
2778}
2779
2781/* print row in OPB format to file stream */
2782static
2784 SCIP* scip, /**< SCIP data structure */
2785 FILE* file, /**< output file (or NULL for standard output) */
2786 const char* type, /**< row type ("=" or ">=") */
2787 SCIP_VAR** vars, /**< array of variables */
2788 SCIP_Real* vals, /**< array of values */
2789 int nvars, /**< number of variables */
2790 SCIP_Real lhs, /**< left hand side */
2791 SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2792 SCIP_Longint* mult, /**< multiplier for the coefficients */
2793 const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2794 )
2795{
2796 SCIP_VAR* var;
2797 char buffer[OPB_MAX_LINELEN];
2798 char linebuffer[OPB_MAX_LINELEN + 1];
2799 int v;
2800 int linecnt;
2801
2802 assert(scip != NULL);
2803 assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2804 assert(mult != NULL);
2805
2806 clearBuffer(linebuffer, &linecnt);
2807
2808 /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution,
2809 * we can stop printing because it is an artificial constraint
2810 */
2811 if( nvars > 0 && strstr(SCIPvarGetName(vars[0]), INDICATORVARNAME) != NULL )
2812 return SCIP_OKAY;
2813
2814 /* check if all coefficients are integral; if not commentstart multiplier */
2815 for( v = 0; v < nvars; ++v )
2816 {
2817 while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
2818 {
2819 if( ABS(*mult) > ABS(*mult * 10) )
2820 return SCIP_INVALIDDATA;
2821 (*mult) *= 10;
2822 }
2823 }
2824
2825 while( !SCIPisIntegral(scip, lhs * (*mult)) )
2826 {
2827 if( ABS(*mult) > ABS(*mult * 10) )
2828 return SCIP_INVALIDDATA;
2829 (*mult) *= 10;
2830 }
2831
2832 /* print comment line if we have to multiply the coefficients to get integrals */
2833 if( ABS(*mult) != 1 )
2834 SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2835
2836 /* if we have a soft constraint print the weight*/
2837 if( weight != 0 )
2838 {
2839 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "] ", weight);
2840 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2841 }
2842
2843 /* print coefficients */
2844 for( v = 0; v < nvars; ++v )
2845 {
2846 SCIP_Bool negated;
2847
2848 var = vars[v];
2849 assert( var != NULL );
2850
2851 negated = SCIPvarIsNegated(var);
2852
2853 if( vals[v] * (*mult) > (SCIP_Real)SCIP_LONGINT_MAX )
2854 {
2855 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)));
2856 }
2857
2858 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
2859 (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2860 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2861 }
2862
2863 /* print left hand side */
2864 if( SCIPisZero(scip, lhs) )
2865 lhs = 0.0;
2866
2867 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
2868 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2869
2870 writeBuffer(scip, file, linebuffer, &linecnt);
2871
2872 return SCIP_OKAY;
2873}
2874
2876/** prints given linear constraint information in OPB format to file stream */
2877static
2879 SCIP* scip, /**< SCIP data structure */
2880 FILE* file, /**< output file (or NULL for standard output) */
2881 SCIP_VAR** vars, /**< array of variables */
2882 SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2883 int nvars, /**< number of variables */
2884 SCIP_Real lhs, /**< left hand side */
2885 SCIP_Real rhs, /**< right hand side */
2886 SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2887 SCIP_Bool transformed, /**< transformed constraint? */
2888 const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2889 )
2890{
2891 SCIP_VAR** activevars;
2892 SCIP_Real* activevals;
2893 SCIP_Real activeconstant;
2894 SCIP_Longint mult;
2895 SCIP_RETCODE retcode;
2896 int nactivevars;
2897 int v;
2898
2899 assert( scip != NULL );
2900 assert( vars != NULL || nvars == 0 );
2901
2902 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2903 return SCIP_OKAY;
2904
2905 nactivevars = nvars;
2906 activevars = NULL;
2907 activevals = NULL;
2908 activeconstant = 0.0;
2909
2910 /* duplicate variable and value array */
2911 if( vars != NULL )
2912 {
2913 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
2914 if( vals != NULL )
2915 {
2916 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
2917 }
2918 else
2919 {
2920 SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2921
2922 for( v = 0; v < nactivevars; ++v )
2923 activevals[v] = 1.0;
2924 }
2925
2926 /* retransform given variables to active variables */
2927 SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2928 }
2929
2930 mult = 1;
2931 retcode = SCIP_OKAY;
2932
2933 if( activevars != NULL )
2934 {
2935 /* print row(s) in OPB format */
2936 if( SCIPisEQ(scip, lhs, rhs) )
2937 {
2938 assert( !SCIPisInfinity(scip, rhs) );
2939
2940 /* equality constraint */
2941 retcode = printRow(scip, file, "=", activevars, activevals, nactivevars, rhs - activeconstant, weight, &mult,
2942 multisymbol);
2943 }
2944 else
2945 {
2946 if( !SCIPisInfinity(scip, -lhs) )
2947 {
2948 /* print inequality ">=" */
2949 retcode = printRow(scip, file, ">=", activevars, activevals, nactivevars, lhs - activeconstant, weight, &mult,
2950 multisymbol);
2951 }
2952
2953 if( !SCIPisInfinity(scip, rhs) )
2954 {
2955 mult *= -1;
2956
2957 /* print inequality ">=" and multiplying all coefficients by -1 */
2958 retcode = printRow(scip, file, ">=", activevars, activevals, nactivevars, rhs - activeconstant, weight, &mult,
2959 multisymbol);
2960 }
2961 }
2962 /* free buffer arrays */
2963 SCIPfreeBufferArray(scip, &activevals);
2964 SCIPfreeBufferArray(scip, &activevars);
2965 }
2966
2967 return retcode;
2968}
2970/** determine total number of split linear and indicator constraints */
2971static
2973 SCIP*const scip, /**< SCIP data structure */
2974 SCIP_CONS**const conss, /**< array with constraints of the problem */
2975 int const nconss, /**< number of constraints in the problem */
2976 int* nlinearconss, /**< pointer to store the total number of split linear constraints */
2977 int* nindicatorconss /**< pointer to store the total number of indicator constraints */
2978 )
2979{
2980 SCIP_CONSHDLR* conshdlr;
2981 const char* conshdlrname;
2982 SCIP_CONS* cons;
2983 int c;
2984
2985 assert(scip != NULL);
2986 assert(conss != NULL || nconss == 0);
2987 assert(nlinearconss != NULL);
2988 assert(nindicatorconss != NULL);
2989
2990 *nlinearconss = 0;
2991 *nindicatorconss = 0;
2992
2993 /* loop over all constraints */
2994 for( c = 0; c < nconss; ++c )
2995 {
2996 SCIP_Real lhs;
2997 SCIP_Real rhs;
2998 SCIP_Bool success;
2999
3000 cons = conss[c];
3001 assert(cons != NULL);
3002 conshdlr = SCIPconsGetHdlr(cons); /*lint !e613*/
3003 assert(conshdlr != NULL);
3004
3005 conshdlrname = SCIPconshdlrGetName(conshdlr);
3006
3007 if( strcmp(conshdlrname, "and") == 0 )
3008 continue;
3009
3010 if( strcmp(conshdlrname, "pseudoboolean") == 0 )
3011 {
3012 if( SCIPgetIndVarPseudoboolean(scip, cons) != NULL )
3013 ++(*nindicatorconss);
3014
3015 continue;
3016 }
3017
3018 if( strcmp(conshdlrname, "indicator") == 0 )
3019 {
3020 ++(*nindicatorconss);
3021
3022 continue;
3023 }
3024
3025 lhs = SCIPconsGetLhs(scip, cons, &success);
3026
3027 if( !success )
3028 continue;
3029
3030 rhs = SCIPconsGetRhs(scip, cons, &success);
3031
3032 if( !success )
3033 continue;
3034
3035 if( SCIPisEQ(scip, lhs, rhs) )
3036 ++(*nlinearconss);
3037 else
3038 {
3039 if( !SCIPisInfinity(scip, -lhs) )
3040 ++(*nlinearconss);
3041
3042 if( !SCIPisInfinity(scip, rhs) )
3043 ++(*nlinearconss);
3044 }
3045 }
3046}
3048/** write constraints */
3049static
3051 SCIP*const scip, /**< SCIP data structure */
3052 FILE*const file, /**< output file, or NULL if standard output should be used */
3053 SCIP_CONS**const conss, /**< array with constraints of the problem */
3054 int const nconss, /**< number of constraints in the problem */
3055 SCIP_VAR**const vars, /**< array with active (binary) variables */
3056 int const nvars, /**< number of active variables in the problem */
3057 SCIP_VAR** const resvars, /**< array of resultant variables */
3058 int const nresvars, /**< number of resultant variables */
3059 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3060 int const*const nandvars, /**< array of numbers of corresponding and-variables */
3061 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3062 SCIP_Bool const existandconshdlr, /**< does and-constrainthandler exist? */
3063 SCIP_Bool const existands, /**< does some and-constraints exist? */
3064 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3065 )
3066{
3067 SCIP_CONSHDLR* conshdlr;
3068 const char* conshdlrname;
3069 SCIP_CONS* cons = NULL;
3070 SCIP_VAR** consvars;
3071 SCIP_Real* consvals;
3072 SCIP_Bool topcostfound = FALSE;
3073 SCIP_RETCODE retcode = SCIP_OKAY;
3074 int nconsvars;
3075 int v, c;
3076 SCIP_HASHMAP* linconssofindicatorsmap = NULL;
3077 SCIP_HASHMAP* linconssofpbsmap = NULL;
3078
3079 assert(scip != NULL);
3080 assert(file != NULL);
3081 assert(conss != NULL || nconss == 0);
3082 assert(vars != NULL || nvars == 0);
3083 assert(resvars != NULL || nresvars == 0);
3084 assert(andvars != NULL || nandvars == 0);
3085 assert(multisymbol != NULL);
3086
3087 if( transformed )
3088 {
3089 conshdlr = SCIPfindConshdlr(scip, "indicator");
3090
3091 /* find artificial linear constraints which correspond to indicator constraints to avoid double printing */
3092 if( conshdlr != NULL )
3093 {
3094 SCIP_CONS** indconss;
3095 int nindconss;
3096
3097 indconss = SCIPconshdlrGetConss(conshdlr);
3098 nindconss = SCIPconshdlrGetNConss(conshdlr);
3099 assert(indconss != NULL || nindconss == 0);
3100
3101 if( nindconss > 0 )
3102 {
3103 SCIP_CONS* lincons;
3104
3105 /* create the linear constraint of indicator constraints hash map */
3106 SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nindconss) );
3107 assert(indconss != NULL);
3108
3109 for( c = 0; c < nindconss; ++c )
3110 {
3111 assert(indconss[c] != NULL);
3112 lincons = SCIPgetLinearConsIndicator(indconss[c]);
3113 assert(lincons != NULL);
3114
3115 /* insert constraints into mapping */
3116 SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)indconss[c]) );
3117 }
3118 }
3119 }
3120
3121 conshdlr = SCIPfindConshdlr(scip, "pseudoboolean");
3122
3123 /* find artifical linear constraints which correspond to indicator constraints to avoid double printing */
3124 if( conshdlr != NULL )
3125 {
3126 SCIP_CONS** pbconss;
3127 int npbconss;
3128
3129 pbconss = SCIPconshdlrGetConss(conshdlr);
3130 npbconss = SCIPconshdlrGetNConss(conshdlr);
3131 assert(pbconss != NULL || npbconss == 0);
3132
3133 if( npbconss > 0 )
3134 {
3135 SCIP_CONS* lincons;
3136
3137 /* create the linear constraint of indicator constraints hash map */
3138 SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), npbconss) );
3139
3140 for( c = 0; c < npbconss; ++c )
3141 {
3142 assert(pbconss[c] != NULL); /*lint !e613*/
3143 lincons = SCIPgetLinearConsPseudoboolean(scip, pbconss[c]); /*lint !e613*/
3144 assert(lincons != NULL);
3145
3146 /* insert constraints into mapping */
3147 SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)pbconss[c]) );
3148 }
3149 }
3150 }
3151 }
3152 /* in original space we cannot ask the constraint handler for its constraints, therefore we have to loop over all
3153 * original to check for artificial linear once
3154 */
3155 else
3156 {
3157 SCIP_CONS* lincons;
3158 SCIP_Bool pbhashmapcreated = FALSE;
3159 SCIP_Bool indhashmapcreated = FALSE;
3160
3161 /* loop over all constraint for printing */
3162 for( c = 0; c < nconss; ++c )
3163 {
3164 conshdlr = SCIPconsGetHdlr(conss[c]); /*lint !e613*/
3165 assert(conshdlr != NULL);
3166
3167 conshdlrname = SCIPconshdlrGetName(conshdlr);
3168
3169 if( strcmp(conshdlrname, "pseudoboolean") == 0 )
3170 {
3171 if( !pbhashmapcreated )
3172 {
3173 /* create the linear constraint of indicator constraints hash map */
3174 SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), nconss) );
3175 pbhashmapcreated = TRUE;
3176 }
3177
3178 lincons = SCIPgetLinearConsPseudoboolean(scip, conss[c]); /*lint !e613*/
3179 assert(lincons != NULL);
3180
3181 /* insert constraints into mapping */
3182 SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)conss[c]) );
3183 }
3184 else if( strcmp(conshdlrname, "indicator") == 0 )
3185 {
3186 if( !indhashmapcreated )
3187 {
3188 /* create the linear constraint of indicator constraints hash map */
3189 SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nconss) );
3190 indhashmapcreated = TRUE;
3191 }
3192
3193 lincons = SCIPgetLinearConsIndicator(conss[c]); /*lint !e613*/
3194 assert(lincons != NULL);
3195
3196 /* insert constraint into mapping */
3197 SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)conss[c]) );
3198 }
3199 }
3200 }
3201
3202 /* loop over all constraint for printing */
3203 for( c = 0; c < nconss && retcode == SCIP_OKAY; ++c )
3204 {
3205 SCIP_CONS* artcons = NULL;
3206 SCIP_VAR* indvar = NULL;
3207 SCIP_Longint weight = 0LL;
3208
3209 cons = conss[c]; /*lint !e613 */
3210 assert(cons != NULL);
3211
3212 conshdlr = SCIPconsGetHdlr(cons);
3213 assert(conshdlr != NULL);
3214
3215 conshdlrname = SCIPconshdlrGetName(conshdlr);
3216 assert(transformed == SCIPconsIsTransformed(cons));
3217
3218 /* in case the transformed is written only constraint are posted which are enabled in the current node */
3219 assert(!transformed || SCIPconsIsEnabled(cons));
3220
3221 if( linconssofindicatorsmap != NULL )
3222 {
3223 artcons = (SCIP_CONS*)SCIPhashmapGetImage(linconssofindicatorsmap, (void*)cons);
3224
3225 if( artcons != NULL )
3226 continue;
3227 }
3228
3229 if( linconssofpbsmap != NULL )
3230 {
3231 artcons = (SCIP_CONS*)SCIPhashmapGetImage(linconssofpbsmap, (void*)cons);
3232
3233 if( artcons != NULL )
3234 {
3235 indvar = SCIPgetIndVarPseudoboolean(scip, artcons);
3236
3237 if( indvar != NULL )
3238 {
3239 weight = (SCIP_Longint)SCIPround(scip, SCIPvarGetObj(indvar));
3240
3241 if( weight == 0 )
3242 {
3243 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));
3244 SCIPinfoMessage(scip, file, "* ");
3245 SCIP_CALL( SCIPprintCons(scip, artcons, file) );
3246 SCIPinfoMessage(scip, file, ";\n");
3247
3248 continue;
3249 }
3250 }
3251 }
3252 }
3253
3254 /* if we found the topcost linear inequality which gives us the maximal cost which could be violated,
3255 * we can stop printing because it is an artificial constraint
3256 */
3257 if( strstr(SCIPconsGetName(cons), TOPCOSTCONSNAME) != NULL )
3258 {
3259 if( topcostfound )
3260 SCIPwarningMessage(scip, "further topcost constraint <%s> will be considered as hard constraint\n", SCIPconsGetName(cons));
3261 else
3262 {
3263 topcostfound = TRUE;
3264
3265 continue;
3266 }
3267 }
3268
3269 if( strcmp(conshdlrname, "linear") == 0 )
3270 {
3271 if( existands )
3272 {
3273 retcode = printNonLinearCons(scip, file,
3275 SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), resvars, nresvars, andvars, nandvars,
3276 weight, transformed, multisymbol);
3277 }
3278 else
3279 {
3280 retcode = printLinearCons(scip, file,
3282 SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), weight, transformed, multisymbol);
3283 }
3284 }
3285 else if( strcmp(conshdlrname, "setppc") == 0 )
3286 {
3287 consvars = SCIPgetVarsSetppc(scip, cons);
3288 nconsvars = SCIPgetNVarsSetppc(scip, cons);
3289
3290 switch( SCIPgetTypeSetppc(scip, cons) )
3291 {
3293 if( existands )
3294 {
3295 retcode = printNonLinearCons(scip, file, consvars, NULL, nconsvars, 1.0, 1.0, resvars, nresvars,
3296 andvars, nandvars, weight, transformed, multisymbol);
3297 }
3298 else
3299 {
3300 retcode = printLinearCons(scip, file,
3301 consvars, NULL, nconsvars, 1.0, 1.0, weight, transformed, multisymbol);
3302 }
3303 break;
3305 if( existands )
3306 {
3307 retcode = printNonLinearCons(scip, file,
3308 consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, resvars, nresvars, andvars, nandvars,
3309 weight, transformed, multisymbol);
3310 }
3311 else
3312 {
3313 retcode = printLinearCons(scip, file,
3314 consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, weight, transformed, multisymbol);
3315 }
3316 break;
3318 if( existands )
3319 {
3320 retcode = printNonLinearCons(scip, file,
3321 consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), resvars, nresvars, andvars, nandvars,
3322 weight, transformed, multisymbol);
3323 }
3324 else
3325 {
3326 retcode = printLinearCons(scip, file,
3327 consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), weight, transformed, multisymbol);
3328 }
3329 break;
3330 }
3331 }
3332 else if( strcmp(conshdlrname, "logicor") == 0 )
3333 {
3334 if( existands )
3335 {
3336 retcode = printNonLinearCons(scip, file,
3338 resvars, nresvars, andvars, nandvars, weight, transformed, multisymbol);
3339 }
3340 else
3341 {
3342 retcode = printLinearCons(scip, file,
3344 1.0, SCIPinfinity(scip), weight, transformed, multisymbol);
3345 }
3346 }
3347 else if( strcmp(conshdlrname, "knapsack") == 0 )
3348 {
3349 SCIP_Longint* weights;
3350
3351 consvars = SCIPgetVarsKnapsack(scip, cons);
3352 nconsvars = SCIPgetNVarsKnapsack(scip, cons);
3353
3354 /* copy Longint array to SCIP_Real array */
3355 weights = SCIPgetWeightsKnapsack(scip, cons);
3356 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
3357 for( v = 0; v < nconsvars; ++v )
3358 consvals[v] = (SCIP_Real)weights[v];
3359
3360 if( existands )
3361 {
3362 retcode = printNonLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip),
3363 (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), resvars, nresvars, andvars, nandvars,
3364 weight, transformed, multisymbol);
3365 }
3366 else
3367 {
3368 retcode = printLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip),
3369 (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), weight, transformed, multisymbol);
3370 }
3371
3372 SCIPfreeBufferArray(scip, &consvals);
3373 }
3374 else if( strcmp(conshdlrname, "varbound") == 0 )
3375 {
3376 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
3377 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
3378
3379 consvars[0] = SCIPgetVarVarbound(scip, cons);
3380 consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
3381
3382 consvals[0] = 1.0;
3383 consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
3384
3385 if( existands )
3386 {
3387 retcode = printNonLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons),
3388 SCIPgetRhsVarbound(scip, cons), resvars, nresvars, andvars, nandvars, weight, transformed, multisymbol);
3389 }
3390 else
3391 {
3392 retcode = printLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons),
3393 SCIPgetRhsVarbound(scip, cons), weight, transformed, multisymbol);
3394 }
3395
3396 SCIPfreeBufferArray(scip, &consvals);
3397 SCIPfreeBufferArray(scip, &consvars);
3398 }
3399 else if( strcmp(conshdlrname, "indicator") == 0 )
3400 {
3401 SCIP_CONS* lincons;
3402 SCIP_VAR* slackvar;
3403
3404 /* get artificial binary indicator variables */
3405 indvar = SCIPgetBinaryVarIndicator(cons);
3406 assert(indvar != NULL);
3407
3409 {
3410 indvar = SCIPvarGetNegationVar(indvar);
3411 assert(indvar != NULL);
3413
3414 /* get the soft cost of this constraint */
3415 weight = (SCIP_Longint)SCIPround(scip, SCIPvarGetObj(indvar));
3416 }
3417 else
3418 {
3420
3421 /* get the soft cost of this constraint */
3422 weight = (SCIP_Longint)SCIPround(scip, -SCIPvarGetObj(indvar));
3423 }
3424
3425 /* get artificial slack variable */
3426 slackvar = SCIPgetSlackVarIndicator(cons);
3427 assert(slackvar != NULL);
3428
3429 /* only need to print indicator constraints with weights on their indicator variable */
3430 if( weight != 0 )
3431 {
3432 SCIP_VAR** scipvarslinear;
3433 SCIP_Real* scipvalslinear;
3434 SCIP_Bool cont;
3435 int nonbinarypos;
3436
3437 lincons = SCIPgetLinearConsIndicator(cons);
3438 assert(lincons != NULL);
3439
3440 nconsvars = SCIPgetNVarsLinear(scip, lincons);
3441 scipvarslinear = SCIPgetVarsLinear(scip, lincons);
3442 scipvalslinear = SCIPgetValsLinear(scip, lincons);
3443
3444 /* allocate temporary memory */
3445 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, scipvarslinear, nconsvars) );
3446 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, scipvalslinear, nconsvars) );
3447
3448 nonbinarypos = -1;
3449 cont = FALSE;
3450
3451 /* find non-binary variable */
3452 for( v = 0; v < nconsvars; ++v )
3453 {
3454 if( SCIPvarGetType(consvars[v]) != SCIP_VARTYPE_BINARY )
3455 {
3456 if( consvars[v] == slackvar )
3457 {
3458 assert(nonbinarypos == -1);
3459 nonbinarypos = v;
3460 }
3461 else
3462 {
3463 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) );
3464 SCIPinfoMessage(scip, file, "* ");
3465 SCIP_CALL( SCIPprintCons(scip, cons, file) );
3466 SCIPinfoMessage(scip, file, ";\n");
3467 cont = TRUE;
3468 break;
3469 }
3470 }
3471 }
3472
3473 /* if we have not found any non-binary variable we do not print the constraint, maybe we should ??? */
3474 if( nonbinarypos == -1 )
3475 {
3476 SCIPwarningMessage(scip, "cannot print linear constraint <%s> of indicator constraint <%s> because it has no slack variable\n", SCIPconsGetName(lincons), SCIPconsGetName(cons) );
3477 SCIPinfoMessage(scip, file, "* ");
3478 SCIP_CALL( SCIPprintCons(scip, cons, file) );
3479 SCIPinfoMessage(scip, file, ";\n");
3480
3481 /* free temporary memory */
3482 SCIPfreeBufferArray(scip, &consvals);
3483 SCIPfreeBufferArray(scip, &consvars);
3484 continue;
3485 }
3486
3487 /* if the constraint has more than two non-binary variables is not printable and we go to the next */
3488 if( cont )
3489 {
3490 /* free temporary memory */
3491 SCIPfreeBufferArray(scip, &consvals);
3492 SCIPfreeBufferArray(scip, &consvars);
3493 continue;
3494 }
3495
3496 assert(0 <= nonbinarypos && nonbinarypos < nconsvars);
3497
3498 /* remove slackvariable in linear constraint for printing */
3499 --nconsvars;
3500 consvars[nonbinarypos] = consvars[nconsvars];
3501 consvals[nonbinarypos] = consvals[nconsvars];
3502
3503 if( existands )
3504 {
3505 retcode = printNonLinearCons(scip, file,
3506 consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
3507 resvars, nresvars, andvars, nandvars,
3508 weight, transformed, multisymbol);
3509 }
3510 else
3511 {
3512 retcode = printLinearCons(scip, file,
3513 consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
3514 weight, transformed, multisymbol);
3515 }
3516
3517 /* free temporary memory */
3518 SCIPfreeBufferArray(scip, &consvals);
3519 SCIPfreeBufferArray(scip, &consvars);
3520 }
3521 else
3522 {
3523 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) );
3524 SCIPinfoMessage(scip, file, "* ");
3525 SCIP_CALL( SCIPprintCons(scip, cons, file) );
3526 SCIPinfoMessage(scip, file, ";\n");
3527 }
3528 }
3529 else if( strcmp(conshdlrname, "and") == 0 )
3530 {
3531 /* all resultants of the and constraint will be replaced by all corresponding variables of this constraint,
3532 * so no and-constraint will be printed directly
3533 */
3534 assert(existandconshdlr);
3535 }
3536 else if( strcmp(conshdlrname, "pseudoboolean") == 0 )
3537 {
3538 /* all and-resultants in linear constraints will be replaced by the corresponding variable products,
3539 * so no pseudoboolean constraint will be printed directly
3540 */
3541 assert(existands);
3542 }
3543 else
3544 {
3545 SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
3546 SCIPinfoMessage(scip, file, "* ");
3547 SCIP_CALL( SCIPprintCons(scip, cons, file) );
3548 SCIPinfoMessage(scip, file, ";\n");
3549 }
3550 }
3551
3552 if( retcode == SCIP_INVALIDDATA )
3553 {
3554 assert(cons != NULL);
3555
3556 SCIPerrorMessage("Cannot print constraint %s with non-integral coefficient or sides in opb-format\n",
3557 SCIPconsGetName(cons));
3558 SCIP_CALL( SCIPprintCons(scip, cons, stderr) );
3559 SCIPinfoMessage(scip, file, ";\n");
3560 }
3561
3562 if( linconssofpbsmap != NULL )
3563 {
3564 /* free hash map */
3565 SCIPhashmapFree(&linconssofpbsmap);
3566 }
3567 if( linconssofindicatorsmap != NULL )
3568 {
3569 /* free hash map */
3570 SCIPhashmapFree(&linconssofindicatorsmap);
3571 }
3572
3573 return retcode;
3574}
3576/* write fixed variables (unless already done because they are an and resultant or and variable) */
3577static
3579 SCIP*const scip, /**< SCIP data structure */
3580 FILE*const file, /**< output file, or NULL if standard output should be used */
3581 SCIP_VAR** vars, /**< array with active (binary) variables */
3582 int nvars, /**< number of active variables in the problem */
3583 SCIP_HASHTABLE*const printedfixing, /**< hashmap to store if a fixed variable was already printed */
3584 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3585 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3586 )
3587{
3588 char linebuffer[OPB_MAX_LINELEN+1];
3589 char buffer[OPB_MAX_LINELEN];
3590 int linecnt;
3591 int v;
3592
3593 assert(scip != NULL);
3594 assert(file != NULL);
3595 assert(vars != NULL || nvars == 0);
3596 assert(printedfixing != NULL);
3597 assert(multisymbol != NULL);
3598
3599 clearBuffer(linebuffer, &linecnt);
3600
3601 /* print variables which are fixed */
3602 for( v = 0; v < nvars; ++v )
3603 {
3604 SCIP_VAR* var;
3605 SCIP_Real lb;
3606 SCIP_Real ub;
3607 SCIP_Bool neg = FALSE;
3608
3609 assert( vars != NULL );
3610 var = vars[v];
3611
3612 if( transformed )
3613 {
3614 /* in case the transformed is written only local bounds are posted which are valid in the current node */
3615 lb = SCIPvarGetLbLocal(var);
3616 ub = SCIPvarGetUbLocal(var);
3617 }
3618 else
3619 {
3620 lb = SCIPvarGetLbOriginal(var);
3621 ub = SCIPvarGetUbOriginal(var);
3622 }
3623 assert(lb > -0.5 && ub < 1.5);
3624 assert(SCIPisFeasIntegral(scip, lb));
3625 assert(SCIPisFeasIntegral(scip, ub));
3626
3627 /* print fixed and-resultants */
3628 if( lb > 0.5 || ub < 0.5 )
3629 {
3630 if( transformed ) {
3631 SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &var, &neg) );
3632 }
3633
3634 if( SCIPhashtableExists(printedfixing, (void*)var) )
3635 continue;
3636
3637 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %.15g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
3638 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3639
3640 /* add variable to the hashmap */
3641 SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
3642 }
3643 }
3644
3645 writeBuffer(scip, file, linebuffer, &linecnt);
3646
3647 return SCIP_OKAY;
3648}
3650/* write and constraints of inactive but relevant and-resultants and and variables which are fixed to one */
3651static
3653 SCIP*const scip, /**< SCIP data structure */
3654 FILE*const file, /**< output file, or NULL if standard output should be used */
3655 SCIP_VAR**const resvars, /**< array of resultant variables */
3656 int const nresvars, /**< number of resultant variables */
3657 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3658 int const*const nandvars, /**< array of numbers of corresponding and-variables */
3659 SCIP_HASHTABLE*const printedfixing, /**< hashmap to store if a fixed variable was already printed */
3660 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3661 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3662 )
3663{
3664 SCIP_VAR* resvar;
3665 SCIP_Longint rhslhs;
3666 char linebuffer[OPB_MAX_LINELEN+1];
3667 char buffer[OPB_MAX_LINELEN];
3668 int linecnt;
3669 int r, v;
3670
3671 assert(scip != NULL);
3672 assert(file != NULL);
3673 assert(resvars != NULL || nresvars == 0);
3674 assert(nandvars != NULL || nresvars == 0);
3675 assert(andvars != NULL || nandvars == NULL);
3676 assert(multisymbol != NULL);
3677
3678 clearBuffer(linebuffer, &linecnt);
3679
3680 /* print and-variables which are fixed */
3681 /* @todo remove this block here and the hashtable and let writeOpbFixedVars() do the job? */
3682 for( r = nresvars - 1; r >= 0; --r )
3683 {
3684 SCIP_VAR* var;
3685 SCIP_Bool neg;
3686 SCIP_Real lb;
3687 SCIP_Real ub;
3688
3689 assert( resvars != NULL );
3690 resvar = resvars[r];
3691
3692 if( transformed )
3693 {
3694 /* in case the transformed is written only local bounds are posted which are valid in the current node */
3695 lb = SCIPvarGetLbLocal(resvar);
3696 ub = SCIPvarGetUbLocal(resvar);
3697 }
3698 else
3699 {
3700 lb = SCIPvarGetLbOriginal(resvar);
3701 ub = SCIPvarGetUbOriginal(resvar);
3702 }
3703
3704 /* print fixed and-resultants */
3705 if( lb > 0.5 || ub < 0.5 )
3706 {
3707 /* coverity[copy_paste_error] */
3708 SCIP_CALL( SCIPgetBinvarRepresentative(scip, resvar, &var, &neg) );
3709
3710 assert(SCIPisFeasIntegral(scip, lb));
3711 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %.15g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
3712 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3713
3714 /* add variable to the hashmap */
3715 SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
3716 }
3717
3718 assert( andvars != NULL && nandvars != NULL );
3719 assert( andvars[r] != NULL || nandvars[r] == 0 );
3720
3721 /* print fixed and-variables */
3722 for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
3723 {
3724 assert( andvars[r] != NULL );
3725 assert( andvars[r][v] != NULL );
3726
3727 if( transformed )
3728 {
3729 /* in case the transformed is written only local bounds are posted which are valid in the current node */
3730 lb = SCIPvarGetLbLocal(andvars[r][v]);
3731 ub = SCIPvarGetUbLocal(andvars[r][v]);
3732 }
3733 else
3734 {
3735 lb = SCIPvarGetLbOriginal(andvars[r][v]);
3736 ub = SCIPvarGetUbOriginal(andvars[r][v]);
3737 }
3738
3739 if( lb > 0.5 || ub < 0.5 )
3740 {
3741 SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
3742
3743 assert(SCIPisFeasIntegral(scip, lb));
3744 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %.15g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
3745 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3746
3747 /* add variable to the hashmap */
3748 SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
3749 }
3750 }
3751 }
3752
3753 /* print and-constraints with fixed and-resultant to zero and all and-constraints with
3754 * aggregated resultant, otherwise we would loose this information
3755 */
3756 for( r = nresvars - 1; r >= 0; --r )
3757 {
3758 assert( resvars != NULL );
3759 resvar = resvars[r];
3760 rhslhs = (SCIPvarGetUbLocal(resvar) < 0.5) ? 0 : ((SCIPvarGetLbLocal(resvar) > 0.5) ? 1 : -1);
3761
3762 /* if and resultant is fixed to 0 and at least one and-variable is fixed to zero, we don't print this redundant constraint */
3763 if( rhslhs == 0 )
3764 {
3765 SCIP_Bool cont;
3766
3767 cont = FALSE;
3768
3769 assert( andvars != NULL && nandvars != NULL );
3770 assert( andvars[r] != NULL || nandvars[r] == 0 );
3771
3772 /* if resultant variable and one other and variable is already zero, so we did not need to print this and
3773 * constraint because all other variables are free
3774 */
3775 for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
3776 {
3777 assert( andvars[r] != NULL );
3778 assert( andvars[r][v] != NULL );
3779
3780 if( SCIPvarGetUbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
3781 {
3782 cont = TRUE;
3783 break;
3784 }
3785 }
3786
3787 if( cont )
3788 continue;
3789 }
3790 /* if and resultant is fixed to 1 and all and-variable are fixed to 1 too, we don't print this redundant constraint */
3791 else if( rhslhs == 1 )
3792 {
3793 SCIP_Bool cont;
3794
3795 cont = TRUE;
3796
3797 assert( andvars != NULL && nandvars != NULL );
3798 assert( andvars[r] != NULL || nandvars[r] == 0 );
3799
3800 /* if all variables are already fixed to one, we do not need to print this and constraint */
3801 for( v = nandvars[r] - 1; v >= 0; --v )
3802 {
3803 assert( andvars[r] != NULL );
3804 assert( andvars[r][v] != NULL );
3805
3806 if( SCIPvarGetLbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
3807 {
3808 cont = FALSE;
3809 break;
3810 }
3811 }
3812
3813 if( cont )
3814 continue;
3815 }
3816
3817 /* print and with fixed or aggregated and-resultant */
3818 /* rhslhs equals to 0 means the and constraint is relevant due to it's not clear on which values the and variables are
3819 * rhslhs equals to 1 means the and constraint is irrelevant cause all and variables have to be 1 too
3820 * rhslhs equals to -1 means the and constraint is relevant cause the variable is only aggregated */
3821 if( !SCIPvarIsActive(resvar) )
3822 {
3823 SCIP_VAR* var;
3824 SCIP_Bool neg;
3825 SCIP_Bool firstprinted;
3826
3827 firstprinted = FALSE;
3828
3829 assert( andvars != NULL && nandvars != NULL );
3830 assert( andvars[r] != NULL || nandvars[r] == 0 );
3831
3832 for( v = nandvars[r] - 1; v >= 0; --v )
3833 {
3834 assert( andvars[r] != NULL );
3835 assert( andvars[r][v] != NULL );
3836
3837 SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
3838
3839 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", (firstprinted) ? multisymbol : "", neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"));
3840 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3841
3842 firstprinted = TRUE;
3843 }
3844
3845 /* if the resultant is aggregated we need to print his binary representation */
3846 if( rhslhs == -1 )
3847 {
3848 int pos;
3849
3850 assert(transformed);
3851
3852 SCIP_CALL( SCIPgetBinvarRepresentative(scip, resvar, &resvar, &neg) );
3853
3854#ifndef NDEBUG
3855 if( neg )
3856 assert(SCIPvarIsActive(SCIPvarGetNegationVar(resvar)));
3857 else
3858 assert(SCIPvarIsActive(resvar));
3859#endif
3860
3861 /* replace and-resultant with corresponding variables */
3862 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, neg ? SCIPvarGetNegationVar(resvar) : resvar, nresvars, &pos) )
3863 {
3864 SCIP_Bool negated;
3865 int a;
3866
3867 assert(andvars != NULL);
3868 assert(nandvars != NULL);
3869 assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
3870 assert(andvars[pos][nandvars[pos] - 1] != NULL);
3871
3872 negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
3873
3874 /* print and-vars */
3875 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, neg ? " +1%s%s%s" : " -1%s%s%s", multisymbol, negated ? "~" : "",
3876 strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
3877 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3878
3879 for(a = nandvars[pos] - 2; a >= 0; --a )
3880 {
3881 negated = SCIPvarIsNegated(andvars[pos][a]);
3882
3883 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
3884 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3885 }
3886
3887 appendBuffer(scip, file, linebuffer, &linecnt, " ");
3888
3889 if( neg )
3890 rhslhs = 1;
3891 else
3892 rhslhs = 0;
3893 }
3894 else
3895 {
3896 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " -1%s%s%s", multisymbol, neg ? "~" : "",
3897 strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(resvar) : resvar), "x"));
3898 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3899
3900 rhslhs = 0;
3901 }
3902 }
3903
3904 /* print rhslhs */
3905 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " = %" SCIP_LONGINT_FORMAT " ;\n", rhslhs);
3906 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3907
3908 writeBuffer(scip, file, linebuffer, &linecnt);
3909 }
3910 }
3911
3912 return SCIP_OKAY;
3913}
3915/* writes problem to file */
3916static
3918 SCIP* scip, /**< SCIP data structure */
3919 FILE* file, /**< output file, or NULL if standard output should be used */
3920 const char* name, /**< problem name */
3921 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
3922 SCIP_OBJSENSE objsense, /**< objective sense */
3923 SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
3924 * extobj = objsense * objscale * (intobj + objoffset) */
3925 SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
3926 SCIP_VAR** vars, /**< array with active (binary) variables */
3927 int nvars, /**< number of active variables in the problem */
3928 SCIP_CONS** conss, /**< array with constraints of the problem */
3929 int nconss, /**< number of constraints in the problem */
3930 SCIP_VAR** const resvars, /**< array of resultant variables */
3931 int const nresvars, /**< number of resultant variables */
3932 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3933 int const*const nandvars, /**< array of numbers of corresponding and-variables */
3934 SCIP_Bool const existandconshdlr, /**< does and-constrainthandler exist? */
3935 SCIP_Bool const existands, /**< does some and-constraints exist? */
3936 SCIP_RESULT* result /**< pointer to store the result of the file writing call */
3937 )
3938{
3939 char multisymbol[OPB_MAX_LINELEN];
3940 SCIP_HASHTABLE* printedfixing;
3941 SCIP_Bool usesymbol;
3942 SCIP_RETCODE retcode;
3943 int nlinearconss;
3944 int nindicatorconss;
3945
3946 assert( scip != NULL );
3947 assert( vars != NULL || nvars == 0 );
3948 assert( conss != NULL || nconss == 0 );
3949 assert( result != NULL );
3950
3951 /* check if should use a multipliers symbol star '*' between coefficients and variables */
3952 SCIP_CALL( SCIPgetBoolParam(scip, "reading/" READER_NAME "/multisymbol", &usesymbol) );
3953 (void) SCIPsnprintf(multisymbol, OPB_MAX_LINELEN, "%s", usesymbol ? " * " : " ");
3954
3955 /* determine how many split linear and indicator constraints exist */
3956 determineTotalNumberLinearConss(scip, conss, nconss, &nlinearconss, &nindicatorconss);
3957
3958 /* print statistics as comment to file */
3959 SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n");
3960 SCIPinfoMessage(scip, file, "* Problem name : %s\n", name);
3961 SCIPinfoMessage(scip, file, "* Variables : %d\n", nvars - nresvars - nindicatorconss);
3962 SCIPinfoMessage(scip, file, "* Constraints : %d\n", nlinearconss);
3963
3964 /* create a hash table */
3965 SCIP_CALL( SCIPhashtableCreate(&printedfixing, SCIPblkmem(scip), nvars,
3966 SCIPvarGetHashkey, SCIPvarIsHashkeyEq, SCIPvarGetHashkeyVal, NULL) );
3967
3968 /* write objective function */
3969 SCIP_CALL( writeOpbObjective(scip, file, vars, nvars, resvars, nresvars, andvars, nandvars,
3970 objsense, objscale, objoffset, multisymbol, existands, transformed) );
3971
3972 /* write constraints */
3973 retcode = writeOpbConstraints(scip, file, conss, nconss, vars, nvars, resvars, nresvars, andvars, nandvars,
3974 multisymbol, existandconshdlr, existands, transformed);
3975
3976 if( existands && (retcode == SCIP_OKAY) )
3977 {
3978 /* write and constraints of inactive but relevant and-resultants and and-variables which are fixed to one
3979 with no fixed and resultant */
3980 SCIP_CALL( writeOpbRelevantAnds(scip, file, resvars, nresvars, andvars, nandvars, printedfixing, multisymbol, transformed) );
3981 }
3982
3983 /* write fixed variables */
3984 SCIP_CALL( writeOpbFixedVars(scip, file, vars, nvars, printedfixing, multisymbol, transformed) );
3985
3986 SCIPhashtableFree(&printedfixing);
3987
3988 *result = SCIP_SUCCESS;
3989
3990 return retcode;
3991}
3992
3993
3994/*
3995 * extern methods
3997
3998/** reads problem from file */
4000 SCIP* scip, /**< SCIP data structure */
4001 SCIP_READER* reader, /**< the file reader itself */
4002 const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
4003 SCIP_RESULT* result /**< pointer to store the result of the file reading call */
4004 )
4005{ /*lint --e{715}*/
4006 OPBINPUT opbinput;
4007 SCIP_RETCODE retcode;
4008 int i;
4009
4010 assert(scip != NULL); /* for lint */
4011 assert(reader != NULL);
4012
4013 /* initialize OPB input data (use block memory because order can change during execution) */
4014 opbinput.file = NULL;
4016 opbinput.linebuf[0] = '\0';
4017 opbinput.linebufsize = OPB_MAX_LINELEN;
4019 opbinput.token[0] = '\0';
4021 opbinput.tokenbuf[0] = '\0';
4022 for( i = 0; i < OPB_MAX_PUSHEDTOKENS; ++i )
4023 {
4024 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(opbinput.pushedtokens[i]), OPB_MAX_LINELEN) ); /*lint !e866 */
4025 }
4026
4027 opbinput.npushedtokens = 0;
4028 opbinput.linenumber = 1;
4029 opbinput.linepos = 0;
4030 opbinput.objsense = SCIP_OBJSENSE_MINIMIZE;
4031 opbinput.eof = FALSE;
4032 opbinput.haserror = FALSE;
4033 opbinput.nproblemcoeffs = 0;
4034 opbinput.wbo = FALSE;
4035 opbinput.topcost = -SCIPinfinity(scip);
4036 opbinput.nindvars = 0;
4037#if GENCONSNAMES == TRUE
4038 opbinput.consnumber = 0;
4039#endif
4040
4041 /* read the file */
4042 retcode = readOPBFile(scip, &opbinput, filename);
4043
4044 /* free dynamically allocated memory */
4045 for( i = OPB_MAX_PUSHEDTOKENS - 1; i >= 0; --i )
4046 {
4047 SCIPfreeBlockMemoryArray(scip, &(opbinput.pushedtokens[i]), OPB_MAX_LINELEN);
4048 }
4049 SCIPfreeBlockMemoryArray(scip, &opbinput.tokenbuf, OPB_MAX_LINELEN);
4051 SCIPfreeBlockMemoryArray(scip, &opbinput.linebuf, opbinput.linebufsize);
4052
4053 if( retcode == SCIP_PLUGINNOTFOUND )
4054 retcode = SCIP_READERROR;
4055
4056 SCIP_CALL( retcode );
4057
4058 if( opbinput.nproblemcoeffs > 0 )
4059 {
4060 SCIPwarningMessage(scip, "there might be <%d> coefficients or weight out of range!\n", opbinput.nproblemcoeffs);
4061 }
4062
4063 /* evaluate the result */
4064 if( opbinput.haserror )
4065 return SCIP_READERROR;
4066 else
4067 {
4068 /* set objective sense */
4069 SCIP_CALL( SCIPsetObjsense(scip, opbinput.objsense) );
4070 *result = SCIP_SUCCESS;
4071 }
4072
4073 return SCIP_OKAY;
4075
4076/** writes problem to file */
4078 SCIP* scip, /**< SCIP data structure */
4079 FILE* file, /**< output file, or NULL if standard output should be used */
4080 const char* name, /**< problem name */
4081 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4082 SCIP_OBJSENSE objsense, /**< objective sense */
4083 SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4084 * extobj = objsense * objscale * (intobj + objoffset) */
4085 SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4086 SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
4087 int nvars, /**< number of active variables in the problem */
4088 int nbinvars, /**< number of binary variables */
4089 int nintvars, /**< number of general integer variables */
4090 int nimplvars, /**< number of implicit integer variables */
4091 int ncontvars, /**< number of continuous variables */
4092 SCIP_VAR** fixedvars, /**< array with fixed variables */
4093 int nfixedvars, /**< number of fixed and aggregated variables in the problem */
4094 SCIP_CONS** conss, /**< array with constraints of the problem */
4095 int nconss, /**< number of constraints in the problem */
4096 SCIP_Bool genericnames, /**< should generic variable and constraint names be used */
4097 SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4098 )
4099{ /*lint --e{715}*/
4100 SCIP_VAR*** andvars;
4101 SCIP_VAR** resvars;
4102 SCIP_Bool existands;
4103 SCIP_Bool existandconshdlr;
4104 SCIP_RETCODE retcode = SCIP_OKAY;
4105 int* nandvars;
4106 int nresvars;
4107 int v;
4108 SCIP_CONSHDLR* indicatorhdlr = SCIPfindConshdlr(scip, "indicator");
4109 int nindicatorconss = indicatorhdlr != NULL ? SCIPconshdlrGetNConss(indicatorhdlr) : 0;
4110
4111 /* computes all and-resultants and their corresponding constraint variables */
4112 /* coverity[leaked_storage] */
4113 SCIP_CALL( computeAndConstraintInfos(scip, transformed, &resvars, &nresvars, &andvars, &nandvars, &existandconshdlr, &existands) );
4114
4115 if( nintvars > 0 || ncontvars + nimplvars > nindicatorconss + nresvars )
4116 {
4117 SCIPwarningMessage(scip, "only binary problems can be written in OPB format.\n");
4118 *result = SCIP_DIDNOTRUN;
4119 }
4120 else
4121 {
4122 if( genericnames )
4123 {
4124#ifndef NDEBUG
4125 /* check for correct names for opb-format */
4126 int idx;
4127 int pos;
4128
4129 for( v = nvars - 1; v >= 0; --v )
4130 {
4131 if( existands )
4132 {
4133 /* and variables are artificial */
4134 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4135 continue;
4136 }
4137
4138 assert(sscanf(SCIPvarGetName(vars[v]), "x%d", &idx) == 1);
4139 }
4140#endif
4141 retcode = writeOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4142 nvars, conss, nconss, resvars, nresvars, andvars, nandvars, existandconshdlr, existands, result);
4143 }
4144 else
4145 {
4146 SCIP_Bool printed;
4147 int idx;
4148 int pos;
4149
4150 printed = FALSE;
4151
4152 /* check if there are already generic names for all (not fixed variables)*/
4153 for( v = nvars - 1; v >= 0; --v )
4154 if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4155 {
4156 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 )
4157 {
4158 SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4159 SCIP_CALL( SCIPprintVar(scip, vars[v], NULL) );
4160 SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4161
4162 if( transformed )
4163 {
4164 SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4165 SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4166 }
4167 else
4168 {
4169 SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4170 SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4171 }
4172 printed = TRUE;
4173 break;
4174 }
4175 }
4176
4177 if( !printed )
4178 {
4179 /* check if there are already generic names for all (fixed variables)*/
4180 for( v = nfixedvars - 1; v >= 0; --v )
4181 if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4182 {
4183 /* coverity[secure_coding] */
4184 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 )
4185 {
4186 SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4187 SCIP_CALL( SCIPprintVar(scip, fixedvars[v], NULL) );
4188 SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4189
4190 if( transformed )
4191 {
4192 SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4193 SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4194 }
4195 else
4196 {
4197 SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4198 SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4199 }
4200 printed = TRUE;
4201 break;
4202 }
4203 }
4204 }
4205
4206 if( !printed )
4207 {
4208#ifndef NDEBUG
4209 for( v = nvars - 1; v >= 0; --v )
4210 {
4211 if( existands )
4212 {
4213 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4214 continue;
4215 }
4216
4217 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 );
4218 }
4219#endif
4220 retcode = writeOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4221 nvars, conss, nconss, resvars, nresvars, andvars, nandvars, existandconshdlr, existands, result);
4222 }
4223 }
4224
4225 *result = SCIP_SUCCESS;
4226 }
4227
4228 if( existands )
4229 {
4230 /* free temporary buffers */
4231 assert(resvars != NULL);
4232 assert(andvars != NULL);
4233 assert(nandvars != NULL);
4234
4235 for( v = nresvars - 1; v >= 0; --v )
4236 {
4237 assert(andvars[v] != NULL);
4238 SCIPfreeMemoryArray(scip, &andvars[v]);
4239 }
4240
4241 SCIPfreeMemoryArray(scip, &nandvars);
4242 SCIPfreeMemoryArray(scip, &andvars);
4243 SCIPfreeMemoryArray(scip, &resvars);
4244 }
4245
4246 if( retcode == SCIP_INVALIDDATA )
4247 return SCIP_WRITEERROR;
4248
4249 return retcode;
4250}
4251
4252/*
4253 * Callback methods of reader
4254 */
4256/** copy method for reader plugins (called when SCIP copies plugins) */
4257static
4258SCIP_DECL_READERCOPY(readerCopyOpb)
4259{ /*lint --e{715}*/
4260 assert(scip != NULL);
4261 assert(reader != NULL);
4262 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4263
4264 /* call inclusion method of reader */
4266
4267 return SCIP_OKAY;
4268}
4269
4271/** problem reading method of reader */
4272static
4273SCIP_DECL_READERREAD(readerReadOpb)
4274{ /*lint --e{715}*/
4275
4276 SCIP_CALL( SCIPreadOpb(scip, reader, filename, result) );
4277
4278 return SCIP_OKAY;
4279}
4280
4282/** problem writing method of reader */
4283static
4284SCIP_DECL_READERWRITE(readerWriteOpb)
4285{ /*lint --e{715}*/
4286
4287 SCIP_CALL( SCIPwriteOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4288 nvars, nbinvars, nintvars, nimplvars, ncontvars, fixedvars, nfixedvars, conss, nconss, genericnames, result) );
4289
4290 return SCIP_OKAY;
4291}
4292
4293/*
4294 * reader specific interface methods
4296
4297/** includes the opb file reader in SCIP */
4299 SCIP* scip /**< SCIP data structure */
4300 )
4301{
4302 SCIP_READER* reader;
4303
4304 /* include reader */
4306
4307 /* set non fundamental callbacks via setter functions */
4308 SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyOpb) );
4309 SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadOpb) );
4310 SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteOpb) );
4311
4312 /* add opb reader parameters */
4314 "reading/" READER_NAME "/dynamicconss", "should model constraints be subject to aging?",
4315 NULL, FALSE, FALSE/*TRUE*/, NULL, NULL) ); /* have to be FALSE, otherwise an error might inccur in restart during branch and bound */
4317 "reading/" READER_NAME "/multisymbol", "use '*' between coefficients and variables by writing to problem?",
4318 NULL, TRUE, FALSE, NULL, NULL) );
4319
4320 return SCIP_OKAY;
4321}
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:5082
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:5260
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5211
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:5235
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:4074
SCIP_RETCODE SCIPreadOpb(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result)
Definition: reader_opb.c:3996
SCIP_RETCODE SCIPincludeReaderOpb(SCIP *scip)
Definition: reader_opb.c:4295
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_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_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_RETCODE 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:12801
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17775
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17565
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18171
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:18051
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17953
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17611
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17785
SCIP_RETCODE SCIPchgVarBranchPriority(SCIP *scip, SCIP_VAR *var, int branchpriority)
Definition: scip_var.c:8103
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17446
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:18071
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:18161
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17601
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17931
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:10105
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:5741
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:3649
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:2677
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:2780
static void clearBuffer(char *linebuffer, int *linecnt)
Definition: reader_opb.c:2110
static SCIP_Bool isSign(OPBINPUT *opbinput, int *sign)
Definition: reader_opb.c:535
static SCIP_DECL_READERREAD(readerReadOpb)
Definition: reader_opb.c:4270
static SCIP_RETCODE getBinVarsRepresentatives(SCIP *const scip, SCIP_VAR **const vars, int const nvars, SCIP_Bool const transformed)
Definition: reader_opb.c:1797
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:3575
#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:2875
static const char commentchars[]
Definition: reader_opb.c:184
static SCIP_DECL_READERWRITE(readerWriteOpb)
Definition: reader_opb.c:4281
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:2171
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:2543
static void writeBuffer(SCIP *scip, FILE *file, char *linebuffer, int *linecnt)
Definition: reader_opb.c:2125
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:1906
static SCIP_RETCODE getActiveVariables(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
Definition: reader_opb.c:1861
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:3047
static void determineTotalNumberLinearConss(SCIP *const scip, SCIP_CONS **const conss, int const nconss, int *nlinearconss, int *nindicatorconss)
Definition: reader_opb.c:2969
#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:2148
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:3914
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:4255
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