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