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-2023 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 SCIP_VAR**** terms, /**< pointer to store the array with nonlinear variables (must be freed by caller) */
782 SCIP_Real** termcoefs, /**< pointer to store the array with nonlinear coefficients (must be freed by caller) */
783 int** ntermvars, /**< pointer to store the number of nonlinear variables in the terms (must be freed by caller) */
784 int*const ntermcoefs, /**< pointer to store the number of nonlinear coefficients */
785 SCIP_Bool*const newsection, /**< pointer to store whether a new section was encountered */
786 SCIP_Bool*const isNonlinear, /**< pointer to store if we have a nonlinear constraint */
787 SCIP_Bool*const issoftcons, /**< pointer to store whether it is a soft constraint (for wbo files) */
788 SCIP_Real*const weight /**< pointer to store the weight of the soft constraint */
789 )
790{
791 SCIP_VAR** tmpvars;
792 SCIP_Real* tmpcoefs;
793 SCIP_Bool havesign;
794 SCIP_Bool havevalue;
795 SCIP_Bool haveweightstart;
796 SCIP_Bool haveweightend;
797 SCIP_Real coef;
798 int coefsign;
799 int lincoefssize;
800 int termcoefssize;
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);
810 assert(terms != NULL);
811 assert(termcoefs != NULL);
815
816 *linvars = NULL;
817 *lincoefs = NULL;
818 *terms = NULL;
819 *termcoefs = NULL;
820 *ntermvars = NULL;
821 *name = '\0';
822 *nlincoefs = 0;
823 *ntermcoefs = 0;
824 *newsection = FALSE;
826 *issoftcons = FALSE;
827
828 SCIPdebugMsg(scip, "read coefficients\n");
829
830 /* read the first token, which may be the name of the line */
832 {
833 /* remember the token in the token buffer */
835
836 /* get the next token and check, whether it is a colon */
838 {
839 if( strcmp(opbinput->token, ":") == 0 )
840 {
841 /* the second token was a colon ':' the first token is a constraint name */
842 (void)SCIPmemccpy(name, opbinput->tokenbuf, '\0', SCIP_MAXSTRLEN);
843
844 name[SCIP_MAXSTRLEN-1] = '\0';
845 SCIPdebugMsg(scip, "(line %d) read constraint name: '%s'\n", opbinput->linenumber, name);
846
847 /* all but the first coefficient need a sign */
848 if( strcmp(name, "soft") == 0 && (SCIPgetNVars(scip) > 0 || SCIPgetNConss(scip) > 0) )
849 {
850 syntaxError(scip, opbinput, "Soft top cost line needs to be the first non-comment line, and without any objective function.\n");
851 return SCIP_OKAY;
852 }
853 }
854 else
855 {
856 /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */
857 SCIPdebugMsg(scip, "(line %d) constraint has no name\n", opbinput->linenumber);
860 }
861 }
862 else
863 {
864 /* there was only one token left: push it back onto the token stack and parse it as coefficient */
866 }
867 }
868 else
869 {
870 assert(SCIPfeof( opbinput->file ) );
871 opbinput->eof = TRUE;
872 return SCIP_OKAY;
873 }
874
875 /* initialize buffers for storing the coefficients */
886
887 /* read the coefficients */
888 coefsign = +1;
889 coef = 1.0;
890 havesign = FALSE;
894 ntmpcoefs = 0;
895 ntmpvars = 0;
896
898 {
899 if( isEndLine(opbinput) )
900 {
901 *newsection = TRUE;
902 goto TERMINATE;
903 }
904
905 /* check if we reached an equation sense */
906 if( isSense(opbinput, NULL) )
907 {
908 /* put the sense back onto the token stack */
910 goto TERMINATE;
911 }
912
913 /* check if we read a sign */
914 if( isSign(opbinput, &coefsign) )
915 {
916 SCIPdebugMsg(scip, "(line %d) read coefficient sign: %+d\n", opbinput->linenumber, coefsign);
917 havesign = TRUE;
918 continue;
919 }
920
921 /* check if we read a value */
922 if( isValue(scip, opbinput, &coef) )
923 {
924 /* coefficients without a sign are treated as "+" */
925 if( (*nlincoefs > 0 || *ntermcoefs > 0 || ntmpcoefs > 0) && !havesign )
926 {
927 coefsign = 1;
928 havesign = TRUE;
929 }
930
931 SCIPdebugMsg(scip, "(line %d) read coefficient value: %g with sign %+d\n", opbinput->linenumber, coef, coefsign);
932 if( havevalue )
933 {
934 syntaxError(scip, opbinput, "two consecutive values");
935 goto TERMINATE;
936 }
937 havevalue = TRUE;
938
939 /* if we read a wbo file, the first line should be something like "soft: <weight>;", where weight is a value or nothing */
940 if( strcmp(name, "soft") == 0 )
941 {
942 assert(ntmpcoefs == 0);
943
944 tmpcoefs[ntmpcoefs] = coefsign * coef;
945 ++ntmpcoefs;
946 }
947
948 continue;
949 }
950
951 /* check if we are reading a soft constraint line, it start with "[<weight>]", where weight is a value */
952 if( *nlincoefs == 0 && *ntermcoefs == 0 && ntmpcoefs == 0 && !havesign && !havevalue && strcmp(name, "soft") != 0 && isStartingSoftConstraintWeight(scip, opbinput) )
953 {
954 if( !opbinput->wbo )
955 {
956 SCIPwarningMessage(scip, "Found in line %d a soft constraint, without having read a starting top-cost line.\n", opbinput->linenumber);
957 }
959
960 continue;
961 }
963 {
964 *weight = coefsign * coef;
965 SCIPdebugMsg(scip, "(line %d) found soft constraint weight: %g\n", opbinput->linenumber, *weight);
966
967 coefsign = +1;
968 havesign = FALSE;
971 *issoftcons = TRUE;
972
973 continue;
974 }
975
976 /* if we read a '[' we should already read a ']', which indicates that we read a soft constraint,
977 * we have a parsing error */
979 {
980 syntaxError(scip, opbinput, "Wrong soft constraint.");
981 goto TERMINATE;
982 }
983
984 /* if we read the first non-comment line of a wbo file we should never be here */
985 if( strcmp(name, "soft") == 0 )
986 {
987 syntaxError(scip, opbinput, "Wrong soft top cost line.");
988 goto TERMINATE;
989 }
990
991 /* the token is a variable name: get the corresponding variables (or create a new ones) */
993
994 if( ntmpvars > 1 )
995 {
996 /* insert non-linear term */
997 *isNonlinear = TRUE;
998
999 SCIPdebugMsg(scip, "(line %d) found linear term: %+g", opbinput->linenumber, coefsign * coef);
1000#ifndef NDEBUG
1001 {
1002 int v;
1003 for( v = 0; v < ntmpvars; ++v )
1004 {
1005 SCIPdebugMsgPrint(scip, " %s * ", SCIPvarGetName(tmpvars[v]));
1006 }
1007 SCIPdebugMsgPrint(scip, "\n");
1008 }
1009#endif
1010 if( !SCIPisZero(scip, coef) )
1011 {
1013 /* resize the terms, ntermvars, and termcoefs array if needed */
1014 if( *ntermcoefs == termcoefssize )
1015 {
1020 }
1022
1023 /* get memory for the last term */
1024 SCIP_CALL( SCIPallocBufferArray(scip, &((*terms)[*ntermcoefs]), ntmpvars) ); /*lint !e866 */
1025
1026 /* set the number of variable in this term */
1027 (*ntermvars)[*ntermcoefs] = ntmpvars;
1028
1029 /* add all variables */
1030 for( --ntmpvars; ntmpvars >= 0; --ntmpvars )
1031 {
1032 (*terms)[*ntermcoefs][ntmpvars] = tmpvars[ntmpvars];
1033 }
1034 /* add coefficient */
1035 (*termcoefs)[*ntermcoefs] = coefsign * coef;
1036
1037 /***********************/
1038 if( !SCIPisIntegral(scip, (*termcoefs)[*ntermcoefs]) )
1039 {
1040 SCIPwarningMessage(scip, "coefficient %g in line %d not integral.\n", (*termcoefs)[*ntermcoefs], opbinput->linenumber);
1041 }
1042
1043 ++(*ntermcoefs);
1044 }
1045
1046 /* reset the flags and coefficient value for the next coefficient */
1047 coefsign = +1;
1048 coef = 1.0;
1049 havesign = FALSE;
1050 havevalue = FALSE;
1051 ntmpvars = 0;
1052 }
1053 else
1054 {
1055 assert(ntmpvars == 1);
1056 /* insert linear term */
1057 SCIPdebugMsg(scip, "(line %d) found linear term: %+g<%s>\n", opbinput->linenumber, coefsign * coef, SCIPvarGetName(tmpvars[0]));
1058 if( !SCIPisZero(scip, coef) )
1059 {
1061 /* resize the vars and coefs array if needed */
1062 if( *nlincoefs >= lincoefssize )
1063 {
1067 }
1069
1070 /* add coefficient */
1071 (*linvars)[*nlincoefs] = tmpvars[0];
1072 (*lincoefs)[*nlincoefs] = coefsign * coef;
1073
1074 /***********************/
1075 if( !SCIPisIntegral(scip, (*lincoefs)[*nlincoefs]) )
1076 {
1077 SCIPwarningMessage(scip, "coefficient %g in line %d not integral.\n", (*lincoefs)[*nlincoefs], opbinput->linenumber);
1078 }
1079
1080 ++(*nlincoefs);
1081 }
1082
1083 /* reset the flags and coefficient value for the next coefficient */
1084 coefsign = +1;
1085 coef = 1.0;
1086 havesign = FALSE;
1087 havevalue = FALSE;
1088 ntmpvars = 0;
1089 }
1090 }
1091
1092 TERMINATE:
1093 if( !opbinput->haserror )
1094 {
1095 /* all variables should be in the right arrays */
1096 assert(ntmpvars == 0);
1097 /* the following is only the case if we read topcost's of a wbo file, we need to move this topcost value to the
1098 * right array */
1099 if( ntmpcoefs > 0 )
1100 {
1101 /* maximal one topcost value is possible */
1102 assert(ntmpcoefs == 1);
1103 /* no other coefficient should be found here */
1104 assert(*nlincoefs == 0 && *ntermcoefs == 0);
1105
1106 /* copy value */
1107 (*lincoefs)[*nlincoefs] = tmpcoefs[0];
1108
1109 /***********************/
1110 if( !SCIPisIntegral(scip, (*lincoefs)[*nlincoefs]) )
1111 {
1112 SCIPwarningMessage(scip, "topcost not integral.\n");
1113 }
1114
1115 *nlincoefs = 1;
1116 }
1117 }
1118 /* clear memory */
1120 SCIPfreeBufferArray(scip, &tmpvars);
1121
1122 return SCIP_OKAY;
1123}
1125/** set the objective section */
1126static
1128 SCIP*const scip, /**< SCIP data structure */
1129 OPBINPUT*const opbinput, /**< OPB reading data */
1130 const char* sense, /**< objective sense */
1131 SCIP_Real const scale, /**< objective scale */
1132 SCIP_VAR**const linvars, /**< array of linear variables */
1133 SCIP_Real*const coefs, /**< array of objective values for linear variables */
1134 int const ncoefs, /**< number of coefficients for linear part */
1135 SCIP_VAR***const terms, /**< array with nonlinear variables */
1136 SCIP_Real*const termcoefs, /**< array of objective values for nonlinear variables */
1137 int*const ntermvars, /**< number of nonlinear variables in the terms */
1138 int const ntermcoefs /**< number of nonlinear coefficients */
1139 )
1140{
1141 assert(scip != NULL);
1142 assert(opbinput != NULL);
1144 assert(ncoefs == 0 || (linvars != NULL && coefs != NULL));
1145 assert(ntermcoefs == 0 || (terms != NULL && ntermvars != NULL && termcoefs != NULL));
1146
1147 if( !hasError(opbinput) )
1148 {
1149 SCIP_VAR* var;
1150 int v;
1151 char name[SCIP_MAXSTRLEN];
1152
1153 if( strcmp(sense, "max" ) == 0 )
1154 opbinput->objsense = SCIP_OBJSENSE_MAXIMIZE;
1155
1156 /* @todo: what todo with non-linear objectives, maybe create the necessary and-constraints and add the arising linear
1157 * objective (with and-resultants) or add a integer variable to this constraint and put only this variable in the
1158 * objective, for this we need to expand the pseudo-boolean constraints to handle integer variables
1159 *
1160 * integer variant is not implemented
1161 */
1162 if( ntermcoefs > 0 )
1163 {
1164#if (LINEAROBJECTIVE == TRUE)
1165 /* all non-linear parts are created as and-constraints, even if the same non-linear part was already part of the objective function */
1166
1167 SCIP_VAR** vars;
1168 int nvars;
1169 int t;
1171
1172 for( t = 0; t < ntermcoefs; ++t )
1173 {
1174 assert(terms != NULL); /* for lint */
1175 assert(ntermvars != NULL);
1176 assert(termcoefs != NULL);
1177
1178 vars = terms[t];
1179 nvars = ntermvars[t];
1180 assert(vars != NULL);
1181 assert(nvars > 1);
1182
1183 /* create auxiliary variable */
1185 SCIP_CALL( SCIPcreateVar(scip, &var, name, 0.0, 1.0, termcoefs[t], SCIP_VARTYPE_BINARY,
1186 TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
1187
1188 /* @todo: check if it is better to change the branching priority for the artificial variables */
1189#if 1
1190 /* change branching priority of artificial variable to -1 */
1192#endif
1193
1194 /* add auxiliary variable to the problem */
1196
1197#ifdef WITH_DEBUG_SOLUTION
1199 {
1200 SCIP_Real val = 0.0;
1201
1202 for( v = nvars - 1; v >= 0; --v )
1203 {
1204 SCIP_CALL( SCIPdebugGetSolVal(scip, vars[v], &val) );
1205 assert(SCIPisFeasZero(scip, val) || SCIPisFeasEQ(scip, val, 1.0));
1206
1207 if( val < 0.5 )
1208 break;
1209 }
1210 SCIP_CALL( SCIPdebugAddSolVal(scip, var, (val < 0.5) ? 0.0 : 1.0) );
1211 }
1212#endif
1213
1214 /* @todo: check whether all constraint creation flags are the best option */
1215 /* create and-constraint */
1216 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "obj_andcons_%d", t);
1218 TRUE, TRUE, TRUE, TRUE, TRUE,
1219 FALSE, FALSE, FALSE, FALSE, FALSE) );
1223
1225 }
1226#else /* now the integer variant */
1228 SCIP_Real lb;
1229 SCIP_Real ub;
1230
1231 lb = 0.0;
1232 ub = 0.0;
1233
1234 /* add all non linear coefficients up */
1235 for( v = 0; v < ntermcoefs; ++v )
1236 {
1237 if( termcoefs[v] < 0 )
1238 lb += termcoefs[v];
1239 else
1240 ub += termcoefs[v];
1241 }
1242 /* add all linear coefficients up */
1243 for( v = 0; v < ncoefs; ++v )
1244 {
1245 if( coefs[v] < 0 )
1246 lb += coefs[v];
1247 else
1248 ub += coefs[v];
1249 }
1250 assert(lb < ub);
1251
1252 /* create auxiliary variable */
1253 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "artificial_int_obj");
1254 SCIP_CALL( SCIPcreateVar(scip, &var, name, lb, ub, 1.0, SCIP_VARTYPE_INTEGER,
1255 TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
1256
1257 /* @todo: check if it is better to change the branching priority for the artificial variables */
1258#if 1
1259 /* change branching priority of artificial variable to -1 */
1261#endif
1262 /* add auxiliary variable to the problem */
1264
1265#ifdef WITH_DEBUG_SOLUTION
1267 {
1268 SCIP_Real artval = 0.0;
1269 SCIP_Real val;
1270
1271 for( t = 0; t < ntermcoefs; ++t )
1272 {
1273 vars = terms[t];
1274 nvars = ntermvars[t];
1275 assert(vars != NULL);
1276 assert(nvars > 1);
1277
1278 for( v = nvars - 1; v >= 0; --v )
1279 {
1280 SCIP_CALL( SCIPdebugGetSolVal(scip, vars[v], &val) );
1281 assert(SCIPisFeasZero(scip, val) || SCIPisFeasEQ(scip, val, 1.0));
1282
1283 if( val < 0.5 )
1284 break;
1285 }
1286
1287 artval += (((val < 0.5) ? 0.0 : 1.0) * termcoefs[t]);
1288 }
1290
1292 }
1293#endif
1294
1295 /* create artificial objection function constraint containing the artificial integer variable */
1296 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "artificial_obj_cons");
1297 SCIP_CALL( SCIPcreateConsPseudoboolean(scip, &pseudocons, name, linvars, ncoefs, coefs, terms, ntermcoefs,
1298 ntermvars, termcoefs, NULL, 0.0, FALSE, var, 0.0, 0.0,
1299 TRUE, TRUE, TRUE, TRUE, TRUE,
1300 FALSE, FALSE, FALSE, FALSE, FALSE) );
1301
1305
1307
1308 return SCIP_OKAY;
1309#endif
1310 }
1311 /* set the objective values */
1312 for( v = 0; v < ncoefs; ++v )
1313 {
1314 assert(linvars != NULL); /* for lint */
1315 assert(coefs != NULL);
1316
1317 if( SCIPvarIsNegated(linvars[v]) )
1318 {
1319 SCIP_VAR* negvar = SCIPvarGetNegationVar(linvars[v]);
1320
1321 SCIP_CALL( SCIPaddOrigObjoffset(scip, coefs[v]) );
1322 SCIP_CALL( SCIPaddVarObj(scip, negvar, -scale * coefs[v]) );
1323 }
1324 else
1325 {
1326 SCIP_CALL( SCIPaddVarObj(scip, linvars[v], scale * coefs[v]) );
1327 }
1328 }
1329 }
1330
1331 return SCIP_OKAY;
1332}
1334/** reads the constraints section */
1335static
1337 SCIP* scip, /**< SCIP data structure */
1338 OPBINPUT* opbinput, /**< OPB reading data */
1339 SCIP_Real objscale, /**< objective scale */
1340 int* nNonlinearConss /**< pointer to store number of nonlinear constraints */
1341 )
1342{
1343 char name[OPB_MAX_LINELEN];
1344 SCIP_CONS* cons;
1345 SCIP_VAR** linvars;
1346 SCIP_Real* lincoefs;
1347 int nlincoefs;
1348 SCIP_VAR*** terms;
1349 SCIP_Real* termcoefs;
1350 int* ntermvars;
1351 int ntermcoefs;
1353 SCIP_RETCODE retcode;
1354 SCIP_Real sidevalue;
1355 SCIP_Real lhs;
1356 SCIP_Real rhs;
1357 SCIP_Bool newsection;
1358 SCIP_Bool initialconss;
1359 SCIP_Bool dynamicconss;
1360 SCIP_Bool dynamicrows;
1361 SCIP_Bool initial;
1362 SCIP_Bool separate;
1363 SCIP_Bool enforce;
1364 SCIP_Bool check;
1365 SCIP_Bool propagate;
1366 SCIP_Bool local;
1367 SCIP_Bool modifiable;
1368 SCIP_Bool dynamic;
1369 SCIP_Bool removable;
1370 SCIP_Bool isNonlinear;
1371 int sidesign;
1372 SCIP_Bool issoftcons;
1373 SCIP_Real weight;
1374 SCIP_VAR* indvar;
1375 char indname[SCIP_MAXSTRLEN];
1376 int t;
1377
1378 assert(scip != NULL);
1379 assert(opbinput != NULL);
1381
1382 weight = -SCIPinfinity(scip);
1383 retcode = SCIP_OKAY;
1384
1385 /* read the objective coefficients */
1386 SCIP_CALL( readCoefficients(scip, opbinput, name, &linvars, &lincoefs, &nlincoefs, &terms, &termcoefs, &ntermvars, &ntermcoefs, &newsection, &isNonlinear, &issoftcons, &weight) );
1387
1388 if( hasError(opbinput) || opbinput->eof )
1389 goto TERMINATE;
1390 if( newsection )
1391 {
1392 if( strcmp(name, "min") == 0 || strcmp(name, "max") == 0 )
1393 {
1394 if( opbinput->wbo )
1395 {
1396 syntaxError(scip, opbinput, "Cannot have an objective function when having soft constraints.\n");
1397 goto TERMINATE;
1398 }
1399
1400 /* set objective function */
1401 SCIP_CALL( setObjective(scip, opbinput, name, objscale, linvars, lincoefs, nlincoefs, terms, termcoefs, ntermvars, ntermcoefs) );
1402 }
1403 else if( strcmp(name, "soft") == 0 )
1404 {
1405 /* we have a "weighted boolean optimization"-file(wbo) */
1406 opbinput->wbo = TRUE;
1407 if( nlincoefs == 0 )
1408 opbinput->topcost = SCIPinfinity(scip);
1409 else
1410 {
1411 assert(nlincoefs == 1);
1412 assert(lincoefs != NULL);
1413 opbinput->topcost = lincoefs[0];
1414 }
1415 SCIPdebugMsg(scip, "Weighted Boolean Optimization problem has topcost of %g\n", opbinput->topcost);
1416 }
1417 else if( nlincoefs > 0 )
1418 syntaxError(scip, opbinput, "expected constraint sense '=' or '>='");
1419 goto TERMINATE;
1420 }
1421
1422 /* read the constraint sense */
1423 if( !getNextToken(scip, opbinput) )
1424 {
1425 syntaxError(scip, opbinput, "expected constraint sense.");
1426 goto TERMINATE;
1427 }
1428 if( !isSense(opbinput, &sense) )
1429 {
1430 syntaxError(scip, opbinput, "expected constraint sense '=' or '>='.");
1431 goto TERMINATE;
1432 }
1433
1434 /* read the right hand side */
1435 sidesign = +1;
1436 if( !getNextToken(scip, opbinput) )
1437 {
1438 syntaxError(scip, opbinput, "missing right hand side");
1439 goto TERMINATE;
1440 }
1441 if( isSign(opbinput, &sidesign) )
1442 {
1443 if( !getNextToken(scip, opbinput) )
1444 {
1445 syntaxError(scip, opbinput, "missing value of right hand side");
1446 goto TERMINATE;
1447 }
1448 }
1449 if( !isValue(scip, opbinput, &sidevalue) )
1450 {
1451 syntaxError(scip, opbinput, "expected value as right hand side");
1452 goto TERMINATE;
1453 }
1455
1456 /* check if we reached the line end */
1458 {
1459 syntaxError(scip, opbinput, "expected endline character ';'");
1460 goto TERMINATE;
1461 }
1462
1463 /* assign the left and right hand side, depending on the constraint sense */
1464 switch( sense ) /*lint !e530*/
1465 {
1466 case OPB_SENSE_GE:
1467 lhs = sidevalue;
1468 rhs = SCIPinfinity(scip);
1469 break;
1470 case OPB_SENSE_LE:
1471 lhs = -SCIPinfinity(scip);
1472 rhs = sidevalue;
1473 break;
1474 case OPB_SENSE_EQ:
1475 lhs = sidevalue;
1476 rhs = sidevalue;
1477 break;
1478 case OPB_SENSE_NOTHING:
1479 default:
1480 SCIPerrorMessage("invalid constraint sense <%d>\n", sense);
1481 return SCIP_INVALIDDATA;
1482 }
1483
1484 /* create and add the linear constraint */
1485 SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &initialconss) );
1486 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &dynamicrows) );
1487 SCIP_CALL( SCIPgetBoolParam(scip, "reading/" READER_NAME "/dynamicconss", &dynamicconss) );
1488
1489 initial = initialconss;
1490 separate = TRUE;
1491 enforce = TRUE;
1492 check = TRUE;
1493 propagate = TRUE;
1494 local = FALSE;
1495 modifiable = FALSE;
1496 dynamic = FALSE;/*dynamicconss;*/
1497 removable = dynamicrows;
1498
1499 /* create corresponding constraint */
1500 if( issoftcons )
1501 {
1503 ++(opbinput->nindvars);
1504 SCIP_CALL( createVariable(scip, &indvar, indname) );
1505
1506 assert(!SCIPisInfinity(scip, -weight));
1507 SCIP_CALL( SCIPchgVarObj(scip, indvar, objscale * weight) );
1508 }
1509 else
1510 indvar = NULL;
1511
1512 if( ntermcoefs > 0 || issoftcons )
1513 {
1514#if GENCONSNAMES == TRUE
1515 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "pseudoboolean%d", opbinput->consnumber);
1516 ++(opbinput->consnumber);
1517#else
1518 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "pseudoboolean");
1519#endif
1520 retcode = SCIPcreateConsPseudoboolean(scip, &cons, name, linvars, nlincoefs, lincoefs, terms, ntermcoefs,
1521 ntermvars, termcoefs, indvar, weight, issoftcons, NULL, lhs, rhs,
1522 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE);
1523 if( retcode != SCIP_OKAY )
1524 goto TERMINATE;
1525 }
1526 else
1527 {
1528#if GENCONSNAMES == TRUE
1529 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "linear%d", opbinput->consnumber);
1530 ++(opbinput->consnumber);
1531#else
1532 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "linear");
1533#endif
1534 retcode = SCIPcreateConsLinear(scip, &cons, name, nlincoefs, linvars, lincoefs, lhs, rhs,
1535 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE);
1536 if( retcode != SCIP_OKAY )
1537 goto TERMINATE;
1538 }
1539
1540 SCIP_CALL( SCIPaddCons(scip, cons) );
1541 SCIPdebugMsg(scip, "(line %d) created constraint: ", opbinput->linenumber);
1543 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1544
1545 if( isNonlinear )
1546 ++(*nNonlinearConss);
1547
1548 TERMINATE:
1549
1550 /* free memory */
1551 for( t = ntermcoefs - 1; t >= 0; --t )
1552 {
1553 assert(terms != NULL); /* for lint */
1555 }
1556
1558 SCIPfreeBufferArrayNull(scip, &termcoefs);
1560 SCIPfreeBufferArrayNull(scip, &lincoefs);
1561 SCIPfreeBufferArrayNull(scip, &linvars);
1562
1563 SCIP_CALL( retcode );
1564
1565 return SCIP_OKAY;
1566}
1568/** tries to read the first comment line which usually contains information about the max size of "and" products */
1569static
1571 SCIP* scip, /**< SCIP data structure */
1572 OPBINPUT* opbinput, /**< OPB reading data */
1573 SCIP_Real* objscale, /**< pointer to store objective scale */
1574 SCIP_Real* objoffset /**< pointer to store objective offset */
1575 )
1576{
1577 SCIP_Bool stop;
1578 char* commentstart;
1579 char* nproducts;
1580 char* str;
1581 int i;
1582
1583 assert(scip != NULL);
1584 assert(opbinput != NULL);
1585 assert(objoffset != NULL);
1586
1587 stop = FALSE;
1589 nproducts = NULL;
1590 *objscale = 1.0;
1591 *objoffset = 0.0;
1592 opbinput->linebuf[opbinput->linebufsize - 2] = '\0';
1593
1594 do
1595 {
1596 if( SCIPfgets(opbinput->linebuf, opbinput->linebufsize, opbinput->file) == NULL )
1597 {
1598 assert( SCIPfeof(opbinput->file) );
1599 break;
1600 }
1601
1602 /* if line is too long for our buffer reallocate buffer */
1603 while( opbinput->linebuf[opbinput->linebufsize - 2] != '\0' )
1604 {
1605 int newsize;
1606
1607 newsize = SCIPcalcMemGrowSize(scip, opbinput->linebufsize + 1);
1609
1610 opbinput->linebuf[newsize-2] = '\0';
1611 if ( SCIPfgets(opbinput->linebuf + opbinput->linebufsize - 1, newsize - opbinput->linebufsize + 1, opbinput->file) == NULL )
1612 return SCIP_READERROR;
1613 opbinput->linebufsize = newsize;
1614 }
1615 opbinput->linebuf[opbinput->linebufsize - 1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
1616
1617 /* read characters after comment symbol */
1618 for( i = 0; commentchars[i] != '\0'; ++i )
1619 {
1621
1622 /* found a comment line */
1623 if( commentstart != NULL )
1624 {
1625 /* search for "#product= xyz" in comment line, where xyz represents the number of and constraints */
1626 nproducts = strstr(opbinput->linebuf, "#product= ");
1627 if( nproducts != NULL )
1628 {
1629 const char delimchars[] = " \t";
1630 char* pos;
1631
1632 nproducts += strlen("#product= ");
1633
1634 pos = strtok(nproducts, delimchars);
1635
1636 if( pos != NULL )
1637 {
1638 SCIPdebugMsg(scip, "%d products supposed to be in file.\n", atoi(pos));
1639 }
1640
1641 pos = strtok (NULL, delimchars);
1642
1643 if( pos != NULL && strcmp(pos, "sizeproduct=") == 0 )
1644 {
1645 pos = strtok (NULL, delimchars);
1646 if( pos != NULL )
1647 {
1648 SCIPdebugMsg(scip, "sizeproducts = %d\n", atoi(pos));
1649 }
1650 }
1651
1652 stop = TRUE;
1653 }
1654
1655 /* search for "Obj. scale : <number>" in comment line */
1656 str = strstr(opbinput->linebuf, "Obj. scale : ");
1657 if( str != NULL )
1658 {
1659 str += strlen("Obj. scale : ");
1660 *objscale = atof(str);
1661 break;
1662 }
1663
1664 /* search for "Obj. offset : <number>" in comment line */
1665 str = strstr(opbinput->linebuf, "Obj. offset : ");
1666 if( str != NULL )
1667 {
1668 str += strlen("Obj. offset : ");
1669 *objoffset = atof(str);
1670 break;
1671 }
1672
1673 /* make sure that comment vanishes */
1674 *commentstart = '\0';
1675
1676 break;
1677 }
1678 }
1679 }
1680 while(commentstart != NULL && !stop);
1681
1682 return SCIP_OKAY;
1683}
1685/** reads an OPB file */
1686static
1688 SCIP* scip, /**< SCIP data structure */
1689 OPBINPUT* opbinput, /**< OPB reading data */
1690 const char* filename /**< name of the input file */
1691 )
1692{
1693 SCIP_Real objscale;
1694 SCIP_Real objoffset;
1695 int nNonlinearConss;
1696 int i;
1697
1698 assert(scip != NULL);
1699 assert(opbinput != NULL);
1700
1701 /* open file */
1702 opbinput->file = SCIPfopen(filename, "r");
1703 if( opbinput->file == NULL )
1704 {
1705 SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
1706 SCIPprintSysError(filename);
1707 return SCIP_NOFILE;
1708 }
1709
1710 /* @todo: reading additional information about the number of and constraints in comments to avoid reallocating
1711 * "opbinput.andconss"
1712 */
1713
1714 /* tries to read the first comment line which usually contains information about the max size of "and" products */
1715 SCIP_CALL( getMaxAndConsDim(scip, opbinput, &objscale, &objoffset) );
1716
1717 /* create problem */
1718 SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
1719
1720 /* opb format supports only minimization; therefore, flip objective sense for negative objective scale */
1721 if( objscale < 0.0 )
1722 opbinput->objsense = (SCIP_OBJSENSE)(-1 * (int)(opbinput->objsense));
1723
1724 if( ! SCIPisZero(scip, objoffset) )
1725 {
1727 }
1728
1729 nNonlinearConss = 0;
1730
1731 while( !SCIPfeof( opbinput->file ) && !hasError(opbinput) )
1732 {
1734 }
1735
1736 /* if we read a wbo file we need to make sure that the top cost won't be exceeded */
1737 if( opbinput->wbo )
1738 {
1740 SCIP_Real* topcosts;
1741 SCIP_VAR** vars;
1742 int nvars;
1743 int ntopcostvars;
1744 SCIP_Longint topcostrhs;
1746
1749 assert(nvars > 0 || vars != NULL);
1750
1753
1754 ntopcostvars = 0;
1755 for( i = nvars - 1; i >= 0; --i )
1757 {
1760 ++ntopcostvars;
1761 }
1762
1763 if( SCIPisIntegral(scip, opbinput->topcost) )
1764 topcostrhs = (SCIP_Longint) SCIPfloor(scip, opbinput->topcost - 1);
1765 else
1767
1769 (SCIP_Real) topcostrhs, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1773
1776 }
1777
1778 /* close file */
1779 SCIPfclose(opbinput->file);
1780
1781 return SCIP_OKAY;
1782}
1783
1784
1785/*
1786 * Local methods (for writing)
1787 */
1789/** transforms given and constraint variables to the corresponding active or negated variables */
1790static
1792 SCIP*const scip, /**< SCIP data structure */
1793 SCIP_VAR**const vars, /**< vars array to get active variables for */
1794 int const nvars, /**< pointer to number of variables and values in vars and vals array */
1795 SCIP_Bool const transformed /**< transformed constraint? */
1796 )
1797{
1798 SCIP_Bool negated;
1799 int v;
1800
1801 assert( scip != NULL );
1802 assert( vars != NULL );
1803 assert( nvars > 0 );
1804
1805 if( transformed )
1806 {
1807 for( v = nvars - 1; v >= 0; --v )
1808 {
1809 /* gets a binary variable that is equal to the given binary variable, and that is either active, fixed, or
1810 * multi-aggregated, or the negated variable of an active, fixed, or multi-aggregated variable
1811 */
1813 }
1814 }
1815 else
1816 {
1817 SCIP_Real scalar;
1818 SCIP_Real constant;
1819
1820 for( v = nvars - 1; v >= 0; --v )
1821 {
1822 scalar = 1.0;
1823 constant = 0.0;
1824
1825 /* retransforms given variable, scalar and constant to the corresponding original variable, scalar and constant,
1826 * if possible; if the retransformation is impossible, NULL is returned as variable
1827 */
1828 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalar, &constant) );
1829
1830 if( vars[v] == NULL )
1831 {
1832 SCIPdebugMsg(scip, "A variable couldn't retransformed to an original variable.\n");
1833 return SCIP_INVALIDDATA;
1834 }
1835 if( SCIPisEQ(scip, scalar, -1.0) && SCIPisEQ(scip, constant, 1.0) )
1836 {
1838 }
1839 else
1840 {
1841 if( !SCIPisEQ(scip, scalar, 1.0) || !SCIPisZero(scip, constant) )
1842 {
1843 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);
1844 return SCIP_INVALIDDATA;
1845 }
1846 }
1847 }
1848 }
1849
1850 return SCIP_OKAY;
1851}
1853/** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
1854static
1856 SCIP* scip, /**< SCIP data structure */
1857 SCIP_VAR** vars, /**< vars array to get active variables for */
1858 SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
1859 int* nvars, /**< pointer to number of variables and values in vars and vals array */
1860 SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
1861 SCIP_Bool transformed /**< transformed constraint? */
1862 )
1863{
1864 int requiredsize;
1865 int v;
1866
1867 assert(scip != NULL);
1868 assert(vars != NULL);
1869 assert(scalars != NULL);
1870 assert(nvars != NULL);
1871 assert(constant != NULL);
1872
1873 if( transformed )
1874 {
1876
1877 if( requiredsize > *nvars )
1878 {
1881
1883 assert( requiredsize <= *nvars );
1884 }
1885 }
1886 else
1887 for( v = 0; v < *nvars; ++v )
1888 {
1889 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalars[v], constant) );
1890
1891 if( vars[v] == NULL )
1892 return SCIP_INVALIDDATA;
1893 }
1894
1895 return SCIP_OKAY;
1896}
1898/* computes all and-resultants and their corresponding constraint variables */
1899static
1901 SCIP*const scip, /**< SCIP data structure */
1902 SCIP_Bool const transformed, /**< transformed problem? */
1903 SCIP_VAR*** resvars, /**< pointer to store all resultant variables */
1904 int* nresvars, /**< pointer to store the number of all resultant variables */
1905 SCIP_VAR**** andvars, /**< pointer to store to all resultant variables their corresponding active( or negated) and-constraint variables */
1906 int** nandvars, /**< pointer to store the number of all corresponding and-variables to their corresponding resultant variable */
1907 SCIP_Bool*const existandconshdlr, /**< pointer to store whether the and-constrainthandler exists*/
1908 SCIP_Bool*const existands /**< pointer to store if their exists some and-constraints */
1909 )
1910{
1911 SCIP_CONSHDLR* conshdlr;
1912
1913 assert(scip != NULL);
1914 assert(resvars != NULL);
1915 assert(nresvars != NULL);
1916 assert(andvars != NULL);
1917 assert(nandvars != NULL);
1919 assert(existands != NULL);
1920
1921 *resvars = NULL;
1922 *nandvars = NULL;
1923 *andvars = NULL;
1924 *nresvars = 0;
1925
1926 /* detect all and-resultants */
1927 conshdlr = SCIPfindConshdlr(scip, "and");
1928 if( conshdlr != NULL )
1929 {
1931 int nandconss;
1932 int* shouldnotbeinand;
1933 int a;
1934 int c;
1935 int r;
1936 int v;
1937 int pos;
1938 int ncontainedands;
1939
1940 andconss = NULL;
1941 nandconss = 0;
1943
1944 /* if we write the original problem we need to get the original and constraints */
1945 if( !transformed )
1946 {
1948 int norigconss;
1949
1952
1953 /* allocate memory for all possible and-constraints */
1955
1956 /* collect all original and-constraints */
1957 for( c = norigconss - 1; c >= 0; --c )
1958 {
1959 conshdlr = SCIPconsGetHdlr(origconss[c]);
1960 assert( conshdlr != NULL );
1961
1962 if( strcmp(SCIPconshdlrGetName(conshdlr), "and") == 0 )
1963 {
1965 ++nandconss;
1966 }
1967 }
1968 }
1969 else
1970 {
1971 nandconss = SCIPconshdlrGetNConss(conshdlr);
1972 andconss = SCIPconshdlrGetConss(conshdlr);
1973 }
1974
1975 assert(andconss != NULL || nandconss == 0);
1976
1978
1979 if( nandconss > 0 )
1980 {
1981 *existands = TRUE;
1982
1983 assert(andconss != NULL);
1984
1988
1989 /* collect all and-constraint variables */
1990 for( c = nandconss - 1; c >= 0; --c )
1991 {
1993
1994 assert(andconss[c] != NULL);
1995
1997 (*nandvars)[c] = SCIPgetNVarsAnd(scip, andconss[c]);
1998 SCIP_CALL( SCIPduplicateMemoryArray(scip, &((*andvars)[c]), scipandvars, (*nandvars)[c]) ); /*lint !e866 */
1999 SCIP_CALL( getBinVarsRepresentatives(scip, (*andvars)[c], (*nandvars)[c], transformed) );
2000
2001 (*resvars)[c] = SCIPgetResultantAnd(scip, andconss[c]);
2002
2003 assert((*andvars)[c] != NULL && (*nandvars)[c] > 0);
2004 assert((*resvars)[c] != NULL);
2005 }
2006
2007 /* sorted the array */
2008 SCIPsortPtrPtrInt((void**)(*resvars), (void**)(*andvars), (*nandvars), SCIPvarComp, (*nresvars));
2009 }
2010 else
2011 *existands = FALSE;
2012
2014
2015 /* check that all and-constraints doesn't contain any and-resultants, if they do try to resolve this */
2016 /* 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
2017 deleted and the inequality from before needs to be added ) */
2018 assert(*nandvars != NULL || *nresvars == 0);
2019 for( r = *nresvars - 1; r >= 0; --r )
2020 {
2021 ncontainedands = 0;
2024 v = 0;
2025
2026 assert(*nandvars != NULL);
2027 while( v < (*nandvars)[r] )
2028 {
2029 assert(*andvars != NULL);
2030 assert(*resvars != NULL);
2031 if( SCIPsortedvecFindPtr((void**)(*resvars), SCIPvarComp, (*andvars)[r][v], *nresvars, &pos) )
2032 {
2033 /* check if the found position "pos" is equal to an already visited and resultant in this constraint,
2034 * than here could exist a directed cycle
2035 */
2036 /* better use tarjan's algorithm
2037 * <http://algowiki.net/wiki/index.php?title=Tarjan%27s_algorithm>,
2038 * <http://en.wikipedia.org/wiki/Tarjan%E2%80%99s_strongly_connected_components_algorithm>
2039 * because it could be that the same resultant is part of this and-constraint and than it would fail
2040 * without no cycle
2041 * Note1: tarjans standard algorithm doesn't find cycle from one node to the same;
2042 * Note2: when tarjan's algorithm find a cycle, it's still possible that this cycle is not "real" e.g.
2043 * y = y ~y z (z can also be a product) where y = 0 follows and therefor only "0 = z" is necessary
2044 */
2045 for( a = ncontainedands - 1; a >= 0; --a )
2046 if( shouldnotbeinand[a] == pos )
2047 {
2048 SCIPwarningMessage(scip, "This should not happen here. The and-constraint with resultant variable: ");
2050 SCIPwarningMessage(scip, "possible contains a loop with and-resultant:");
2051 SCIP_CALL( SCIPprintVar(scip, (*resvars)[pos], NULL) );
2052
2053 /* free memory iff necessary */
2055 if( !transformed )
2056 {
2058 }
2059 return SCIP_INVALIDDATA;
2060 }
2061 SCIPdebugMsg(scip, "Another and-constraint contains and-resultant:");
2063 SCIPdebugMsg(scip, "Trying to resolve.\n");
2064
2067
2068 /* try to resolve containing ands */
2069
2070 /* resize array and number of variables */
2071 (*nandvars)[r] = (*nandvars)[r] + (*nandvars)[pos] - 1;
2072 SCIP_CALL( SCIPreallocMemoryArray(scip, &((*andvars)[r]), (*nandvars)[r]) ); /*lint !e866 */
2073
2074 /* copy all variables */
2075 for( a = (*nandvars)[pos] - 1; a >= 0; --a )
2076 (*andvars)[r][(*nandvars)[r] - a - 1] = (*andvars)[pos][a];
2077
2078 /* check same position with new variable, so we do not increase v */
2079 }
2080 else
2081 ++v;
2082 }
2083 }
2085
2086 /* free memory iff necessary */
2087 if( !transformed )
2088 {
2090 }
2091 }
2092 else
2093 {
2094 SCIPdebugMsg(scip, "found no and-constraint-handler\n");
2095 *existands = FALSE;
2097 }
2098
2099 return SCIP_OKAY;
2100}
2102/** clears the given line buffer */
2103static
2104void clearBuffer(
2105 char* linebuffer, /**< line */
2106 int* linecnt /**< number of characters in line */
2107 )
2108{
2109 assert( linebuffer != NULL );
2110 assert( linecnt != NULL );
2111
2112 (*linecnt) = 0;
2113 linebuffer[0] = '\0';
2114}
2115
2117/** ends the given line with '\\0' and prints it to the given file stream */
2118static
2119void writeBuffer(
2120 SCIP* scip, /**< SCIP data structure */
2121 FILE* file, /**< output file (or NULL for standard output) */
2122 char* linebuffer, /**< line */
2123 int* linecnt /**< number of characters in line */
2124 )
2125{
2126 assert( scip != NULL );
2127 assert( linebuffer != NULL );
2128 assert( linecnt != NULL );
2129 assert( 0 <= *linecnt && *linecnt < OPB_MAX_LINELEN );
2130
2131 if( (*linecnt) > 0 )
2132 {
2133 linebuffer[(*linecnt)] = '\0';
2134 SCIPinfoMessage(scip, file, "%s", linebuffer);
2136 }
2137}
2138
2140/** appends extension to line and prints it to the give file stream if the line buffer get full */
2141static
2142void appendBuffer(
2143 SCIP* scip, /**< SCIP data structure */
2144 FILE* file, /**< output file (or NULL for standard output) */
2145 char* linebuffer, /**< line buffer */
2146 int* linecnt, /**< number of characters in line */
2147 const char* extension /**< string to extent the line */
2148 )
2149{
2150 assert(scip != NULL);
2152 assert(linecnt != NULL);
2153 assert(extension != NULL);
2154
2155 if( (*linecnt) + (int) strlen(extension) >= OPB_MAX_LINELEN - 1 )
2157
2158 /* append extension to linebuffer */
2159 (void) strncat(linebuffer, extension, OPB_MAX_LINELEN - (unsigned int)(*linecnt));
2160 (*linecnt) += (int) strlen(extension);
2161}
2163/** write objective function */
2164static
2166 SCIP*const scip, /**< SCIP data structure */
2167 FILE*const file, /**< output file, or NULL if standard output should be used */
2168 SCIP_VAR**const vars, /**< array with active (binary) variables */
2169 int const nvars, /**< number of active variables in the problem */
2170 SCIP_VAR** const resvars, /**< array of resultant variables */
2171 int const nresvars, /**< number of resultant variables */
2172 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2173 int const*const nandvars, /**< array of numbers of corresponding and-variables */
2174 SCIP_OBJSENSE const objsense, /**< objective sense */
2175 SCIP_Real const objscale, /**< scalar applied to objective function; external objective value is
2176 * extobj = objsense * objscale * (intobj + objoffset) */
2177 SCIP_Real const objoffset, /**< objective offset from bound shifting and fixing */
2178 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
2179 SCIP_Bool const existands, /**< does some and-constraints exist? */
2180 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
2181 )
2182{
2183 SCIP_VAR* var;
2185 char buffer[OPB_MAX_LINELEN];
2186 SCIP_Longint mult;
2187 SCIP_Bool objective;
2188 int v;
2189 int linecnt;
2190 int pos;
2191
2192 assert(scip != NULL);
2193 assert(file != NULL);
2194 assert(vars != NULL || nvars == 0);
2195 assert(resvars != NULL || nresvars == 0);
2196 assert(andvars != NULL || nandvars == NULL);
2198
2199 mult = 1;
2200 objective = !SCIPisZero(scip, objoffset);
2201
2203
2204 /* check if a objective function exits and compute the multiplier to
2205 * shift the coefficients to integers */
2206 for( v = 0; v < nvars; ++v )
2207 {
2208 var = vars[v]; /*lint !e613 */
2209
2210#ifndef NDEBUG
2211 {
2212 /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
2213 if( !transformed )
2216 }
2217#endif
2218
2219 /* we found a indicator variable so we assume this is a wbo file */
2221 {
2222 /* find the topcost linear inequality which gives us the maximal cost which could be violated by our
2223 * solution, which is an artificial constraint and print this at first
2224 *
2225 * @note: only linear constraint handler is enough in problem stage, otherwise it could be any upgraded linear
2226 * constraint which handles pure binary variables
2227 */
2228 SCIP_CONSHDLR* conshdlr;
2230 SCIP_Bool printed;
2231
2232 printed = FALSE;
2234
2235 if( topcostcons != NULL )
2236 {
2237 conshdlr = SCIPconsGetHdlr(topcostcons);
2238 assert(conshdlr != NULL);
2239
2240 if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0 )
2242 else if( strcmp(SCIPconshdlrGetName(conshdlr), "knapsack") == 0 )
2243 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %" SCIP_LONGINT_FORMAT ";\n",
2245 else if( strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0 )
2246 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: 1;\n");
2247 else
2248 {
2249 SCIPABORT();
2250 return SCIP_INVALIDDATA; /*lint !e527 */
2251 }
2252 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2254 printed = TRUE;
2255 }
2256 /* following works only in transformed stage */
2257 else
2258 {
2259 /* first try linear constraints */
2260 conshdlr = SCIPfindConshdlr(scip, "linear");
2261
2262 if( conshdlr != NULL )
2263 {
2264 SCIP_CONS** conss;
2265 int nconss;
2266 int c;
2267
2268 conss = SCIPconshdlrGetConss(conshdlr);
2269 nconss = SCIPconshdlrGetNConss(conshdlr);
2270
2271 assert(conss != NULL || nconss == 0);
2272
2273 for( c = 0; c < nconss; ++c )
2274 {
2275 SCIP_VAR** linvars;
2276 int nlinvars;
2277 int w;
2278 SCIP_Bool topcostfound;
2279 SCIP_CONS* cons;
2280
2281 cons = conss[c]; /*lint !e613 */
2282 assert(cons != NULL);
2283
2284 linvars = SCIPgetVarsLinear(scip, cons);
2285 nlinvars = SCIPgetNVarsLinear(scip, cons);
2286
2287 assert(linvars != NULL || nlinvars == 0);
2289
2290 for( w = 0; w < nlinvars; ++w )
2291 {
2292 if( strstr(SCIPvarGetName(linvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2294 else
2295 {
2298 }
2299 }
2300
2301 if( topcostfound )
2302 {
2303 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetRhsLinear(scip, cons));
2304 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2306 printed = TRUE;
2307 break;
2308 }
2309 }
2310 }
2311
2312 if( !printed )
2313 {
2314 /* second try knapsack constraints */
2315 conshdlr = SCIPfindConshdlr(scip, "knapsack");
2316
2317 if( conshdlr != NULL )
2318 {
2319 SCIP_CONS** conss;
2320 int nconss;
2321 int c;
2322
2323 conss = SCIPconshdlrGetConss(conshdlr);
2324 nconss = SCIPconshdlrGetNConss(conshdlr);
2325
2326 assert(conss != NULL || nconss == 0);
2327
2328 for( c = 0; c < nconss; ++c )
2329 {
2330 SCIP_VAR** topvars;
2331 int ntopvars;
2332 int w;
2333 SCIP_Bool topcostfound;
2334 SCIP_CONS* cons;
2335
2336 cons = conss[c]; /*lint !e613 */
2337 assert(cons != NULL);
2338
2341
2342 assert(topvars != NULL || ntopvars == 0);
2344
2345 for( w = 0; w < ntopvars; ++w )
2346 {
2347 if( strstr(SCIPvarGetName(topvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2349 else
2350 {
2353 }
2354 }
2355
2356 if( topcostfound )
2357 {
2358 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %" SCIP_LONGINT_FORMAT ";\n",
2360 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2362 printed = TRUE;
2363 break;
2364 }
2365 }
2366 }
2367 }
2368
2369 if( !printed )
2370 {
2371 /* third try setppc constraints */
2372 conshdlr = SCIPfindConshdlr(scip, "setppc");
2373
2374 if( conshdlr != NULL )
2375 {
2376 SCIP_CONS** conss;
2377 int nconss;
2378 int c;
2379
2380 conss = SCIPconshdlrGetConss(conshdlr);
2381 nconss = SCIPconshdlrGetNConss(conshdlr);
2382
2383 assert(conss != NULL || nconss == 0);
2384
2385 for( c = 0; c < nconss; ++c )
2386 {
2387 SCIP_VAR** topvars;
2388 int ntopvars;
2389 int w;
2390 SCIP_Bool topcostfound;
2391 SCIP_CONS* cons;
2392
2393 cons = conss[c]; /*lint !e613 */
2394 assert(cons != NULL);
2395
2398
2399 assert(topvars != NULL || ntopvars == 0);
2401
2402 for( w = 0; w < ntopvars; ++w )
2403 {
2404 if( strstr(SCIPvarGetName(topvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2406 else
2407 {
2410 }
2411 }
2412
2413 if( topcostfound )
2414 {
2415 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: 1;\n");
2416 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2418 printed = TRUE;
2419 break;
2420 }
2421 }
2422 }
2423 }
2424 }
2425
2426 /* no topcost constraint found, so print empty topcost line, which means there is no upper bound on violated soft constraints */
2427 if( !printed )
2428 {
2429 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: ;\n");
2430 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2432 }
2433
2434 return SCIP_OKAY;
2435 }
2436
2438 {
2439 objective = TRUE;
2441 {
2442 assert(mult * 10 > mult);
2443 mult *= 10;
2444 }
2445 }
2446 }
2447
2448 if( objective )
2449 {
2450 /* opb format supports only minimization; therefore, a maximization problem has to be converted */
2451 if( ( objsense == SCIP_OBJSENSE_MAXIMIZE ) != ( objscale < 0.0 ) )
2452 mult *= -1;
2453
2454 /* there exist a objective function*/
2455 SCIPinfoMessage(scip, file, "* Obj. scale : %.15g\n", objscale / mult);
2456 SCIPinfoMessage(scip, file, "* Obj. offset : %.15g\n", objoffset * mult);
2457
2459
2460 SCIPdebugMsg(scip, "print objective function multiplied with %" SCIP_LONGINT_FORMAT "\n", mult);
2461
2462 appendBuffer(scip, file, linebuffer, &linecnt, "min:");
2463
2464#ifndef NDEBUG
2465 if( existands )
2466 {
2467 int c;
2468 /* check that these variables are sorted */
2469 for( c = nresvars - 1; c > 0; --c )
2470 assert(SCIPvarGetIndex(resvars[c]) >= SCIPvarGetIndex(resvars[c - 1])); /*lint !e613 */
2471 }
2472#endif
2473
2474 for( v = nvars - 1; v >= 0; --v )
2475 {
2476 SCIP_Bool negated;
2477 var = vars[v]; /*lint !e613 */
2478
2479 assert(var != NULL);
2480
2482 continue;
2483
2485
2486 assert( linecnt != 0 );
2487
2488 if( SCIPvarGetObj(var) * mult > (SCIP_Real)SCIP_LONGINT_MAX )
2489 {
2490 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));
2491 }
2492
2493 /* replace and-resultant with corresponding variables */
2495 {
2496 int a;
2497
2498 assert(andvars != NULL);
2499 assert(nandvars != NULL);
2500 assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
2501 assert(andvars[pos][nandvars[pos] - 1] != NULL);
2502
2503 negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2504
2505 /* print and-vars */
2506 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2507 (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "",
2508 strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
2509 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2510
2511 for(a = nandvars[pos] - 2; a >= 0; --a )
2512 {
2514
2515 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2516 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2517 }
2518 }
2519 else
2520 {
2521 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2522 (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2523 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2524 }
2525 }
2526
2527 /* and objective function line ends with a ';' */
2528 appendBuffer(scip, file, linebuffer, &linecnt, " ;\n");
2530 }
2531
2532 return SCIP_OKAY;
2533}
2535/* print maybe non linear row in OPB format to file stream */
2536static
2538 SCIP*const scip, /**< SCIP data structure */
2539 FILE*const file, /**< output file (or NULL for standard output) */
2540 char const*const type, /**< row type ("=" or ">=") */
2541 SCIP_VAR**const vars, /**< array of variables */
2542 SCIP_Real const*const vals, /**< array of values */
2543 int const nvars, /**< number of variables */
2544 SCIP_Real lhs, /**< left hand side */
2545 SCIP_VAR** const resvars, /**< array of resultant variables */
2546 int const nresvars, /**< number of resultant variables */
2547 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2548 int const*const nandvars, /**< array of numbers of corresponding and-variables */
2549 SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2550 SCIP_Longint*const mult, /**< multiplier for the coefficients */
2551 char const*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2552 )
2553{
2554 SCIP_VAR* var;
2555 char buffer[OPB_MAX_LINELEN];
2556 char linebuffer[OPB_MAX_LINELEN + 1];
2557 int v;
2558 int pos;
2559 int linecnt;
2560
2561 assert(scip != NULL);
2562 assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2563 assert(mult != NULL);
2564 assert(resvars != NULL);
2565 assert(nresvars > 0);
2566 assert(andvars != NULL && nandvars != NULL);
2567
2569
2570 /* check if all coefficients are internal; if not commentstart multiplier */
2571 for( v = 0; v < nvars; ++v )
2572 {
2573 while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
2574 {
2575 if( ABS(*mult) > ABS(*mult * 10) )
2576 return SCIP_INVALIDDATA;
2577 (*mult) *= 10;
2578 }
2579 }
2580
2581 while( !SCIPisIntegral(scip, lhs * (*mult)) )
2582 {
2583 if( ABS(*mult) > ABS(*mult * 10) )
2584 return SCIP_INVALIDDATA;
2585 (*mult) *= 10;
2586 }
2587
2588 /* print comment line if we have to multiply the coefficients to get integrals */
2589 if( ABS(*mult) != 1 )
2590 SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2591
2592#ifndef NDEBUG
2593 /* check that these variables are sorted */
2594 for( v = nresvars - 1; v > 0; --v )
2596#endif
2597
2598 /* if we have a soft constraint print the weight*/
2599 if( weight != 0 )
2600 {
2601 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "] ", weight);
2602 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2603 }
2604
2605 /* print coefficients */
2606 for( v = 0; v < nvars; ++v )
2607 {
2608 SCIP_Bool negated;
2609
2610 var = vars[v];
2611 assert( var != NULL );
2612
2614
2615 /* replace and-resultant with corresponding variables */
2616 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) )
2617 {
2618 int a;
2619
2620 assert(andvars != NULL);
2621 assert(nandvars != NULL);
2622 assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
2623 assert(andvars[pos][nandvars[pos] - 1] != NULL);
2624
2625 negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2626
2627 if( vals[v] * (*mult) > (SCIP_Real)SCIP_LONGINT_MAX )
2628 {
2629 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)));
2630 }
2631
2632 /* print and-vars */
2633 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s",
2634 (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "",
2635 strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x") );
2636 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2637
2638 for(a = nandvars[pos] - 2; a >= 0; --a )
2639 {
2641
2642 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2643 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2644 }
2645
2646 appendBuffer(scip, file, linebuffer, &linecnt, " ");
2647 }
2648 else
2649 {
2650 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
2651 (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2652 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2653 }
2654 }
2655
2656 /* print left hand side */
2657 if( SCIPisZero(scip, lhs) )
2658 lhs = 0.0;
2659
2660 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
2661 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2662
2664
2665 return SCIP_OKAY;
2666}
2667
2669/** prints given maybe non-linear constraint information in OPB format to file stream */
2670static
2672 SCIP*const scip, /**< SCIP data structure */
2673 FILE*const file, /**< output file (or NULL for standard output) */
2674 SCIP_VAR**const vars, /**< array of variables */
2675 SCIP_Real*const vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2676 int const nvars, /**< number of variables */
2677 SCIP_Real const lhs, /**< left hand side */
2678 SCIP_Real const rhs, /**< right hand side */
2679 SCIP_VAR** const resvars, /**< array of resultant variables */
2680 int const nresvars, /**< number of resultant variables */
2681 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2682 int const*const nandvars, /**< array of numbers of corresponding and-variables */
2683 SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2684 SCIP_Bool const transformed, /**< transformed constraint? */
2685 char const*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2686 )
2687{
2689 SCIP_Real* activevals;
2690 SCIP_Real activeconstant;
2691 SCIP_Longint mult;
2692 SCIP_RETCODE retcode;
2693 int nactivevars;
2694 int v;
2695
2696 assert(scip != NULL);
2697 assert(vars != NULL || nvars == 0);
2698 assert(resvars != NULL);
2699 assert(nresvars > 0);
2700 assert(andvars != NULL && nandvars != NULL);
2701
2702 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2703 return SCIP_OKAY;
2704
2706 activevars = NULL;
2707 activevals = NULL;
2708 activeconstant = 0.0;
2709
2710 /* duplicate variable and value array */
2711 if( vars != NULL )
2712 {
2714 if( vals != NULL )
2715 {
2717 }
2718 else
2719 {
2721
2722 for( v = 0; v < nactivevars; ++v )
2723 activevals[v] = 1.0;
2724 }
2725
2726 /* retransform given variables to active variables */
2728 }
2729
2730 mult = 1;
2731 retcode = SCIP_OKAY;
2732
2733 /* print row(s) in OPB format */
2734 if( SCIPisEQ(scip, lhs, rhs) )
2735 {
2736 assert( !SCIPisInfinity(scip, rhs) );
2737
2738 /* equality constraint */
2739 retcode = printNLRow(scip, file, "=", activevars, activevals, nactivevars, rhs - activeconstant, resvars,
2741 }
2742 else
2743 {
2744 if( !SCIPisInfinity(scip, -lhs) )
2745 {
2746 /* print inequality ">=" */
2747 retcode = printNLRow(scip, file, ">=", activevars, activevals, nactivevars, lhs - activeconstant, resvars,
2749 }
2750
2751 if( !SCIPisInfinity(scip, rhs) )
2752 {
2753 mult *= -1;
2754
2755 /* print inequality ">=" and multiplying all coefficients by -1 */
2756 retcode = printNLRow(scip, file, ">=", activevars, activevals, nactivevars, rhs - activeconstant, resvars,
2758 }
2759 }
2760
2761 /* free buffer arrays */
2762 if( vars != NULL )
2763 {
2766 }
2767
2768 return retcode;
2769}
2770
2772/* print row in OPB format to file stream */
2773static
2775 SCIP* scip, /**< SCIP data structure */
2776 FILE* file, /**< output file (or NULL for standard output) */
2777 const char* type, /**< row type ("=" or ">=") */
2778 SCIP_VAR** vars, /**< array of variables */
2779 SCIP_Real* vals, /**< array of values */
2780 int nvars, /**< number of variables */
2781 SCIP_Real lhs, /**< left hand side */
2782 SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2783 SCIP_Longint* mult, /**< multiplier for the coefficients */
2784 const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2785 )
2786{
2787 SCIP_VAR* var;
2788 char buffer[OPB_MAX_LINELEN];
2789 char linebuffer[OPB_MAX_LINELEN + 1];
2790 int v;
2791 int linecnt;
2792
2793 assert(scip != NULL);
2794 assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2795 assert(mult != NULL);
2796
2798
2799 /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution,
2800 * we can stop printing because it is an artificial constraint
2801 */
2802 if( nvars > 0 && strstr(SCIPvarGetName(vars[0]), INDICATORVARNAME) != NULL )
2803 return SCIP_OKAY;
2804
2805 /* check if all coefficients are integral; if not commentstart multiplier */
2806 for( v = 0; v < nvars; ++v )
2807 {
2808 while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
2809 {
2810 if( ABS(*mult) > ABS(*mult * 10) )
2811 return SCIP_INVALIDDATA;
2812 (*mult) *= 10;
2813 }
2814 }
2815
2816 while( !SCIPisIntegral(scip, lhs * (*mult)) )
2817 {
2818 if( ABS(*mult) > ABS(*mult * 10) )
2819 return SCIP_INVALIDDATA;
2820 (*mult) *= 10;
2821 }
2822
2823 /* print comment line if we have to multiply the coefficients to get integrals */
2824 if( ABS(*mult) != 1 )
2825 SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2826
2827 /* if we have a soft constraint print the weight*/
2828 if( weight != 0 )
2829 {
2830 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "] ", weight);
2831 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2832 }
2833
2834 /* print coefficients */
2835 for( v = 0; v < nvars; ++v )
2836 {
2837 SCIP_Bool negated;
2838
2839 var = vars[v];
2840 assert( var != NULL );
2841
2843
2844 if( vals[v] * (*mult) > (SCIP_Real)SCIP_LONGINT_MAX )
2845 {
2846 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)));
2847 }
2848
2849 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
2850 (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2851 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2852 }
2853
2854 /* print left hand side */
2855 if( SCIPisZero(scip, lhs) )
2856 lhs = 0.0;
2857
2858 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
2859 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2860
2862
2863 return SCIP_OKAY;
2864}
2865
2867/** prints given linear constraint information in OPB format to file stream */
2868static
2870 SCIP* scip, /**< SCIP data structure */
2871 FILE* file, /**< output file (or NULL for standard output) */
2872 SCIP_VAR** vars, /**< array of variables */
2873 SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2874 int nvars, /**< number of variables */
2875 SCIP_Real lhs, /**< left hand side */
2876 SCIP_Real rhs, /**< right hand side */
2877 SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2878 SCIP_Bool transformed, /**< transformed constraint? */
2879 const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2880 )
2881{
2883 SCIP_Real* activevals;
2884 SCIP_Real activeconstant;
2885 SCIP_Longint mult;
2886 SCIP_RETCODE retcode;
2887 int nactivevars;
2888 int v;
2889
2890 assert( scip != NULL );
2891 assert( vars != NULL || nvars == 0 );
2892
2893 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2894 return SCIP_OKAY;
2895
2897 activevars = NULL;
2898 activevals = NULL;
2899 activeconstant = 0.0;
2900
2901 /* duplicate variable and value array */
2902 if( vars != NULL )
2903 {
2905 if( vals != NULL )
2906 {
2908 }
2909 else
2910 {
2912
2913 for( v = 0; v < nactivevars; ++v )
2914 activevals[v] = 1.0;
2915 }
2916
2917 /* retransform given variables to active variables */
2919 }
2920
2921 mult = 1;
2922 retcode = SCIP_OKAY;
2923
2924 /* print row(s) in OPB format */
2925 if( SCIPisEQ(scip, lhs, rhs) )
2926 {
2927 assert( !SCIPisInfinity(scip, rhs) );
2928
2929 /* equality constraint */
2930 retcode = printRow(scip, file, "=", activevars, activevals, nactivevars, rhs - activeconstant, weight, &mult,
2931 multisymbol);
2932 }
2933 else
2934 {
2935 if( !SCIPisInfinity(scip, -lhs) )
2936 {
2937 /* print inequality ">=" */
2938 retcode = printRow(scip, file, ">=", activevars, activevals, nactivevars, lhs - activeconstant, weight, &mult,
2939 multisymbol);
2940 }
2941
2942 if( !SCIPisInfinity(scip, rhs) )
2943 {
2944 mult *= -1;
2945
2946 /* print inequality ">=" and multiplying all coefficients by -1 */
2947 retcode = printRow(scip, file, ">=", activevars, activevals, nactivevars, rhs - activeconstant, weight, &mult,
2948 multisymbol);
2949 }
2950 }
2951
2952 /* free buffer arrays */
2953 if( vars != NULL )
2954 {
2957 }
2958
2959 return retcode;
2960}
2962/* print row in OPB format to file stream */
2963static
2965 SCIP*const scip, /**< SCIP data structure */
2966 FILE*const file, /**< output file (or NULL for standard output) */
2967 const char* type, /**< row type ("=" or ">=") */
2968 SCIP_VAR**const linvars, /**< array of variables */
2969 SCIP_Real*const linvals, /**< array of values */
2970 int const nlinvars, /**< number of variables */
2971 SCIP_VAR***const termvars, /**< term array with array of variables to print */
2972 int*const ntermvars, /**< array with number of variables in each term */
2973 SCIP_Real*const termvals, /**< array of coefficient values for non-linear variables */
2974 int const ntermvals, /**< number non-linear variables in the problem */
2975 SCIP_Bool**const negatedarrays, /**< array of arrays to know which variable in a non-linear part is negated */
2976 SCIP_VAR*const indvar, /**< indicator variable, or NULL */
2977 SCIP_Real lhs, /**< left hand side */
2978 SCIP_Longint* mult, /**< multiplier for the coefficients */
2979 const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2980 )
2981{
2982 SCIP_VAR* var;
2983 char buffer[OPB_MAX_LINELEN];
2984 char linebuffer[OPB_MAX_LINELEN + 1];
2985 int v;
2986 int t;
2987 int linecnt;
2988
2989 assert(scip != NULL);
2990 assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2991 assert(linvars != NULL || nlinvars == 0);
2992 assert(linvals != NULL || nlinvars == 0);
2993 assert(termvars != NULL || ntermvals == 0);
2994 assert(ntermvars != NULL || ntermvals == 0);
2995 assert(termvals != NULL || ntermvals == 0);
2996 assert(negatedarrays != NULL || ntermvals == 0);
2997 assert(mult != NULL);
2998
3000
3001 /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution,
3002 * we can stop printing because it is an artificial constraint
3003 */
3004 if( ntermvals == 0 && nlinvars > 0 && strstr(SCIPvarGetName(linvars[0]), INDICATORVARNAME) != NULL ) /*lint !e613 */
3005 return SCIP_OKAY;
3006
3007 /* check if all linear coefficients are internal; if not commentstart multiplier */
3008 for( v = 0; v < nlinvars; ++v )
3009 {
3010 while( !SCIPisIntegral(scip, linvals[v] * (*mult)) ) /*lint !e613 */
3011 {
3012 if( ABS(*mult) > ABS(*mult * 10) )
3013 return SCIP_INVALIDDATA;
3014 (*mult) *= 10;
3015 }
3016 }
3017
3018 /* check if all non-linear coefficients are internal; if not commentstart multiplier */
3019 for( v = 0; v < ntermvals; ++v )
3020 {
3021 while( !SCIPisIntegral(scip, termvals[v] * (*mult)) ) /*lint !e613 */
3022 {
3023 if( ABS(*mult) > ABS(*mult * 10) )
3024 return SCIP_INVALIDDATA;
3025 (*mult) *= 10;
3026 }
3027 }
3028
3029 while( !SCIPisIntegral(scip, lhs * (*mult)) )
3030 {
3031 if( ABS(*mult) > ABS(*mult * 10) )
3032 return SCIP_INVALIDDATA;
3033 (*mult) *= 10;
3034 }
3035
3036 /* print comment line if we have to multiply the coefficients to get integrals */
3037 if( ABS(*mult) != 1 )
3038 SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
3039
3040 /* if indicator variable exist we have a soft constraint */
3041 if( indvar != NULL )
3042 {
3043 SCIP_Real weight;
3044
3045 weight = SCIPvarGetObj(indvar);
3046 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+g] ", weight);
3047 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3048 }
3049
3050 /* print linear part */
3051 for( v = 0; v < nlinvars; ++v )
3052 {
3053 SCIP_Bool negated;
3054
3055 var = linvars[v]; /*lint !e613 */
3056 assert(var != NULL);
3057
3059
3060 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
3061 (SCIP_Longint) SCIPround(scip, linvals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x")); /*lint !e613 */
3062 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3063 }
3064
3065 /* print non-linear part */
3066 for( t = 0; t < ntermvals; ++t )
3067 {
3068 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT, (SCIP_Longint) SCIPround(scip, termvals[t] * (*mult))); /*lint !e613 */
3069 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3070
3071 for( v = 0; v < ntermvars[t]; ++v ) /*lint !e613 */
3072 {
3073 SCIP_Bool negated;
3074
3075 var = termvars[t][v]; /*lint !e613 */
3076 assert(var != NULL);
3077
3078 negated = negatedarrays[t][v]; /*lint !e613 */
3079
3081 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3082 }
3083 appendBuffer(scip, file, linebuffer, &linecnt, " ");
3084 }
3085
3086 /* print left hand side */
3087 if( SCIPisZero(scip, lhs) )
3088 lhs = 0.0;
3089
3090 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
3091 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3092
3094
3095 return SCIP_OKAY;
3096}
3097
3099/** prints given pseudo boolean constraint information in OPB format to file stream */
3100static
3102 SCIP*const scip, /**< SCIP data structure */
3103 FILE*const file, /**< output file, or NULL if standard output should be used */
3104 SCIP_VAR**const linvars, /**< array with variables of linear part */
3105 SCIP_Real*const linvals, /**< array of coefficients values of linear part */
3106 int const nlinvars, /**< number variables in linear part of the problem */
3107 SCIP_VAR***const termvars, /**< term array with array of variables to print */
3108 int*const ntermvars, /**< array with number of variables in each term */
3109 SCIP_Real*const termvals, /**< array of coefficient values for non-linear variables */
3110 int const ntermvals, /**< number non-linear variables in the problem */
3111 SCIP_VAR*const indvar, /**< indicator variable, or NULL */
3112 SCIP_Real const lhs, /**< left hand side of constraint */
3113 SCIP_Real const rhs, /**< right hand side of constraint */
3114 SCIP_Bool transformed, /**< should the transformed problem be printed ? */
3115 const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
3116 )
3117{
3119 SCIP_Bool** negatedarrays;
3121 SCIP_Real* activelinvals;
3122 int nactivelinvars;
3123 SCIP_Real activelinconstant;
3124 SCIP_Longint mult;
3125 SCIP_RETCODE retcode;
3126 int v;
3127
3128 assert(scip != NULL);
3129 assert(linvars != NULL || nlinvars == 0);
3130 assert(linvals != NULL || nlinvars == 0);
3131 assert(termvars != NULL || 0 == ntermvals);
3132 assert(ntermvars != NULL || 0 == ntermvals);
3133 assert(termvals != NULL || 0 == ntermvals);
3134 assert(lhs <= rhs);
3135
3136 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
3137 return SCIP_OKAY;
3138
3139 activelinconstant = 0.0;
3140
3141 /* duplicate variable and value array for linear part */
3142 nactivelinvars = nlinvars;
3143 if( nactivelinvars > 0 )
3144 {
3147
3148 /* retransform given variables to active variables */
3150 }
3151 else
3152 {
3155 }
3156
3157 /* create non-linear information for printing */
3158 if( ntermvals > 0 )
3159 {
3160 assert(termvars != NULL);
3161 assert(ntermvars != NULL);
3162 assert(termvals != NULL);
3163
3166 for( v = ntermvals - 1; v >= 0; --v )
3167 {
3168 assert(ntermvars[v] > 0); /*lint !e613 */
3169
3170 if( transformed )
3171 {
3172 SCIP_CALL( SCIPallocBufferArray(scip, &(activetermvars[v]), ntermvars[v]) ); /*lint !e866 */
3173 SCIP_CALL( SCIPallocBufferArray(scip, &(negatedarrays[v]), ntermvars[v]) ); /*lint !e866 */
3174
3175 /* get binary representatives of binary variables in non-linear terms */
3177 }
3178 else
3179 {
3180 SCIP_CALL( SCIPduplicateBufferArray(scip, &(activetermvars[v]), termvars[v], ntermvars[v]) ); /*lint !e866 */
3181 SCIP_CALL( SCIPallocBufferArray(scip, &(negatedarrays[v]), ntermvars[v]) ); /*lint !e866 */
3182 BMSclearMemoryArray(negatedarrays[v], ntermvars[v]); /*lint !e866 */
3183 }
3184 }
3185 }
3186 else
3187 {
3190 }
3191
3192 mult = 1;
3193 retcode = SCIP_OKAY;
3194
3195 /* print row(s) in OPB format */
3196 if( SCIPisEQ(scip, lhs, rhs) )
3197 {
3198 assert( !SCIPisInfinity(scip, rhs) );
3199
3200 /* equality constraint */
3203 }
3204 else
3205 {
3206 if( !SCIPisInfinity(scip, -lhs) )
3207 {
3208 /* print inequality ">=" */
3211 }
3212
3213 if( !SCIPisInfinity(scip, rhs) )
3214 {
3215 mult *= -1;
3216
3217 /* print inequality ">=" and multiplying all coefficients by -1 */
3218 /* coverity[var_deref_model] */
3221 }
3222 }
3223
3224 /* free buffers for non-linear arrays */
3225 if( ntermvals > 0 )
3226 {
3229
3230 for( v = 0; v < ntermvals; ++v )
3231 {
3232 assert(negatedarrays[v] != NULL);
3233 assert(activetermvars[v] != NULL);
3236 }
3239 }
3240
3241 /* free buffer for linear arrays */
3242 if( nactivelinvars > 0 )
3243 {
3246 }
3247
3248 return retcode;
3249}
3251/** determine total number of linear constraints split into lhs/rhs */
3252static
3254 SCIP*const scip, /**< SCIP data structure */
3255 SCIP_CONS**const conss, /**< array with constraints of the problem */
3256 int const nconss, /**< number of constraints in the problem */
3257 int* nlinearconss, /**< pointer to store the total number of linear constraints */
3258 int* nsplitlinearconss /**< pointer to store the total number of linear constraints split into lhs/rhs */
3259 )
3260{
3261 SCIP_CONSHDLR* conshdlr;
3262 const char* conshdlrname;
3263 SCIP_CONS* cons;
3264 int c;
3265
3266 assert(scip != NULL);
3267 assert(conss != NULL || nconss == 0);
3270
3271 *nlinearconss = 0;
3272 *nsplitlinearconss = 0;
3273
3274 /* loop over all constraints */
3275 for( c = 0; c < nconss; ++c )
3276 {
3277 cons = conss[c];
3278 assert(cons != NULL);
3279 conshdlr = SCIPconsGetHdlr(cons); /*lint !e613*/
3280 assert(conshdlr != NULL);
3281
3283
3284 if( strcmp(conshdlrname, "linear") == 0 )
3285 {
3286 if( ! SCIPisInfinity(scip, SCIPgetLhsLinear(scip, cons)) )
3287 ++(*nsplitlinearconss);
3288
3289 if( ! SCIPisInfinity(scip, SCIPgetRhsLinear(scip, cons)) )
3290 ++(*nsplitlinearconss);
3291
3292 ++(*nlinearconss);
3293 }
3294
3295 if( strcmp(conshdlrname, "varbound") == 0 )
3296 {
3298 ++(*nsplitlinearconss);
3299
3301 ++(*nsplitlinearconss);
3302
3303 ++(*nlinearconss);
3304 }
3305 }
3306}
3308/** write constraints */
3309static
3311 SCIP*const scip, /**< SCIP data structure */
3312 FILE*const file, /**< output file, or NULL if standard output should be used */
3313 SCIP_CONS**const conss, /**< array with constraints of the problem */
3314 int const nconss, /**< number of constraints in the problem */
3315 SCIP_VAR**const vars, /**< array with active (binary) variables */
3316 int const nvars, /**< number of active variables in the problem */
3317 SCIP_VAR** const resvars, /**< array of resultant variables */
3318 int const nresvars, /**< number of resultant variables */
3319 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3320 int const*const nandvars, /**< array of numbers of corresponding and-variables */
3321 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3322 SCIP_Bool const existandconshdlr, /**< does and-constrainthandler exist? */
3323 SCIP_Bool const existands, /**< does some and-constraints exist? */
3324 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3325 )
3326{
3327 SCIP_CONSHDLR* conshdlr;
3328 const char* conshdlrname;
3329 SCIP_CONS* cons;
3330 SCIP_VAR** consvars;
3331 SCIP_Real* consvals;
3332 SCIP_RETCODE retcode;
3333 int nconsvars;
3334 int v, c;
3337
3338 assert(scip != NULL);
3339 assert(file != NULL);
3340 assert(conss != NULL || nconss == 0);
3341 assert(vars != NULL || nvars == 0);
3342 assert(resvars != NULL || nresvars == 0);
3343 assert(andvars != NULL || nandvars == 0);
3345
3346 if( transformed )
3347 {
3348 conshdlr = SCIPfindConshdlr(scip, "indicator");
3349
3350 /* find artificial linear constraints which correspond to indicator constraints to avoid double printing */
3351 if( conshdlr != NULL )
3352 {
3353 SCIP_CONS** indconss;
3354 int nindconss;
3355
3356 indconss = SCIPconshdlrGetConss(conshdlr);
3357 nindconss = SCIPconshdlrGetNConss(conshdlr);
3358 assert(indconss != NULL || nindconss == 0);
3359
3360 if( nindconss > 0 )
3361 {
3362 SCIP_CONS* lincons;
3363
3364 /* create the linear constraint of indicator constraints hash map */
3366 assert(indconss != NULL);
3367
3368 for( c = 0; c < nindconss; ++c )
3369 {
3370 assert(indconss[c] != NULL);
3371 lincons = SCIPgetLinearConsIndicator(indconss[c]);
3372 assert(lincons != NULL);
3373
3374 /* insert constraint into mapping between */
3375 SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)lincons) );
3376 }
3377 }
3378 }
3379
3380 conshdlr = SCIPfindConshdlr(scip, "pseudoboolean");
3381
3382 /* find artifical linear constraints which correspond to indicator constraints to avoid double printing */
3383 if( conshdlr != NULL )
3384 {
3386 int npbconss;
3387
3388 pbconss = SCIPconshdlrGetConss(conshdlr);
3389 npbconss = SCIPconshdlrGetNConss(conshdlr);
3390 assert(pbconss != NULL || npbconss == 0);
3391
3392 if( npbconss > 0 )
3393 {
3394 SCIP_CONS* lincons;
3395
3396 /* create the linear constraint of indicator constraints hash map */
3398
3399 for( c = 0; c < npbconss; ++c )
3400 {
3401 assert(pbconss[c] != NULL); /*lint !e613*/
3402 lincons = SCIPgetLinearConsPseudoboolean(scip, pbconss[c]); /*lint !e613*/
3403 assert(lincons != NULL);
3404
3405 /* insert constraint into mapping between */
3406 SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)lincons) );
3407 }
3408 }
3409 }
3410 }
3411 /* in original space we cannot ask the constraint handler for its constraints, therefore we have to loop over all
3412 * original to check for artificial linear once
3413 */
3414 else
3415 {
3416 SCIP_CONS* lincons;
3417 SCIP_Bool pbhashmapcreated = FALSE;
3418 SCIP_Bool indhashmapcreated = FALSE;
3419
3420 /* loop over all constraint for printing */
3421 for( c = 0; c < nconss; ++c )
3422 {
3423 conshdlr = SCIPconsGetHdlr(conss[c]); /*lint !e613*/
3424 assert(conshdlr != NULL);
3425
3427
3428 if( strcmp(conshdlrname, "pseudoboolean") == 0 )
3429 {
3430 if( !pbhashmapcreated )
3431 {
3432 /* create the linear constraint of indicator constraints hash map */
3435 }
3436
3437 lincons = SCIPgetLinearConsPseudoboolean(scip, conss[c]); /*lint !e613*/
3438 assert(lincons != NULL);
3439
3440 /* insert constraint into mapping between */
3441 SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)lincons) );
3442 }
3443 else if( strcmp(conshdlrname, "indicator") == 0 )
3444 {
3445 if( !indhashmapcreated )
3446 {
3447 /* create the linear constraint of indicator constraints hash map */
3450 }
3451
3452 lincons = SCIPgetLinearConsIndicator(conss[c]); /*lint !e613*/
3453 assert(lincons != NULL);
3454
3455 /* insert constraint into mapping between */
3456 SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)lincons) );
3457 }
3458 }
3459 }
3460
3461 retcode = SCIP_OKAY;
3462 cons = NULL;
3463
3464 /* loop over all constraint for printing */
3465 for( c = 0; c < nconss && retcode == SCIP_OKAY; ++c )
3466 {
3468
3469 artcons = NULL;
3470
3471 cons = conss[c]; /*lint !e613 */
3472 assert(cons != NULL);
3473
3474 conshdlr = SCIPconsGetHdlr(cons);
3475 assert(conshdlr != NULL);
3476
3478 assert(transformed == SCIPconsIsTransformed(cons));
3479
3480 /* in case the transformed is written only constraint are posted which are enabled in the current node */
3481 assert(!transformed || SCIPconsIsEnabled(cons));
3482
3483 if( linconssofpbsmap != NULL )
3487
3488 if( artcons == NULL )
3489 {
3490 if( strcmp(conshdlrname, "linear") == 0 )
3491 {
3492 if( existands )
3493 {
3494 retcode = printNonLinearCons(scip, file,
3497 0LL, transformed, multisymbol);
3498 }
3499 else
3500 {
3501 retcode = printLinearCons(scip, file,
3503 SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), 0LL, transformed, multisymbol);
3504 }
3505 }
3506 else if( strcmp(conshdlrname, "setppc") == 0 )
3507 {
3508 consvars = SCIPgetVarsSetppc(scip, cons);
3509 nconsvars = SCIPgetNVarsSetppc(scip, cons);
3510
3511 switch( SCIPgetTypeSetppc(scip, cons) )
3512 {
3514 if( existands )
3515 {
3516 retcode = printNonLinearCons(scip, file, consvars, NULL, nconsvars, 1.0, 1.0, resvars, nresvars,
3517 andvars, nandvars, 0LL, transformed, multisymbol);
3518 }
3519 else
3520 {
3521 retcode = printLinearCons(scip, file,
3522 consvars, NULL, nconsvars, 1.0, 1.0, 0LL, transformed, multisymbol);
3523 }
3524 break;
3526 if( existands )
3527 {
3528 retcode = printNonLinearCons(scip, file,
3529 consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, resvars, nresvars, andvars, nandvars,
3530 0LL, transformed, multisymbol);
3531 }
3532 else
3533 {
3534 retcode = printLinearCons(scip, file,
3535 consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, 0LL, transformed, multisymbol);
3536 }
3537 break;
3539 if( existands )
3540 {
3541 retcode = printNonLinearCons(scip, file,
3542 consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), resvars, nresvars, andvars, nandvars,
3543 0LL, transformed, multisymbol);
3544 }
3545 else
3546 {
3547 retcode = printLinearCons(scip, file,
3548 consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), 0LL, transformed, multisymbol);
3549 }
3550 break;
3551 }
3552 }
3553 else if( strcmp(conshdlrname, "logicor") == 0 )
3554 {
3555 if( existands )
3556 {
3557 retcode = printNonLinearCons(scip, file,
3559 resvars, nresvars, andvars, nandvars, 0LL, transformed, multisymbol);
3560 }
3561 else
3562 {
3563 retcode = printLinearCons(scip, file,
3565 1.0, SCIPinfinity(scip), 0LL, transformed, multisymbol);
3566 }
3567 }
3568 else if( strcmp(conshdlrname, "knapsack") == 0 )
3569 {
3570 SCIP_Longint* weights;
3571
3572 consvars = SCIPgetVarsKnapsack(scip, cons);
3573 nconsvars = SCIPgetNVarsKnapsack(scip, cons);
3574
3575 /* copy Longint array to SCIP_Real array */
3576 weights = SCIPgetWeightsKnapsack(scip, cons);
3578 for( v = 0; v < nconsvars; ++v )
3579 consvals[v] = (SCIP_Real)weights[v];
3580
3581 if( existands )
3582 {
3583 retcode = printNonLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip),
3585 0LL, transformed, multisymbol);
3586 }
3587 else
3588 {
3589 retcode = printLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip),
3590 (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), 0LL, transformed, multisymbol);
3591 }
3592
3594 }
3595 else if( strcmp(conshdlrname, "varbound") == 0 )
3596 {
3597 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
3599
3600 consvars[0] = SCIPgetVarVarbound(scip, cons);
3601 consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
3602
3603 consvals[0] = 1.0;
3605
3606 if( existands )
3607 {
3608 retcode = printNonLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons),
3610 }
3611 else
3612 {
3613 retcode = printLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons),
3614 SCIPgetRhsVarbound(scip, cons), 0LL, transformed, multisymbol);
3615 }
3616
3617 SCIPfreeBufferArray(scip, &consvars);
3619 }
3620 else if( strcmp(conshdlrname, "pseudoboolean") == 0 )
3621 {
3622 SCIP_VAR*** termvars;
3623 int* ntermvars;
3624 int termvarssize;
3626 SCIP_Real* andcoefs ;
3627 SCIP_VAR** linvars;
3628 SCIP_Real* lincoefs ;
3629 int nlinvars;
3630 int t;
3631
3632 /* get the required array size for the variables array and for the number of variables in each variable array */
3634 assert(termvarssize >= 0);
3635
3636 /* allocate temporary memory */
3641
3642 /* get all corresponding and-constraints and therefor all variables */
3644 for( t = termvarssize - 1; t >= 0; --t )
3645 {
3648 }
3649
3650 /* gets number of linear variables without artificial terms variables of pseudoboolean constraint */
3652
3653 /* allocate temporary memory */
3654 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinvars) );
3655 SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nlinvars) );
3656
3657 /* gets linear constraint of pseudoboolean constraint */
3658 SCIP_CALL( SCIPgetLinDatasWithoutAndPseudoboolean(scip, cons, linvars, lincoefs, &nlinvars) );
3659
3660 retcode = printPseudobooleanCons(scip, file, linvars, lincoefs, nlinvars,
3663
3664 /* free temporary memory */
3665 SCIPfreeBufferArray(scip, &lincoefs);
3666 SCIPfreeBufferArray(scip, &linvars);
3668 SCIPfreeBufferArray(scip, &andcoefs);
3671 }
3672 else if( strcmp(conshdlrname, "indicator") == 0 )
3673 {
3674 SCIP_CONS* lincons;
3675 SCIP_VAR* indvar;
3676 SCIP_VAR* slackvar;
3677 SCIP_Longint weight;
3678
3679 /* get artificial binary indicator variables */
3680 indvar = SCIPgetBinaryVarIndicator(cons);
3681 assert(indvar != NULL);
3682
3684 {
3685 indvar = SCIPvarGetNegationVar(indvar);
3686 assert(indvar != NULL);
3688
3689 /* get the soft cost of this constraint */
3690 weight = (SCIP_Longint) SCIPvarGetObj(indvar);
3691 }
3692 else
3693 {
3695
3696 /* get the soft cost of this constraint */
3697 weight = -(SCIP_Longint) SCIPvarGetObj(indvar);
3698 }
3699
3700 /* get artificial slack variable */
3701 slackvar = SCIPgetSlackVarIndicator(cons);
3702 assert(slackvar != NULL);
3703
3704 /* only need to print indicator constraints with weights on their indicator variable */
3705 if( weight != 0 )
3706 {
3708 SCIP_Real* scipvalslinear;
3709 SCIP_Bool cont;
3710 int nonbinarypos;
3711
3712 lincons = SCIPgetLinearConsIndicator(cons);
3713 assert(lincons != NULL);
3714
3715 nconsvars = SCIPgetNVarsLinear(scip, lincons);
3718
3719 /* allocate temporary memory */
3720 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, scipvarslinear, nconsvars) );
3722
3723 nonbinarypos = -1;
3724 cont = FALSE;
3725
3726 /* find non-binary variable */
3727 for( v = 0; v < nconsvars; ++v )
3728 {
3729 if( SCIPvarGetType(consvars[v]) != SCIP_VARTYPE_BINARY )
3730 {
3731 if( consvars[v] == slackvar )
3732 {
3733 assert(nonbinarypos == -1);
3734 nonbinarypos = v;
3735 }
3736 else
3737 {
3738 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) );
3739 SCIPinfoMessage(scip, file, "* ");
3740 SCIP_CALL( SCIPprintCons(scip, cons, file) );
3741 SCIPinfoMessage(scip, file, ";\n");
3742 cont = TRUE;
3743 break;
3744 }
3745 }
3746 }
3747
3748 /* if we have not found any non-binary variable we do not print the constraint, maybe we should ??? */
3749 if( nonbinarypos == -1 )
3750 {
3751 SCIPwarningMessage(scip, "cannot print linear constraint <%s> of indicator constraint <%s> because it has no slack variable\n", SCIPconsGetName(lincons), SCIPconsGetName(cons) );
3752 SCIPinfoMessage(scip, file, "* ");
3753 SCIP_CALL( SCIPprintCons(scip, cons, file) );
3754 SCIPinfoMessage(scip, file, ";\n");
3755
3756 /* free temporary memory */
3758 SCIPfreeBufferArray(scip, &consvars);
3759 continue;
3760 }
3761
3762 /* if the constraint has more than two non-binary variables is not printable and we go to the next */
3763 if( cont )
3764 {
3765 /* free temporary memory */
3767 SCIPfreeBufferArray(scip, &consvars);
3768 continue;
3769 }
3770
3771 assert(0 <= nonbinarypos && nonbinarypos < nconsvars);
3772
3773 /* remove slackvariable in linear constraint for printing */
3774 --nconsvars;
3775 consvars[nonbinarypos] = consvars[nconsvars];
3776 consvals[nonbinarypos] = consvals[nconsvars];
3777
3778 if( existands )
3779 {
3780 retcode = printNonLinearCons(scip, file,
3781 consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
3783 weight, transformed, multisymbol);
3784 }
3785 else
3786 {
3787 retcode = printLinearCons(scip, file,
3788 consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
3789 weight, transformed, multisymbol);
3790 }
3791
3792 /* free temporary memory */
3794 SCIPfreeBufferArray(scip, &consvars);
3795 }
3796 else
3797 {
3798 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) );
3799 SCIPinfoMessage(scip, file, "* ");
3800 SCIP_CALL( SCIPprintCons(scip, cons, file) );
3801 SCIPinfoMessage(scip, file, ";\n");
3802 }
3803 }
3804 else if( strcmp(conshdlrname, "and") == 0 )
3805 {
3806 /* all resultants of the and constraint will be replaced by all corresponding variables of this constraint,
3807 * so no and-constraint will be printed directly */
3809 }
3810 else
3811 {
3812 SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
3813 SCIPinfoMessage(scip, file, "* ");
3814 SCIP_CALL( SCIPprintCons(scip, cons, file) );
3815 SCIPinfoMessage(scip, file, ";\n");
3816 }
3817 }
3818 }
3819
3820 if( retcode == SCIP_INVALIDDATA )
3821 {
3822 assert(cons != NULL);
3823
3824 SCIPerrorMessage("Cannot print constraint %s with non-integral coefficient or sides in opb-format\n",
3825 SCIPconsGetName(cons));
3827 SCIPinfoMessage(scip, file, ";\n");
3828 }
3829
3830 if( linconssofpbsmap != NULL )
3831 {
3832 /* free hash map */
3834 }
3836 {
3837 /* free hash map */
3839 }
3840
3841 return retcode;
3842}
3844/* write fixed variables (unless already done because they are an and resultant or and variable) */
3845static
3847 SCIP*const scip, /**< SCIP data structure */
3848 FILE*const file, /**< output file, or NULL if standard output should be used */
3849 SCIP_VAR** vars, /**< array with active (binary) variables */
3850 int nvars, /**< number of active variables in the problem */
3851 SCIP_HASHTABLE*const printedfixing, /**< hashmap to store if a fixed variable was already printed */
3852 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3853 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3854 )
3855{
3857 char buffer[OPB_MAX_LINELEN];
3858 int linecnt;
3859 int v;
3860
3861 assert(scip != NULL);
3862 assert(file != NULL);
3863 assert(vars != NULL || nvars == 0);
3866
3868
3869 /* print variables which are fixed */
3870 for( v = 0; v < nvars; ++v )
3871 {
3872 SCIP_VAR* var;
3873 SCIP_Real lb;
3874 SCIP_Real ub;
3875 SCIP_Bool neg = FALSE;
3876
3877 assert( vars != NULL );
3878 var = vars[v];
3879
3880 if( transformed )
3881 {
3882 /* in case the transformed is written only local bounds are posted which are valid in the current node */
3883 lb = SCIPvarGetLbLocal(var);
3884 ub = SCIPvarGetUbLocal(var);
3885 }
3886 else
3887 {
3890 }
3891 assert(lb > -0.5 && ub < 1.5);
3894
3895 /* print fixed and-resultants */
3896 if( lb > 0.5 || ub < 0.5 )
3897 {
3898 if( transformed ) {
3900 }
3901
3903 continue;
3904
3905 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
3906 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3907
3908 /* add variable to the hashmap */
3910 }
3911 }
3912
3914
3915 return SCIP_OKAY;
3916}
3918/* write and constraints of inactive but relevant and-resultants and and variables which are fixed to one */
3919static
3921 SCIP*const scip, /**< SCIP data structure */
3922 FILE*const file, /**< output file, or NULL if standard output should be used */
3923 SCIP_VAR**const resvars, /**< array of resultant variables */
3924 int const nresvars, /**< number of resultant variables */
3925 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3926 int const*const nandvars, /**< array of numbers of corresponding and-variables */
3927 SCIP_HASHTABLE*const printedfixing, /**< hashmap to store if a fixed variable was already printed */
3928 char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3929 SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3930 )
3931{
3932 SCIP_VAR* resvar;
3933 SCIP_Longint rhslhs;
3935 char buffer[OPB_MAX_LINELEN];
3936 int linecnt;
3937 int r, v;
3938
3939 assert(scip != NULL);
3940 assert(file != NULL);
3941 assert(resvars != NULL || nresvars == 0);
3942 assert(nandvars != NULL || nresvars == 0);
3943 assert(andvars != NULL || nandvars == NULL);
3945
3947
3948 /* print and-variables which are fixed */
3949 /* @todo remove this block here and the hashtable and let writeOpbFixedVars() do the job? */
3950 for( r = nresvars - 1; r >= 0; --r )
3951 {
3952 SCIP_VAR* var;
3953 SCIP_Bool neg;
3954 SCIP_Real lb;
3955 SCIP_Real ub;
3956
3957 assert( resvars != NULL );
3958 resvar = resvars[r];
3959
3960 if( transformed )
3961 {
3962 /* in case the transformed is written only local bounds are posted which are valid in the current node */
3963 lb = SCIPvarGetLbLocal(resvar);
3964 ub = SCIPvarGetUbLocal(resvar);
3965 }
3966 else
3967 {
3968 lb = SCIPvarGetLbOriginal(resvar);
3969 ub = SCIPvarGetUbOriginal(resvar);
3970 }
3971
3972 /* print fixed and-resultants */
3973 if( lb > 0.5 || ub < 0.5 )
3974 {
3975 /* coverity[copy_paste_error] */
3977
3979 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
3980 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3981
3982 /* add variable to the hashmap */
3984 }
3985
3986 assert( andvars != NULL && nandvars != NULL );
3987 assert( andvars[r] != NULL || nandvars[r] == 0 );
3988
3989 /* print fixed and-variables */
3990 for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
3991 {
3992 assert( andvars[r] != NULL );
3993 assert( andvars[r][v] != NULL );
3994
3995 if( transformed )
3996 {
3997 /* in case the transformed is written only local bounds are posted which are valid in the current node */
3998 lb = SCIPvarGetLbLocal(andvars[r][v]);
3999 ub = SCIPvarGetUbLocal(andvars[r][v]);
4000 }
4001 else
4002 {
4003 lb = SCIPvarGetLbOriginal(andvars[r][v]);
4004 ub = SCIPvarGetUbOriginal(andvars[r][v]);
4005 }
4006
4007 if( lb > 0.5 || ub < 0.5 )
4008 {
4009 SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
4010
4012 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
4013 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4014
4015 /* add variable to the hashmap */
4017 }
4018 }
4019 }
4020
4021 /* print and-constraints with fixed and-resultant to zero and all and-constraints with
4022 * aggregated resultant, otherwise we would loose this information
4023 */
4024 for( r = nresvars - 1; r >= 0; --r )
4025 {
4026 assert( resvars != NULL );
4027 resvar = resvars[r];
4028 rhslhs = (SCIPvarGetUbLocal(resvar) < 0.5) ? 0 : ((SCIPvarGetLbLocal(resvar) > 0.5) ? 1 : -1);
4029
4030 /* if and resultant is fixed to 0 and at least one and-variable is fixed to zero, we don't print this redundant constraint */
4031 if( rhslhs == 0 )
4032 {
4033 SCIP_Bool cont;
4034
4035 cont = FALSE;
4036
4037 assert( andvars != NULL && nandvars != NULL );
4038 assert( andvars[r] != NULL || nandvars[r] == 0 );
4039
4040 /* if resultant variable and one other and variable is already zero, so we did not need to print this and
4041 * constraint because all other variables are free
4042 */
4043 for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
4044 {
4045 assert( andvars[r] != NULL );
4046 assert( andvars[r][v] != NULL );
4047
4048 if( SCIPvarGetUbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
4049 {
4050 cont = TRUE;
4051 break;
4052 }
4053 }
4054
4055 if( cont )
4056 continue;
4057 }
4058 /* if and resultant is fixed to 1 and all and-variable are fixed to 1 too, we don't print this redundant constraint */
4059 else if( rhslhs == 1 )
4060 {
4061 SCIP_Bool cont;
4062
4063 cont = TRUE;
4064
4065 assert( andvars != NULL && nandvars != NULL );
4066 assert( andvars[r] != NULL || nandvars[r] == 0 );
4067
4068 /* if all variables are already fixed to one, we do not need to print this and constraint */
4069 for( v = nandvars[r] - 1; v >= 0; --v )
4070 {
4071 assert( andvars[r] != NULL );
4072 assert( andvars[r][v] != NULL );
4073
4074 if( SCIPvarGetLbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
4075 {
4076 cont = FALSE;
4077 break;
4078 }
4079 }
4080
4081 if( cont )
4082 continue;
4083 }
4084
4085 /* print and with fixed or aggregated and-resultant */
4086 /* rhslhs equals to 0 means the and constraint is relevant due to it's not clear on which values the and variables are
4087 * rhslhs equals to 1 means the and constraint is irrelevant cause all and variables have to be 1 too
4088 * rhslhs equals to -1 means the and constraint is relevant cause the variable is only aggregated */
4089 if( !SCIPvarIsActive(resvar) )
4090 {
4091 SCIP_VAR* var;
4092 SCIP_Bool neg;
4093 SCIP_Bool firstprinted;
4094
4096
4097 assert( andvars != NULL && nandvars != NULL );
4098 assert( andvars[r] != NULL || nandvars[r] == 0 );
4099
4100 for( v = nandvars[r] - 1; v >= 0; --v )
4101 {
4102 assert( andvars[r] != NULL );
4103 assert( andvars[r][v] != NULL );
4104
4105 SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
4106
4107 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", (firstprinted) ? multisymbol : "", neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"));
4108 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4109
4111 }
4112
4113 /* if the resultant is aggregated we need to print his binary representation */
4114 if( rhslhs == -1 )
4115 {
4116 int pos;
4117
4118 assert(transformed);
4119
4120 SCIP_CALL( SCIPgetBinvarRepresentative(scip, resvar, &resvar, &neg) );
4121
4122#ifndef NDEBUG
4123 if( neg )
4125 else
4126 assert(SCIPvarIsActive(resvar));
4127#endif
4128
4129 /* replace and-resultant with corresponding variables */
4130 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, neg ? SCIPvarGetNegationVar(resvar) : resvar, nresvars, &pos) )
4131 {
4132 SCIP_Bool negated;
4133 int a;
4134
4135 assert(andvars != NULL);
4136 assert(nandvars != NULL);
4137 assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
4138 assert(andvars[pos][nandvars[pos] - 1] != NULL);
4139
4140 negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
4141
4142 /* print and-vars */
4143 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, neg ? " +1%s%s%s" : " -1%s%s%s", multisymbol, negated ? "~" : "",
4144 strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
4145 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4146
4147 for(a = nandvars[pos] - 2; a >= 0; --a )
4148 {
4150
4151 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
4152 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4153 }
4154
4155 appendBuffer(scip, file, linebuffer, &linecnt, " ");
4156
4157 if( neg )
4158 rhslhs = 1;
4159 else
4160 rhslhs = 0;
4161 }
4162 else
4163 {
4164 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " -1%s%s%s", multisymbol, neg ? "~" : "",
4165 strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(resvar) : resvar), "x"));
4166 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4167
4168 rhslhs = 0;
4169 }
4170 }
4171
4172 /* print rhslhs */
4173 (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " = %" SCIP_LONGINT_FORMAT " ;\n", rhslhs);
4174 appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4175
4177 }
4178 }
4179
4180 return SCIP_OKAY;
4181}
4183/* writes problem to file */
4184static
4186 SCIP* scip, /**< SCIP data structure */
4187 FILE* file, /**< output file, or NULL if standard output should be used */
4188 const char* name, /**< problem name */
4189 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4190 SCIP_OBJSENSE objsense, /**< objective sense */
4191 SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4192 * extobj = objsense * objscale * (intobj + objoffset) */
4193 SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4194 SCIP_VAR** vars, /**< array with active (binary) variables */
4195 int nvars, /**< number of active variables in the problem */
4196 SCIP_CONS** conss, /**< array with constraints of the problem */
4197 int nconss, /**< number of constraints in the problem */
4198 SCIP_VAR** const resvars, /**< array of resultant variables */
4199 int const nresvars, /**< number of resultant variables */
4200 SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
4201 int const*const nandvars, /**< array of numbers of corresponding and-variables */
4202 SCIP_Bool const existandconshdlr, /**< does and-constrainthandler exist? */
4203 SCIP_Bool const existands, /**< does some and-constraints exist? */
4204 SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4205 )
4206{
4209 SCIP_Bool usesymbol;
4210 SCIP_RETCODE retcode;
4211 int nlinearconss;
4213
4214 assert( scip != NULL );
4215 assert( vars != NULL || nvars == 0 );
4216 assert( conss != NULL || nconss == 0 );
4217 assert( result != NULL );
4218
4219 /* check if should use a multipliers symbol star '*' between coefficients and variables */
4220 SCIP_CALL( SCIPgetBoolParam(scip, "reading/" READER_NAME "/multisymbol", &usesymbol) );
4221 (void) SCIPsnprintf(multisymbol, OPB_MAX_LINELEN, "%s", usesymbol ? " * " : " ");
4222
4223 /* determine how many linear constraints are split */
4225
4226 /* print statistics as comment to file */
4227 SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n");
4228 SCIPinfoMessage(scip, file, "* Problem name : %s\n", name);
4229 SCIPinfoMessage(scip, file, "* Variables : %d (all binary)\n", nvars);
4230 SCIPinfoMessage(scip, file, "* Constraints : %d\n", nconss - nlinearconss + nsplitlinearconss);
4231
4232 /* create a hash table */
4235
4236 /* write objective function */
4238 objsense, objscale, objoffset, multisymbol, existands, transformed) );
4239
4240 /* write constraints */
4241 retcode = writeOpbConstraints(scip, file, conss, nconss, vars, nvars, resvars, nresvars, andvars, nandvars,
4242 multisymbol, existandconshdlr, existands, transformed);
4243
4244 if( existands && (retcode == SCIP_OKAY) )
4245 {
4246 /* write and constraints of inactive but relevant and-resultants and and-variables which are fixed to one
4247 with no fixed and resultant */
4249 }
4250
4251 /* write fixed variables */
4253
4255
4257
4258 return retcode;
4259}
4260
4261
4262/*
4263 * extern methods
4265
4266/** reads problem from file */
4268 SCIP* scip, /**< SCIP data structure */
4269 SCIP_READER* reader, /**< the file reader itself */
4270 const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
4271 SCIP_RESULT* result /**< pointer to store the result of the file reading call */
4272 )
4273{ /*lint --e{715}*/
4275 SCIP_RETCODE retcode;
4276 int i;
4277
4278 assert(scip != NULL); /* for lint */
4279 assert(reader != NULL);
4280
4281 /* initialize OPB input data */
4282 opbinput.file = NULL;
4284 opbinput.linebuf[0] = '\0';
4285 opbinput.linebufsize = OPB_MAX_LINELEN;
4287 opbinput.token[0] = '\0';
4289 opbinput.tokenbuf[0] = '\0';
4290 for( i = 0; i < OPB_MAX_PUSHEDTOKENS; ++i )
4291 {
4292 SCIP_CALL( SCIPallocBufferArray(scip, &(opbinput.pushedtokens[i]), OPB_MAX_LINELEN) ); /*lint !e866 */
4293 }
4294
4295 opbinput.npushedtokens = 0;
4296 opbinput.linenumber = 1;
4297 opbinput.linepos = 0;
4299 opbinput.eof = FALSE;
4300 opbinput.haserror = FALSE;
4301 opbinput.nproblemcoeffs = 0;
4302 opbinput.wbo = FALSE;
4303 opbinput.topcost = -SCIPinfinity(scip);
4304 opbinput.nindvars = 0;
4305#if GENCONSNAMES == TRUE
4306 opbinput.consnumber = 0;
4307#endif
4308
4309 /* read the file */
4310 retcode = readOPBFile(scip, &opbinput, filename);
4311
4312 /* free dynamically allocated memory */
4313 for( i = OPB_MAX_PUSHEDTOKENS - 1; i >= 0; --i )
4314 {
4315 SCIPfreeBufferArrayNull(scip, &(opbinput.pushedtokens[i]));
4316 }
4319 SCIPfreeBlockMemoryArray(scip, &opbinput.linebuf, opbinput.linebufsize);
4320
4321 if( retcode == SCIP_PLUGINNOTFOUND )
4322 retcode = SCIP_READERROR;
4323
4324 SCIP_CALL( retcode );
4325
4326 if( opbinput.nproblemcoeffs > 0 )
4327 {
4328 SCIPwarningMessage(scip, "there might be <%d> coefficients or weight out of range!\n", opbinput.nproblemcoeffs);
4329 }
4330
4331 /* evaluate the result */
4332 if( opbinput.haserror )
4333 return SCIP_READERROR;
4334 else
4335 {
4336 /* set objective sense */
4337 SCIP_CALL( SCIPsetObjsense(scip, opbinput.objsense) );
4339 }
4340
4341 return SCIP_OKAY;
4343
4344/** writes problem to file */
4346 SCIP* scip, /**< SCIP data structure */
4347 FILE* file, /**< output file, or NULL if standard output should be used */
4348 const char* name, /**< problem name */
4349 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4350 SCIP_OBJSENSE objsense, /**< objective sense */
4351 SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4352 * extobj = objsense * objscale * (intobj + objoffset) */
4353 SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4354 SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
4355 int nvars, /**< number of active variables in the problem */
4356 int nbinvars, /**< number of binary variables */
4357 int nintvars, /**< number of general integer variables */
4358 int nimplvars, /**< number of implicit integer variables */
4359 int ncontvars, /**< number of continuous variables */
4360 SCIP_VAR** fixedvars, /**< array with fixed variables */
4361 int nfixedvars, /**< number of fixed and aggregated variables in the problem */
4362 SCIP_CONS** conss, /**< array with constraints of the problem */
4363 int nconss, /**< number of constraints in the problem */
4364 SCIP_Bool genericnames, /**< should generic variable and constraint names be used */
4365 SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4366 )
4367{ /*lint --e{715}*/
4368 SCIP_RETCODE retcode = SCIP_OKAY;
4369
4370 if( nvars != nbinvars && (nintvars > 0 || SCIPfindConshdlr(scip, "indicator") != NULL
4371 || ncontvars + nimplvars != SCIPconshdlrGetNConss(SCIPfindConshdlr(scip, "indicator"))) )
4372 {
4373 SCIPwarningMessage(scip, "only binary problems can be written in OPB format.\n");
4375 }
4376 else
4377 {
4378 SCIP_VAR*** andvars;
4379 SCIP_VAR** resvars;
4380 int* nandvars;
4381 SCIP_Bool existands;
4382 SCIP_Bool existandconshdlr;
4383 int nresvars;
4384 int v;
4385
4386 /* computes all and-resultants and their corresponding constraint variables */
4387 /* coverity[leaked_storage] */
4389
4390 if( genericnames )
4391 {
4392#ifndef NDEBUG
4393 /* check for correct names for opb-format */
4394 int idx;
4395 int pos;
4396
4397 for( v = nvars - 1; v >= 0; --v )
4398 {
4399 if( existands )
4400 {
4401 /* and variables are artificial */
4402 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4403 continue;
4404 }
4405
4406 assert(sscanf(SCIPvarGetName(vars[v]), "x%d", &idx) == 1);
4407 }
4408#endif
4409 retcode = writeOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4411 }
4412 else
4413 {
4414 SCIP_Bool printed;
4415 int idx;
4416 int pos;
4417
4418 printed = FALSE;
4419
4420 /* check if there are already generic names for all (not fixed variables)*/
4421 for( v = nvars - 1; v >= 0; --v )
4422 if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4423 {
4424 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 )
4425 {
4426 SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4428 SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4429
4430 if( transformed )
4431 {
4432 SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4433 SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4434 }
4435 else
4436 {
4437 SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4438 SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4439 }
4440 printed = TRUE;
4441 break;
4442 }
4443 }
4444
4445 if( !printed )
4446 {
4447 /* check if there are already generic names for all (fixed variables)*/
4448 for( v = nfixedvars - 1; v >= 0; --v )
4449 if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4450 {
4451 /* coverity[secure_coding] */
4452 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 )
4453 {
4454 SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4455 SCIP_CALL( SCIPprintVar(scip, fixedvars[v], NULL) );
4456 SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4457
4458 if( transformed )
4459 {
4460 SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4461 SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4462 }
4463 else
4464 {
4465 SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4466 SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4467 }
4468 printed = TRUE;
4469 break;
4470 }
4471 }
4472 }
4473
4474 if( !printed )
4475 {
4476#ifndef NDEBUG
4477 for( v = nvars - 1; v >= 0; --v )
4478 {
4479 if( existands )
4480 {
4481 if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4482 continue;
4483 }
4484
4485 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 );
4486 }
4487#endif
4488 retcode = writeOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4490 }
4491 }
4492
4493 if( existands )
4494 {
4495 /* free temporary buffers */
4496 assert(resvars != NULL);
4497 assert(andvars != NULL);
4498 assert(nandvars != NULL);
4499
4500 for( v = nresvars - 1; v >= 0; --v )
4501 {
4502 assert(andvars[v] != NULL);
4504 }
4508 }
4509
4511 }
4512
4513 if( retcode == SCIP_INVALIDDATA )
4514 return SCIP_WRITEERROR;
4515
4516 return retcode;
4517}
4518
4519/*
4520 * Callback methods of reader
4521 */
4523/** copy method for reader plugins (called when SCIP copies plugins) */
4524static
4526{ /*lint --e{715}*/
4527 assert(scip != NULL);
4528 assert(reader != NULL);
4530
4531 /* call inclusion method of reader */
4533
4534 return SCIP_OKAY;
4535}
4536
4538/** problem reading method of reader */
4539static
4541{ /*lint --e{715}*/
4542
4543 SCIP_CALL( SCIPreadOpb(scip, reader, filename, result) );
4544
4545 return SCIP_OKAY;
4546}
4547
4549/** problem writing method of reader */
4550static
4552{ /*lint --e{715}*/
4553
4554 SCIP_CALL( SCIPwriteOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4555 nvars, nbinvars, nintvars, nimplvars, ncontvars, fixedvars, nfixedvars, conss, nconss, genericnames, result) );
4556
4557 return SCIP_OKAY;
4558}
4559
4560/*
4561 * reader specific interface methods
4563
4564/** includes the opb file reader in SCIP */
4566 SCIP* scip /**< SCIP data structure */
4567 )
4568{
4570
4571 /* include reader */
4573
4574 /* set non fundamental callbacks via setter functions */
4578
4579 /* add opb reader parameters */
4581 "reading/" READER_NAME "/dynamicconss", "should model constraints be subject to aging?",
4582 NULL, FALSE, FALSE/*TRUE*/, NULL, NULL) ); /* have to be FALSE, otherwise an error might inccur in restart during branch and bound */
4584 "reading/" READER_NAME "/multisymbol", "use '*' between coefficients and variables by writing to problem?",
4585 NULL, TRUE, FALSE, NULL, NULL) );
4586
4587 return SCIP_OKAY;
4588}
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 SCIP_MAXSTRLEN
Definition def.h:302
#define SCIP_Longint
Definition def.h:171
#define TRUE
Definition def.h:95
#define FALSE
Definition def.h:96
#define SCIP_CALL_ABORT(x)
Definition def.h:367
#define SCIPABORT()
Definition def.h:360
#define SCIP_LONGINT_MAX
Definition def.h:172
#define SCIP_CALL(x)
Definition def.h:388
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:4997
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:5175
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:5126
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:5150
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:3058
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3211
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition misc.c:3106
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition misc.c:3024
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition misc.c:2296
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2609
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:2246
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2497
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:4595
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4180
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:886
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4552
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8108
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition scip_cons.c:2482
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition cons.c:8397
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition cons.c:8185
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8088
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1119
#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 SCIPfreeBufferArrayNull(scip, ptr)
Definition scip_mem.h:137
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:1738
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:12763
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:17570
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:17360
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:17966
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition var.c:17846
SCIP_RETCODE SCIPgetBinvarRepresentatives(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **repvars, SCIP_Bool *negated)
Definition scip_var.c:1644
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:17748
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:17406
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:17580
SCIP_RETCODE SCIPchgVarBranchPriority(SCIP *scip, SCIP_VAR *var, int branchpriority)
Definition scip_var.c:7980
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:17241
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition var.c:17866
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1248
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition scip_var.c:1527
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:17956
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:17396
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition var.c:17726
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:9885
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition scip_var.c:4513
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition scip_var.c:1597
SCIP_RETCODE SCIPaddVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real addobj)
Definition scip_var.c:4562
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
void SCIPsortPtrPtrInt(void **ptrarray1, void **ptrarray2, int *intarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10788
void SCIPprintSysError(const char *message)
Definition misc.c:10680
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition misc.c:10655
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
#define NULL
Definition lpi_spx1.cpp:161
memory allocation routines
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:132
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
static SCIP_RETCODE readCoefficients(SCIP *const scip, OPBINPUT *const opbinput, char *const name, SCIP_VAR ***linvars, SCIP_Real **lincoefs, int *const nlincoefs, SCIP_VAR ****terms, SCIP_Real **termcoefs, int **ntermvars, int *const ntermcoefs, SCIP_Bool *const newsection, SCIP_Bool *const isNonlinear, SCIP_Bool *const issoftcons, SCIP_Real *const weight)
Definition reader_opb.c:770
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
#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