OpenGM  2.3.x
Discrete Graphical Model Library
dynamicprogramming.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_DYNAMICPROGRAMMING_HXX
3 #define OPENGM_DYNAMICPROGRAMMING_HXX
4 
5 #include <typeinfo>
6 #include <limits>
9 
10 namespace opengm {
11 
15  template<class GM, class ACC>
16  class DynamicProgramming : public Inference<GM, ACC> {
17  public:
18  typedef ACC AccumulationType;
19  typedef ACC AccumulatorType;
20  typedef GM GraphicalModelType;
27 
28 
29  template<class _GM>
30  struct RebindGm{
32  };
33 
34  template<class _GM,class _ACC>
37  };
38 
39  struct Parameter {
41 
42  }
43  template<class P>
44  Parameter(const P &p)
45  : roots_(p.roots_){
46  }
47 
48  std::vector<IndexType> roots_;
49  };
50 
51  DynamicProgramming(const GraphicalModelType&, const Parameter& = Parameter());
53 
54  std::string name() const;
55  const GraphicalModelType& graphicalModel() const;
57  template< class VISITOR>
58  InferenceTermination infer(VISITOR &);
59  InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const;
60 
61 
62  void getNodeInfo(const IndexType Inode, std::vector<ValueType>& values, std::vector<std::vector<LabelType> >& substates, std::vector<IndexType>& nodes) const;
63 
64 
65  private:
66  const GraphicalModelType& gm_;
67  Parameter para_;
68  MyValueType* valueBuffer_;
69  MyStateType* stateBuffer_;
70  std::vector<MyValueType*> valueBuffers_;
71  std::vector<MyStateType*> stateBuffers_;
72  std::vector<size_t> nodeOrder_;
73  std::vector<size_t> orderedNodes_;
74  bool inferenceStarted_;
75  };
76 
77  template<class GM, class ACC>
78  inline std::string
80  return "DynamicProgramming";
81  }
82 
83  template<class GM, class ACC>
86  return gm_;
87  }
88 
89  template<class GM, class ACC>
91  {
92  free(valueBuffer_);
93  free(stateBuffer_);
94  }
95 
96  template<class GM, class ACC>
98  (
99  const GraphicalModelType& gm,
100  const Parameter& para
101  )
102  : gm_(gm), inferenceStarted_(false)
103  {
104  OPENGM_ASSERT(gm_.isAcyclic());
105  para_ = para;
106 
107  // Set nodeOrder
108  std::vector<size_t> numChildren(gm_.numberOfVariables(),0);
109  std::vector<size_t> nodeList;
110  size_t orderCount = 0;
111  size_t varCount = 0;
112  nodeOrder_.resize(gm_.numberOfVariables(),std::numeric_limits<std::size_t>::max());
113  size_t rootCounter=0;
114  while(varCount < gm_.numberOfVariables() && orderCount < gm_.numberOfVariables()){
115  if(rootCounter<para_.roots_.size()){
116  nodeOrder_[para_.roots_[rootCounter]] = orderCount++;
117  nodeList.push_back(para_.roots_[rootCounter]);
118  ++rootCounter;
119  }
120  else if(nodeOrder_[varCount]==std::numeric_limits<std::size_t>::max()){
121  nodeOrder_[varCount] = orderCount++;
122  nodeList.push_back(varCount);
123  }
124  ++varCount;
125  while(nodeList.size()>0){
126  size_t node = nodeList.back();
127  nodeList.pop_back();
128  for(typename GM::ConstFactorIterator it=gm_.factorsOfVariableBegin(node); it !=gm_.factorsOfVariableEnd(node); ++it){
129  const typename GM::FactorType& factor = gm_[(*it)];
130  if( factor.numberOfVariables() == 2 ){
131  if( factor.variableIndex(1) == node && nodeOrder_[factor.variableIndex(0)]==std::numeric_limits<std::size_t>::max() ){
132  nodeOrder_[factor.variableIndex(0)] = orderCount++;
133  nodeList.push_back(factor.variableIndex(0));
134  ++numChildren[node];
135  }
136  if( factor.variableIndex(0) == node && nodeOrder_[factor.variableIndex(1)]==std::numeric_limits<std::size_t>::max() ){
137  nodeOrder_[factor.variableIndex(1)] = orderCount++;
138  nodeList.push_back(factor.variableIndex(1));
139  ++numChildren[node];
140  }
141  }
142  }
143  }
144  }
145 
146  // Allocate memmory
147  size_t memSizeValue = 0;
148  size_t memSizeState = 0;
149  for(size_t i=0; i<gm_.numberOfVariables();++i){
150  memSizeValue += gm_.numberOfLabels(i);
151  memSizeState += gm.numberOfLabels(i) * numChildren[i];
152  }
153  valueBuffer_ = (MyValueType*) malloc(memSizeValue*sizeof(MyValueType));
154  stateBuffer_ = (MyStateType*) malloc(memSizeState*sizeof(MyStateType));
155  valueBuffers_.resize(gm_.numberOfVariables());
156  stateBuffers_.resize(gm_.numberOfVariables());
157 
158  MyValueType* valuePointer = valueBuffer_;
159  MyStateType* statePointer = stateBuffer_;
160  for(size_t i=0; i<gm_.numberOfVariables();++i){
161  valueBuffers_[i] = valuePointer;
162  valuePointer += gm.numberOfLabels(i);
163  stateBuffers_[i] = statePointer;
164  statePointer += gm.numberOfLabels(i) * numChildren[i];
165  }
166 
167  orderedNodes_.resize(gm_.numberOfVariables(),std::numeric_limits<std::size_t>::max());
168  for(size_t i=0; i<gm_.numberOfVariables(); ++i)
169  orderedNodes_[nodeOrder_[i]] = i;
170 
171  }
172 
173  template<class GM, class ACC>
174  inline InferenceTermination
176  EmptyVisitorType v;
177  return infer(v);
178  }
179 
180  template<class GM, class ACC>
181  template<class VISITOR>
182  inline InferenceTermination
184  (
185  VISITOR & visitor
186  ){
187  visitor.begin(*this);
188  inferenceStarted_ = true;
189  for(size_t i=1; i<=gm_.numberOfVariables();++i){
190  const size_t node = orderedNodes_[gm_.numberOfVariables()-i];
191  // set buffer neutral
192  for(size_t n=0; n<gm_.numberOfLabels(node); ++n){
193  OperatorType::neutral(valueBuffers_[node][n]);
194  }
195  // accumulate messages
196  size_t childrenCounter = 0;
197  for(typename GM::ConstFactorIterator it=gm_.factorsOfVariableBegin(node); it !=gm_.factorsOfVariableEnd(node); ++it){
198  const typename GM::FactorType& factor = gm_[(*it)];
199 
200  // unary
201  if(factor.numberOfVariables()==1 ){
202  for(size_t n=0; n<gm_.numberOfLabels(node); ++n){
203  const ValueType fac = factor(&n);
204  OperatorType::op(fac, valueBuffers_[node][n]);
205  }
206  }
207 
208  //pairwise
209  if( factor.numberOfVariables()==2 ){
210  size_t vec[] = {0,0};
211  if(factor.variableIndex(0) == node && nodeOrder_[factor.variableIndex(1)]>nodeOrder_[node] ){
212  const size_t node2 = factor.variableIndex(1);
213  MyStateType s;
214  MyValueType v,v2;
215  for(vec[0]=0; vec[0]<gm_.numberOfLabels(node); ++vec[0]){
216  ACC::neutral(v);
217  for(vec[1]=0; vec[1]<gm_.numberOfLabels(node2); ++vec[1]){
218  const ValueType fac = factor(vec);
219  OperatorType::op(fac,valueBuffers_[node2][vec[1]],v2) ;
220  if(ACC::bop(v2,v)){
221  v=v2;
222  s=vec[1];
223  }
224  }
225  stateBuffers_[node][childrenCounter*gm_.numberOfLabels(node)+vec[0]] = s;
226  OperatorType::op(v,valueBuffers_[node][vec[0]]);
227  }
228  ++childrenCounter;
229 
230  }
231  if(factor.variableIndex(1) == node && nodeOrder_[factor.variableIndex(0)]>nodeOrder_[node]){
232  const size_t node2 = factor.variableIndex(0);
233  MyStateType s;
234  MyValueType v,v2;
235  for(vec[1]=0; vec[1]<gm_.numberOfLabels(node); ++vec[1]){
236  ACC::neutral(v);
237  for(vec[0]=0; vec[0]<gm_.numberOfLabels(node2); ++vec[0]){
238  const ValueType fac = factor(vec);
239  OperatorType::op(fac,valueBuffers_[node2][vec[0]],v2);
240  if(ACC::bop(v2,v)){
241  v=v2;
242  s=vec[0];
243  }
244  }
245  stateBuffers_[node][childrenCounter*gm_.numberOfLabels(node)+vec[1]] = s;
246  OperatorType::op(v,valueBuffers_[node][vec[1]]);
247  }
248  ++childrenCounter;
249  }
250  }
251  // higher order
252  if( factor.numberOfVariables()>2 ){
253  throw std::runtime_error("This implementation of Dynamic Programming does only support second order models so far, but could be extended.");
254  }
255 
256  }
257  }
258  visitor.end(*this);
259  return NORMAL;
260  }
261 
262  template<class GM, class ACC>
264  (
265  std::vector<LabelType>& arg,
266  const size_t n
267  ) const {
268  if(n > 1) {
269  arg.assign(gm_.numberOfVariables(), 0);
270  return UNKNOWN;
271  }
272  else {
273  if(inferenceStarted_) {
274  std::vector<size_t> nodeList;
275  arg.assign(gm_.numberOfVariables(), std::numeric_limits<LabelType>::max() );
276  size_t var = 0;
277  while(var < gm_.numberOfVariables()){
278  if(arg[var]==std::numeric_limits<LabelType>::max()){
279  MyValueType v; ACC::neutral(v);
280  for(size_t i=0; i<gm_.numberOfLabels(var); ++i){
281  if(ACC::bop(valueBuffers_[var][i], v)){
282  v = valueBuffers_[var][i];
283  arg[var]=i;
284  }
285  }
286  nodeList.push_back(var);
287  }
288  ++var;
289  while(nodeList.size()>0){
290  size_t node = nodeList.back();
291  size_t childrenCounter = 0;
292  nodeList.pop_back();
293  for(typename GM::ConstFactorIterator it=gm_.factorsOfVariableBegin(node); it !=gm_.factorsOfVariableEnd(node); ++it){
294  const typename GM::FactorType& factor = gm_[(*it)];
295  if(factor.numberOfVariables()==2 ){
296  if(factor.variableIndex(1)==node && nodeOrder_[factor.variableIndex(0)] > nodeOrder_[node] ){
297  arg[factor.variableIndex(0)] = stateBuffers_[node][childrenCounter*gm_.numberOfLabels(node)+arg[node]];
298  nodeList.push_back(factor.variableIndex(0));
299  ++childrenCounter;
300  }
301  if(factor.variableIndex(0)==node && nodeOrder_[factor.variableIndex(1)] > nodeOrder_[node] ){
302  arg[factor.variableIndex(1)] = stateBuffers_[node][childrenCounter*gm_.numberOfLabels(node)+arg[node]];
303  nodeList.push_back(factor.variableIndex(1));
304  ++childrenCounter;
305  }
306  }
307  }
308  }
309  }
310  return NORMAL;
311  } else {
312  arg.assign(gm_.numberOfVariables(), 0);
313  return UNKNOWN;
314  }
315  }
316  }
317 
318  template<class GM, class ACC>
319  inline void DynamicProgramming<GM, ACC>::getNodeInfo(const IndexType Inode, std::vector<ValueType>& values, std::vector<std::vector<LabelType> >& substates, std::vector<IndexType>& nodes) const{
320  values.clear();
321  substates.clear();
322  nodes.clear();
323  values.resize(gm_.numberOfLabels(Inode));
324  substates.resize(gm_.numberOfLabels(Inode));
325  std::vector<LabelType> arg;
326  bool firstround = true;
327  std::vector<size_t> nodeList;
328  for(IndexType i=0;i<gm_.numberOfLabels(Inode); ++i){
329  arg.assign(gm_.numberOfVariables(), std::numeric_limits<LabelType>::max() );
330  arg[Inode]=i;
331  values[i]=valueBuffers_[Inode][i];
332  nodeList.push_back(Inode);
333  if(i!=0){
334  firstround=false;
335  }
336 
337  while(nodeList.size()>0){
338  size_t node = nodeList.back();
339  size_t childrenCounter = 0;
340  nodeList.pop_back();
341  for(typename GM::ConstFactorIterator it=gm_.factorsOfVariableBegin(node); it !=gm_.factorsOfVariableEnd(node); ++it){
342  const typename GM::FactorType& factor = gm_[(*it)];
343  if(factor.numberOfVariables()==2 ){
344  if(factor.variableIndex(1)==node && nodeOrder_[factor.variableIndex(0)] > nodeOrder_[node] ){
345  arg[factor.variableIndex(0)] = stateBuffers_[node][childrenCounter*gm_.numberOfLabels(node)+arg[node]];
346  substates[i].push_back(stateBuffers_[node][childrenCounter*gm_.numberOfLabels(node)+arg[node]]);
347  if(firstround==true){
348  nodes.push_back(factor.variableIndex(0));
349  }
350  nodeList.push_back(factor.variableIndex(0));
351  ++childrenCounter;
352  }
353  if(factor.variableIndex(0)==node && nodeOrder_[factor.variableIndex(1)] > nodeOrder_[node] ){
354  arg[factor.variableIndex(1)] = stateBuffers_[node][childrenCounter*gm_.numberOfLabels(node)+arg[node]];
355  substates[i].push_back(stateBuffers_[node][childrenCounter*gm_.numberOfLabels(node)+arg[node]]);
356  if(firstround==true){
357  nodes.push_back(factor.variableIndex(1));
358  }
359  nodeList.push_back(factor.variableIndex(1));
360  ++childrenCounter;
361  }
362  }
363  }
364  }
365  }
366  }
367 
368 
369 } // namespace opengm
370 
371 #endif // #ifndef OPENGM_DYNAMICPROGRAMMING_HXX
372 
The OpenGM namespace.
Definition: config.hxx:43
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
output a solution
GraphicalModelType::IndexType IndexType
Definition: inference.hxx:49
GraphicalModelType::ValueType ValueType
Definition: inference.hxx:50
Inference algorithm interface.
Definition: inference.hxx:43
void getNodeInfo(const IndexType Inode, std::vector< ValueType > &values, std::vector< std::vector< LabelType > > &substates, std::vector< IndexType > &nodes) const
visitors::VerboseVisitor< DynamicProgramming< GM, ACC > > VerboseVisitorType
visitors::EmptyVisitor< DynamicProgramming< GM, ACC > > EmptyVisitorType
InferenceTermination infer()
DynamicProgramming< _GM, ACC > type
GraphicalModelType::LabelType LabelType
Definition: inference.hxx:48
DynamicProgramming(const GraphicalModelType &, const Parameter &=Parameter())
const GraphicalModelType & graphicalModel() const
InferenceTermination
Definition: inference.hxx:24
visitors::TimingVisitor< DynamicProgramming< GM, ACC > > TimingVisitorType