OpenGM  2.3.x
Discrete Graphical Model Library
canonical_view.hxx
Go to the documentation of this file.
1 //
2 // File: canonical_view.hxx
3 //
4 // This file is part of OpenGM.
5 //
6 // Copyright (C) 2015 Stefan Haller
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 //
26 
27 #pragma once
28 #ifndef OPENGM_UTILITIES_CANONICAL_FACTORS_HXX
29 #define OPENGM_UTILITIES_CANONICAL_FACTORS_HXX
30 
31 #include <map>
32 #include <vector>
33 
39 
40 
41 namespace opengm {
42 
43 namespace canonical_view {
44 
61 
62 } // namespace canonical_view
63 
64 
66 namespace canonical_view_internal {
67 
68  // The type of the GraphicalModel is complicated, but can’t be typedef’d
69  // easilty. That’s why we use this handy type generator.
70  template<class GM>
71  struct Generator {
72  private:
73  typedef typename GM::ValueType ValType;
74  typedef typename GM::IndexType IndType;
75  typedef typename GM::LabelType LabType;
76  typedef typename GM::FunctionTypeList OldTypeList;
77 
78  // We extend the type list of the old model and add some more
79  // functions.
80  typedef ConstantFunction<ValType, IndType, LabType> ConstFunType;
81  typedef AccumulatedViewFunction<GM> AccViewType;
82  typedef typename meta::TypeListGenerator<ConstFunType, AccViewType>::type NewTypeList;
83 
84  public:
85  typedef GraphicalModel<
86  typename GM::ValueType,
87  typename GM::OperatorType,
88  typename meta::MergeTypeListsWithoutDups<OldTypeList, NewTypeList>::type,
89  typename GM::SpaceType
90  > type;
91  };
92 
93  // Helper for perform the actual cloning (if requested by template
94  // parameter). The first GM parameter is expected be the CanonicalView.
95  template<class GM, canonical_view::CloneOption CLONE>
96  struct CloneHelper;
97 
98  template<class GM>
99  struct CloneHelper<GM, canonical_view::CloneNever> {
100  template<class FUNC>
101  static const FUNC& handleInjected(const FUNC &func) { return func; }
102 
103  template<class FUNC>
104  static const FUNC& handleView(const FUNC &func) { return func; }
105  };
106 
107  template<class GM>
108  struct CloneHelper<GM, canonical_view::CloneViews> {
109  template<class FUNC>
110  static const FUNC& handleInjected(const FUNC &func) { return func; }
111 
112  template<class FUNC>
113  static typename GM::ExplFuncType handleView(const FUNC &func)
114  {
115  typename GM::ExplFuncType result;
116  cloneAsExplicitFunction(func, result);
117  return result;
118  }
119  };
120 
121  template<class GM>
122  struct CloneHelper<GM, canonical_view::CloneDeep> {
123  template<class FUNC>
124  static typename GM::ExplFuncType handleInjected(const FUNC &func)
125  {
126  typename GM::ExplFuncType result;
127  cloneAsExplicitFunction(func, result);
128  return result;
129  }
130 
131  template<class FUNC>
132  static typename GM::ExplFuncType handleView(const FUNC &func)
133  {
134  typename GM::ExplFuncType result;
135  cloneAsExplicitFunction(func, result);
136  return result;
137  }
138  };
139 
140 
141  // This functor is run on the factor of the wrapped GraphicalModel. It
142  // will reinject the original function into the wrapper for the
143  // GraphicalModel.
144  template<class GM, canonical_view::CloneOption CLONE>
145  class FunctionInjectionFunctor {
146  public:
147  FunctionInjectionFunctor(GM &gm)
148  : gm_(&gm)
149  {
150  }
151 
152  template<class FUNCTION>
153  void operator()(FUNCTION &func)
154  {
155  result_ = gm_->addFunction(CloneHelper<GM, CLONE>::handleInjected(func));
156  }
157 
158  typename GM::FunctionIdentifier result() const
159  {
160  return result_;
161  }
162 
163  private:
164  GM *gm_;
165  typename GM::FunctionIdentifier result_;
166  };
167 
168  // This class injects a function of the wrapped GraphicalModel. Additional
169  // it uses a map to remember already injected functions. One original
170  // function is thus only inserted into the wrapper once.
171  template<class WRAPPER, class WRAPPED, canonical_view::CloneOption CLONE>
172  class FunctionInjector {
173  public:
174  FunctionInjector
175  (
176  WRAPPER &gm
177  )
178  : gm_(&gm)
179  {
180  }
181 
182  typename WRAPPER::FunctionIdentifier
183  inject
184  (
185  const typename WRAPPED::FactorType &factor
186  )
187  {
188  typename WRAPPED::FunctionIdentifier id(factor.functionIndex(), factor.functionType());
189 
190  typename MapType::const_iterator it = map_.find(id);
191  if (it != map_.end())
192  return it->second;
193 
194  FunctionInjectionFunctor<WRAPPER, CLONE> injector(*gm_);
195  factor.callFunctor(injector);
196  typename WRAPPER::FunctionIdentifier result = injector.result();
197  map_[id] = result;
198  return result;
199  }
200 
201  private:
202  typedef std::map<
203  typename WRAPPED::FunctionIdentifier,
204  typename WRAPPER::FunctionIdentifier
205  > MapType;
206 
207  WRAPPER *gm_;
208  MapType map_;
209  };
210 
211 } // namespace canonical_view_internal
213 
214 
226 template<class GM, canonical_view::CloneOption CLONE = canonical_view::CloneNever>
227 class CanonicalView : public canonical_view_internal::Generator<GM>::type {
228 public:
229  typedef typename canonical_view_internal::Generator<GM>::type Parent;
231 
232  typedef typename Parent::IndexType IndexType;
233  typedef typename Parent::LabelType LabelType;
234  typedef typename Parent::ValueType ValueType;
235  typedef typename Parent::FunctionIdentifier FunctionIdentifier;
236 
240 
241  typedef canonical_view_internal::FunctionInjector<MyType, GM, CLONE> FunctionInjectorType;
242  typedef canonical_view_internal::CloneHelper<MyType, CLONE> CloneHelperType;
243 
244  CanonicalView(const GM &gm)
245  : Parent(gm.space())
246  {
247  // FIXME: Use opengm::FastSequence, but operator< is missing. :-(
248  typedef std::vector<IndexType> Variables;
249  typedef std::vector<const typename GM::FactorType*> Factors;
250  typedef std::vector<Factors> UnaryFactors;
251  typedef std::map<Variables, Factors> FactorMap;
252  typedef std::map<FunctionIdentifier, typename GM::FunctionIdentifier> FunctionMap;
253 
254  FunctionInjectorType injector(*this);
255  UnaryFactors unaryFactors(gm.numberOfVariables());
256  FactorMap otherFactors;
257 
258  // Append all unary factors to the corresponding unary factor vector.
259  // All other factors are inserted into the factor map. The keys are the
260  // variable indices of the factor, so we group factors of the same
261  // variables together.
262  for (IndexType i = 0; i < gm.numberOfFactors(); ++i) {
263  const typename GM::FactorType &f = gm[i];
264  if (f.numberOfVariables() == 1) {
265  unaryFactors[f.variableIndex(0)].push_back(&f);
266  } else {
267  std::vector<IndexType> vars(f.variableIndicesBegin(), f.variableIndicesEnd());
268  otherFactors[vars].push_back(&f);
269  }
270  }
271 
272  // Associate each variable with *exactly* one unary factor. (Create
273  // an empty factor if missing.)
274  for (IndexType i = 0; i < gm.numberOfVariables(); ++i) {
275  FunctionIdentifier fid;
276  IndexType vars[1] = { i };
277 
278  // Note: Use of curly braces to create new scope.
279  switch (unaryFactors[i].size()) {
280  case 0: { // Create new “empty” factor.
281  LabelType shape[1] = { gm.numberOfLabels(i) };
282  ConstFuncType func(shape, shape+1, 0);
283  fid = this->addFunction(func);
284  break;
285  }
286  case 1: { // Reuse old function.
287  fid = injector.inject(*unaryFactors[i][0]);
288  break;
289  }
290  default: { // Create a new view function.
291  ViewFuncType func(unaryFactors[i].begin(), unaryFactors[i].end());
292  fid = this->addFunction(CloneHelperType::handleView(func));
293  break;
294  }
295  }
296 
297  this->addFactor(fid, vars, vars+1);
298  }
299 
300  // Accumulate all other factors (with order != 1).
301  for (typename FactorMap::const_iterator it = otherFactors.begin(); it != otherFactors.end(); ++it) {
302  const Variables &vars= it ->first;
303  const Factors &factors = it->second;
304  FunctionIdentifier fid;
305 
306  OPENGM_ASSERT_OP(factors.size(), >, 0);
307  if (factors.size() == 1) {
308  // Reuse old function.
309  fid = injector.inject(*factors[0]);
310  } else {
311  // Create new view function.
312  ViewFuncType func(it->second.begin(), it->second.end());
313  fid = this->addFunction(CloneHelperType::handleView(func));
314  }
315 
316  this->addFactor(fid, vars.begin(), vars.end());
317  }
318  }
319 };
320 
321 } // namespace opengm
322 
323 #endif
Constant function.
Definition: constant.hxx:19
Parent::IndexType IndexType
The OpenGM namespace.
Definition: config.hxx:43
ExplicitFunction< T, I, L > cloneAsExplicitFunction(const FUNC &function)
AccumulatedViewFunction< GM > ViewFuncType
canonical_view_internal::Generator< GM >::type Parent
CloneOption
Controls cloning behavior of a CanonicalView.
Parent::ValueType ValueType
#define OPENGM_ASSERT_OP(a, op, b)
runtime assertion
Definition: opengm.hxx:53
CanonicalView(const GM &gm)
ExplicitFunction< ValueType, IndexType, LabelType > ExplFuncType
ConstantFunction< ValueType, IndexType, LabelType > ConstFuncType
Parent::LabelType LabelType
canonical_view_internal::CloneHelper< MyType, CLONE > CloneHelperType
CanonicalView< GM, CLONE > MyType
Parent::FunctionIdentifier FunctionIdentifier
canonical_view_internal::FunctionInjector< MyType, GM, CLONE > FunctionInjectorType
Canonical view of an arbitrary GraphicalModel.