OpenGM  2.3.x
Discrete Graphical Model Library
lsatr.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_LSATR_HXX
3 #define OPENGM_LSATR_HXX
4 
5 #include <algorithm>
6 #include <vector>
7 #include <string>
8 #include <iostream>
9 
10 #include "opengm/opengm.hxx"
13 
14 #include <maxflowlib.h>
15 
16 #ifndef NOVIGRA
17 #include "vigra/multi_distance.hxx"
18 #include "vigra/multi_array.hxx"
19 #endif
20 
21 namespace opengm {
22 
36 
37 
38 
40  LSA_TR_WeightedEdge(double aw, size_t au, size_t av): w(aw), u(au), v(av){}
41  double w;
42  size_t u;
43  size_t v;
44  };
45 
46 
47  template<class LabelType>
49  public:
50  enum DISTANCE {HAMMING, EUCLIDEAN};
51 
52  LSA_TR_HELPER() { distanceType_= EUCLIDEAN;};
53  ~LSA_TR_HELPER(){ if(graph_!=NULL){delete graph_; delete changedList_;} };
54  template<class GM>
55  void init(const GM&, const std::vector<LabelType>& );
56  void set(const double);
57  void set(const std::vector<LabelType>&, const double);
58  double optimize(std::vector<LabelType>&);
59  void setDistanceType(const DISTANCE d){ distanceType_=d; };
60 
61  double eval(const std::vector<LabelType>&) const;
62  double evalAprox(const std::vector<LabelType>&,const std::vector<LabelType>&, const double) const;
63  void evalBoth(const std::vector<LabelType>& label, const std::vector<LabelType>& workingPoint, const double lambda, double& value, double& valueAprox) const;
64 
65  private:
66  typedef maxflowLib::Graph<double,double,double> graph_type;
67  typedef maxflowLib::Block<typename graph_type::node_id> block_type;
68 
69  void updateDistance();
70 
71  size_t numVar_;
72  double lambda_;
73  double constTerm_;
74  double constTermApproximation_;
75  double constTermTrustRegion_;
76  std::vector<LabelType> workingPoint_;
77  std::vector<double> distance_;
78  std::vector<double> unaries_;
79  std::vector<double> approxUnaries_;
80  std::vector< LSA_TR_WeightedEdge> supEdges_;
81  std::vector< LSA_TR_WeightedEdge> subEdges_;
82  graph_type* graph_;
83  block_type* changedList_;
84  bool solved_;
85  DISTANCE distanceType_;
86  std::vector<size_t> shape_;
87  };
88 
89 
90  template<class GM, class ACC>
91  class LSA_TR : public Inference<GM, ACC>
92  {
93  public:
94  typedef ACC AccumulationType;
95  typedef GM GraphicalModelType;
100 
101 
102  template<class _GM>
103  struct RebindGm{
105  };
106 
107  template<class _GM,class _ACC>
110  };
111 
112 
113  class Parameter {
114  public:
115  enum DISTANCE {HAMMING, EUCLIDEAN};
116  size_t randSeed_;
117  double maxLambda_;
123 
125  randSeed_ = 42;
126  maxLambda_ = 1e5;
127  initialLambda_ = 0.1;
128  precisionLambda_ = 1e-9; // used to compare GEO lambda in parametric maxflow
129  lambdaMultiplier_ = 2; // used for jumps in backtracking;
130  reductionRatio_ = 0.25; // used to decide whether to increase or decrease lambda using the multiplier
131  distance_ = EUCLIDEAN;
132  }
133 
134  template<class P>
135  Parameter(const P & p)
136  : randSeed_(p.randSeed_),
137  maxLambda_(p.maxLambda_),
138  initialLambda_(p.initialLambda_),
139  precisionLambda_(p.precisionLambda_),
140  lambdaMultiplier_(p.lambdaMultiplier_),
141  reductionRatio_(p.reductionRatio_),
142  distance_(p.distance_){
143 
144  }
145  };
146 
147  LSA_TR(const GraphicalModelType&);
148  LSA_TR(const GraphicalModelType&, const Parameter&);
149  ~LSA_TR();
150  std::string name() const;
151  const GraphicalModelType& graphicalModel() const;
153  void reset();
154  template<class VisitorType>
155  InferenceTermination infer(VisitorType&);
156  void setStartingPoint(typename std::vector<LabelType>::const_iterator);
157  virtual InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const ;
158  virtual ValueType value()const{ return gm_.evaluate(curState_);}
159 
160  private:
161  void init();
162  double findMinimalChangeBrakPoint(const double lambda, const std::vector<LabelType>& workingPoint);
163 
164  LSA_TR_HELPER<LabelType> helper_;
165  const GraphicalModelType& gm_;
166  Parameter param_;
167  std::vector<LabelType> curState_;
168  size_t numVar_;
169 
170  ValueType constTerm_;
171  std::vector<ValueType> unaries_;
172  std::vector<LSA_TR_WeightedEdge> subEdges_;
173  std::vector<LSA_TR_WeightedEdge> supEdges_;
174  std::vector<ValueType> approxUnaries_;
175 
176  };
177 
179  template<class LabelType>
180  template<class GM>
181  void LSA_TR_HELPER<LabelType>::init(const GM& gm, const std::vector<LabelType>& workingPoint){
182  typedef size_t IndexType;
183  solved_ = false;
184  numVar_ = gm.numberOfVariables();
185  workingPoint_ = workingPoint;
186  lambda_ = 0.2;
187  constTerm_ = 0;
188  unaries_.resize(numVar_,0);
189  distance_.resize(numVar_,0);
190 
191  const LabelType label00[] = {0,0};
192  const LabelType label01[] = {0,1};
193  const LabelType label10[] = {1,0};
194  const LabelType label11[] = {1,1};
195  for(IndexType f=0; f<gm.numberOfFactors();++f){
196  OPENGM_ASSERT(gm[f].numberOfVariables() <= 2);
197  if(gm[f].numberOfVariables() == 0){
198  constTerm_ += gm[f](label00);
199  }
200  else if(gm[f].numberOfVariables() == 1){
201  const double v0 = gm[f](label00);
202  const double v1 = gm[f](label11);
203  const IndexType var0 = gm[f].variableIndex(0);
204  constTerm_ += v0;
205  unaries_[var0] += v1-v0;
206  }
207  else if(gm[f].numberOfVariables() == 2){
208  const double v00 = gm[f](label00);
209  const double v01 = gm[f](label01);
210  const double v10 = gm[f](label10);
211  const double v11 = gm[f](label11);
212  const IndexType var0 = gm[f].variableIndex(0);
213  const IndexType var1 = gm[f].variableIndex(1);
214  constTerm_ += v00;
215  const double D = 0.5*(v11-v00);
216  const double M = 0.5*(v10-v01);
217  unaries_[var0] += D+M;
218  unaries_[var1] += D-M;
219  const double V = v10-v00-D-M;
220  if(V>0){//submodular
221  subEdges_.push_back( LSA_TR_WeightedEdge(V,var0,var1));
222  }
223  else if(V<0){//supermodular
224  unaries_[var0] += V;
225  unaries_[var1] += V;
226  supEdges_.push_back( LSA_TR_WeightedEdge(-2*V,var0,var1));
227  }
228  }
229  }
230  std::cout << std::endl;
231  std::cout << subEdges_.size() <<" submodular edges."<<std::endl;
232  std::cout << supEdges_.size() <<" supermodular edges."<<std::endl;
233 
234  graph_ = new graph_type(gm.numberOfVariables(),subEdges_.size()+1);
235  changedList_ = new block_type(gm.numberOfVariables());
236 
237  graph_->add_node(numVar_);
238  for(size_t i=0; i<subEdges_.size(); ++i){
239  graph_->add_edge( subEdges_[i].u, subEdges_[i].v, subEdges_[i].w, subEdges_[i].w);
240  }
241  approxUnaries_.assign(unaries_.begin(),unaries_.end());
242  for(size_t i=0; i<supEdges_.size(); ++i){
243  const size_t var0 = supEdges_[i].u;
244  const size_t var1 = supEdges_[i].v;
245  const double w = supEdges_[i].w;
246  if(workingPoint[var0]==1)
247  approxUnaries_[var1] += w;
248  if(workingPoint[var1]==1)
249  approxUnaries_[var0] += w;
250  if(workingPoint[var0]==1 && workingPoint[var1]==1)
251  constTermApproximation_ -= w;
252  }
253 
254 
255  shape_.resize(1,numVar_);
256  std::vector<size_t> neigbor_count(numVar_,0);
257  for(size_t i=0; i<supEdges_.size(); ++i){
258  ++neigbor_count[supEdges_[i].u];
259  ++neigbor_count[supEdges_[i].v];
260  }
261  for(size_t i=0; i<subEdges_.size(); ++i){
262  ++neigbor_count[subEdges_[i].u];
263  ++neigbor_count[subEdges_[i].v];
264  }
265  size_t min_deg = *std::min_element(neigbor_count.begin(),neigbor_count.end());
266  std::vector<size_t> corners;
267  for(size_t i=0; i<neigbor_count.size(); ++i)
268  if (neigbor_count[i] == min_deg)
269  corners.push_back(i);
270  if(corners.size()==4){
271  if( !(corners[1]-corners[0] != corners[3]-corners[2])&&
272  !(corners[0] != 0 || corners[3] != numVar_-1) ){
273  shape_.resize(2);
274  shape_[0] = corners[1]-corners[0]+1;
275  shape_[1] = numVar_ / shape_[0];
276  }
277  }
278  if(shape_.size() ==1 && distanceType_ == EUCLIDEAN)
279  std::cout << "Warning : Shape of labeling is 1 and Euclidean distance does not make sense! Maybe autodetection of shape fails ..." <<std::endl;
280 
281 
282 
283  updateDistance();
284  constTermTrustRegion_ = 0;
285  for(int i=0; i<approxUnaries_.size(); ++i){
286  approxUnaries_[i] += lambda_*distance_[i];
287  graph_->add_tweights( i, 0, approxUnaries_[i]);
288  if(distance_[i]<0)
289  constTermTrustRegion_-=lambda_*distance_[i];
290  }
291  };
292 
293  template<class LabelType>
295  if (distanceType_==HAMMING){
296  for(int i=0; i<numVar_; ++i){
297  if(workingPoint_[i]==0){
298  distance_[i] = 1;
299  }
300  else{
301  distance_[i] = -1;
302  }
303  }
304  }
305 #ifdef NOVIGRA
306  else if(distanceType_==EUCLIDEAN){
307  std::cout << "Warning : The useage of euclidean distance requires VIGRA!" <<std::endl;
308  std::cout << " Vigra is disabled -> Switch to Hamming distance!" <<std::endl;
309  distanceType_=HAMMING;
310  for(int i=0; i<numVar_; ++i){
311  if(workingPoint_[i]==0){
312  distance_[i] = 1;
313  }
314  else{
315  distance_[i] = -1;
316  }
317  }
318  }
319 #else
320  else if(distanceType_==EUCLIDEAN){
321  std::vector<size_t> s = shape_;
322  std::vector<double> dist0(numVar_,0);
323  std::vector<double> dist1(numVar_,0);
324  if(s.size()==1){
325  typedef vigra::MultiArrayView<1, LabelType> ArrayType;
326  typedef vigra::MultiArrayView<1, double> DArrayType;
327  typedef typename ArrayType::difference_type ShapeType;
328  ShapeType shape(s[0]);
329  ShapeType stride(1);
330 
331 
332  ArrayType source( shape, stride, &workingPoint_[0] );
333  DArrayType dest0( shape, stride, &dist0[0] );
334  DArrayType dest1( shape, stride, &dist1[0] );
335 
336  vigra::separableMultiDistance(source, dest0, false);
337  vigra::separableMultiDistance(source, dest1, true);
338  for(int i=0; i<numVar_; ++i){
339  if(workingPoint_[i]==0){
340  distance_[i] = (dist1[i]-0.5);
341  }
342  else{
343  distance_[i] = -(dist0[i]-0.5);
344  }
345  }
346  }
347  else if(s.size()==2){
348  typedef vigra::MultiArrayView<2, LabelType> ArrayType;
349  typedef vigra::MultiArrayView<2, double> DArrayType;
350  typedef typename ArrayType::difference_type ShapeType;
351  ShapeType shape(s[0],s[1]);
352  ShapeType stride(1,s[0]);
353 
354 
355  ArrayType source( shape, stride, &workingPoint_[0] );
356  DArrayType dest0( shape, stride, &dist0[0] );
357  DArrayType dest1( shape, stride, &dist1[0] );
358 
359  vigra::separableMultiDistance(source, dest0, false);
360  vigra::separableMultiDistance(source, dest1, true);
361  for(int i=0; i<numVar_; ++i){
362  if(workingPoint_[i]==0){
363  distance_[i] = (dist1[i]-0.5);
364  }
365  else{
366  distance_[i] = -(dist0[i]-0.5);
367  }
368  }
369  }
370  else if(s.size()==3){
371  typedef vigra::MultiArrayView<3, LabelType> ArrayType;
372  typedef vigra::MultiArrayView<3, double> DArrayType;
373  typedef typename ArrayType::difference_type ShapeType;
374  ShapeType shape(s[0],s[1],s[2]);
375  ShapeType stride(1,s[0],s[0]*s[1]);
376 
377 
378  ArrayType source( shape, stride, &workingPoint_[0] );
379  DArrayType dest0( shape, stride, &dist0[0] );
380  DArrayType dest1( shape, stride, &dist1[0] );
381 
382  vigra::separableMultiDistance(source, dest0, false);
383  vigra::separableMultiDistance(source, dest1, true);
384  for(int i=0; i<numVar_; ++i){
385  if(workingPoint_[i]==0){
386  distance_[i] = (dist1[i]-0.5);
387  }
388  else{
389  distance_[i] = -(dist0[i]-0.5);
390  }
391  }
392  }
393  }//end EUCLIDEAN
394 #endif
395  else{
396  std::cout <<"Unknown distance"<<std::endl;
397  }
398  return;
399  }
400 
401  template<class LabelType>
402  double LSA_TR_HELPER<LabelType>::optimize(std::vector<LabelType>& label){
403  double value;
404  //std::cout << lambda_ <<std::endl;
405  if(solved_){ //use warmstart
406  value = graph_->maxflow(true,changedList_);
407  for (typename graph_type::node_id* ptr = changedList_->ScanFirst(); ptr; ptr = changedList_->ScanNext()) {
408  typename graph_type::node_id var = *ptr;
409  OPENGM_ASSERT(var>=0 && var<numVar_);
410  graph_->remove_from_changed_list(var);
411  }
412 
413  for(size_t var=0; var<numVar_; ++var) {
414  if (graph_->what_segment(var) == graph_type::SOURCE) { label[var]=1;}
415  else { label[var]=0;}
416  }
417  changedList_->Reset();
418  }
419  else{ //first round without warmstart
420  value = graph_->maxflow();
421  for(size_t var=0; var<numVar_; ++var) {
422  if (graph_->what_segment(var) == graph_type::SOURCE) { label[var]=1;}
423  else { label[var]=0;}
424  }
425  solved_=true;
426  }
427  return value + constTerm_ + constTermApproximation_ + constTermTrustRegion_;
428  }
429 
430  template<class LabelType>
431  void LSA_TR_HELPER<LabelType>::set(const double newLambda){
432  if( newLambda == lambda_ ) return;
433  double difLambda = newLambda - lambda_;
434  lambda_ = newLambda;
435  constTermTrustRegion_ = 0;
436  if(solved_){
437  for(int i=0; i<approxUnaries_.size(); ++i){
438  double oldcap = graph_->get_trcap(i);
439  approxUnaries_[i] += difLambda*distance_[i];
440  graph_->add_tweights( i, 0, difLambda*distance_[i] );
441  if(distance_[i]<0)
442  constTermTrustRegion_ -= difLambda*distance_[i];
443  double newcap = graph_->get_trcap(i);
444  if (!((newcap > 0 && oldcap > 0)||(newcap < 0 && oldcap < 0))){
445  graph_->mark_node(i);
446  }
447  }
448  }else{
449  for(int i=0; i<approxUnaries_.size(); ++i){
450  approxUnaries_[i] += difLambda*distance_[i];
451  graph_->add_tweights( i, 0, difLambda*distance_[i] );
452  if(distance_[i]<0)
453  constTermTrustRegion_ -= difLambda*distance_[i];
454  }
455  }
456  }
457 
458  template<class LabelType>
459  void LSA_TR_HELPER<LabelType>::set(const std::vector<LabelType>& newWorkingPoint, const double newLambda){
460  workingPoint_ = newWorkingPoint;
461  lambda_ = newLambda;
462  constTermTrustRegion_ = 0;
463  constTermApproximation_ = 0;
464 
465  updateDistance();
466 
467  std::vector<double> newApproxUnaries = unaries_;
468  for(size_t i=0; i<supEdges_.size(); ++i){
469  const size_t var0 = supEdges_[i].u;
470  const size_t var1 = supEdges_[i].v;
471  const double w = supEdges_[i].w;
472  if(workingPoint_[var0]==1)
473  newApproxUnaries[var1] += w;
474  if(workingPoint_[var1]==1)
475  newApproxUnaries[var0] += w;
476  if(workingPoint_[var0]==1 && workingPoint_[var1]==1)
477  constTermApproximation_ -= w;
478  }
479  if(solved_){
480  for(int i=0; i<numVar_; ++i){
481  double oldcap = graph_->get_trcap(i);
482  newApproxUnaries[i] += lambda_*distance_[i];
483  graph_->add_tweights( i, 0, newApproxUnaries[i]-approxUnaries_[i] );
484  if(distance_[i]<0)
485  constTermTrustRegion_ -= lambda_*distance_[i];
486  double newcap = graph_->get_trcap(i);
487  if (!((newcap > 0 && oldcap > 0)||(newcap < 0 && oldcap < 0))){
488  graph_->mark_node(i);
489  }
490  }
491  }else{
492  for(int i=0; i<numVar_; ++i){
493  newApproxUnaries[i] += lambda_*distance_[i];
494  graph_->add_tweights( i, 0, newApproxUnaries[i]-approxUnaries_[i]);
495  if(distance_[i]<0)
496  constTermTrustRegion_ -= lambda_*distance_[i];
497  }
498  }
499  approxUnaries_.assign(newApproxUnaries.begin(),newApproxUnaries.end());
500 
501  }
502 
503 
504  template<class LabelType>
505  double LSA_TR_HELPER<LabelType>::eval(const std::vector<LabelType>& label) const
506  {
507  typedef double ValueType;
508  ValueType v = constTerm_;
509  for(size_t var=0; var<numVar_;++var)
510  if(label[var]==1)
511  v += unaries_[var];
512  for(size_t i=0; i<subEdges_.size(); ++i)
513  if(label[subEdges_[i].u] != label[subEdges_[i].v])
514  v += subEdges_[i].w;
515  for(size_t i=0; i<supEdges_.size(); ++i)
516  if(label[supEdges_[i].u] == 1 && label[supEdges_[i].v] == 1)
517  v += supEdges_[i].w;
518  return v;
519  }
520 
521  template<class LabelType>
522  double LSA_TR_HELPER<LabelType>::evalAprox(const std::vector<LabelType>& label, const std::vector<LabelType>& workingPoint, const double lambda) const
523  {
524  typedef double ValueType;
525  ValueType v = constTerm_;
526  for(size_t var=0; var<numVar_;++var)
527  if(label[var]==1)
528  v += unaries_[var];
529  for(size_t i=0; i<subEdges_.size(); ++i)
530  if(label[subEdges_[i].u] != label[subEdges_[i].v])
531  v += subEdges_[i].w;
532  for(size_t i=0; i<supEdges_.size(); ++i){
533  if(label[supEdges_[i].u] == 1 && workingPoint[supEdges_[i].v] == 1 )
534  v += supEdges_[i].w;
535  if(workingPoint[supEdges_[i].u] == 1 && label[supEdges_[i].v] == 1 )
536  v += supEdges_[i].w;
537  if(workingPoint[supEdges_[i].u] == 1 && workingPoint[supEdges_[i].v] == 1 )
538  v -= supEdges_[i].w;
539  }
540  for(size_t i=0; i<numVar_; ++i){
541  if(label[i] != workingPoint[i])
542  v += lambda * std::fabs(distance_[i]);
543  }
544  return v;
545  }
546 
547  template<class LabelType>
548  void LSA_TR_HELPER<LabelType>::evalBoth(const std::vector<LabelType>& label, const std::vector<LabelType>& workingPoint, const double lambda, double& value, double& valueAprox) const
549  {
550  value = constTerm_;
551  for(size_t var=0; var<numVar_;++var)
552  if(label[var]==1)
553  value += unaries_[var];
554  for(size_t i=0; i<subEdges_.size(); ++i)
555  if(label[subEdges_[i].u] != label[subEdges_[i].v])
556  value += subEdges_[i].w;
557  valueAprox = value;
558  for(size_t i=0; i<supEdges_.size(); ++i){
559  if(label[supEdges_[i].u] == 1 && label[supEdges_[i].v] == 1 )
560  value += supEdges_[i].w;
561  if(label[supEdges_[i].u] == 1 && workingPoint[supEdges_[i].v] == 1 )
562  valueAprox += supEdges_[i].w;
563  if(workingPoint[supEdges_[i].u] == 1 && label[supEdges_[i].v] == 1 )
564  valueAprox += supEdges_[i].w;
565  if(workingPoint[supEdges_[i].u] == 1 && workingPoint[supEdges_[i].v] == 1 )
566  valueAprox -= supEdges_[i].w;
567  }
568  for(size_t i=0; i<numVar_; ++i){
569  if(label[i] != workingPoint[i])
570  valueAprox += lambda * std::fabs(distance_[i]);
571  }
572  }
573 
574 
575 
577 
578  template<class GM, class ACC>
580 
581  template<class GM, class ACC>
582  inline
584  (
585  const GraphicalModelType& gm
586  )
587  : gm_(gm),
588  param_(Parameter())
589  {
590  init();
591  }
592 
593  template<class GM, class ACC>
595  (
596  const GraphicalModelType& gm,
597  const Parameter& parameter
598  )
599  : gm_(gm),
600  param_(parameter)
601  {
602  init();
603  }
604 
605  template<class GM, class ACC>
606  void LSA_TR<GM, ACC>::init()
607  {
608  srand(param_.randSeed_);
609  numVar_ = gm_.numberOfVariables();
610  curState_.resize(numVar_,1);
611  for (size_t i=0; i<numVar_; ++i) curState_[i]= rand()%2;
612  helper_.init(gm_, curState_);
613  if(param_.distance_ == Parameter::HAMMING)
614  helper_.setDistanceType(LSA_TR_HELPER<LabelType>::HAMMING);
615  else if(param_.distance_ == Parameter::EUCLIDEAN)
616  helper_.setDistanceType(LSA_TR_HELPER<LabelType>::EUCLIDEAN);
617  else
618  std::cout << "Warning: Unknown distance type !"<<std::endl;
619  }
620 
621 
622  template<class GM, class ACC>
623  inline void
625  {
626  curState_.resize(numVar_,1);
627  }
628 
629  template<class GM, class ACC>
630  inline void
631  LSA_TR<GM,ACC>::setStartingPoint(typename std::vector<typename LSA_TR<GM,ACC>::LabelType>::const_iterator begin) {
632  curState_.assign(begin, begin+numVar_);
633  }
634 
635  template<class GM, class ACC>
636  inline std::string
638  {
639  return "LSA_TR";
640  }
641 
642  template<class GM, class ACC>
643  inline const typename LSA_TR<GM, ACC>::GraphicalModelType&
645  {
646  return gm_;
647  }
648 
649  template<class GM, class ACC>
650  inline InferenceTermination
652  {
654  return infer(v);
655  }
656 
657 
658  template<class GM, class ACC>
659  template<class VisitorType>
661  (
662  VisitorType& visitor
663  )
664  {
665  const ValueType tau1 = 0;
666  const ValueType tau2 = param_.reductionRatio_;
667  bool exitInf=false;
668  std::vector<LabelType> label(numVar_);
669  std::vector<ValueType> energies;
670  std::vector<ValueType> energiesAprox;
671  double lambda = param_.initialLambda_;
672  helper_.set(curState_,lambda);
673  visitor.begin(*this);
674 
675  ValueType curr_value_aprox = helper_.evalAprox(curState_, curState_, lambda);
676  ValueType curr_value = helper_.eval(curState_);
677  bool changedWorkingpoint = false;
678  bool changedLambda = false;
679  ValueType value_after;
680  ValueType value_after_aprox;
681 
682  OPENGM_ASSERT(std::fabs(curr_value-gm_.evaluate(curState_))<0.0001);
683  for (size_t i=0; i<10000 ; ++i){
684  //std::cout << "round "<<i<<" (lambda = "<<lambda<<"): " <<std::endl;
685  if(lambda>param_.maxLambda_) break;
686 
687  if(changedWorkingpoint)
688  helper_.set(curState_,lambda);
689  else if(changedLambda)
690  helper_.set(lambda);
691  changedWorkingpoint = false;
692  changedLambda = false;
693  helper_.optimize(label);
694  helper_.evalBoth(label, curState_, lambda, value_after, value_after_aprox);
695 
696  //if(std::fabs(curr_value_aprox-curr_value)>0.0001)
697  // std::cout << "WARNING : "<< helper_.evalAprox(curState_, curState_, lambda) << " != " << helper_.eval(curState_) << " == " <<gm_.evaluate(curState_)<<std::endl;
698  OPENGM_ASSERT(std::fabs(helper_.eval(curState_)-gm_.evaluate(curState_))<0.0001);
699  OPENGM_ASSERT(helper_.eval(curState_) == curr_value);
700  OPENGM_ASSERT(std::fabs(helper_.eval(label)-gm_.evaluate(label))<0.0001);
701 
702  const ValueType P = curr_value_aprox - value_after_aprox;
703  const ValueType R = curr_value - value_after;
704 
705 
706 
707  //std::cout <<P << " " <<curr_value_aprox << " " << value_after_aprox <<std::endl;
708  if(P==0){
709  // ** Search for smallest possible step (largest penalty that give progress)
710  //std::cout << "Approximation does not improve energy ... searching for better lambda ... "<< std::flush;
711  lambda = findMinimalChangeBrakPoint(lambda, curState_);
712  helper_.set(lambda);
713  helper_.optimize(label);
714  //std::cout<<"set lambda to "<< lambda <<std::endl;
715 
716  helper_.evalBoth(label, curState_, lambda, value_after, value_after_aprox);
717  const ValueType P = curr_value_aprox - value_after_aprox;
718  const ValueType R = curr_value - value_after;
719  if(R<=0){
720  visitor(*this);
721  break;
722  }else if(R>0){
723  // ** Update Working Point
724  //std::cout<<"Update Working Point"<<std::endl;
725  curState_.assign(label.begin(),label.end());
726  changedWorkingpoint = true;
727  curr_value = value_after;
728  curr_value_aprox = value_after;
729  //OPENGM_ASSERT(std::fabs( curr_value_aprox-helper_.evalAprox(curState_, curState_, lambda) )<0.0001);
730  }
731  }
732  else{
733  if(P<0) std::cout << "WARNING : "<< curr_value_aprox << " < " << value_after_aprox << std::endl;
734  if(R>tau1){
735  // ** Update Working Point
736  //std::cout<<"Update Working Point"<<std::endl;
737  curState_.assign(label.begin(),label.end());
738  changedWorkingpoint = true;
739  //helper_.set(curState_,lambda);
740  curr_value = value_after;
741  curr_value_aprox = value_after;
742  //OPENGM_ASSERT(std::fabs( curr_value_aprox-helper_.evalAprox(curState_, curState_, lambda) )<0.0001);
743  }
744  }
745 
746  // ** Update trust region term
747  if(R/P>tau2){ ;
748  lambda = lambda / param_.lambdaMultiplier_;
749  changedLambda = true;
750  //helper_.set(lambda);
751  //std::cout<<"Decrease TR to "<< lambda <<std::endl;
752  }
753  else{
754  lambda = lambda * param_.lambdaMultiplier_;
755  changedLambda = true;
756  //helper_.set(lambda);
757  //std::cout<<"Increase TR to "<< lambda<<std::endl;
758  }
759 
760  // ** Store values
761  energies.push_back (curr_value);
762  energiesAprox.push_back(value_after_aprox);
763 
764  // ** Call Visitor
765  if( visitor(*this) != visitors::VisitorReturnFlag::ContinueInf ) break;
766  }
767 
768  visitor.end(*this);
769  return NORMAL;
770  }
771 
772  template<class GM, class ACC>
773  inline InferenceTermination
775  (
776  std::vector<LabelType>& x,
777  const size_t N
778  ) const
779  {
780  if(N==1) {
781  //x.resize(gm_.numberOfVariables());
782  //for (size_t i=0; i<gm_.numberOfVariables(); ++i)
783  // x[i] = curState_[i];
784  x.assign(curState_.begin(), curState_.end());
785  return NORMAL;
786  }
787  else {
788  return UNKNOWN;
789  }
790  }
791 
792 
793  template<class GM, class ACC>
794  double LSA_TR<GM,ACC>::findMinimalChangeBrakPoint(const double lambda, const std::vector<LabelType>& workingPoint){
795 
796  ValueType topLambda = lambda;
797  ValueType bottomLambda = param_.precisionLambda_;
798  std::vector<LabelType> topLabel(numVar_);
799  std::vector<LabelType> bottomLabel(numVar_);
800  std::vector<LabelType> label(numVar_);
801  // upper bound for best lambda
802  while(true){
803  helper_.set(topLambda);
804  helper_.optimize(topLabel);
805  if(!std::equal(topLabel.begin(),topLabel.end(),workingPoint.begin()))
806  topLambda = topLambda * 2;
807  else
808  break;
809  }
810 
811  // lower bound for lambda
812  helper_.set(bottomLambda);
813  helper_.optimize(bottomLabel);
814 
815  // binary search for minimal change point
816  while(true){
817  double middleLambda = (topLambda + bottomLambda)/2.0;
818  //std::cout <<"test "<< bottomLambda<<" < "<<middleLambda<<" < "<<topLambda<<std::endl;
819  helper_.set(middleLambda);
820  helper_.optimize(label);
821 
822  if(!std::equal(label.begin(),label.end(),topLabel.begin())){
823  bottomLambda = middleLambda;
824  bottomLabel = label;
825  }
826  else if(!std::equal(label.begin(),label.end(),bottomLabel.begin())){
827  topLambda = middleLambda;
828  topLabel = label;
829  }
830  else{
831  return bottomLambda;
832  }
833  if((topLambda-bottomLambda) < param_.precisionLambda_){
834  return bottomLambda;
835  }
836  }
837  }
838 
839 } // namespace opengm
840 
841 #endif // #ifndef OPENGM_LSATR_HXX
LSA_TR< _GM, ACC > type
Definition: lsatr.hxx:104
The OpenGM namespace.
Definition: config.hxx:43
GM GraphicalModelType
Definition: lsatr.hxx:95
opengm::visitors::EmptyVisitor< LSA_TR< GM, ACC > > EmptyVisitorType
Definition: lsatr.hxx:98
std::string name() const
Definition: lsatr.hxx:637
Parameter(const P &p)
Definition: lsatr.hxx:135
void set(const double)
Definition: lsatr.hxx:431
void infer(const typename INF::GraphicalModelType &gm, const typename INF::Parameter &param, std::vector< typename INF::LabelType > &conf)
Definition: inference.hxx:34
void reset()
Definition: lsatr.hxx:624
ACC AccumulationType
Definition: lsatr.hxx:94
double eval(const std::vector< LabelType > &) const
Definition: lsatr.hxx:505
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
LSA_TR< _GM, _ACC > type
Definition: lsatr.hxx:109
void init(const GM &, const std::vector< LabelType > &)
Definition: lsatr.hxx:181
virtual ValueType value() const
return the solution (value)
Definition: lsatr.hxx:158
void setDistanceType(const DISTANCE d)
Definition: lsatr.hxx:59
opengm::visitors::TimingVisitor< LSA_TR< GM, ACC > > TimingVisitorType
Definition: lsatr.hxx:99
void setStartingPoint(typename std::vector< LabelType >::const_iterator)
set initial labeling
Definition: lsatr.hxx:631
const GraphicalModelType & graphicalModel() const
Definition: lsatr.hxx:644
double optimize(std::vector< LabelType > &)
Definition: lsatr.hxx:402
double evalAprox(const std::vector< LabelType > &, const std::vector< LabelType > &, const double) const
Definition: lsatr.hxx:522
GraphicalModelType::ValueType ValueType
Definition: inference.hxx:50
Local Submodular Approximation with Trust Region regularization .
Definition: lsatr.hxx:39
Inference algorithm interface.
Definition: inference.hxx:43
virtual InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
output a solution
Definition: lsatr.hxx:775
OPENGM_GM_TYPE_TYPEDEFS
Definition: lsatr.hxx:96
LSA_TR_WeightedEdge(double aw, size_t au, size_t av)
Definition: lsatr.hxx:40
GraphicalModelType::LabelType LabelType
Definition: inference.hxx:48
opengm::visitors::VerboseVisitor< LSA_TR< GM, ACC > > VerboseVisitorType
Definition: lsatr.hxx:97
void evalBoth(const std::vector< LabelType > &label, const std::vector< LabelType > &workingPoint, const double lambda, double &value, double &valueAprox) const
Definition: lsatr.hxx:548
LSA_TR(const GraphicalModelType &)
Definition: lsatr.hxx:584
InferenceTermination infer()
Definition: lsatr.hxx:651
InferenceTermination
Definition: inference.hxx:24