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