SCIP-SDP  3.1.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
objreader_sdpa.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 
43 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
44 #include "objreader_sdpa.h"
45 
46 #include <cassert> // for assert
47 #include <cctype> // for isspace
48 #include <cstdio> // for printf
49 #include <cstdlib> // for abs /*lint !e10*//*lint !e129*/
50 #include <istream> // for istream, etc
51 #include <string> // for getline, string
52 
53 #include "BlockMemoryAllocator.h" // for BlockMemoryAllocator
54 #include "ScipStreamBuffer.h" // for ScipStreamBuffer
55 #include "scipsdp/cons_sdp.h" // for SCIPcreateConsSdp
56 
57 #include "scip/cons_linear.h" // for SCIPaddCoefLinear, etc
58 #include "scip/scip.h" // for SCIPinfinity, etc
59 
60 /* turn off lint warnings for whole file: */
61 /*lint --e{788,818}*/
62 
63 namespace
64 {
65 
66 /* drop spaces and all brackets that are allowed within the blocks in the sdpa format */
67  inline void drop_space(std::istream& line)
68  {
69  while(std::isspace(line.peek()) || line.peek() == '(' || line.peek() == '{' || line.peek() == ')' || line.peek() == '}' || line.peek() == ',')
70  {
71  line.ignore(1);/*lint !e747*//*lint !e534*/
72  }
73  return;
74  }
75 
76  inline void drop_rest_line (std::istream& s)
77  {
78  std::string tmp;
79  std::getline(s, tmp);/*lint !e534*/
80  return;
81  }
82 
83 }
84 
85 namespace scip
86 {
87 
89  static
90  SCIP_RETCODE dropComments(
91  std::istream* file /* the file instance that is read */
92  )
93  {
94  char fst_col('"');
95  fst_col = (*file).peek();/*lint !e734*//*lint !e838*/
96  while (fst_col == '"' || fst_col == '*')
97  {
98  drop_rest_line(*file);
99  fst_col = (*file).peek();/*lint !e734*/
100  }
101  return SCIP_OKAY;
102  }
103 
104  /* drop spaces and all brackets that are allowed within the blocks in the sdpa format, throws an error if it reaches a newline */
105  static
106  SCIP_RETCODE dropSpaceNewlineError(std::istream& line)
107  {
108  if ( line.peek() == '\n' )
109  {
110  SCIPerrorMessage("Input File invalid, SDP/LP-block rows need to consist of five entries each, see data_format.txt\n");
111  return SCIP_ERROR;
112  }
113  while(std::isspace(line.peek()) || line.peek() == '(' || line.peek() == '{' || line.peek() == ')' || line.peek() == '}' || line.peek() == ',')
114  {
115  line.ignore(1);/*lint !e747*//*lint !e534*/
116  if ( line.peek() == '\n' )
117  {
118  SCIPerrorMessage("Input File invalid, SDP/LP-block rows need to consist of five entries each, see data_format.txt\n");
119  return SCIP_ERROR;
120  }
121  }
122  return SCIP_OKAY;
123  }
124 
125  /* checks that only spaces, newlines or comments follow in the current line */
126  static
127  SCIP_RETCODE checkForLineEnd(std::istream& line)
128  {
129  if ( line.peek() == '\n' || line.peek() == '"' || line.peek() == '*' || line.peek() == EOF )
130  {
131  return SCIP_OKAY;
132  }
133  while(std::isspace(line.peek()) || line.peek() == '(' || line.peek() == '{' || line.peek() == ')' || line.peek() == '}' || line.peek() == ',')
134  {
135  line.ignore(1);/*lint !e747*//*lint !e534*/
136  if ( line.peek() == '\n' || line.peek() == '"' || line.peek() == '*' || line.peek() == EOF )
137  {
138  return SCIP_OKAY;
139  }
140  else if (std::isspace(line.peek()) || line.peek() == '(' || line.peek() == '{' || line.peek() == ')' || line.peek() == '}' || line.peek() == ',')
141  continue;
142  else
143  {
144  SCIPerrorMessage("Input File invalid, SDP/LP-block rows need to consist of five entries each, see data_format.txt\n");
145  return SCIP_ERROR;
146  }
147  }
148  return SCIP_OKAY;
149  }
150 
152  static
153  SCIP_RETCODE testDigit(
154  std::istream* file /* the file instance that is read */
155  )
156  {
157  if ( (! isdigit((*file).peek())) && (! ((*file).peek() == '-')) )
158  {
159  SCIPerrorMessage("Input File invalid, got character '%c', but only numerals allowed in SDP/LP-block rows, see data_format.txt\n", (*file).peek());
160  return SCIP_ERROR;
161  }
162 
163  return SCIP_OKAY;
164  }
165 
167  static
168  SCIP_RETCODE checkIndex(
169  const char* indexname, /* name of the index that will be used in the error message */
170  int value, /* value to check against the upper bound */
171  int ub /* upper bound to check against */
172  )
173  {
174  if ( value > ub )
175  {
176  SCIPerrorMessage("In an SDP/LP-block-line %s index %d was larger than given number of %ss %d.\n", indexname, value, indexname, ub);
177  return SCIP_ERROR;
178  }
179  return SCIP_OKAY;
180  }
181 
191  SCIP* scip,
192  SCIP_READER* reader,
193  const char* filename,
194  SCIP_RESULT* result
195  )
196  {/*lint --e{715}*/
197  *result = SCIP_DIDNOTRUN;
198 
199  int numvars; //Number of variables
200  int numblocks; //Number of all blocks (SDP + LP)
201  int numsdpblocks; //Number of SDP-blocks
202  int numlpblocks; //Number of LP-blocks
203  int alllpblocksize; //Size of all LP-blocks added
204  int* nvarnonz; // nblockvarnonz[i] gives the number of nonzeros for variable i
205 #ifndef NDEBUG
206  int snprintfreturn; // to check return codes of snprintf
207 #endif
208 
209  std::vector<int, BlockMemoryAllocator<int> > blockpattern =
210  std::vector<int, BlockMemoryAllocator<int> >(BlockMemoryAllocator<int>(scip)); //Vector with the sizes of all blocks
211  std::vector<SCIP_Real> object; //Objectivevector
212  std::vector<SDPBlock> blockstruct; //Blockstructure
213  LPBlock LPData; //LP Data
214  std::vector<bool> blockislp; //Is the block an LP block?
215  std::vector<int> intvars; //Indices of integer variables
216  std::vector <int> lp_block_num;
217  std::vector <int> lp_block_size;
218  int new_row_index;
219  bool lp_block_already_done;
220 
221  SCIP_FILE* scip_file = SCIPfopen(filename, "r");
222  if (!scip_file)
223  return SCIP_READERROR;
224 
225  // setup buffer
226  ScipStreamBuffer scip_buffer(scip, scip_file, true);
227 
228  // setup our stream from the new buffer
229  std::istream file(&scip_buffer);
230 
231  if( !file )
232  return SCIP_READERROR;
233  file.clear();
234 
235  SCIP_CALL(dropComments(&file));
236 
237  // read numvar
238  drop_space(file);
239  file >> numvars;
240  drop_rest_line(file);
241 
242  SCIP_CALL(dropComments(&file));
243 
244  // read numblocks
245  drop_space(file);
246  file >> numblocks;
247 
248  drop_rest_line(file);
249 
250  numlpblocks = 0;
251  numsdpblocks = 0;
252  alllpblocksize = 0;
253 
254  SCIP_CALL(dropComments(&file));
255 
256  // read block pattern
257  blockpattern = std::vector<int, BlockMemoryAllocator<int> >(numblocks, 0, BlockMemoryAllocator<int>(scip));
258  blockislp = std::vector<bool>(numblocks, false);/*lint !e747*//*lint !e732*/
259  lp_block_num = std::vector<int>(numblocks, 0);
260  lp_block_size = std::vector<int>(numblocks, 0);
261 
262  for (int j = 0; j < numblocks; ++j)
263  {
264  drop_space(file);
265  file >> blockpattern[j];/*lint !e747*//*lint !e732*/
266  if (blockpattern[j] > 0)/*lint !e747*//*lint !e732*/
267  {
268  numsdpblocks++;
269  blockstruct.push_back(SDPBlock(blockpattern[j]));/*lint !e747*//*lint !e732*/
270 
271  }
272  else if (blockpattern[j] < 0)/*lint !e747*//*lint !e732*/
273  {
274  //LP block has a negative coefficient!
275  numlpblocks++;
276  alllpblocksize += abs(blockpattern[j]);/*lint !e747*//*lint !e732*/
277  blockislp[j] = true;/*lint !e747*//*lint !e732*//*lint !e1793*/
278  blockstruct.push_back(SDPBlock(0));
279  lp_block_num[j] = numlpblocks;/*lint !e747*//*lint !e732*/
280  lp_block_size[numlpblocks - 1] = abs(blockpattern[j]);/*lint !e747*//*lint !e732*/
281 
282  }
283  else
284  printf("Blocklength 0 seems a bit odd, don't you think!\n");
285  }
286 
287  assert(numblocks == numsdpblocks + numlpblocks);
288 
289  drop_rest_line(file);
290  drop_space(file);
291 
292  SCIP_CALL(dropComments(&file));
293 
294  // read objective
295  object = std::vector<SCIP_Real>(numvars, 0.0);/*lint !e747*//*lint !e732*/
296  for (int i = 0; i < numvars; ++i)
297  {
298  file >> object[i];/*lint !e747*//*lint !e732*/
299  drop_space(file);
300  }
301 
302  SCIPdebugMessage("Number of variables: %d \n", numvars);
303  SCIPdebugMessage("Number of blocks: %d \n", numblocks);
304  SCIPdebugMessage("Number of SDP- and LP-cones: %d, %d \n", numsdpblocks, numlpblocks);
305 
306 
307  // construct blocks
308 
309  //construct LP block
310  LPData.rows = std::vector<LProw>(alllpblocksize);/*lint !e747*//*lint !e732*/
311  LPData.numrows = alllpblocksize;
312  SCIPdebugMessage("Number of LP constraints: %d\n", alllpblocksize);
313 
314  std::string commentline;
315 
316  // read data
317  while(!file.eof())
318  {
319  if(file.peek() == '*') // comment
320  {
321  std::getline(file, commentline);/*lint !e534*/
322  if (commentline.find("*INT") == 0) // if current line starts with *INT then go to Integer definitions
323  {
324  drop_space(file); // drop \newline
325  break;
326  }
327  else // usual comment line
328  {
329  drop_space(file);
330  }
331  }
332  else
333  {
334  int var_index, block_index; // block id
335  int row_index, col_index; // position in matrix
336  SCIP_Real val;
337  drop_space(file);
338 
339  SCIP_CALL( testDigit(&file) );
340  file >> var_index;
341  SCIP_CALL( checkIndex("variable", var_index, numvars) );
342  SCIP_CALL( dropSpaceNewlineError(file) );
343 
344  SCIP_CALL( testDigit(&file) );
345  file >> block_index;
346  SCIP_CALL( checkIndex("block", block_index, numblocks) );
347  SCIP_CALL( dropSpaceNewlineError(file) );
348 
349  SCIP_CALL( testDigit(&file) );
350  file >> row_index;
351  SCIP_CALL( checkIndex("row", row_index, (blockislp[block_index - 1] ? LPData.numrows : blockstruct[block_index - 1].blocksize)) );/*lint !e732*//*lint !e747*/
352  SCIP_CALL( dropSpaceNewlineError(file) );
353 
354  SCIP_CALL( testDigit(&file) );
355  file >> col_index;
356  SCIP_CALL( checkIndex("column", col_index, (blockislp[block_index - 1] ? LPData.numrows : blockstruct[block_index - 1].blocksize)) );/*lint !e732*//*lint !e747*/
357  SCIP_CALL( dropSpaceNewlineError(file) );
358 
359  SCIP_CALL( testDigit(&file) );
360  file >> val;
361  SCIP_CALL( checkForLineEnd(file) );
362 
363  if (SCIPisEQ(scip, val, 0.0))
364  {
365  drop_rest_line(file);
366  drop_space(file);
367  continue;
368  }
369 
370  //sdp-block
371  if (!blockislp[block_index - 1])/*lint !e732*//*lint !e747*/
372  {
373  if (row_index < col_index)
374  {
375  int save_row = row_index;
376  row_index = col_index;
377  col_index = save_row;
378  }
379 
380  if (var_index == 0)
381  {
382  blockstruct[block_index - 1].constcolumns.push_back(col_index);/*lint !e732*//*lint !e747*/
383  blockstruct[block_index - 1].constrows.push_back(row_index);/*lint !e732*//*lint !e747*/
384  blockstruct[block_index - 1].constvalues.push_back(val);/*lint !e732*//*lint !e747*/
385  blockstruct[block_index - 1].constnum_nonzeros++;/*lint !e732*//*lint !e747*/
386  }
387  else
388  {
389  blockstruct[block_index - 1].columns.push_back(col_index);/*lint !e732*//*lint !e747*/
390  blockstruct[block_index - 1].rows.push_back(row_index);/*lint !e732*//*lint !e747*/
391  blockstruct[block_index - 1].values.push_back(val);/*lint !e732*//*lint !e747*/
392  blockstruct[block_index - 1].variables.push_back(var_index);/*lint !e732*//*lint !e747*/
393  blockstruct[block_index - 1].num_nonzeros++;/*lint !e732*//*lint !e747*/
394  }
395  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*/
396  }
397  //lp-block
398  else if (blockislp[block_index - 1])/*lint !e732*//*lint !e747*/
399  {
400  assert(row_index == col_index);
401  if ( lp_block_num[block_index - 1] == 1 )/*lint !e732*//*lint !e747*/
402  new_row_index = row_index - 1;
403  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
404  {
405  int rowoffset;
406  int b;
407 
408  rowoffset = 0;
409 
410  for ( b = 0; b < lp_block_num[block_index - 1] - 1; b++ )/*lint !e732*//*lint !e747*/
411  rowoffset += lp_block_size[b];/*lint !e732*//*lint !e747*/
412 
413  new_row_index = rowoffset + row_index - 1;
414  }
415  LPData.rows[new_row_index].data.push_back(std::make_pair(var_index, val));/*lint !e732*//*lint !e747*/
416  SCIPdebugMessage("LP entry: row: %d, var: %d, val: %g\n", new_row_index, var_index,val );
417  }
418 
419  drop_rest_line(file);
420  drop_space(file);
421  }
422  }
423 
424  //read integer variables
425  intvars = std::vector<int>(numvars, 0);
426 
427  while(file.peek() == '*')
428  {
429  int index;/*lint !e578*/
430  file.ignore(1);/*lint !e534*//*lint !e747*/
431  file >> index;
432  //in the SDPA-file the variable numbers start at 1!
433  intvars[index - 1] = 1;/*lint !e732*//*lint !e747*/
434  SCIPdebugMessage("Variable %d is integer.\n", index - 1);
435  drop_rest_line(file);
436  drop_space(file);
437  }
438 
439 
440  /************************/
441  /* create empty problem */
442  /************************/
443 
444  SCIP_CALL( SCIPcreateProb(scip, filename, 0, 0, 0, 0, 0, 0, 0) );
445 
446  /*****************/
447  /* add variables */
448  /*****************/
449 
450  std::vector<SCIP_VAR*> VariablesX ( numvars );/*lint !e732*//*lint !e747*/
451 
452  for ( int i = 0; i < numvars; ++i)
453  {
454  SCIP_VAR* var;
455  char var_name[SCIP_MAXSTRLEN];
456 #ifndef NDEBUG
457  snprintfreturn = SCIPsnprintf(var_name, SCIP_MAXSTRLEN, "X_%d", i);
458  assert( snprintfreturn < SCIP_MAXSTRLEN);
459 #else
460  (void)SCIPsnprintf(var_name, SCIP_MAXSTRLEN, "X_%d", i);
461 #endif
462 
463 
464  if (intvars[i] == 1)/*lint !e732*//*lint !e747*/
465  {
466  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*/
467  }
468  else
469  {
470  SCIP_CALL( SCIPcreateVar(scip, &var, var_name, -SCIPinfinity(scip), SCIPinfinity(scip), object[i],
471  SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, 0, 0, 0, 0, 0));/*lint !e732*//*lint !e747*/
472  }
473 
474  SCIP_CALL( SCIPaddVar(scip, var) );
475  VariablesX[i] = var;/*lint !e732*//*lint !e747*/
476 
477  /* release variable for the reader. */
478  SCIP_CALL( SCIPreleaseVar(scip, &var) );
479  }
480 
481 
482  /*********************************/
483  /* create SDP and LP constraints */
484  /*********************************/
485 
486  lp_block_already_done = false;
487  for (int bindex = 0; bindex < numblocks; ++bindex)
488  {
489  if (!blockislp[bindex])/*lint !e732*//*lint !e747*/
490  {
491  int nvars;
492  int nnonz;
493  int blocksize;
494  int* varind; /* this is used to sort the nonzeroes by variable-indices and check which variables are actually included in this block */
495  int* col;
496  int* row;
497  SCIP_Real* val;
498  int** colpointer;
499  int** rowpointer;
500  SCIP_Real** valpointer;
501  SCIP_Var** vars;
502  int constnnonz;
503  int* constcol;
504  int* constrow;
505  SCIP_Real* constval;
506  int k;
507  int ind;
508  int nextindaftervar;
509  int firstindforvar;
510  SCIP_Bool varused;
511 
512  SCIPdebugMessage("Begin construction of SDP constraint for block %d.\n", bindex);
513 
514  blocksize = blockpattern[bindex];/*lint !e732*//*lint !e747*/
515  nnonz = blockstruct[bindex].num_nonzeros;/*lint !e732*//*lint !e747*/
516  ind = 0;
517 
518  /* allocate memory */
519  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &varind, blockstruct[bindex].num_nonzeros) );/*lint !e732*//*lint !e530*/
520  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &col, blockstruct[bindex].num_nonzeros) );/*lint !e732*//*lint !e530*/
521  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &row, blockstruct[bindex].num_nonzeros) );/*lint !e732*//*lint !e530*/
522  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &val, blockstruct[bindex].num_nonzeros) );/*lint !e732*//*lint !e530*/
523  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &colpointer, numvars) );/*lint !e732*//*lint !e530*/
524  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &rowpointer, numvars) );/*lint !e732*//*lint !e530*/
525  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &valpointer, numvars) );/*lint !e732*//*lint !e530*/
526  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &vars, numvars) );/*lint !e732*//*lint !e530*/
527 
528  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &constcol, blockstruct[bindex].constnum_nonzeros) );/*lint !e732*//*lint !e530*/
529  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &constrow, blockstruct[bindex].constnum_nonzeros) );/*lint !e732*//*lint !e530*/
530  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &constval, blockstruct[bindex].constnum_nonzeros) );/*lint !e732*//*lint !e530*/
531 
532  /* allocate memory for nblockvarnonz & initialize it with zero */
533  SCIP_CALL(SCIPallocBlockMemoryArray(scip, &nvarnonz, numvars));/*lint !e530*/
534  for (int i = 0; i < numvars; i++)
535  nvarnonz[i] = 0;
536 
537  /* prepare the constant arrays */
538  for (k = 0; k < blockstruct[bindex].constnum_nonzeros; ++k)/*lint !e732*//*lint !e747*/
539  {
540  if ( ! SCIPisZero(scip, blockstruct[bindex].constvalues[k]) )/*lint !e732*//*lint !e747*/
541  {
542  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 */
543  constrow[ind] = blockstruct[bindex].constrows[k] - 1;/*lint !e732*//*lint !e747*/
544  constval[ind] = blockstruct[bindex].constvalues[k];/*lint !e732*//*lint !e747*/
545  ind++;
546  }
547  }
548  constnnonz = ind;
549 
550  /* prepare the non-constant arrays */
551  ind = 0;
552  for (k = 0; k < nnonz; ++k)
553  {
554  if ( ! SCIPisZero(scip, blockstruct[bindex].values[k]) )/*lint !e732*//*lint !e747*/
555  {
556  varind[ind] = blockstruct[bindex].variables[k] - 1;/*lint !e732*//*lint !e747*/
557  col[ind] = blockstruct[bindex].columns[k] - 1;/*lint !e732*//*lint !e747*/
558  row[ind] = blockstruct[bindex].rows[k] - 1;/*lint !e732*//*lint !e747*/
559  val[ind] = blockstruct[bindex].values[k];/*lint !e732*//*lint !e747*/
560  ind++;
561  }
562  }
563  nnonz = ind;
564 
565  SCIPsortIntIntIntReal(varind, col, row, val, nnonz); /* sort the nonzeroes by non-decreasing variable indices */
566 
567  /* create the pointer arrays and insert used variables into vars-array */
568  nextindaftervar = 0;
569  ind = 0; /* sdp index of the current variable */
570  for (k = 0; k < numvars; k++)
571  {
572  varused = FALSE;
573  firstindforvar = nextindaftervar; /* this variable starts where the last one ended */
574  while (nextindaftervar < nnonz && varind[nextindaftervar] == k) /* get the first index that doesn't belong to this variable */
575  {
576  nextindaftervar++;
577  varused = TRUE;
578  nvarnonz[ind]++;
579  }
580  if (varused)
581  {
582  vars[ind] = VariablesX[k];/*lint !e732*//*lint !e747*/ /* if the variable is used, add it to the vars array */
583  colpointer[ind] = &col[firstindforvar]; /* save a pointer to the first nonzero belonging to this variable */
584  rowpointer[ind] = &row[firstindforvar];
585  valpointer[ind] = &val[firstindforvar];
586  ind++;
587  }
588  }
589 
590  assert (nextindaftervar == nnonz);
591 
592  /* this was only needed to compute the vars arrays */
593  SCIPfreeBlockMemoryArray(scip, &varind, blockstruct[bindex].num_nonzeros);/*lint !e747*/
594 
595  nvars = ind;
596 
597  SCIP_CONS* sdpcon;
598  char sdpcon_name[SCIP_MAXSTRLEN];
599 #ifndef NDEBUG
600  snprintfreturn = SCIPsnprintf(sdpcon_name, SCIP_MAXSTRLEN, "SDP-Constraint-%d", bindex);
601  assert( snprintfreturn < SCIP_MAXSTRLEN);
602 #else
603  (void) SCIPsnprintf(sdpcon_name, SCIP_MAXSTRLEN, "SDP-Constraint-%d", bindex);
604 #endif
605  SCIP_CALL( SCIPcreateConsSdp(scip, &sdpcon, sdpcon_name, nvars, nnonz, blocksize, nvarnonz, colpointer,
606  rowpointer, valpointer, vars, constnnonz, constcol, constrow, constval) );
607 
608 #ifdef SCIP_MORE_DEBUG
609  SCIP_CALL( SCIPprintCons(scip, sdpcon, NULL) );
610 #endif
611 
612  SCIP_CALL( SCIPaddCons(scip, sdpcon) );
613 
614  SCIP_CALL( SCIPreleaseCons(scip, &sdpcon) );
615 
616  /* free the used arrays */
617  SCIPfreeBlockMemoryArray(scip, &nvarnonz, numvars);
618  SCIPfreeBlockMemoryArray(scip, &constval, blockstruct[bindex].constnum_nonzeros);/*lint !e747*/
619  SCIPfreeBlockMemoryArray(scip, &constrow, blockstruct[bindex].constnum_nonzeros);/*lint !e747*/
620  SCIPfreeBlockMemoryArray(scip, &constcol, blockstruct[bindex].constnum_nonzeros);/*lint !e747*/
621  SCIPfreeBlockMemoryArray(scip, &vars, numvars);
622  SCIPfreeBlockMemoryArray(scip, &valpointer, numvars);
623  SCIPfreeBlockMemoryArray(scip, &rowpointer, numvars);
624  SCIPfreeBlockMemoryArray(scip, &colpointer, numvars);
625  SCIPfreeBlockMemoryArray(scip, &val, blockstruct[bindex].num_nonzeros);/*lint !e747*/
626  SCIPfreeBlockMemoryArray(scip, &row, blockstruct[bindex].num_nonzeros);/*lint !e747*/
627  SCIPfreeBlockMemoryArray(scip, &col, blockstruct[bindex].num_nonzeros);/*lint !e747*/
628 
629  SCIPdebugMessage("Construction of SDP constraint for block %d completed.\n", bindex);
630  }
631  else
632  {
633  //construct lp-block only once
634  if (!lp_block_already_done)
635  {
636  lp_block_already_done = true;
637  SCIPdebugMessage("Begin construction of LP (block %d).\n", bindex);
638 
639  for (int row_i = 0; row_i < LPData.numrows; ++row_i)
640  {
641  SCIP_CONS* LPcon;
642  char LPcon_name[SCIP_MAXSTRLEN];
643 #ifndef NDEBUG
644  snprintfreturn = SCIPsnprintf(LPcon_name, SCIP_MAXSTRLEN, "LP-Con-%d", row_i);
645  assert( snprintfreturn < SCIP_MAXSTRLEN );
646 #else
647  (void) SCIPsnprintf(LPcon_name, SCIP_MAXSTRLEN, "LP-Con-%d", row_i);
648 #endif
649 
650  //Get right hand side of the constraint
651  SCIP_Real LPlhs = 0.0;
652 
653  for (unsigned int var_i = 0; var_i < LPData.rows[row_i].data.size(); ++var_i)/*lint !e732*//*lint !e747*/
654  {
655  if (LPData.rows[row_i].data[var_i].first == 0)/*lint !e732*//*lint !e747*/
656  {
657  LPlhs = LPData.rows[row_i].data[var_i].second;/*lint !e732*//*lint !e747*/
658  }
659  }
660 
661  //Create constraint
662  SCIP_CALL( SCIPcreateConsLinear(scip, &LPcon, LPcon_name, 0, 0, 0, LPlhs, SCIPinfinity(scip), TRUE, TRUE,
663  TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE));
664 
665  SCIP_CALL( SCIPaddCons(scip, LPcon) );
666 
667  //Insert variables into constraint:
668  for (unsigned int var_i = 0; var_i < LPData.rows[row_i].data.size(); ++var_i)/*lint !e732*//*lint !e747*/
669  {
670  if (LPData.rows[row_i].data[var_i].first != 0)/*lint !e732*//*lint !e747*/
671  {
672  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*/
673  }
674  }
675 #ifdef SCIP_MORE_DEBUG
676  SCIP_CALL( SCIPprintCons(scip, LPcon, NULL) );
677 #endif
678  SCIP_CALL( SCIPreleaseCons(scip, &LPcon) );
679  }
680  }
681  }
682  }
683 
684  *result = SCIP_SUCCESS;
685 
686  return SCIP_OKAY;
687  }
688 
689 }//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)
std::vector< LProw > rows
Reader for SDPA-Files.
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)
virtual SCIP_RETCODE scip_read(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result)
static SCIP_RETCODE dropComments(std::istream *file)