Scippy

GCG

Branch-and-Price & Column Generation for Everyone

rowgraph_def.h
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program */
4 /* GCG --- Generic Column Generation */
5 /* a Dantzig-Wolfe decomposition based extension */
6 /* of the branch-cut-and-price framework */
7 /* SCIP --- Solving Constraint Integer Programs */
8 /* */
9 /* Copyright (C) 2010-2021 Operations Research, RWTH Aachen University */
10 /* Zuse Institute Berlin (ZIB) */
11 /* */
12 /* This program is free software; you can redistribute it and/or */
13 /* modify it under the terms of the GNU Lesser General Public License */
14 /* as published by the Free Software Foundation; either version 3 */
15 /* of the License, or (at your option) any later version. */
16 /* */
17 /* This program is distributed in the hope that it will be useful, */
18 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
19 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
20 /* GNU Lesser General Public License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with this program; if not, write to the Free Software */
24 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
25 /* */
26 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27 
28 /**@file rowgraph_def.h
29  * @brief A row graph where each row is a node and rows are adjacent if they share a variable
30  * @author Martin Bergner
31  * @author Annika Thome
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 // #define SCIP_DEBUG
36 
37 #ifndef GCG_ROWGRAPH_DEF_H_
38 #define GCG_ROWGRAPH_DEF_H_
39 
40 #include "rowgraph.h"
41 #include <algorithm>
42 
43 namespace gcg {
44 
45 template <class T>
47  SCIP* scip, /**< SCIP data structure */
48  Weights w /**< weights for the given graph */
49  ) : MatrixGraph<T>(scip,w), graph(scip)
50 {
51  this->graphiface = &graph;
52  this->name = std::string("rowgraph");
53 }
54 
55 template <class T>
57 {
58  // TODO Auto-generated destructor stub
59 }
60 
61 template <class T>
63  DEC_DECOMP** decomp /**< decomposition structure to generate */
64 )
65 {
66  int nblocks;
67  SCIP_HASHMAP* constoblock;
68 
69  int *nsubscipconss;
70  int i;
71  SCIP_CONS **conss;
72  SCIP_Bool emptyblocks = FALSE;
73  std::vector<int> partition = graph.getPartition();
74  conss = SCIPgetConss(this->scip_);
75  nblocks = *(std::max_element(partition.begin(), partition.end()))+1;
76 
77  SCIP_CALL( SCIPallocBufferArray(this->scip_, &nsubscipconss, nblocks) );
78  BMSclearMemoryArray(nsubscipconss, nblocks);
79 
80  SCIP_CALL( SCIPhashmapCreate(&constoblock, SCIPblkmem(this->scip_), this->nconss) );
81 
82  /* assign constraints to partition */
83  for( i = 0; i < this->nconss; i++ )
84  {
85  int block = partition[i];
86 
87  if(block == -1)
88  {
89  SCIP_CALL( SCIPhashmapInsert(constoblock, conss[i], (void*) (size_t) (nblocks +1)) );
90  }
91  else
92  { assert(block >= 0);
93  assert(block < nblocks);
94  SCIP_CALL( SCIPhashmapInsert(constoblock, conss[i], (void*) (size_t) (block +1)) );
95  ++(nsubscipconss[block]);
96  }
97 
98  }
99 
100 
101  // TODO: remove- FOR DEBUG ONLY!!!
102  std::vector<int> nsubscipconss_dbg(nblocks);
103 
104  /* first, make sure that there are constraints in every block, otherwise the hole thing is useless */
105  for( i = 0; i < nblocks; ++i )
106  {
107  // TODO: remove- FOR DEBUG ONLY!!!
108  nsubscipconss_dbg[i] = nsubscipconss[i];
109  if( nsubscipconss[i] == 0 )
110  {
111  SCIPdebugMessage("Block %d does not have any constraints!\n", i);
112  emptyblocks = TRUE;
113  }
114  }
115 
116  if( !emptyblocks )
117  {
118  SCIP_CALL( DECdecompCreate(this->scip_, decomp) );
119  SCIP_CALL( DECfilloutDecompFromConstoblock(this->scip_, *decomp, constoblock, nblocks, FALSE) );
120  }
121  else {
122  SCIPhashmapFree(&constoblock);
123  *decomp = NULL;
124  }
125 
126  SCIPfreeBufferArray(this->scip_, &nsubscipconss);
127  return SCIP_OKAY;
128 }
129 
130 template <class T>
132  PARTIALDECOMP* oldpartialdec,
133  PARTIALDECOMP** firstpartialdec,
134  PARTIALDECOMP** secondpartialdec,
135  DETPROBDATA* detprobdata
136  )
137 {
138  int nblocks;
139  SCIP_HASHMAP* constoblock;
140 
141  int *nsubscipconss;
142  int i;
143  SCIP_Bool emptyblocks = FALSE;
144 
145  //fillout conssForGraph
146  std::vector<int> conssForGraph; /** stores the conss included by the graph */
147  std::vector<bool> conssBool(oldpartialdec->getNConss(), false); /**< true, if the cons will be part of the graph */
148  bool found;
149 
150  for(int c = 0; c < oldpartialdec->getNOpenconss(); ++c)
151  {
152  int cons = oldpartialdec->getOpenconss()[c];
153  found = false;
154  for(int v = 0; v < oldpartialdec->getNOpenvars() && !found; ++v)
155  {
156  int var = oldpartialdec->getOpenvars()[v];
157  for(i = 0; i < detprobdata->getNVarsForCons(cons) && !found; ++i)
158  {
159  if(var == detprobdata->getVarsForCons(cons)[i])
160  {
161  conssBool[cons] = true;
162  found = true;
163  }
164  }
165  }
166  }
167 
168  for(int c = 0; c < oldpartialdec->getNOpenconss(); ++c)
169  {
170  int cons = oldpartialdec->getOpenconss()[c];
171  if(conssBool[cons])
172  conssForGraph.push_back(cons);
173  }
174 
175  std::vector<int> partition = graph.getPartition();
176  nblocks = *(std::max_element(partition.begin(), partition.end()))+1;
177 
178  SCIP_CALL( SCIPallocBufferArray(this->scip_, &nsubscipconss, nblocks) );
179  BMSclearMemoryArray(nsubscipconss, nblocks);
180 
181  SCIP_CALL( SCIPhashmapCreate(&constoblock, SCIPblkmem(this->scip_), this->nconss) );
182 
183  /* assign constraints to partition */
184  for( i = 0; i < this->nconss; i++ )
185  {
186  int block = partition[i];
187 
188  if(block == -1)
189  {
190  SCIP_CALL( SCIPhashmapInsert(constoblock, (void*) (size_t) conssForGraph[i], (void*) (size_t) (nblocks +1)) );
191  }
192  else
193  { assert(block >= 0);
194  assert(block < nblocks);
195  SCIP_CALL( SCIPhashmapInsert(constoblock, (void*) (size_t) conssForGraph[i], (void*) (size_t) (block +1)) );
196  ++(nsubscipconss[block]);
197  }
198 
199  }
200 
201  /* first, make sure that there are constraints in every block, otherwise the hole thing is useless */
202  for( i = 0; i < nblocks; ++i )
203  {
204  if( nsubscipconss[i] == 0 )
205  {
206  SCIPdebugMessage("Block %d does not have any constraints!\n", i);
207  emptyblocks = TRUE;
208  }
209  }
210 
211  if( !emptyblocks )
212  {
213  if( firstpartialdec != NULL )
214  {
215  (*firstpartialdec) = new PARTIALDECOMP(oldpartialdec);
216  SCIP_CALL((*firstpartialdec)->assignPartialdecFromConstoblock(constoblock, nblocks));
217  }
218  if( secondpartialdec != NULL )
219  {
220  (*secondpartialdec) = new PARTIALDECOMP(oldpartialdec);
221  SCIP_CALL((*secondpartialdec)->assignBorderFromConstoblock(constoblock, nblocks));
222  }
223  SCIPhashmapFree(&constoblock);
224  }
225  else
226  {
227  SCIPhashmapFree(&constoblock);
228  if( firstpartialdec != NULL )
229  {
230  (*firstpartialdec) = NULL;
231  }
232  if( secondpartialdec != NULL )
233  {
234  (*secondpartialdec) = NULL;
235  }
236  }
237 
238  SCIPfreeBufferArray(this->scip_, &nsubscipconss);
239  return SCIP_OKAY;
240 }
241 
242 template <class T>
244  SCIP_CONS** conss, /**< constraints for which graph should be created */
245  SCIP_VAR** vars, /**< variables for which graph should be created */
246  int nconss_, /**< number of constraints */
247  int nvars_ /**< number of variables */
248  )
249 {
250  int i;
251  int j;
252  int k;
253  int l;
254  SCIP_Bool success;
255 
256  std::pair< int, int> edge;
257  std::vector< std::pair< int, int> > edges;
258 
259  assert(conss != NULL);
260  assert(vars != NULL);
261  assert(nvars_ > 0);
262  assert(nconss_ > 0);
263 
264  this->nvars = nvars_;
265  this->nconss = nconss_;
266 
267  /* go through all constraints */
268  for( i = 0; i < this->nconss; ++i )
269  {
270  TCLIQUE_WEIGHT weight;
271 
272  /* calculate weight of node */
273  weight = this->weights.calculate(conss[i]);
274 
275  this->graph.addNode(i, weight);
276  }
277 
278  /* go through all constraints */
279  for( i = 0; i < this->nconss; ++i )
280  {
281  SCIP_VAR **curvars1;
282 
283  int ncurvars1;
284  SCIP_CALL( SCIPgetConsNVars(this->scip_, conss[i], &ncurvars1, &success) );
285  assert(success);
286  if( ncurvars1 == 0 )
287  continue;
288 
289  /*
290  * may work as is, as we are copying the constraint later regardless
291  * if there are variables in it or not
292  */
293  SCIP_CALL( SCIPallocBufferArray(this->scip_, &curvars1, ncurvars1) );
294  SCIP_CALL( SCIPgetConsVars(this->scip_, conss[i], curvars1, ncurvars1, &success) );
295  assert(success);
296 
297  /* go through all constraints */
298  for( j = 0; j < i; ++j )
299  {
300  SCIP_VAR **curvars2;
301  SCIP_Bool continueloop;
302  int ncurvars2;
303  SCIP_CALL( SCIPgetConsNVars(this->scip_, conss[j], &ncurvars2, &success) );
304  assert(success);
305  if( ncurvars2 == 0 )
306  continue;
307 
308  edge = std::make_pair(MIN(i, j), MAX(i, j) );
309 
310  /* check if edge was not already added to graph */
311  if(edges.end() != std::find(edges.begin(), edges.end(), edge) )
312  continue;
313 
314  /*if(this->graph.edge(i, j))
315  continue;
316  */
317  continueloop = FALSE;
318  /*
319  * may work as is, as we are copying the constraint later regardless
320  * if there are variables in it or not
321  */
322  SCIP_CALL( SCIPallocBufferArray(this->scip_, &curvars2, ncurvars2) );
323  SCIP_CALL( SCIPgetConsVars(this->scip_, conss[j], curvars2, ncurvars2, &success) );
324  assert(success);
325 
326 
327  /** @todo skip all variables that have a zero coeffient or where all coefficients add to zero */
328  /** @todo Do more then one entry per variable actually work? */
329 
330  for( k = 0; k < ncurvars1; ++k )
331  {
332  SCIP_VAR* var1;
333  int varIndex1;
334 
335  if( SCIPgetStage(this->scip_) >= SCIP_STAGE_TRANSFORMED)
336  var1 = SCIPvarGetProbvar(curvars1[k]);
337  else
338  var1 = curvars1[k];
339 
340  if( !GCGisVarRelevant(var1) )
341  continue;
342 
343  assert(var1 != NULL);
344  varIndex1 = SCIPvarGetProbindex(var1);
345  assert(varIndex1 >= 0);
346  assert(varIndex1 < this->nvars);
347 
348  for( l = 0; l < ncurvars2; ++l )
349  {
350  SCIP_VAR* var2;
351  int varIndex2;
352 
353  if( SCIPgetStage(this->scip_) >= SCIP_STAGE_TRANSFORMED)
354  var2 = SCIPvarGetProbvar(curvars2[l]);
355  else
356  var2 = curvars2[l];
357 
358  if( !GCGisVarRelevant(var2) )
359  continue;
360 
361  assert(var2 != NULL);
362  varIndex2 = SCIPvarGetProbindex(var2);
363  assert(varIndex2 >= 0);
364  assert(varIndex2 < this->nvars);
365 
366  if(varIndex1 == varIndex2)
367  {
368  SCIP_CALL( this->graph.addEdge(i, j) );
369 
370  edges.push_back(edge);
371  std::sort(edges.begin(), edges.end());
372 
373  /*
374  * this->graph.flush();
375  */
376 
377  continueloop = TRUE;
378  break;
379  }
380  }
381  if(continueloop)
382  break;
383  }
384  SCIPfreeBufferArray(this->scip_, &curvars2);
385  }
386  SCIPfreeBufferArray(this->scip_, &curvars1);
387  }
388  this->graph.flush();
389 
390  return SCIP_OKAY;
391 }
392 
393 } /* namespace gcg */
394 #endif
virtual SCIP_RETCODE createDecompFromPartition(DEC_DECOMP **decomp)
Definition: rowgraph_def.h:62
A row graph where each row is a node and rows are adjacent if they share a variable.
int getNOpenvars()
Gets size of vector containing variables not assigned yet.
virtual SCIP_RETCODE createPartialdecFromPartition(PARTIALDECOMP *oldpartialdec, PARTIALDECOMP **firstpartialdec, PARTIALDECOMP **secondpartialdec, DETPROBDATA *detprobdata)
Definition: rowgraph_def.h:131
gcg::Graph< T > graph
Definition: rowgraph.h:48
SCIP_Bool GCGisVarRelevant(SCIP_VAR *var)
Definition: scip_misc.c:41
RowGraph(SCIP *scip, Weights w)
Definition: rowgraph_def.h:46
GraphInterface * graphiface
Definition: matrixgraph.h:63
static SCIP_RETCODE partition(SCIP *scip, SCIP_VAR **J, int *Jsize, SCIP_Longint *priority, SCIP_VAR **F, int Fsize, SCIP_VAR **origvar, SCIP_Real *median)
SCIP_RETCODE DECfilloutDecompFromConstoblock(SCIP *scip, DEC_DECOMP *decomp, SCIP_HASHMAP *constoblock, int nblocks, SCIP_Bool staircase)
Definition: decomp.c:1455
virtual ~RowGraph()
Definition: rowgraph_def.h:56
const int * getOpenconss()
Gets array containing constraints not assigned yet.
int getNConss()
Gets the number of constraints.
std::string name
Definition: matrixgraph.h:56
class to manage partial decompositions
int getNVarsForCons(int consIndex)
returns the number of variables for a given constraint
int getNOpenconss()
Gets size of vector containing constraints not assigned yet.
SCIP_RETCODE DECdecompCreate(SCIP *scip, DEC_DECOMP **decdecomp)
Definition: decomp.c:471
virtual SCIP_RETCODE createFromMatrix(SCIP_CONS **conss, SCIP_VAR **vars, int nconss_, int nvars_)
Definition: rowgraph_def.h:243
std::vector< int > & getVarsForCons(int consIndex)
returns the variable indices of the coefficient matrix for a constraint
const int * getOpenvars()
Gets array containing variables not assigned yet.