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