OpenGM  2.3.x
Discrete Graphical Model Library
graphicalmodeldecomposer.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_GRAPHICALMODELDECOMPOSER_HXX
3 #define OPENGM_GRAPHICALMODELDECOMPOSER_HXX
4 
5 #include <exception>
6 #include <set>
7 #include <vector>
8 #include <list>
9 #include <map>
10 #include <queue>
11 #include <limits>
12 
16 
17 namespace opengm {
18 
20 
21 template <class GM>
22 class GraphicalModelDecomposer
23 {
24 public:
25  typedef GM GraphicalModelType;
26  typedef GraphicalModelDecomposition DecompositionType;
27  typedef typename GraphicalModelType::FactorType FactorType;
28  typedef typename GraphicalModelType::FunctionIdentifier FunctionIdentifierType;
29  typedef typename DecompositionType::SubFactor SubFactorType;
30  typedef typename DecompositionType::SubVariable SubVariableType;
31  typedef typename DecompositionType::SubFactorListType SubFactorListType;
32  typedef typename DecompositionType::SubVariableListType SubVariableListType;
33 
34  typedef typename GraphicalModelType::ValueType ValueType;
35  typedef typename GraphicalModelType::OperatorType OperatorType;
36  //typedef ScaledViewFunction<GraphicalModelType> ViewFunctionType;
37  //typedef GraphicalModel<ValueType, OperatorType, ViewFunctionType> SubGmType;
38 
39  // Constructor
40  GraphicalModelDecomposer();
41 
42  // Decompose Methods
43  DecompositionType decomposeManual(const GraphicalModelType&, const std::vector<std::vector<size_t> >& subModelFactors) const;
44  DecompositionType decomposeIntoTree(const GraphicalModelType&) const;
45  DecompositionType decomposeIntoSpanningTrees(const GraphicalModelType&) const;
46  DecompositionType decomposeIntoKFans(const GraphicalModelType&, const std::vector<std::set<size_t> >&) const;
47  DecompositionType decomposeIntoKFans(const GraphicalModelType&, const size_t k) const;
48  DecompositionType decomposeIntoClosedBlocks(const GraphicalModelType&, const std::vector<std::set<size_t> >&) const;
49  DecompositionType decomposeIntoOpenBlocks(const GraphicalModelType&, const std::vector<std::set<size_t> >&) const;
50  DecompositionType decomposeIntoClosedBlocks(const GraphicalModelType&, const size_t) const;
51 };
52 
53 template <class GM>
54 inline GraphicalModelDecomposer<GM>::
55 GraphicalModelDecomposer()
56 {}
57 
58 template <class GM>
59 inline typename GraphicalModelDecomposer<GM>::DecompositionType GraphicalModelDecomposer<GM>::
60 decomposeManual
61 (
62  const GraphicalModelType& gm,
63  const std::vector<std::vector<size_t> >& subModelFactors
64 ) const
65 {
66  DecompositionType decomposition = GraphicalModelDecomposition(gm.numberOfVariables(),gm.numberOfFactors(),0);
67  for(size_t subModel=0; subModel<subModelFactors.size(); ++subModel) {
68  decomposition.addSubModel();
69  }
70  for(size_t subModel=0; subModel<subModelFactors.size(); ++subModel) {
71  std::vector<size_t> subVariableIds(gm.numberOfVariables(),gm.numberOfVariables());
72  //for(size_t factorId=0; factorId<subModelFactors[subModel].size(); ++factorId) {
73  for(size_t nn=0; nn<subModelFactors[subModel].size(); ++nn) {
74  size_t factorId = subModelFactors[subModel][nn];
75  std::vector<size_t> subVariableIndices(gm[factorId].numberOfVariables());
76  for(size_t j=0; j<gm[factorId].numberOfVariables(); ++j) {
77  const size_t variableIndex = gm[factorId].variableIndex(j);
78  if(subVariableIds[variableIndex] == gm.numberOfVariables()) {
79  subVariableIds[variableIndex] = decomposition.addSubVariable(subModel,variableIndex);
80  }
81  subVariableIndices[j] = subVariableIds[variableIndex];
82  }
83  decomposition.addSubFactor( subModel, factorId, subVariableIndices );
84  }
85  }
86  decomposition.reorder();
87  return decomposition;
88 }
89 
90 template <class GM>
91 inline typename GraphicalModelDecomposer<GM>::DecompositionType GraphicalModelDecomposer<GM>::
92 decomposeIntoTree
93 (
94  const GraphicalModelType& gm
95 ) const
96 {
97  DecompositionType decomposition = GraphicalModelDecomposition(gm.numberOfVariables(),gm.numberOfFactors(),0);
98 
99  decomposition.addSubModel();
100  Partition<size_t> partition(gm.numberOfVariables());
101  for(size_t variableId=0; variableId<gm.numberOfVariables();++variableId) {
102  decomposition.addSubVariable(0,variableId);
103  }
104  for(size_t factorId=0; factorId<gm.numberOfFactors(); ++factorId) {
105  std::map<size_t, size_t> counters;
106  std::vector<size_t> subVariableIndices(gm[factorId].numberOfVariables());
107  for(size_t j=0; j<gm[factorId].numberOfVariables(); ++j) {
108  const size_t variableIndex = gm[factorId].variableIndex(j);
109  if( ++counters[partition.find(variableIndex)] > 1) {
110  subVariableIndices[j] = decomposition.addSubVariable(0,variableIndex);
111  }
112  else{
113  subVariableIndices[j] = variableIndex;
114  }
115  }
116  decomposition.addSubFactor(0,factorId,subVariableIndices);
117  for(size_t j=1; j<gm[factorId].numberOfVariables(); ++j) {
118  partition.merge(gm[factorId].variableIndex(j-1), gm[factorId].variableIndex(j));
119  }
120  }
121  decomposition.reorder();
122  return decomposition;
123 }
124 
125 template <class GM>
126 inline typename GraphicalModelDecomposer<GM>::DecompositionType GraphicalModelDecomposer<GM>::
127 decomposeIntoSpanningTrees
128 (
129  const GraphicalModelType& gm
130 ) const
131 {
132  DecompositionType decomposition = GraphicalModelDecomposition(gm.numberOfVariables(),gm.numberOfFactors(),0);
133 
134  std::list<size_t> blackList;
135  std::list<size_t> grayList;
136  std::list<size_t> whiteList;
137  for(size_t j=0; j<gm.numberOfFactors(); ++j) {
138  whiteList.push_back(j);
139  }
140 
141  while(!whiteList.empty()) {
142  size_t subModelId = decomposition.addSubModel();
143  for(size_t variableId=0; variableId<gm.numberOfVariables();++variableId) {
144  decomposition.addSubVariable(subModelId,variableId);
145  }
146 
147  Partition<size_t> partition(gm.numberOfVariables());
148  std::list<size_t>* currentList;
149 
150  for(size_t listSwap=0; listSwap<2; ++listSwap) {
151  if(listSwap == 0) {
152  currentList = &whiteList; // add white factors in the first round
153  }
154  else {
155  currentList = &blackList; // add black factors in the second round
156  }
157 
158  std::list<size_t>::iterator it = currentList->begin();
159  while(it != currentList->end()) {
160  // check if *it can be inserted into the submodel
161  bool insert = true;
162  const FactorType& factor = gm[*it];
163  std::map<size_t, size_t> counters;
164  for(size_t j=0; j<factor.numberOfVariables(); ++j) {
165  if( ++counters[partition.find(factor.variableIndex(j))] > 1) {
166  //factor has 2 variabels of the same set
167  insert = false;
168  break;
169  }
170  }
171  if(insert) {
172  std::vector<size_t> subVariableIndices(factor.numberOfVariables());
173  for(size_t j=0; j<factor.numberOfVariables(); ++j) {
174  const size_t variableId = factor.variableIndex(j);
175  subVariableIndices[j] = variableId;
176  }
177  decomposition.addSubFactor(subModelId,(*it),subVariableIndices);
178 
179  if(currentList == &whiteList) {
180  grayList.push_back(*it);
181  it = currentList->erase(it);
182  }
183  else {
184  ++it;
185  }
186  for(size_t j=1; j<factor.numberOfVariables(); ++j) {
187  partition.merge(factor.variableIndex(j-1), factor.variableIndex(j));
188  }
189  }
190  else {
191  ++it;
192  }
193  }
194  }
195  blackList.insert(blackList.end(), grayList.begin(), grayList.end());
196  grayList.clear();
197  }
198  return decomposition;
199 }
200 
201 template <class GM>
202 inline typename GraphicalModelDecomposer<GM>::DecompositionType GraphicalModelDecomposer<GM>::
203 decomposeIntoKFans
204 (
205  const GraphicalModelType& gm,
206  const size_t k
207 ) const
208 {
209  DecompositionType decomposition = GraphicalModelDecomposition(gm.numberOfVariables(),gm.numberOfFactors(),0);
210 
211  const size_t numberOfVariables = gm.numberOfVariables();
212  const size_t numberOfSubproblems = (size_t)(ceil((double)(numberOfVariables)/(double)(k)));
213  std::vector<std::set<size_t> > innerFanVariables(numberOfSubproblems);
214  size_t counter = 0;
215  for(size_t subModelId=0; subModelId<numberOfSubproblems; ++subModelId) {
216  for(size_t i=0; i<k; ++i) {
217  innerFanVariables[subModelId].insert(counter);
218  counter = (counter+1) % numberOfVariables;
219  }
220  }
221  return decomposeIntoKFans(gm, innerFanVariables);
222 }
223 
224 template <class GM>
225 inline typename GraphicalModelDecomposer<GM>::DecompositionType GraphicalModelDecomposer<GM>::
226 decomposeIntoKFans
227 (
228  const GraphicalModelType& gm,
229  const std::vector<std::set<size_t> >& innerFanVariables
230 ) const
231 {
232  DecompositionType decomposition = GraphicalModelDecomposition(gm.numberOfVariables(),gm.numberOfFactors(),0);
233 
234  //const size_t numberOfVariables = gm.numberOfVariables();
235  const size_t numberOfSubproblems = innerFanVariables.size();
236 
237  for(size_t subModelId=0;subModelId<numberOfSubproblems;++subModelId) {
238  decomposition.addSubModel();
239  // find variables connected to inner fan.
240  std::vector<bool> includedVars(gm.numberOfVariables(),false);
241  std::vector<size_t> subVars(gm.numberOfVariables());
242  for(typename std::set<size_t>::iterator vit=innerFanVariables[subModelId].begin(); vit!=innerFanVariables[subModelId].end();++vit){
243  const size_t var = *vit;
244  includedVars[var] = true;
245  for(typename GM::ConstFactorIterator fit=gm.factorsOfVariableBegin(var); fit!=gm.factorsOfVariableEnd(var); ++fit){
246  for(size_t n=0; n<gm[*fit].numberOfVariables();++n){
247  includedVars[gm[*fit].variableIndex(n)] = true;
248  }
249  }
250  }
251  for(size_t variableId=0; variableId<gm.numberOfVariables();++variableId) {
252  if(includedVars[variableId]){
253  subVars[variableId] = decomposition.addSubVariable(subModelId,variableId);
254  }
255  }
256 
257  // find factors of subproblems
258  for(size_t factorId=0; factorId<gm.numberOfFactors(); ++factorId) {
259  if(gm[factorId].numberOfVariables()==0) {
260  if(subModelId==0){
261  std::vector<size_t> subVariableIndices(0);
262  decomposition.addSubFactor(subModelId,factorId,subVariableIndices);
263  }
264  }
265  else if(gm[factorId].numberOfVariables()==1) {
266  if(includedVars[gm[factorId].variableIndex(0)]){
267  std::vector<size_t> subVariableIndices(1, subVars[gm[factorId].variableIndex(0)]);
268  decomposition.addSubFactor(subModelId,factorId,subVariableIndices);
269  }
270  }
271  else if(gm[factorId].numberOfVariables()==2) {
272  if(includedVars[gm[factorId].variableIndex(0)] && includedVars[gm[factorId].variableIndex(1)]){
273  if( (innerFanVariables[subModelId].count(gm[factorId].variableIndex(0)) > 0 ) ||
274  (innerFanVariables[subModelId].count(gm[factorId].variableIndex(1)) > 0 )) {
275  std::vector<size_t> subVariableIndices(2);
276  subVariableIndices[0] = subVars[gm[factorId].variableIndex(0)];
277  subVariableIndices[1] = subVars[gm[factorId].variableIndex(1)];
278  decomposition.addSubFactor(subModelId,factorId,subVariableIndices);
279  }
280  }
281  }
282  else{
283  throw RuntimeError("The k-fan decomposition currently supports only models of order <= 2.");
284  }
285  }
286  }
287  return decomposition;
288 }
289 
290 template <class GM>
291 inline typename GraphicalModelDecomposer<GM>::DecompositionType GraphicalModelDecomposer<GM>::
292 decomposeIntoOpenBlocks
293 (
294  const GraphicalModelType& gm,
295  const std::vector<std::set<size_t> >& innerVariables
296 ) const
297 {
298  DecompositionType decomposition = GraphicalModelDecomposition(gm.numberOfVariables(),gm.numberOfFactors(),0);
299 
300  const size_t numberOfVariables = gm.numberOfVariables();
301  const size_t numberOfSubproblems = innerVariables.size();
302  std::vector<size_t> subVariableMap(numberOfVariables);
303 
304  for(size_t subModelId=0;subModelId<numberOfSubproblems;++subModelId) {
305  decomposition.addSubModel();
306  for(typename std::vector<size_t>::iterator it = subVariableMap.begin(); it !=subVariableMap.end(); ++it)
307  *it = std::numeric_limits<std::size_t>::max();
308  for(typename std::set<size_t>::const_iterator it=innerVariables[subModelId].begin();it!=innerVariables[subModelId].end(); ++it)
309  subVariableMap[*it]=decomposition.addSubVariable(subModelId,*it);
310 
311  // find factors of subproblems
312  for(size_t factorId=0; factorId<gm.numberOfFactors(); ++factorId) {
313  if(gm[factorId].numberOfVariables()==0) {
314  std::vector<size_t> subVariableIndices(0);
315  decomposition.addSubFactor(subModelId,factorId,subVariableIndices);
316  }
317  else{
318  bool test = true;
319  for(size_t i=0; i<gm[factorId].numberOfVariables(); ++i) {
320  test = test && (subVariableMap[gm[factorId].variableIndex(i)] != std::numeric_limits<std::size_t>::max());
321  }
322  if(test) {
323  std::vector<size_t> subVariableIndices(gm[factorId].numberOfVariables());
324  for(size_t i=0; i<gm[factorId].numberOfVariables(); ++i) {
325  subVariableIndices[i] = subVariableMap[gm[factorId].variableIndex(i)];
326  }
327  decomposition.addSubFactor(subModelId,factorId,subVariableIndices);
328  }
329  }
330  }
331  }
332  return decomposition;
333 }
334 
335 template <class GM>
336 inline typename GraphicalModelDecomposer<GM>::DecompositionType GraphicalModelDecomposer<GM>::
337 decomposeIntoClosedBlocks
338 (
339  const GraphicalModelType& gm,
340  const size_t numBlocks
341 ) const
342 {
343  std::vector<std::set<size_t> > innerVariables(numBlocks);
344  double fractalBlocksize = (1.0*gm.numberOfVariables())/numBlocks;
345  size_t var = 0;
346  for(size_t i=0; i<numBlocks;++i) {
347  while(var < fractalBlocksize*(i+1)+0.0000001 && var < gm.numberOfVariables()) {
348  innerVariables[i].insert(var++);
349  }
350  if( var != gm.numberOfVariables()) {
351  --var;
352  }
353  }
354  return decomposeIntoClosedBlocks(gm,innerVariables);
355 }
356 
357 template <class GM>
358 inline typename GraphicalModelDecomposer<GM>::DecompositionType GraphicalModelDecomposer<GM>::
359 decomposeIntoClosedBlocks
360 (
361  const GraphicalModelType& gm,
362  const std::vector<std::set<size_t> >& innerVariables
363 ) const
364 {
365  DecompositionType decomposition = GraphicalModelDecomposition(gm.numberOfVariables(),gm.numberOfFactors(),0);
366 
367  const size_t numberOfVariables = gm.numberOfVariables();
368  const size_t numberOfSubproblems = innerVariables.size();
369  std::vector<size_t> subVariableMap(numberOfVariables);
370 
371  for(size_t subModelId=0;subModelId<numberOfSubproblems;++subModelId) {
372  decomposition.addSubModel();
373  for(typename std::vector<size_t>::iterator it = subVariableMap.begin(); it !=subVariableMap.end(); ++it)
374  *it = std::numeric_limits<std::size_t>::max();
375  for(typename std::set<size_t>::const_iterator it=innerVariables[subModelId].begin();it!=innerVariables[subModelId].end(); ++it)
376  subVariableMap[*it]=decomposition.addSubVariable(subModelId,*it);
377 
378  // find factors of subproblems
379  for(size_t factorId=0; factorId<gm.numberOfFactors(); ++factorId) {
380  if(gm[factorId].numberOfVariables()==0) {
381  std::vector<size_t> subVariableIndices(0);
382  decomposition.addSubFactor(subModelId,factorId,subVariableIndices);
383  }
384  else{
385  bool test = false;
386  for(size_t i=0; i<gm[factorId].numberOfVariables(); ++i) {
387  test = test || (innerVariables[subModelId].count(gm[factorId].variableIndex(i))>0);
388  }
389  if(test) {
390  std::vector<size_t> subVariableIndices(gm[factorId].numberOfVariables());
391  for(size_t i=0; i<gm[factorId].numberOfVariables(); ++i) {
392  const size_t varId = gm[factorId].variableIndex(i);
393  if(subVariableMap[varId] == std::numeric_limits<std::size_t>::max()) {
394  subVariableMap[varId] = decomposition.addSubVariable(subModelId,varId);
395  }
396  subVariableIndices[i] = subVariableMap[gm[factorId].variableIndex(i)];
397  }
398  decomposition.addSubFactor(subModelId,factorId,subVariableIndices);
399  }
400  }
401  }
402  }
403  decomposition.reorder();
404  return decomposition;
405 }
406 
408 
409 } // namespace opengm
410 
411 #endif // #ifndef OPENGM_GRAPHICALMODELDECOMPOSER_HXX
The OpenGM namespace.
Definition: config.hxx:43