58 #include "scip/cons_linear.h"
59 #include "scip/cons_indicator.h"
60 #include "scip/scip.h"
69 inline void drop_space(std::istream& line)
71 while(std::isspace(line.peek()) || line.peek() ==
'(' || line.peek() ==
'{' || line.peek() ==
')' || line.peek() ==
'}' || line.peek() ==
',')
78 inline void drop_rest_line (std::istream& s)
97 fst_col = (*file).peek();
98 while (fst_col ==
'"' || fst_col ==
'*')
100 drop_rest_line(*file);
101 fst_col = (*file).peek();
110 if ( line.peek() ==
'\n' )
112 SCIPerrorMessage(
"Input File invalid, SDP/LP-block rows need to consist of five entries each, see data_format.txt\n");
115 while(std::isspace(line.peek()) || line.peek() ==
'(' || line.peek() ==
'{' || line.peek() ==
')' || line.peek() ==
'}' || line.peek() ==
',')
118 if ( line.peek() ==
'\n' )
120 SCIPerrorMessage(
"Input File invalid, SDP/LP-block rows need to consist of five entries each, see data_format.txt\n");
131 if ( line.peek() ==
'\n' || line.peek() ==
'"' || line.peek() ==
'*' || line.peek() == EOF )
135 while(std::isspace(line.peek()) || line.peek() ==
'(' || line.peek() ==
'{' || line.peek() ==
')' || line.peek() ==
'}' || line.peek() ==
',')
138 if ( line.peek() ==
'\n' || line.peek() ==
'"' || line.peek() ==
'*' || line.peek() == EOF )
142 else if (std::isspace(line.peek()) || line.peek() ==
'(' || line.peek() ==
'{' || line.peek() ==
')' || line.peek() ==
'}' || line.peek() ==
',')
146 SCIPerrorMessage(
"Input File invalid, SDP/LP-block rows need to consist of five entries each, see data_format.txt\n");
159 if ( (! isdigit((*file).peek())) && (! ((*file).peek() ==
'-')) )
161 SCIPerrorMessage(
"Input File invalid, got character '%c', but only numerals allowed in SDP/LP-block rows, see data_format.txt\n", (*file).peek());
171 const char* indexname,
178 SCIPerrorMessage(
"In an SDP/LP-block-line %s index %d was larger than given number of %ss %d.\n", indexname, value, indexname, ub);
195 const char* filename,
199 *result = SCIP_DIDNOTRUN;
211 std::vector<int, BlockMemoryAllocator<int> > blockpattern =
213 std::vector<SCIP_Real> object;
214 std::vector<SDPBlock> blockstruct;
216 std::vector<bool> blockislp;
217 std::vector<int> intvars;
218 std::vector <int> lp_block_num;
219 std::vector <int> lp_block_size;
221 bool lp_block_already_done;
223 SCIP_FILE* scip_file = SCIPfopen(filename,
"r");
225 return SCIP_READERROR;
231 std::istream file(&scip_buffer);
234 return SCIP_READERROR;
242 drop_rest_line(file);
250 drop_rest_line(file);
260 blockislp = std::vector<bool>(numblocks,
false);
261 lp_block_num = std::vector<int>(numblocks, 0);
262 lp_block_size = std::vector<int>(numblocks, 0);
264 for (
int j = 0; j < numblocks; ++j)
267 file >> blockpattern[j];
268 if (blockpattern[j] > 0)
271 blockstruct.push_back(
SDPBlock(blockpattern[j]));
274 else if (blockpattern[j] < 0)
278 alllpblocksize += abs(blockpattern[j]);
281 lp_block_num[j] = numlpblocks;
282 lp_block_size[numlpblocks - 1] = abs(blockpattern[j]);
286 printf(
"Blocklength 0 seems a bit odd, don't you think!\n");
289 assert(numblocks == numsdpblocks + numlpblocks);
291 drop_rest_line(file);
297 object = std::vector<SCIP_Real>(numvars, 0.0);
298 for (
int i = 0; i < numvars; ++i)
304 SCIPdebugMessage(
"Number of variables: %d \n", numvars);
305 SCIPdebugMessage(
"Number of blocks: %d \n", numblocks);
306 SCIPdebugMessage(
"Number of SDP- and LP-cones: %d, %d \n", numsdpblocks, numlpblocks);
312 LPData.
rows = std::vector<LProw>(alllpblocksize);
313 LPData.
numrows = alllpblocksize;
314 SCIPdebugMessage(
"Number of LP constraints: %d\n", alllpblocksize);
316 std::string commentline;
321 if(file.peek() ==
'*')
323 std::getline(file, commentline);
324 if (commentline.find(
"*INT") == 0)
336 int var_index, block_index;
337 int row_index, col_index;
343 SCIP_CALL(
checkIndex(
"variable", var_index, numvars) );
348 SCIP_CALL(
checkIndex(
"block", block_index, numblocks) );
353 SCIP_CALL(
checkIndex(
"row", row_index, (blockislp[block_index - 1] ? LPData.
numrows : blockstruct[block_index - 1].blocksize)) );
358 SCIP_CALL(
checkIndex(
"column", col_index, (blockislp[block_index - 1] ? LPData.
numrows : blockstruct[block_index - 1].blocksize)) );
365 if (SCIPisEQ(scip, val, 0.0))
367 drop_rest_line(file);
373 if (!blockislp[block_index - 1])
375 if (row_index < col_index)
377 int save_row = row_index;
378 row_index = col_index;
379 col_index = save_row;
384 blockstruct[block_index - 1].constcolumns.push_back(col_index);
385 blockstruct[block_index - 1].constrows.push_back(row_index);
386 blockstruct[block_index - 1].constvalues.push_back(val);
387 blockstruct[block_index - 1].constnum_nonzeros++;
391 blockstruct[block_index - 1].columns.push_back(col_index);
392 blockstruct[block_index - 1].rows.push_back(row_index);
393 blockstruct[block_index - 1].values.push_back(val);
394 blockstruct[block_index - 1].variables.push_back(var_index);
395 blockstruct[block_index - 1].num_nonzeros++;
397 SCIPdebugMessage(
"SDP entry: block_index: %d, row: %d, col: %d, var: %d, val: %g\n", block_index, row_index, col_index, var_index,val );
400 else if (blockislp[block_index - 1])
402 assert(row_index == col_index);
403 if ( lp_block_num[block_index - 1] == 1 )
404 new_row_index = row_index - 1;
412 for ( b = 0; b < lp_block_num[block_index - 1] - 1; b++ )
413 rowoffset += lp_block_size[b];
415 new_row_index = rowoffset + row_index - 1;
417 LPData.
rows[new_row_index].data.push_back(std::make_pair(var_index, val));
418 SCIPdebugMessage(
"LP entry: row: %d, var: %d, val: %g\n", new_row_index, var_index,val );
421 drop_rest_line(file);
427 intvars = std::vector<int>(numvars, 0);
429 while(file.peek() ==
'*')
435 intvars[index - 1] = 1;
436 SCIPdebugMessage(
"Variable %d is integer.\n", index - 1);
437 drop_rest_line(file);
446 SCIP_CALL( SCIPcreateProb(scip, filename, 0, 0, 0, 0, 0, 0, 0) );
452 std::vector<SCIP_VAR*> VariablesX ( numvars );
454 for (
int i = 0; i < numvars; ++i)
457 char var_name[SCIP_MAXSTRLEN];
459 snprintfreturn = SCIPsnprintf(var_name, SCIP_MAXSTRLEN,
"X_%d", i);
460 assert( snprintfreturn < SCIP_MAXSTRLEN);
462 (void)SCIPsnprintf(var_name, SCIP_MAXSTRLEN,
"X_%d", i);
468 SCIP_CALL( SCIPcreateVar(scip, &var, var_name, -SCIPinfinity(scip), SCIPinfinity(scip),
object[i], SCIP_VARTYPE_INTEGER, TRUE, FALSE, 0, 0, 0, 0, 0));
472 SCIP_CALL( SCIPcreateVar(scip, &var, var_name, -SCIPinfinity(scip), SCIPinfinity(scip),
object[i],
473 SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, 0, 0, 0, 0, 0));
476 SCIP_CALL( SCIPaddVar(scip, var) );
480 SCIP_CALL( SCIPreleaseVar(scip, &var) );
488 lp_block_already_done =
false;
489 for (
int bindex = 0; bindex < numblocks; ++bindex)
491 if (!blockislp[bindex])
502 SCIP_Real** valpointer;
514 SCIPdebugMessage(
"Begin construction of SDP constraint for block %d.\n", bindex);
516 blocksize = blockpattern[bindex];
517 nnonz = blockstruct[bindex].num_nonzeros;
521 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &varind, blockstruct[bindex].num_nonzeros) );
522 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &col, blockstruct[bindex].num_nonzeros) );
523 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &row, blockstruct[bindex].num_nonzeros) );
524 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &val, blockstruct[bindex].num_nonzeros) );
525 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &colpointer, numvars) );
526 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &rowpointer, numvars) );
527 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &valpointer, numvars) );
528 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &vars, numvars) );
530 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &constcol, blockstruct[bindex].constnum_nonzeros) );
531 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &constrow, blockstruct[bindex].constnum_nonzeros) );
532 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &constval, blockstruct[bindex].constnum_nonzeros) );
535 SCIP_CALL(SCIPallocBlockMemoryArray(scip, &nvarnonz, numvars));
536 for (
int i = 0; i < numvars; i++)
540 for (k = 0; k < blockstruct[bindex].constnum_nonzeros; ++k)
542 if ( ! SCIPisZero(scip, blockstruct[bindex].constvalues[k]) )
544 constcol[ind] = blockstruct[bindex].constcolumns[k] - 1;
545 constrow[ind] = blockstruct[bindex].constrows[k] - 1;
546 constval[ind] = blockstruct[bindex].constvalues[k];
554 for (k = 0; k < nnonz; ++k)
556 if ( ! SCIPisZero(scip, blockstruct[bindex].values[k]) )
558 varind[ind] = blockstruct[bindex].variables[k] - 1;
559 col[ind] = blockstruct[bindex].columns[k] - 1;
560 row[ind] = blockstruct[bindex].rows[k] - 1;
561 val[ind] = blockstruct[bindex].values[k];
567 SCIPsortIntIntIntReal(varind, col, row, val, nnonz);
572 for (k = 0; k < numvars; k++)
575 firstindforvar = nextindaftervar;
576 while (nextindaftervar < nnonz && varind[nextindaftervar] == k)
584 vars[ind] = VariablesX[k];
585 colpointer[ind] = &col[firstindforvar];
586 rowpointer[ind] = &row[firstindforvar];
587 valpointer[ind] = &val[firstindforvar];
592 assert (nextindaftervar == nnonz);
595 SCIPfreeBlockMemoryArray(scip, &varind, blockstruct[bindex].num_nonzeros);
600 char sdpcon_name[SCIP_MAXSTRLEN];
602 snprintfreturn = SCIPsnprintf(sdpcon_name, SCIP_MAXSTRLEN,
"SDP-Constraint-%d", bindex);
603 assert( snprintfreturn < SCIP_MAXSTRLEN);
605 (void) SCIPsnprintf(sdpcon_name, SCIP_MAXSTRLEN,
"SDP-Constraint-%d", bindex);
607 SCIP_CALL(
SCIPcreateConsSdp(scip, &sdpcon, sdpcon_name, nvars, nnonz, blocksize, nvarnonz, colpointer,
608 rowpointer, valpointer, vars, constnnonz, constcol, constrow, constval) );
610 #ifdef SCIP_MORE_DEBUG
611 SCIP_CALL( SCIPprintCons(scip, sdpcon, NULL) );
614 SCIP_CALL( SCIPaddCons(scip, sdpcon) );
616 SCIP_CALL( SCIPreleaseCons(scip, &sdpcon) );
619 SCIPfreeBlockMemoryArray(scip, &nvarnonz, numvars);
620 SCIPfreeBlockMemoryArray(scip, &constval, blockstruct[bindex].constnum_nonzeros);
621 SCIPfreeBlockMemoryArray(scip, &constrow, blockstruct[bindex].constnum_nonzeros);
622 SCIPfreeBlockMemoryArray(scip, &constcol, blockstruct[bindex].constnum_nonzeros);
623 SCIPfreeBlockMemoryArray(scip, &vars, numvars);
624 SCIPfreeBlockMemoryArray(scip, &valpointer, numvars);
625 SCIPfreeBlockMemoryArray(scip, &rowpointer, numvars);
626 SCIPfreeBlockMemoryArray(scip, &colpointer, numvars);
627 SCIPfreeBlockMemoryArray(scip, &val, blockstruct[bindex].num_nonzeros);
628 SCIPfreeBlockMemoryArray(scip, &row, blockstruct[bindex].num_nonzeros);
629 SCIPfreeBlockMemoryArray(scip, &col, blockstruct[bindex].num_nonzeros);
631 SCIPdebugMessage(
"Construction of SDP constraint for block %d completed.\n", bindex);
636 if (!lp_block_already_done)
640 lp_block_already_done =
true;
641 SCIPdebugMessage(
"Begin construction of LP (block %d).\n", bindex);
643 for (
int row_i = 0; row_i < LPData.
numrows; ++row_i)
646 char LPcon_name[SCIP_MAXSTRLEN];
649 snprintfreturn = SCIPsnprintf(LPcon_name, SCIP_MAXSTRLEN,
"LP-Con-%d", row_i);
650 assert( snprintfreturn < SCIP_MAXSTRLEN );
652 (void) SCIPsnprintf(LPcon_name, SCIP_MAXSTRLEN,
"LP-Con-%d", row_i);
656 SCIP_Real LPlhs = 0.0;
658 for (
unsigned int var_i = 0; var_i < LPData.
rows[row_i].data.size(); ++var_i)
660 if (LPData.
rows[row_i].data[var_i].first == 0)
662 LPlhs = LPData.
rows[row_i].data[var_i].second;
667 for (
unsigned int var_i = 0; var_i < LPData.
rows[row_i].data.size(); ++var_i)
669 if (LPData.
rows[row_i].data[var_i].first < 0)
678 SCIP_CALL( SCIPcreateConsLinear(scip, &LPcon, LPcon_name, 0, 0, 0, LPlhs, SCIPinfinity(scip), TRUE, TRUE,
679 TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE));
681 SCIP_CALL( SCIPaddCons(scip, LPcon) );
684 for (
unsigned int var_i = 0; var_i < LPData.
rows[row_i].data.size(); ++var_i)
686 if (LPData.
rows[row_i].data[var_i].first != 0)
688 SCIP_CALL( SCIPaddCoefLinear(scip, LPcon, VariablesX[LPData.
rows[row_i].data[var_i].first - 1], LPData.
rows[row_i].data[var_i].second) );
691 #ifdef SCIP_MORE_DEBUG
692 SCIP_CALL( SCIPprintCons(scip, LPcon, NULL) );
694 SCIP_CALL( SCIPreleaseCons(scip, &LPcon) );
701 char cons_name[SCIP_MAXSTRLEN];
704 snprintfreturn = SCIPsnprintf(cons_name, SCIP_MAXSTRLEN,
"cons_indicator_%d", nindconss);
705 assert( snprintfreturn < SCIP_MAXSTRLEN);
707 (void)SCIPsnprintf(cons_name, SCIP_MAXSTRLEN,
"cons_indicator_%d", nindconss);
713 assert( indicator <= 1 );
716 SCIP_CALL( SCIPcreateConsLinear(scip, &LPcon, LPcon_name, 0, 0, 0, LPlhs, SCIPinfinity(scip), TRUE, TRUE,
717 TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE));
720 for (
unsigned int var_i = 0; var_i < LPData.
rows[row_i].data.size(); ++var_i)
722 if (LPData.
rows[row_i].data[var_i].first > 0)
724 SCIP_CALL( SCIPaddCoefLinear(scip, LPcon, VariablesX[LPData.
rows[row_i].data[var_i].first - 1], LPData.
rows[row_i].data[var_i].second) );
726 else if (LPData.
rows[row_i].data[var_i].first < 0)
728 char var_name[SCIP_MAXSTRLEN];
729 SCIP_Bool infeasible;
731 snprintfreturn = SCIPsnprintf(var_name, SCIP_MAXSTRLEN,
"s_%d", nindconss);
732 assert( snprintfreturn < SCIP_MAXSTRLEN);
734 (void)SCIPsnprintf(var_name, SCIP_MAXSTRLEN,
"s_%d", nindconss);
741 indvar = VariablesX[-1 * LPData.
rows[row_i].data[var_i].first - 1];
742 #ifdef SCIP_WARN_INDICATOR
743 SCIPwarningMessage(scip,
"Changing type of variable %s to binary, since it appears as an indicator variable "
744 "in constraint %s\n", SCIPvarGetName(indvar), LPcon_name);
746 assert(SCIPvarIsIntegral( VariablesX[-1 * LPData.
rows[row_i].data[var_i].first - 1] ));
747 SCIP_CALL( SCIPchgVarLbGlobal(scip, indvar, 0.0) );
748 SCIP_CALL( SCIPchgVarUbGlobal(scip, indvar, 1.0) );
749 SCIP_CALL( SCIPchgVarType(scip, indvar, SCIP_VARTYPE_BINARY, &infeasible) );
752 SCIP_CALL( SCIPcreateVar(scip, &slackvar, var_name, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, 0, 0, 0, 0, 0));
754 SCIP_CALL( SCIPaddVar(scip, slackvar) );
757 SCIP_CALL( SCIPaddCoefLinear(scip, LPcon, slackvar, +1.0) );
762 SCIP_CALL( SCIPcreateConsIndicatorLinCons( scip, &indcons, cons_name, indvar, LPcon, slackvar,
763 TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
764 SCIP_CALL( SCIPaddCons(scip, LPcon) );
765 SCIP_CALL( SCIPaddCons(scip, indcons) );
768 SCIP_CALL( SCIPprintCons(scip, indcons, NULL) );
772 SCIP_CALL( SCIPreleaseCons(scip, &indcons) );
773 SCIP_CALL( SCIPreleaseVar(scip, &slackvar) );
774 SCIP_CALL( SCIPreleaseCons(scip, &LPcon) );
781 *result = SCIP_SUCCESS;
An STL allocator class using SCIP block memory.
An std::streambuf that uses SCIP I/O routines (suitable for reading)
static SCIP_RETCODE dropSpaceNewlineError(std::istream &line)
virtual SCIP_RETCODE scip_read(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result)
Reader for SDPA-Files with indicator constraints (-var in linear constraint => indicator constraint w...
std::vector< LProw > rows
Constraint handler for SDP-constraints.
static SCIP_RETCODE checkForLineEnd(std::istream &line)
SCIP_RETCODE SCIPcreateConsSdp(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, int nnonz, int blocksize, int *nvarnonz, int **col, int **row, SCIP_Real **val, SCIP_VAR **vars, int constnnonz, int *constcol, int *constrow, SCIP_Real *constval)
static SCIP_RETCODE checkIndex(const char *indexname, int value, int ub)
static SCIP_RETCODE testDigit(std::istream *file)
static SCIP_RETCODE dropComments(std::istream *file)