OpenGM  2.3.x
Discrete Graphical Model Library
fastPD.hxx
Go to the documentation of this file.
1 #ifndef FASTPD_HXX_
2 #define FASTPD_HXX_
3 
10 
11 
12 #include "Fast_PD.h"
13 
14 namespace opengm {
15  namespace external {
16 
22  // FastPD
28  template<class GM>
29  class FastPD : public Inference<GM, opengm::Minimizer> {
30  public:
31  typedef GM GraphicalModelType;
37 
39  struct Parameter {
42  }
45  };
46  // construction
47  FastPD(const GraphicalModelType& gm, const Parameter& para = Parameter());
48  // destruction
49  ~FastPD();
50  // query
51  std::string name() const;
52  const GraphicalModelType& graphicalModel() const;
53  // inference
54  template<class VISITOR>
55  InferenceTermination infer(VISITOR & visitor);
57  InferenceTermination arg(std::vector<LabelType>&, const size_t& = 1) const;
58  typename GM::ValueType bound() const;
59  typename GM::ValueType value() const;
60 
62  ReparametrizerType * getReparametrizer(const typename ReparametrizerType::Parameter& params=typename ReparametrizerType::Parameter())const;
63 
64  protected:
65  const GraphicalModelType& gm_;
67  fastPDLib::CV_Fast_PD* pdInference_;
70 
71  fastPDLib::CV_Fast_PD::Real* labelCosts_;
72  int numPairs_;
73  int* pairs_;
74  fastPDLib::CV_Fast_PD::Real* distance_;
75  fastPDLib::CV_Fast_PD::Real* weights_;
76 
77  bool sameNumberOfLabels() const;
78  void setLabelCosts();
79  void getNumPairs();
80  void setPairs();
81  void setDistance();
82  void setWeights();
83  bool sameEnergyTable();
84  };
85 
86  template<class GM>
88  : gm_(gm), parameter_(para), pdInference_(NULL), labelCosts_(NULL),
89  numPairs_(0), pairs_(NULL), distance_(NULL), weights_(NULL) {
91  OPENGM_ASSERT(gm_.maxFactorOrder(2));
92 
93  setLabelCosts();
94  getNumPairs();
95  setPairs();
96  setDistance();
97  setWeights();
98 
99  if(sameEnergyTable()==false){
100  throw std::runtime_error("Error: Tables are not proportional");
101  }
102 
103  pdInference_ = new fastPDLib::CV_Fast_PD(
104  gm_.numberOfVariables(),
105  gm_.numberOfLabels(0),
106  labelCosts_,
107  numPairs_,
108  pairs_,
109  distance_,
111  weights_
112  );
113 
114  // set initial value and lower bound
117  }
118 
119  template<class GM>
121  if(pdInference_) {
122  delete pdInference_;
123  }
124  if(labelCosts_) {
125  delete[] labelCosts_;
126  }
127  if(pairs_) {
128  delete[] pairs_;
129  }
130  if(distance_) {
131  delete[] distance_;
132  }
133  if(weights_) {
134  delete[] weights_;
135  }
136  }
137 
138  template<class GM>
139  inline std::string FastPD<GM>::name() const {
140  return "FastPD";
141  }
142 
143  template<class GM>
145  return gm_;
146  }
147 
148  template<class GM>
150  EmptyVisitorType visitor;
151  return this->infer(visitor);
152  }
153 
154  template<class GM>
155  template<class VISITOR>
156  inline InferenceTermination FastPD<GM>::infer(VISITOR & visitor) {
157  visitor.begin(*this);
158  // TODO check for possible visitor injection method
159  // TODO this is slow, check if fast_pd allows energy extraction
160  if(pdInference_ != NULL) {
161  pdInference_->run();
162  std::vector<LabelType> result;
163  arg(result);
164  value_ = gm_.evaluate(result);
165  }
166  visitor.end(*this);
167  return NORMAL;
168  }
169 
170  template<class GM>
171  inline InferenceTermination FastPD<GM>::arg(std::vector<LabelType>& arg, const size_t& n) const {
172  OPENGM_ASSERT(pdInference_ != NULL);
173 
174  arg.resize(gm_.numberOfVariables());
175  for(IndexType i = 0; i < gm_.numberOfVariables(); i++) {
176  arg[i] = pdInference_->_pinfo[i].label;
177  }
178  return NORMAL;
179  }
180 
181  // == OLD ==
182  //template<class GM>
183  //inline typename GM::ValueType FastPD<GM>::bound() const {
184  // return lowerBound_;
185  //}
186 
187  template<class GM>
188  typename GM::ValueType FastPD<GM>::bound()const
189  {
190  ValueType boundValue=0;
191  IndexType pwId=0;
192  std::vector<IndexType> factorId2pwId(gm_.numberOfFactors(),std::numeric_limits<IndexType>::max());
193  for (IndexType factorId=0;factorId<gm_.numberOfFactors();++factorId)
194  if (gm_[factorId].numberOfVariables()==2)
195  factorId2pwId[factorId]=pwId++;
196 
197  for (IndexType factorId=0;factorId<gm_.numberOfFactors();++factorId)
198  {
199  const typename GM::FactorType& f=gm_[factorId];
200  ValueType res=std::numeric_limits<ValueType>::infinity(), res1;
201  if (f.numberOfVariables()==1)
202  {
203  IndexType varId=f.variableIndex(0);
204  for (LabelType label=0;label<gm_.numberOfLabels(varId);++label)
205  {
206  res1=f(&label);
207  for (IndexType i=0;i<gm_.numberOfFactors(varId);++i)
208  {
209  IndexType fId=gm_.factorOfVariable(varId,i);
210  if (gm_[fId].numberOfVariables()==2)
211  {
212  OPENGM_ASSERT(factorId2pwId[fId]<std::numeric_limits<IndexType>::max());
213  if (gm_[fId].variableIndex(0)==varId)
214  res1+=pdInference_->_y[label*numPairs_+factorId2pwId[fId]];
215  else
216  res1-=pdInference_->_y[label*numPairs_+factorId2pwId[fId]];
217  }
218  }
219  res=std::min(res,res1);
220  }
221  }else if (f.numberOfVariables()==2)
222  {
223  pwId=factorId2pwId[factorId];
224  OPENGM_ASSERT(pwId<std::numeric_limits<IndexType>::max());
225  IndexType varId0=f.variableIndex(0),varId1=f.variableIndex(1);
226  for (LabelType label0=0;label0<gm_.numberOfLabels(varId0);++label0)
227  for (LabelType label1=0;label1<gm_.numberOfLabels(varId1);++label1)
228  {
229  std::vector<LabelType> labels(2); labels[0]=label0; labels[1]=label1;
230  res1=f(labels.begin())-pdInference_->_y[label0*numPairs_+pwId]+pdInference_->_y[label1*numPairs_+pwId];
231  res=std::min(res,res1);
232  }
233  }else{
234  AccumulationType::ineutral(boundValue);
235  return boundValue;
236  //throw std::runtime_error("FastPD: only factors of order 1 and 2 are supported!");
237  }
238  boundValue+=res;
239  }
240 
241  return boundValue;
242  }
243 
244  template<class GM>
245  inline typename GM::ValueType FastPD<GM>::value() const {
246  return value_;
247  }
248 
249  template<class GM>
250  inline bool FastPD<GM>::sameNumberOfLabels() const {
251  OPENGM_ASSERT(gm_.numberOfVariables() > 0);
252  LabelType numLabels = gm_.numberOfLabels(0);
253  for(IndexType i = 1; i < gm_.numberOfVariables(); i++) {
254  if(gm_.numberOfLabels(i) != numLabels) {
255  return false;
256  }
257  }
258  return true;
259  }
260 
261  template<class GM>
263  labelCosts_ = new fastPDLib::CV_Fast_PD::Real[gm_.numberOfVariables() * gm_.numberOfLabels(0)];
264  for(IndexType i = 0; i < gm_.numberOfVariables() * gm_.numberOfLabels(0); i++) {
265  labelCosts_[i] = 0;
266  }
267 
268  for(IndexType i = 0; i < gm_.numberOfVariables(); i++) {
269  for(IndexType j = 0; j < gm_.numberOfFactors(i); j++) {
270  IndexType gmFactorIndex = gm_.factorOfVariable(i, j);
271  if(gm_.numberOfVariables(gmFactorIndex) == 1) {
272  for(IndexType k = 0; k < gm_.numberOfLabels(0); k++) {
273  labelCosts_[k * gm_.numberOfVariables() + i ] += gm_[gmFactorIndex](&k);
274  }
275  }
276  }
277  }
278  }
279 
280  template<class GM>
281  inline void FastPD<GM>::getNumPairs() {
282  for(IndexType i = 0; i < gm_.numberOfFactors(); i++) {
283  if(gm_.numberOfVariables(i) == 2) {
284  numPairs_++;
285  }
286  }
287  }
288 
289  template<class GM>
290  inline void FastPD<GM>::setPairs() {
291  pairs_ = new int[numPairs_ * 2];
292  int currentPair = 0;
293  for(IndexType i = 0; i < gm_.numberOfFactors(); i++) {
294  if(gm_.numberOfVariables(i) == 2) {
295  pairs_[currentPair * 2] = gm_[i].variableIndex(0);
296  pairs_[(currentPair * 2) + 1] = gm_[i].variableIndex(1);
297  currentPair++;
298  }
299  }
300  }
301 
302  template<class GM>
303  inline void FastPD<GM>::setDistance() {
304  distance_ = new fastPDLib::CV_Fast_PD::Real[gm_.numberOfLabels(0) * gm_.numberOfLabels(0)];
305  for(IndexType k = 0; k < gm_.numberOfLabels(0); k++) {
306  for(IndexType l = 0; l < gm_.numberOfLabels(0); l++) {
307  distance_[(l * gm_.numberOfLabels(0)) + k] = 0;
308  }
309  }
310  for(IndexType i = 0; i < gm_.numberOfFactors(); i++) {
311  if(gm_.numberOfVariables(i) == 2) {
312  for(IndexType k = 0; k < gm_.numberOfLabels(0); k++) {
313  for(IndexType l = 0; l < gm_.numberOfLabels(0); l++) {
314  IndexType index[] = {k, l};
315  distance_[(l * gm_.numberOfLabels(0)) + k] = gm_[i](index);
316  }
317  }
318  break;
319  }
320  }
321  }
322 
323  template<class GM>
324  inline void FastPD<GM>::setWeights() {
325  weights_ = new fastPDLib::CV_Fast_PD::Real[numPairs_];
326  int currentPair = 0;
327  for(IndexType i = 0; i < gm_.numberOfFactors(); i++) {
328  if(gm_.numberOfVariables(i) == 2) {
329  OPENGM_ASSERT(currentPair < numPairs_);
330  IndexType k;
331  for(k = 0; k < gm_.numberOfLabels(0); k++) {
332  IndexType l;
333  for(l = 0; l < gm_.numberOfLabels(0); l++) {
334  IndexType index[] = {k, l};
335  if((gm_[i](index) != 0) && (distance_[(l * gm_.numberOfLabels(0)) + k] != 0)) {
336  double currentWeight = static_cast<double>(gm_[i](index)) / static_cast<double>(distance_[(l * gm_.numberOfLabels(0)) + k]);
337  weights_[currentPair] = static_cast<fastPDLib::CV_Fast_PD::Real>(currentWeight);
338  if(fabs(currentWeight - static_cast<double>(weights_[currentPair])) > OPENGM_FLOAT_TOL) {
339  throw(RuntimeError("Function not supported"));
340  }
341  currentPair++;
342  break;
343  }
344  }
345  if(l != gm_.numberOfLabels(0)) {
346  break;
347  }
348  }
349  if(k == gm_.numberOfLabels(0)) {
350  weights_[currentPair] = 0;
351  currentPair++;
352  }
353  }
354  }
355  OPENGM_ASSERT(currentPair == numPairs_);
356  }
357 
358  template<class GM>
360  int currentPair = 0;
361  for(IndexType i = 0; i < gm_.numberOfFactors(); i++) {
362  if(gm_.numberOfVariables(i) == 2) {
363  for(IndexType k = 0; k < gm_.numberOfLabels(0); k++) {
364  for(IndexType l = 0; l < gm_.numberOfLabels(0); l++) {
365  IndexType index[] = {k, l};
366  if(fabs(gm_[i](index) - (distance_[(l * gm_.numberOfLabels(0)) + k] * weights_[currentPair])) > OPENGM_FLOAT_TOL) {
367  return false;
368  }
369  }
370  }
371  currentPair++;
372  }
373  }
374  OPENGM_ASSERT(currentPair == numPairs_);
375  return true;
376  }
377 
378  template<class GM>
380  {
381  ReparametrizerType* pReparametrizer=new ReparametrizerType(gm_);
382 
383  ReparametrizerType lpreparametrizer(gm_);
384  typename ReparametrizerType::RepaStorageType& reparametrization=pReparametrizer->Reparametrization();
385  typedef typename ReparametrizerType::RepaStorageType::uIterator uIterator;
386 
387  //counting p/w factors
388  IndexType pwNum=0;
389  for (IndexType factorId=0;factorId<gm_.numberOfFactors();++factorId)
390  if (gm_[factorId].numberOfVariables()==2) ++pwNum;
391 
392  const fastPDLib::CV_Fast_PD::Real* y=pdInference_->_y;
393 
394  IndexType pwId=0;
395  for (IndexType factorId=0;factorId<gm_.numberOfFactors();++factorId)
396  {
397  if (gm_[factorId].numberOfVariables()!=2) continue;
398  for (IndexType i=0;i<2;++i)
399  {
400  std::pair<uIterator,uIterator> iter=reparametrization.getIterators(factorId,i);
401  LabelType label=0;
402  ValueType mul=(i==0 ? 1 : -1);
403  for (;iter.first!=iter.second;++iter.first)
404  {
405  *iter.first=-mul*y[label*pwNum+pwId];
406  ++label;
407  }
408  }
409 
410  ++pwId;
411  }
412 
413 
414  return pReparametrizer;
415  }
416 
417 
418  } // namespace external
419 } // namespace opengm
420 
421 #endif /* FASTPD_HXX_ */
InferenceTermination arg(std::vector< LabelType > &, const size_t &=1) const
Definition: fastPD.hxx:171
#define OPENGM_FLOAT_TOL
const GraphicalModelType & graphicalModel() const
Definition: fastPD.hxx:144
The OpenGM namespace.
Definition: config.hxx:43
fastPDLib::CV_Fast_PD * pdInference_
Definition: fastPD.hxx:67
visitors::TimingVisitor< FastPD< GM > > TimingVisitorType
Definition: fastPD.hxx:36
FastPD(const GraphicalModelType &gm, const Parameter &para=Parameter())
Definition: fastPD.hxx:87
GM::ValueType bound() const
return a bound on the solution
Definition: fastPD.hxx:188
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
GM::ValueType value() const
return the solution (value)
Definition: fastPD.hxx:245
LPReparametrisationStorage< GM > RepaStorageType
const GraphicalModelType & gm_
Definition: fastPD.hxx:65
GraphicalModelType::IndexType IndexType
Definition: inference.hxx:40
LPReparametrizer< GM, opengm::Minimizer > ReparametrizerType
Definition: fastPD.hxx:61
FastPD FastPD inference algorithm class.
Definition: fastPD.hxx:29
visitors::VerboseVisitor< FastPD< GM > > VerboseVisitorType
Definition: fastPD.hxx:34
std::string name() const
Definition: fastPD.hxx:139
ReparametrizerType * getReparametrizer(const typename ReparametrizerType::Parameter &params=typename ReparametrizerType::Parameter()) const
Definition: fastPD.hxx:379
GraphicalModelType::ValueType ValueType
Definition: inference.hxx:41
static T ineutral()
inverse neutral element (with return)
Definition: minimizer.hxx:25
Inference algorithm interface.
Definition: inference.hxx:34
opengm::Minimizer AccumulationType
Definition: fastPD.hxx:32
InferenceTermination infer()
Definition: fastPD.hxx:149
bool sameNumberOfLabels() const
Definition: fastPD.hxx:250
static T neutral()
neutral element (with return)
Definition: minimizer.hxx:16
size_t numberOfIterations_
number of iterations
Definition: fastPD.hxx:44
visitors::EmptyVisitor< FastPD< GM > > EmptyVisitorType
Definition: fastPD.hxx:35
fastPDLib::CV_Fast_PD::Real * labelCosts_
Definition: fastPD.hxx:71
RepaStorageType & Reparametrization()
GraphicalModelType::LabelType LabelType
Definition: inference.hxx:39
Minimization as a unary accumulation.
Definition: minimizer.hxx:12
fastPDLib::CV_Fast_PD::Real * weights_
Definition: fastPD.hxx:75
fastPDLib::CV_Fast_PD::Real * distance_
Definition: fastPD.hxx:74
OpenGM runtime error.
Definition: opengm.hxx:100
InferenceTermination
Definition: inference.hxx:24