SCIP-SDP  3.1.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
objreader_sdpaind.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of SCIPSDP - a solving framework for mixed-integer */
4 /* semidefinite programs based on SCIP. */
5 /* */
6 /* Copyright (C) 2011-2013 Discrete Optimization, TU Darmstadt */
7 /* EDOM, FAU Erlangen-Nürnberg */
8 /* 2014-2018 Discrete Optimization, TU Darmstadt */
9 /* */
10 /* */
11 /* This program is free software; you can redistribute it and/or */
12 /* modify it under the terms of the GNU Lesser General Public License */
13 /* as published by the Free Software Foundation; either version 3 */
14 /* of the License, or (at your option) any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU Lesser General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with this program; if not, write to the Free Software */
23 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
24 /* */
25 /* */
26 /* Based on SCIP - Solving Constraint Integer Programs */
27 /* Copyright (C) 2002-2018 Zuse Institute Berlin */
28 /* SCIP is distributed under the terms of the SCIP Academic Licence, */
29 /* see file COPYING in the SCIP distribution. */
30 /* */
31 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
32 
40 /*#define SCIP_DEBUG*/
41 /*#define SCIP_MORE_DEBUG*/
42 /*#define SCIP_WARN_INDICATOR*/
43 
44 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
45 #include "objreader_sdpaind.h"
46 
47 #include <cassert> // for assert
48 #include <cctype> // for isspace
49 #include <cstdio> // for printf
50 #include <cstdlib> // for abs /*lint !e10*//*lint !e129*/
51 #include <istream> // for istream, etc
52 #include <string> // for getline, string
53 
54 #include "BlockMemoryAllocator.h" // for BlockMemoryAllocator
55 #include "ScipStreamBuffer.h" // for ScipStreamBuffer
56 #include "scipsdp/cons_sdp.h" // for SCIPcreateConsSdp
57 
58 #include "scip/cons_linear.h" // for SCIPaddCoefLinear, etc
59 #include "scip/cons_indicator.h" // for SCIPcreateConsIndicatorLinCons
60 #include "scip/scip.h" // for SCIPinfinity, etc
61 
62 /* turn off lint warnings for whole file: */
63 /*lint --e{788,818}*/
64 
65 namespace
66 {
67 
68 /* drop spaces and all brackets that are allowed within the blocks in the sdpa format */
69  inline void drop_space(std::istream& line)
70  {
71  while(std::isspace(line.peek()) || line.peek() == '(' || line.peek() == '{' || line.peek() == ')' || line.peek() == '}' || line.peek() == ',')
72  {
73  line.ignore(1);/*lint !e747*//*lint !e534*/
74  }
75  return;
76  }
77 
78  inline void drop_rest_line (std::istream& s)
79  {
80  std::string tmp;
81  std::getline(s, tmp);/*lint !e534*/
82  return;
83  }
84 
85 }
86 
87 namespace scip
88 {
89 
91  static
92  SCIP_RETCODE dropComments(
93  std::istream* file /* the file instance that is read */
94  )
95  {
96  char fst_col('"');
97  fst_col = (*file).peek();/*lint !e734*//*lint !e838*/
98  while (fst_col == '"' || fst_col == '*')
99  {
100  drop_rest_line(*file);
101  fst_col = (*file).peek();/*lint !e734*/
102  }
103  return SCIP_OKAY;
104  }
105 
106  /* drop spaces and all brackets that are allowed within the blocks in the sdpa format, throws an error if it reaches a newline */
107  static
108  SCIP_RETCODE dropSpaceNewlineError(std::istream& line)
109  {
110  if ( line.peek() == '\n' )
111  {
112  SCIPerrorMessage("Input File invalid, SDP/LP-block rows need to consist of five entries each, see data_format.txt\n");
113  return SCIP_ERROR;
114  }
115  while(std::isspace(line.peek()) || line.peek() == '(' || line.peek() == '{' || line.peek() == ')' || line.peek() == '}' || line.peek() == ',')
116  {
117  line.ignore(1);/*lint !e747*//*lint !e534*/
118  if ( line.peek() == '\n' )
119  {
120  SCIPerrorMessage("Input File invalid, SDP/LP-block rows need to consist of five entries each, see data_format.txt\n");
121  return SCIP_ERROR;
122  }
123  }
124  return SCIP_OKAY;
125  }
126 
127  /* checks that only spaces, newlines or comments follow in the current line */
128  static
129  SCIP_RETCODE checkForLineEnd(std::istream& line)
130  {
131  if ( line.peek() == '\n' || line.peek() == '"' || line.peek() == '*' || line.peek() == EOF )
132  {
133  return SCIP_OKAY;
134  }
135  while(std::isspace(line.peek()) || line.peek() == '(' || line.peek() == '{' || line.peek() == ')' || line.peek() == '}' || line.peek() == ',')
136  {
137  line.ignore(1);/*lint !e747*//*lint !e534*/
138  if ( line.peek() == '\n' || line.peek() == '"' || line.peek() == '*' || line.peek() == EOF )
139  {
140  return SCIP_OKAY;
141  }
142  else if (std::isspace(line.peek()) || line.peek() == '(' || line.peek() == '{' || line.peek() == ')' || line.peek() == '}' || line.peek() == ',')
143  continue;
144  else
145  {
146  SCIPerrorMessage("Input File invalid, SDP/LP-block rows need to consist of five entries each, see data_format.txt\n");
147  return SCIP_ERROR;
148  }
149  }
150  return SCIP_OKAY;
151  }
152 
154  static
155  SCIP_RETCODE testDigit(
156  std::istream* file /* the file instance that is read */
157  )
158  {
159  if ( (! isdigit((*file).peek())) && (! ((*file).peek() == '-')) )
160  {
161  SCIPerrorMessage("Input File invalid, got character '%c', but only numerals allowed in SDP/LP-block rows, see data_format.txt\n", (*file).peek());
162  return SCIP_ERROR;
163  }
164 
165  return SCIP_OKAY;
166  }
167 
169  static
170  SCIP_RETCODE checkIndex(
171  const char* indexname, /* name of the index that will be used in the error message */
172  int value, /* value to check against the upper bound */
173  int ub /* upper bound to check against */
174  )
175  {
176  if ( value > ub )
177  {
178  SCIPerrorMessage("In an SDP/LP-block-line %s index %d was larger than given number of %ss %d.\n", indexname, value, indexname, ub);
179  return SCIP_ERROR;
180  }
181  return SCIP_OKAY;
182  }
183 
193  SCIP* scip,
194  SCIP_READER* reader,
195  const char* filename,
196  SCIP_RESULT* result
197  )
198  {/*lint --e{715}*/
199  *result = SCIP_DIDNOTRUN;
200 
201  int numvars; //Number of variables
202  int numblocks; //Number of all blocks (SDP + LP)
203  int numsdpblocks; //Number of SDP-blocks
204  int numlpblocks; //Number of LP-blocks
205  int alllpblocksize; //Size of all LP-blocks added
206  int* nvarnonz; // nblockvarnonz[i] gives the number of nonzeros for variable i
207 #ifndef NDEBUG
208  int snprintfreturn; // to check return codes of snprintf
209 #endif
210 
211  std::vector<int, BlockMemoryAllocator<int> > blockpattern =
212  std::vector<int, BlockMemoryAllocator<int> >(BlockMemoryAllocator<int>(scip)); //Vector with the sizes of all blocks
213  std::vector<SCIP_Real> object; //Objectivevector
214  std::vector<SDPBlock> blockstruct; //Blockstructure
215  LPBlock LPData; //LP Data
216  std::vector<bool> blockislp; //Is the block an LP block?
217  std::vector<int> intvars; //Indices of integer variables
218  std::vector <int> lp_block_num;
219  std::vector <int> lp_block_size;
220  int new_row_index;
221  bool lp_block_already_done;
222 
223  SCIP_FILE* scip_file = SCIPfopen(filename, "r");
224  if (!scip_file)
225  return SCIP_READERROR;
226 
227  // setup buffer
228  ScipStreamBuffer scip_buffer(scip, scip_file, true);
229 
230  // setup our stream from the new buffer
231  std::istream file(&scip_buffer);
232 
233  if( !file )
234  return SCIP_READERROR;
235  file.clear();
236 
237  SCIP_CALL(dropComments(&file));
238 
239  // read numvar
240  drop_space(file);
241  file >> numvars;
242  drop_rest_line(file);
243 
244  SCIP_CALL(dropComments(&file));
245 
246  // read numblocks
247  drop_space(file);
248  file >> numblocks;
249 
250  drop_rest_line(file);
251 
252  numlpblocks = 0;
253  numsdpblocks = 0;
254  alllpblocksize = 0;
255 
256  SCIP_CALL(dropComments(&file));
257 
258  // read block pattern
259  blockpattern = std::vector<int, BlockMemoryAllocator<int> >(numblocks, 0, BlockMemoryAllocator<int>(scip));
260  blockislp = std::vector<bool>(numblocks, false);/*lint !e747*//*lint !e732*/
261  lp_block_num = std::vector<int>(numblocks, 0);
262  lp_block_size = std::vector<int>(numblocks, 0);
263 
264  for (int j = 0; j < numblocks; ++j)
265  {
266  drop_space(file);
267  file >> blockpattern[j];/*lint !e747*//*lint !e732*/
268  if (blockpattern[j] > 0)/*lint !e747*//*lint !e732*/
269  {
270  numsdpblocks++;
271  blockstruct.push_back(SDPBlock(blockpattern[j]));/*lint !e747*//*lint !e732*/
272 
273  }
274  else if (blockpattern[j] < 0)/*lint !e747*//*lint !e732*/
275  {
276  //LP block has a negative coefficient!
277  numlpblocks++;
278  alllpblocksize += abs(blockpattern[j]);/*lint !e747*//*lint !e732*/
279  blockislp[j] = true;/*lint !e747*//*lint !e732*//*lint !e1793*/
280  blockstruct.push_back(SDPBlock(0));
281  lp_block_num[j] = numlpblocks;/*lint !e747*//*lint !e732*/
282  lp_block_size[numlpblocks - 1] = abs(blockpattern[j]);/*lint !e747*//*lint !e732*/
283 
284  }
285  else
286  printf("Blocklength 0 seems a bit odd, don't you think!\n");
287  }
288 
289  assert(numblocks == numsdpblocks + numlpblocks);
290 
291  drop_rest_line(file);
292  drop_space(file);
293 
294  SCIP_CALL(dropComments(&file));
295 
296  // read objective
297  object = std::vector<SCIP_Real>(numvars, 0.0);/*lint !e747*//*lint !e732*/
298  for (int i = 0; i < numvars; ++i)
299  {
300  file >> object[i];/*lint !e747*//*lint !e732*/
301  drop_space(file);
302  }
303 
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);
307 
308 
309  // construct blocks
310 
311  //construct LP block
312  LPData.rows = std::vector<LProw>(alllpblocksize);/*lint !e747*//*lint !e732*/
313  LPData.numrows = alllpblocksize;
314  SCIPdebugMessage("Number of LP constraints: %d\n", alllpblocksize);
315 
316  std::string commentline;
317 
318  // read data
319  while(!file.eof())
320  {
321  if(file.peek() == '*') // comment
322  {
323  std::getline(file, commentline);/*lint !e534*/
324  if (commentline.find("*INT") == 0) // if current line starts with *INT then go to Integer definitions
325  {
326  drop_space(file); // drop \newline
327  break;
328  }
329  else // usual comment line
330  {
331  drop_space(file);
332  }
333  }
334  else
335  {
336  int var_index, block_index; // block id
337  int row_index, col_index; // position in matrix
338  SCIP_Real val;
339  drop_space(file);
340 
341  SCIP_CALL( testDigit(&file) );
342  file >> var_index;
343  SCIP_CALL( checkIndex("variable", var_index, numvars) );
344  SCIP_CALL( dropSpaceNewlineError(file) );
345 
346  SCIP_CALL( testDigit(&file) );
347  file >> block_index;
348  SCIP_CALL( checkIndex("block", block_index, numblocks) );
349  SCIP_CALL( dropSpaceNewlineError(file) );
350 
351  SCIP_CALL( testDigit(&file) );
352  file >> row_index;
353  SCIP_CALL( checkIndex("row", row_index, (blockislp[block_index - 1] ? LPData.numrows : blockstruct[block_index - 1].blocksize)) );/*lint !e732*//*lint !e747*/
354  SCIP_CALL( dropSpaceNewlineError(file) );
355 
356  SCIP_CALL( testDigit(&file) );
357  file >> col_index;
358  SCIP_CALL( checkIndex("column", col_index, (blockislp[block_index - 1] ? LPData.numrows : blockstruct[block_index - 1].blocksize)) );/*lint !e732*//*lint !e747*/
359  SCIP_CALL( dropSpaceNewlineError(file) );
360 
361  SCIP_CALL( testDigit(&file) );
362  file >> val;
363  SCIP_CALL( checkForLineEnd(file) );
364 
365  if (SCIPisEQ(scip, val, 0.0))
366  {
367  drop_rest_line(file);
368  drop_space(file);
369  continue;
370  }
371 
372  //sdp-block
373  if (!blockislp[block_index - 1])/*lint !e732*//*lint !e747*/
374  {
375  if (row_index < col_index)
376  {
377  int save_row = row_index;
378  row_index = col_index;
379  col_index = save_row;
380  }
381 
382  if (var_index == 0)
383  {
384  blockstruct[block_index - 1].constcolumns.push_back(col_index);/*lint !e732*//*lint !e747*/
385  blockstruct[block_index - 1].constrows.push_back(row_index);/*lint !e732*//*lint !e747*/
386  blockstruct[block_index - 1].constvalues.push_back(val);/*lint !e732*//*lint !e747*/
387  blockstruct[block_index - 1].constnum_nonzeros++;/*lint !e732*//*lint !e747*/
388  }
389  else
390  {
391  blockstruct[block_index - 1].columns.push_back(col_index);/*lint !e732*//*lint !e747*/
392  blockstruct[block_index - 1].rows.push_back(row_index);/*lint !e732*//*lint !e747*/
393  blockstruct[block_index - 1].values.push_back(val);/*lint !e732*//*lint !e747*/
394  blockstruct[block_index - 1].variables.push_back(var_index);/*lint !e732*//*lint !e747*/
395  blockstruct[block_index - 1].num_nonzeros++;/*lint !e732*//*lint !e747*/
396  }
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 );/*lint !e525*/
398  }
399  //lp-block
400  else if (blockislp[block_index - 1])/*lint !e732*//*lint !e747*/
401  {
402  assert(row_index == col_index);
403  if ( lp_block_num[block_index - 1] == 1 )/*lint !e732*//*lint !e747*/
404  new_row_index = row_index - 1;
405  else //we combine all lp blocks to a single one, so we add the total number of rows of earlier blocks to the row index
406  {
407  int rowoffset;
408  int b;
409 
410  rowoffset = 0;
411 
412  for ( b = 0; b < lp_block_num[block_index - 1] - 1; b++ )/*lint !e732*//*lint !e747*/
413  rowoffset += lp_block_size[b];/*lint !e732*//*lint !e747*/
414 
415  new_row_index = rowoffset + row_index - 1;
416  }
417  LPData.rows[new_row_index].data.push_back(std::make_pair(var_index, val));/*lint !e732*//*lint !e747*/
418  SCIPdebugMessage("LP entry: row: %d, var: %d, val: %g\n", new_row_index, var_index,val );
419  }
420 
421  drop_rest_line(file);
422  drop_space(file);
423  }
424  }
425 
426  //read integer variables
427  intvars = std::vector<int>(numvars, 0);
428 
429  while(file.peek() == '*')
430  {
431  int index;/*lint !e578*/
432  file.ignore(1);/*lint !e534*//*lint !e747*/
433  file >> index;
434  //in the SDPA-file the variable numbers start at 1!
435  intvars[index - 1] = 1;/*lint !e732*//*lint !e747*/
436  SCIPdebugMessage("Variable %d is integer.\n", index - 1);
437  drop_rest_line(file);
438  drop_space(file);
439  }
440 
441 
442  /************************/
443  /* create empty problem */
444  /************************/
445 
446  SCIP_CALL( SCIPcreateProb(scip, filename, 0, 0, 0, 0, 0, 0, 0) );
447 
448  /*****************/
449  /* add variables */
450  /*****************/
451 
452  std::vector<SCIP_VAR*> VariablesX ( numvars );/*lint !e732*//*lint !e747*/
453 
454  for ( int i = 0; i < numvars; ++i)
455  {
456  SCIP_VAR* var;
457  char var_name[SCIP_MAXSTRLEN];
458 #ifndef NDEBUG
459  snprintfreturn = SCIPsnprintf(var_name, SCIP_MAXSTRLEN, "X_%d", i);
460  assert( snprintfreturn < SCIP_MAXSTRLEN);
461 #else
462  (void)SCIPsnprintf(var_name, SCIP_MAXSTRLEN, "X_%d", i);
463 #endif
464 
465 
466  if (intvars[i] == 1)/*lint !e732*//*lint !e747*/
467  {
468  SCIP_CALL( SCIPcreateVar(scip, &var, var_name, -SCIPinfinity(scip), SCIPinfinity(scip), object[i], SCIP_VARTYPE_INTEGER, TRUE, FALSE, 0, 0, 0, 0, 0));/*lint !e732*//*lint !e747*/
469  }
470  else
471  {
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));/*lint !e732*//*lint !e747*/
474  }
475 
476  SCIP_CALL( SCIPaddVar(scip, var) );
477  VariablesX[i] = var;/*lint !e732*//*lint !e747*/
478 
479  /* release variable for the reader. */
480  SCIP_CALL( SCIPreleaseVar(scip, &var) );
481  }
482 
483 
484  /*********************************/
485  /* create SDP and LP constraints */
486  /*********************************/
487 
488  lp_block_already_done = false;
489  for (int bindex = 0; bindex < numblocks; ++bindex)
490  {
491  if (!blockislp[bindex])/*lint !e732*//*lint !e747*/
492  {
493  int nvars;
494  int nnonz;
495  int blocksize;
496  int* varind; /* this is used to sort the nonzeroes by variable-indices and check which variables are actually included in this block */
497  int* col;
498  int* row;
499  SCIP_Real* val;
500  int** colpointer;
501  int** rowpointer;
502  SCIP_Real** valpointer;
503  SCIP_Var** vars;
504  int constnnonz;
505  int* constcol;
506  int* constrow;
507  SCIP_Real* constval;
508  int k;
509  int ind;
510  int nextindaftervar;
511  int firstindforvar;
512  SCIP_Bool varused;
513 
514  SCIPdebugMessage("Begin construction of SDP constraint for block %d.\n", bindex);
515 
516  blocksize = blockpattern[bindex];/*lint !e732*//*lint !e747*/
517  nnonz = blockstruct[bindex].num_nonzeros;/*lint !e732*//*lint !e747*/
518  ind = 0;
519 
520  /* allocate memory */
521  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &varind, blockstruct[bindex].num_nonzeros) );/*lint !e732*//*lint !e530*/
522  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &col, blockstruct[bindex].num_nonzeros) );/*lint !e732*//*lint !e530*/
523  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &row, blockstruct[bindex].num_nonzeros) );/*lint !e732*//*lint !e530*/
524  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &val, blockstruct[bindex].num_nonzeros) );/*lint !e732*//*lint !e530*/
525  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &colpointer, numvars) );/*lint !e732*//*lint !e530*/
526  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &rowpointer, numvars) );/*lint !e732*//*lint !e530*/
527  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &valpointer, numvars) );/*lint !e732*//*lint !e530*/
528  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &vars, numvars) );/*lint !e732*//*lint !e530*/
529 
530  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &constcol, blockstruct[bindex].constnum_nonzeros) );/*lint !e732*//*lint !e530*/
531  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &constrow, blockstruct[bindex].constnum_nonzeros) );/*lint !e732*//*lint !e530*/
532  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &constval, blockstruct[bindex].constnum_nonzeros) );/*lint !e732*//*lint !e530*/
533 
534  /* allocate memory for nblockvarnonz & initialize it with zero */
535  SCIP_CALL(SCIPallocBlockMemoryArray(scip, &nvarnonz, numvars));/*lint !e530*/
536  for (int i = 0; i < numvars; i++)
537  nvarnonz[i] = 0;
538 
539  /* prepare the constant arrays */
540  for (k = 0; k < blockstruct[bindex].constnum_nonzeros; ++k)/*lint !e732*//*lint !e747*/
541  {
542  if ( ! SCIPisZero(scip, blockstruct[bindex].constvalues[k]) )/*lint !e732*//*lint !e747*/
543  {
544  constcol[ind] = blockstruct[bindex].constcolumns[k] - 1;/*lint !e732*//*lint !e747*/ /* the sdpa format counts from 1 to blocksize, we want to start from 0 */
545  constrow[ind] = blockstruct[bindex].constrows[k] - 1;/*lint !e732*//*lint !e747*/
546  constval[ind] = blockstruct[bindex].constvalues[k];/*lint !e732*//*lint !e747*/
547  ind++;
548  }
549  }
550  constnnonz = ind;
551 
552  /* prepare the non-constant arrays */
553  ind = 0;
554  for (k = 0; k < nnonz; ++k)
555  {
556  if ( ! SCIPisZero(scip, blockstruct[bindex].values[k]) )/*lint !e732*//*lint !e747*/
557  {
558  varind[ind] = blockstruct[bindex].variables[k] - 1;/*lint !e732*//*lint !e747*/
559  col[ind] = blockstruct[bindex].columns[k] - 1;/*lint !e732*//*lint !e747*/
560  row[ind] = blockstruct[bindex].rows[k] - 1;/*lint !e732*//*lint !e747*/
561  val[ind] = blockstruct[bindex].values[k];/*lint !e732*//*lint !e747*/
562  ind++;
563  }
564  }
565  nnonz = ind;
566 
567  SCIPsortIntIntIntReal(varind, col, row, val, nnonz); /* sort the nonzeroes by non-decreasing variable indices */
568 
569  /* create the pointer arrays and insert used variables into vars-array */
570  nextindaftervar = 0;
571  ind = 0; /* sdp index of the current variable */
572  for (k = 0; k < numvars; k++)
573  {
574  varused = FALSE;
575  firstindforvar = nextindaftervar; /* this variable starts where the last one ended */
576  while (nextindaftervar < nnonz && varind[nextindaftervar] == k) /* get the first index that doesn't belong to this variable */
577  {
578  nextindaftervar++;
579  varused = TRUE;
580  nvarnonz[ind]++;
581  }
582  if (varused)
583  {
584  vars[ind] = VariablesX[k];/*lint !e732*//*lint !e747*/ /* if the variable is used, add it to the vars array */
585  colpointer[ind] = &col[firstindforvar]; /* save a pointer to the first nonzero belonging to this variable */
586  rowpointer[ind] = &row[firstindforvar];
587  valpointer[ind] = &val[firstindforvar];
588  ind++;
589  }
590  }
591 
592  assert (nextindaftervar == nnonz);
593 
594  /* this was only needed to compute the vars arrays */
595  SCIPfreeBlockMemoryArray(scip, &varind, blockstruct[bindex].num_nonzeros);/*lint !e747*/
596 
597  nvars = ind;
598 
599  SCIP_CONS* sdpcon;
600  char sdpcon_name[SCIP_MAXSTRLEN];
601 #ifndef NDEBUG
602  snprintfreturn = SCIPsnprintf(sdpcon_name, SCIP_MAXSTRLEN, "SDP-Constraint-%d", bindex);
603  assert( snprintfreturn < SCIP_MAXSTRLEN);
604 #else
605  (void) SCIPsnprintf(sdpcon_name, SCIP_MAXSTRLEN, "SDP-Constraint-%d", bindex);
606 #endif
607  SCIP_CALL( SCIPcreateConsSdp(scip, &sdpcon, sdpcon_name, nvars, nnonz, blocksize, nvarnonz, colpointer,
608  rowpointer, valpointer, vars, constnnonz, constcol, constrow, constval) );
609 
610 #ifdef SCIP_MORE_DEBUG
611  SCIP_CALL( SCIPprintCons(scip, sdpcon, NULL) );
612 #endif
613 
614  SCIP_CALL( SCIPaddCons(scip, sdpcon) );
615 
616  SCIP_CALL( SCIPreleaseCons(scip, &sdpcon) );
617 
618  /* free the used arrays */
619  SCIPfreeBlockMemoryArray(scip, &nvarnonz, numvars);
620  SCIPfreeBlockMemoryArray(scip, &constval, blockstruct[bindex].constnum_nonzeros);/*lint !e747*/
621  SCIPfreeBlockMemoryArray(scip, &constrow, blockstruct[bindex].constnum_nonzeros);/*lint !e747*/
622  SCIPfreeBlockMemoryArray(scip, &constcol, blockstruct[bindex].constnum_nonzeros);/*lint !e747*/
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);/*lint !e747*/
628  SCIPfreeBlockMemoryArray(scip, &row, blockstruct[bindex].num_nonzeros);/*lint !e747*/
629  SCIPfreeBlockMemoryArray(scip, &col, blockstruct[bindex].num_nonzeros);/*lint !e747*/
630 
631  SCIPdebugMessage("Construction of SDP constraint for block %d completed.\n", bindex);
632  }
633  else
634  {
635  //construct lp-block only once
636  if (!lp_block_already_done)
637  {
638  int nindconss = 0;
639 
640  lp_block_already_done = true;
641  SCIPdebugMessage("Begin construction of LP (block %d).\n", bindex);
642 
643  for (int row_i = 0; row_i < LPData.numrows; ++row_i)
644  {
645  SCIP_CONS* LPcon;
646  char LPcon_name[SCIP_MAXSTRLEN];
647  int indicator = 0;
648 #ifndef NDEBUG
649  snprintfreturn = SCIPsnprintf(LPcon_name, SCIP_MAXSTRLEN, "LP-Con-%d", row_i);
650  assert( snprintfreturn < SCIP_MAXSTRLEN );
651 #else
652  (void) SCIPsnprintf(LPcon_name, SCIP_MAXSTRLEN, "LP-Con-%d", row_i);
653 #endif
654 
655  //Get right hand side of the constraint
656  SCIP_Real LPlhs = 0.0;
657 
658  for (unsigned int var_i = 0; var_i < LPData.rows[row_i].data.size(); ++var_i)/*lint !e732*//*lint !e747*/
659  {
660  if (LPData.rows[row_i].data[var_i].first == 0)/*lint !e732*//*lint !e747*/
661  {
662  LPlhs = LPData.rows[row_i].data[var_i].second;/*lint !e732*//*lint !e747*/
663  }
664  }
665 
666  /* check for indicator constraint */
667  for (unsigned int var_i = 0; var_i < LPData.rows[row_i].data.size(); ++var_i)/*lint !e732*//*lint !e747*/
668  {
669  if (LPData.rows[row_i].data[var_i].first < 0)/*lint !e732*//*lint !e747*/
670  indicator++;
671  }
672 
673  if (indicator == 0)
674  {
675  /* regular linear constraint */
676 
677  //Create constraint
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));
680 
681  SCIP_CALL( SCIPaddCons(scip, LPcon) );
682 
683  //Insert variables into constraint:
684  for (unsigned int var_i = 0; var_i < LPData.rows[row_i].data.size(); ++var_i)/*lint !e732*//*lint !e747*/
685  {
686  if (LPData.rows[row_i].data[var_i].first != 0)/*lint !e732*//*lint !e747*/
687  {
688  SCIP_CALL( SCIPaddCoefLinear(scip, LPcon, VariablesX[LPData.rows[row_i].data[var_i].first - 1], LPData.rows[row_i].data[var_i].second) );/*lint !e732*//*lint !e747*/
689  }
690  }
691  #ifdef SCIP_MORE_DEBUG
692  SCIP_CALL( SCIPprintCons(scip, LPcon, NULL) );
693  #endif
694  SCIP_CALL( SCIPreleaseCons(scip, &LPcon) );
695  }
696  else
697  {
698  SCIP_VAR* indvar;
699  SCIP_VAR* slackvar;
700  SCIP_CONS* indcons;
701  char cons_name[SCIP_MAXSTRLEN];
702 
703 #ifndef NDEBUG
704  snprintfreturn = SCIPsnprintf(cons_name, SCIP_MAXSTRLEN, "cons_indicator_%d", nindconss);
705  assert( snprintfreturn < SCIP_MAXSTRLEN);
706 #else
707  (void)SCIPsnprintf(cons_name, SCIP_MAXSTRLEN, "cons_indicator_%d", nindconss);
708 #endif
709 
710  /* indicator constraint */
711 
712  /* each indicator constraint should only have a single indicator variable */
713  assert( indicator <= 1 );
714 
715  //Create constraint
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));
718 
719  //Insert variables into constraint:
720  for (unsigned int var_i = 0; var_i < LPData.rows[row_i].data.size(); ++var_i)/*lint !e732*//*lint !e747*/
721  {
722  if (LPData.rows[row_i].data[var_i].first > 0)/*lint !e732*//*lint !e747*/
723  {
724  SCIP_CALL( SCIPaddCoefLinear(scip, LPcon, VariablesX[LPData.rows[row_i].data[var_i].first - 1], LPData.rows[row_i].data[var_i].second) );/*lint !e732*//*lint !e747*/
725  }
726  else if (LPData.rows[row_i].data[var_i].first < 0)/*lint !e732*//*lint !e747*/
727  {
728  char var_name[SCIP_MAXSTRLEN];
729  SCIP_Bool infeasible;
730 #ifndef NDEBUG
731  snprintfreturn = SCIPsnprintf(var_name, SCIP_MAXSTRLEN, "s_%d", nindconss);
732  assert( snprintfreturn < SCIP_MAXSTRLEN);
733 #else
734  (void)SCIPsnprintf(var_name, SCIP_MAXSTRLEN, "s_%d", nindconss);
735 #endif
736  nindconss++;
737 
738  /* store indvar, note that we need to make it binary now, since otherwise the indicator constraint handler
739  * will throw an assert later and we cannot verify that it is binary now, so we print a warning
740  */
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);
745 #endif
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) );
750 
751  /* create slack variable and add it to the constraint*/
752  SCIP_CALL( SCIPcreateVar(scip, &slackvar, var_name, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, 0, 0, 0, 0, 0));/*lint !e732*//*lint !e747*/
753 
754  SCIP_CALL( SCIPaddVar(scip, slackvar) );
755 
756  /* slack variable has coefficient +1 since we have a >= 0 constraint */
757  SCIP_CALL( SCIPaddCoefLinear(scip, LPcon, slackvar, +1.0) );/*lint !e732*//*lint !e747*/
758  }
759  }
760 
761  /* add constraint */
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) );
766 
767 #if SCIP_MORE_DEBUG
768  SCIP_CALL( SCIPprintCons(scip, indcons, NULL) );
769 #endif
770 
771  /* release both conss and the slackvar */
772  SCIP_CALL( SCIPreleaseCons(scip, &indcons) );
773  SCIP_CALL( SCIPreleaseVar(scip, &slackvar) );
774  SCIP_CALL( SCIPreleaseCons(scip, &LPcon) );
775  }
776  }
777  }
778  }
779  }
780 
781  *result = SCIP_SUCCESS;
782 
783  return SCIP_OKAY;
784  }
785 
786 }//end of namespace scip
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)
Definition: cons_sdp.c:3006
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)