Scippy

GCG

Branch-and-Price & Column Generation for Everyone

columngraph_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 columngraph_def.h
29  * @brief A row graph where each column is a node and columns are adjacent if they appear in one row
30  * @author Martin Bergner
31  * @author Annika Thome
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 
36 #ifndef GCG_COLUMNGRAPH_DEF_H_
37 #define GCG_COLUMNGRAPH_DEF_H_
38 
39 #include "columngraph.h"
40 #include <algorithm>
41 #include <utility>
42 #include <vector>
43 
44 namespace gcg {
45 
46 template <class T>
48  SCIP* scip, /**< SCIP data structure */
49  Weights w /**< weights for the given graph */
50  ) : MatrixGraph<T>(scip, w), graph(scip)
51 {
52  this->graphiface = &graph;
53  this->name = std::string("columngraph");
54 }
55 
56 template <class T>
58 {
59  // TODO Auto-generated destructor stub
60 }
61 
62 template <class T>
64  DEC_DECOMP** decomp
65 )
66 {
67  int nblocks;
68  SCIP_HASHMAP* constoblock;
69 
70  int *nsubscipconss;
71  int i;
72  SCIP_CONS **conss;
73  SCIP_Bool emptyblocks = FALSE;
74  std::vector<int> partition = graph.getPartition();
75  conss = SCIPgetConss(this->scip_);
76  nblocks = *(std::max_element(partition.begin(), partition.end()))+1;
77 
78  SCIP_CALL( SCIPallocBufferArray(this->scip_, &nsubscipconss, nblocks) );
79  BMSclearMemoryArray(nsubscipconss, nblocks);
80 
81  SCIP_CALL( SCIPhashmapCreate(&constoblock, SCIPblkmem(this->scip_), this->nconss) );
82 
83  /* assign constraints to partition */
84  for( i = 0; i < this->nconss; i++ )
85  {
86  int block = partition[i];
87  SCIP_CALL( SCIPhashmapInsert(constoblock, conss[i], (void*) (size_t) (block +1)) );
88  ++(nsubscipconss[block]);
89  }
90 
91  /* first, make sure that there are constraints in every block, otherwise the hole thing is useless */
92  for( i = 0; i < nblocks; ++i )
93  {
94  if( nsubscipconss[i] == 0 )
95  {
96  SCIPdebugMessage("Block %d does not have any constraints!\n", i);
97  emptyblocks = TRUE;
98  }
99  }
100 
101  if( !emptyblocks )
102  {
103  SCIP_CALL( DECdecompCreate(this->scip_, decomp) );
104  SCIP_CALL( DECfilloutDecompFromConstoblock(this->scip_, *decomp, constoblock, nblocks, FALSE) );
105  }
106  else {
107  SCIPhashmapFree(&constoblock);
108  *decomp = NULL;
109  }
110 
111  SCIPfreeBufferArray(this->scip_, &nsubscipconss);
112  return SCIP_OKAY;
113 }
114 
115 
116 template <class T>
118  SCIP_CONS** conss, /**< constraints for which graph should be created */
119  SCIP_VAR** vars, /**< variables for which graph should be created */
120  int nconss_, /**< number of constraints */
121  int nvars_ /**< number of variables */
122  )
123 {
124  int i;
125  int j;
126  int k;
127  SCIP_Bool success;
128  std::pair< int, int> edge;
129  std::vector< std::pair< int, int> > edges;
130 
131  assert(conss != NULL);
132  assert(vars != NULL);
133  assert(nvars_ > 0);
134  assert(nconss_ > 0);
135 
136  this->nvars = nvars_;
137  this->nconss = nconss_;
138 
139  /* go through all variables */
140  for( i = 0; i < this->nvars; ++i )
141  {
142  TCLIQUE_WEIGHT weight;
143 
144  /* calculate weight of node */
145  weight = this->weights.calculate(vars[i]);
146 
147  this->graph.addNode(i, weight);
148  }
149 
150  /* go through all constraints */
151  for( i = 0; i < this->nconss; ++i )
152  {
153  SCIP_VAR **curvars;
154 
155  int ncurvars;
156  SCIP_CALL( SCIPgetConsNVars(this->scip_, conss[i], &ncurvars, &success) );
157  assert(success);
158  if( ncurvars == 0 )
159  continue;
160 
161  /*
162  * may work as is, as we are copying the constraint later regardless
163  * if there are variables in it or not
164  */
165  SCIP_CALL( SCIPallocBufferArray(this->scip_, &curvars, ncurvars) );
166  SCIP_CALL( SCIPgetConsVars(this->scip_, conss[i], curvars, ncurvars, &success) );
167  assert(success);
168 
169  /** @todo skip all variables that have a zero coeffient or where all coefficients add to zero */
170  /** @todo Do more then one entry per variable actually work? */
171 
172  for( j = 0; j < ncurvars; ++j )
173  {
174  SCIP_VAR* var1;
175  int varIndex1;
176 
177  if( SCIPgetStage(this->scip_) >= SCIP_STAGE_TRANSFORMED)
178  var1 = SCIPvarGetProbvar(curvars[j]);
179  else
180  var1 = curvars[j];
181 
182  if( !GCGisVarRelevant(var1) )
183  continue;
184 
185  assert(var1 != NULL);
186  varIndex1 = SCIPvarGetProbindex(var1);
187  assert(varIndex1 >= 0);
188  assert(varIndex1 < this->nvars);
189 
190  for( k = 0; k < j; ++k )
191  {
192  SCIP_VAR* var2;
193  int varIndex2;
194 
195  if( SCIPgetStage(this->scip_) >= SCIP_STAGE_TRANSFORMED)
196  var2 = SCIPvarGetProbvar(curvars[k]);
197  else
198  var2 = curvars[k];
199 
200  if( !GCGisVarRelevant(var2) )
201  continue;
202 
203  assert(var2 != NULL);
204  varIndex2 = SCIPvarGetProbindex(var2);
205  assert(varIndex2 >= 0);
206  assert(varIndex2 < this->nvars);
207 
208  edge = std::make_pair(MIN(varIndex1, varIndex2), MAX(varIndex1, varIndex2) );
209 
210  /* check if edge was not already added to graph */
211  if(edges.end() == std::find(edges.begin(), edges.end(), edge) )
212  {
213 
214  SCIP_CALL( this->graph.addEdge(varIndex1, varIndex2) );
215  edges.push_back(edge);
216  std::sort(edges.begin(), edges.end());
217  }
218  }
219  }
220  SCIPfreeBufferArray(this->scip_, &curvars);
221  }
222 
223  this->graph.flush();
224  return SCIP_OKAY;
225 }
226 
227 } /* namespace gcg */
228 
229 #endif
ColumnGraph(SCIP *scip, Weights w)
virtual ~ColumnGraph()
SCIP_Bool GCGisVarRelevant(SCIP_VAR *var)
Definition: scip_misc.c:41
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
A row graph where each column is a node and columns are adjacent if they appear in a row.
virtual SCIP_RETCODE createFromMatrix(SCIP_CONS **conss, SCIP_VAR **vars, int nconss_, int nvars_)
std::string name
Definition: matrixgraph.h:56
SCIP_RETCODE DECdecompCreate(SCIP *scip, DEC_DECOMP **decdecomp)
Definition: decomp.c:471
virtual SCIP_RETCODE createDecompFromPartition(DEC_DECOMP **decomp)