OpenGM  2.3.x
Discrete Graphical Model Library
trws_subproblemsolver.hxx
Go to the documentation of this file.
1 #ifndef TRWS_SUBPROBLEMSOLVER_HXX_
2 #define TRWS_SUBPROBLEMSOLVER_HXX_
3 #include <iostream>
4 #include <list>
5 #include <algorithm>
6 #include <utility>
7 #include <functional>
8 #include <valarray>
9 
12 
13 #ifdef TRWS_DEBUG_OUTPUT
15 #endif
16 
17 namespace opengm {
18 namespace trws_base{
19 
20 #ifdef TRWS_DEBUG_OUTPUT
21 using OUT::operator <<;
22 #endif
23 
24 template<class GM>
26 {
27 public:
28  //typedef GraphicalModel GM;
29  typedef typename GM::ValueType ValueType;
30  typedef typename GM::IndexType IndexType;
31  typedef typename GM::LabelType LabelType;
32  typedef std::vector<IndexType> IndexList;
33  typedef std::vector<ValueType> UnaryFactor;
34  typedef enum{Direct,Reverse} MoveDirection;
36 
37  SequenceStorage(const GM& masterModel,const VariableToFactorMap& var2FactorMap,const IndexList& variableList, const IndexList& pwFactorList,const IndexList& numberOfTreesPerFactor);
38 
40  IndexType size()const{return (IndexType)_directIndex.size();};//<! returns number of variables in the sequence
41 
42 #ifdef TRWS_DEBUG_OUTPUT
43  void PrintTestData(std::ostream& fout)const;
44 #endif
45 
47 
48  /*
49  * Serving functions:
50  */
51  /*
52  * allocates the container (*pfactors) with sizes, corresponding to all unary factors of the associated graphoical model
53  */
54  void AllocateUnaryFactors(std::vector<UnaryFactor>* pfactors);
55  MoveDirection pwDirection(IndexType pwInd)const{assert(pwInd<_pwDirection.size()); return _pwDirection[pwInd];};
56  IndexType pwForwardFactor(IndexType var)const{assert(var<_pwForwardIndex.size()); return _pwForwardIndex[var];}
57  const GM& masterModel()const{return _masterModel;}
58  /*
59  * unary factors access
60  */
61  const UnaryFactor& unaryFactors(IndexType indx)const{assert(indx<_unaryFactors.size()); return _unaryFactors[indx];}
62  typename UnaryFactor::iterator ufBegin(IndexType indx){assert(indx<_unaryFactors.size()); return _unaryFactors[indx].begin();}
63  typename UnaryFactor::iterator ufEnd (IndexType indx){assert(indx<_unaryFactors.size()); return _unaryFactors[indx].end() ;}
64  IndexType varIndex(IndexType var)const{assert(var<_directIndex.size()); return _directIndex[var];};
65 
66  template<class ITERATOR>
67  ValueType evaluate(ITERATOR labeling);
68 private:
69  void _ConsistencyCheck();
70  void _Reset(const IndexList& numOfSequencesPerFactor);//TODO: set weights from a vector
71  void _Reset(IndexType var,IndexType numOfSequences);//TODO: set weights from a vector
72 
73  const GM& _masterModel;
75  IndexList _directIndex;
76  IndexList _pwForwardIndex;
77  std::vector<UnaryFactor> _unaryFactors;
78  std::vector<MoveDirection> _pwDirection;
79  const VariableToFactorMap& _var2FactorMap;
80 };
81 
82 //===== class FunctionParameters ========================================
83 
84 template<class GM>
86 {
87 public:
88  typedef enum {GENERAL,POTTS} FunctionType;
89  typedef typename GM::ValueType ValueType;
90 // typedef std::valarray<ValueType> ParameterStorageType;
91  typedef std::vector<ValueType> ParameterStorageType;
92  typedef typename GM::IndexType IndexType;
93  typedef typename GM::LabelType LabelType;
94 
95  FunctionParameters(const GM& gm);
96  FunctionType getFunctionType(IndexType factorId)const
97  {
98  OPENGM_ASSERT(factorId<_factorTypes.size());
99  return _factorTypes[factorId];
100  };
101  const ParameterStorageType& getFunctionParameters(IndexType factorId)const
102  {
103  // _checkConsistency();
104  OPENGM_ASSERT(factorId < _parameters.size());
105  return _parameters[factorId];
106  }
107 #ifdef TRWS_DEBUG_OUTPUT
108  void PrintStatusData(std::ostream& fout);
109 #endif
110 private:
111  void _checkConsistency() const;
112  void _getPottsParameters(const typename GM::FactorType& factor,ParameterStorageType* pstorage)const;
113  const GM& _gm;
114  std::vector<ParameterStorageType> _parameters;
115  std::vector<FunctionType> _factorTypes;
116 };
117 
118 template<class GM>
120 : _gm(gm),_parameters(_gm.numberOfFactors()),_factorTypes(_gm.numberOfFactors())
121 {
122  for (IndexType i=0;i<_gm.numberOfFactors();++i)
123  {
124  const typename GM::FactorType& f=_gm[i];
125 
126  if ((f.numberOfVariables()==2) && f.isPotts())
127  {
128  _factorTypes[i]=POTTS;
129  _getPottsParameters(f,&_parameters[i]);
130  }else _factorTypes[i]=GENERAL;
131  }
132 
133 // _checkConsistency();
134 }
135 
136 template<class GM>
138 {
139  OPENGM_ASSERT(_parameters.size()==_gm.numberOfFactors());
140  OPENGM_ASSERT(_factorTypes.size()==_gm.numberOfFactors());
141  for (size_t i=0;i<_parameters.size();++i)
142  if (_factorTypes[i]==POTTS)
143  {
144  OPENGM_ASSERT(_parameters[i].size()==2);
145  }
146 }
147 
148 template<class GM>
149 void FunctionParameters<GM>::_getPottsParameters(const typename GM::FactorType& f,ParameterStorageType* pstorage)const
150 {
151 // pstorage->resize(2,0.0);
152  pstorage->assign(2,0.0);
153  LabelType v00[]={0,0};
154  LabelType v01[]={0,1};
155  LabelType v10[]={1,0};
156  if ((f.numberOfLabels(0)>0) && (f.numberOfLabels(1)>0))
157  (*pstorage)[1]=f(&v00[0]);
158  if (f.numberOfLabels(0)>1)
159  (*pstorage)[0]=f(&v10[0])-f(&v00[0]);
160  else if (f.numberOfLabels(1)>1)
161  (*pstorage)[0]=f(&v01[0])-f(&v00[0]);
162 }
163 
164 #ifdef TRWS_DEBUG_OUTPUT
165 template<class GM>
166 void FunctionParameters<GM>:: PrintStatusData(std::ostream& fout)
167 {
168  size_t numPotts=0;
169  for (size_t i=0;i<_parameters.size();++i) numPotts+= (_factorTypes[i]==POTTS ? 1 : 0) ;
170  fout << "Total number of factors:" <<_factorTypes.size()<<std::endl;
171  fout << "Number of POTTS p/w factors:" << numPotts <<std::endl;
172 }
173 #endif
174 
175 //===== class Dynamic Programming ========================================
176 
177 template<class GM,class ACC,class InputIterator>
179 {
180 public:
181 typedef GM GMType;
182 typedef ACC ACCType;
183 typedef typename GM::ValueType ValueType;
184 typedef typename GM::IndexType IndexType;
185 typedef typename GM::LabelType LabelType;
186 
187 typedef InputIterator InputIteratorType;
189 typedef typename Storage::IndexList IndexList;
192 typedef std::vector<IndexList> IndexTable;
194 typedef typename UnaryFactor::const_iterator ConstIterator;
195 typedef typename GM::FactorType Factor;
196 typedef std::pair<typename UnaryFactor::const_iterator,typename UnaryFactor::const_iterator> const_iterators_pair;
197 
198 public:
199 static const IndexType NaN;//=std::numeric_limits<IndexType>::max();
200 
201 DynamicProgramming(Storage& storage,const FactorProperties& factorProperties,bool fastComputations=true);//:_storage(storage){};
202 //private:
204 //public:
218 void InitMove(MoveDirection movedirection){_InitMove(1.0,movedirection);};
220 virtual void Move();//performs forward move//TODO: remove virtual ?
221 virtual void PushBack();//performs a single step of the move and sums up corresponding fw-bk marginals//TODO: remove virtual ?
222 virtual void MoveBack();//performs size() steps with PushBack();//TODO: remove virtual ?
226 const_iterators_pair GetMarginals()const{return std::make_pair(_marginals[_currentUnaryIndex].begin(),_marginals[_currentUnaryIndex].end());};
227 const_iterators_pair GetMarginals(IndexType indx)const{assert(indx<_marginals.size()); return std::make_pair(_marginals[indx].begin(),_marginals[indx].end());};
228 
229 ValueType GetObjectiveValue()const{return _objectiveValue;};
230 /*
231  * Returns value of the objective partition function, corresponding to the marginals returned by GetMarginals()
232  */
233 virtual ValueType ComputeObjectiveValue()=0;//{return ACC::neutral<ValueType>();}
234 /*
235  * increases weights of the current unary factor and corresponding temporary array _currentUnaryFactor
236  * the end-begin should be defined and equal to the number of labels in the current unary factor
237  */
238 
239 virtual void IncreaseUnaryWeights(InputIteratorType begin,InputIteratorType end);
240 /*
241  * call it if you have performed operations of the move by calling Push()/PushBack() and want to have _logPartition computed correctly
242  */
243 virtual void FinalizeMove();
247 LabelType numOfLabels()const{const_iterators_pair p=GetMarginals(); return p.second-p.first;}
248 virtual void UpdateMarginals();
249 
250 virtual IndexType getNextPWId()const;
251 virtual IndexType getPrevPWId()const;
252 
253 MoveDirection getMoveDirection()const{return _moveDirection;}
254 IndexType size()const{return (IndexType)_storage.size();}
255 template<class ITERATOR>
256 ValueType evaluate(ITERATOR labeling){return _storage.evaluate(labeling);}
260 #ifdef TRWS_DEBUG_OUTPUT
261 virtual void PrintTestData(std::ostream& fout)const;
262 #endif
263 
265 
266 protected:
267 
268 void _PottsUnaryTransform(LabelType newSize,const typename FactorProperties::ParameterStorageType& params);
269 
271 void _InitMove(ValueType rho,MoveDirection movedirection);
272 virtual void _Push();//performs a single step of the move
273 void _core_InitMoves(ValueType rho,MoveDirection movedirection);
274 void _PushMessagesToFactor();//updates _currentPWFactor+=marginals
275 void _ClearMessages(UnaryFactor* pbuffer=0);//makes 0 message in each p/w pencil; updates _currentPWFactor and _marginals(begin0+1)
276 virtual void _makeLocalCopyOfPWFactor(LabelType trgsize);//makes a local copy of a p/w factor taking into account the processing order
278 virtual void _BackUpForwardMarginals(){};
279 virtual void _InitCurrentUnaryBuffer(IndexType index);
280 
281 IndexType _core_next(IndexType begin,MoveDirection dir)const;
282 IndexType _next(IndexType begin)const;
283 IndexType _previous(IndexType begin)const;
284 IndexType _nextPWIndex()const;
285 
287 Storage& _storage;
288 const FactorProperties& _factorProperties;
289 
290 std::vector<UnaryFactor> _marginals;
291 
292 ValueType _objectiveValue;
293 ValueType _rho; //current smoothing constant
294 MoveDirection _moveDirection;
296 
297 //------processing data for a current step
298 UnaryFactor _currentPWFactor;
301 //------Calculation optimizations
302 mutable UnaryFactor _unaryTemp;
304 };
305 
306 //typedef DynamicProgramming MaxSumSolver;
307 template<class GM,class ACC,class InputIterator>
308 class MaxSumSolver : public DynamicProgramming<GM,ACC,InputIterator>
309 {
310 public:
312  typedef typename parent::ValueType ValueType;
313  typedef typename parent::IndexType IndexType;
314  typedef typename parent::LabelType LabelType;
316  typedef std::vector<LabelType> LabelingType;
318  typedef typename parent::Factor Factor;
320 
321  //MaxSumSolver(Storage& storage):parent(storage){};
322  MaxSumSolver(typename parent::Storage& storage,const FactorProperties& factorProperties,bool fastComputations=true)
323  :parent(storage,factorProperties,fastComputations),
324  _labeling(parent::size(),parent::NaN)
325  // ,_factorParameters(2,0.0)
326  {};
327 
328 #ifdef TRWS_DEBUG_OUTPUT
329  void PrintTestData(std::ostream& fout)const
330  {
331  parent::PrintTestData(fout);
332  fout << "_labeling: "<<_labeling<<std::endl;
333  }
334 #endif
335 
336  ValueType ComputeObjectiveValue();
337  const LabelingType& arg(){return _labeling;}
338 
339  void FinalizeMove();
340 
341 protected:
342  void _Push();
343  void _SumUpBackwardEdges(UnaryFactor* u, LabelType fixedLabel)const;
345  LabelingType _labeling;
346  mutable UnaryFactor _marginalsTemp;
347 // mutable typename FactorProperties::ParameterStorageType _factorParameters;
348 };
349 
350 template<class GM,class ACC,class InputIterator>
352 {
353  OPENGM_ASSERT((parent::_currentUnaryIndex==0)||(parent::_currentUnaryIndex==parent::size()-1));
354  OPENGM_ASSERT(_labeling[parent::_currentUnaryIndex]<parent::_marginals[parent::_currentUnaryIndex].size());
355  //Backup _currentUnaryIndex
356  IndexType bk_currentUnaryIndex=parent::_currentUnaryIndex;
357  //... and _MoveDirection
358  typename parent::MoveDirection bk_moveDirection=parent::_moveDirection;
359  parent::_moveDirection=parent::Storage::ReverseDirection(parent::_moveDirection);
360 
361  //move to the end and compute the sum. Use View function of the GM
362  LabelType optLabel=_labeling[parent::_currentUnaryIndex];
363 
364  for (IndexType i=1;i<parent::size();++i)
365  {
366  parent::_currentUnaryIndex=parent::_next(parent::_currentUnaryIndex);
367  _marginalsTemp=parent::_marginals[parent::_currentUnaryIndex];
368  _SumUpBackwardEdges(&_marginalsTemp,optLabel);
369 
370  _labeling[parent::_currentUnaryIndex]=optLabel=std::max_element(_marginalsTemp.begin(),_marginalsTemp.end(),
371  ACC::template ibop<ValueType>)-_marginalsTemp.begin();
372  }
373 
374  //restore the _currentUnaryIndex and _MoveDirection
375  parent::_moveDirection=bk_moveDirection;
376  parent::_currentUnaryIndex=bk_currentUnaryIndex;
377 }
378 
379 template<class GM,class ACC,class InputIterator>
382 {
383  _labeling[parent::_currentUnaryIndex]=std::max_element(parent::_marginals[parent::_currentUnaryIndex].begin(),
384  parent::_marginals[parent::_currentUnaryIndex].end(),ACC::template ibop<ValueType>)
385  -parent::_marginals[parent::_currentUnaryIndex].begin();
386  return parent::_marginals[parent::_currentUnaryIndex][_labeling[parent::_currentUnaryIndex]];
387 }
388 
389 template<class GM,class ACC,class InputIterator>
391 {
392  parent::FinalizeMove();
393  _EstimateOptimalLabeling();
394 };
395 
396 template <class T,class ACC> struct compToValue : std::unary_function <T,T> {
397  compToValue(T val):_val(val){};
398  T operator() (T x) const
399  {return (ACC::template bop<T>(x,_val) ? x : _val);}
400 private:
401  T _val;
402 };
403 
404 template<class GM,class ACC,class InputIterator>
405 void DynamicProgramming<GM,ACC,InputIterator>::_PottsUnaryTransform(LabelType newSize,const typename FactorProperties::ParameterStorageType& params)
406 {
407  OPENGM_ASSERT(params.size()==2);
408  UnaryFactor* puf=&(_currentUnaryFactor);
409 
410 // if (newSize< puf->size())
411 // puf->resize(newSize);//Bug!
412 
413  typename UnaryFactor::iterator bestValIt=std::max_element(puf->begin(),puf->end(),ACC::template ibop<ValueType>);
414  ValueType bestVal=*bestValIt;
415  ValueType secondBestVal=bestVal;
416 //if (puf->size()>1){
417  if (ACC::bop(params[0],static_cast<ValueType>(0.0)))
418  {
419  *bestValIt=ACC::template neutral<ValueType>();
420  secondBestVal=*std::max_element(puf->begin(),puf->end(),ACC::template ibop<ValueType>);
421  *bestValIt=bestVal;
422  }
423 //}else{std::cout << "1: puf->size()="<<puf->size()<<std::endl;}
424 
425  transform_inplace(puf->begin(),puf->end(),compToValue<ValueType,ACC>(bestVal+params[0]));
426 
427 //if (puf->size()>1){
428  if (ACC::bop(params[0],static_cast<ValueType>(0.0)))
429  ACC::op(secondBestVal+params[0],bestVal,*bestValIt);
430 //}else{std::cout << "2: puf->size()="<<puf->size()<<std::endl;}
431 
432  if (params[1]!=0.0)
433  transform_inplace(puf->begin(),puf->end(),std::bind1st(std::plus<ValueType>(),params[1]));
434 
435  if (newSize< puf->size())
436  puf->resize(newSize);//BSD: Bug fixed?
437  else if (newSize > puf->size())
438  {
439  puf->resize(newSize,params[0]+params[1]+bestVal);
440 // std::cout <<"puf.size()="<<puf->size()<<", bestVal="<<bestVal<<", params[0]="<<params[0]<<", params[1]="<<params[1]
441 // <<", (*puf)[1]="<<(*puf)[1]<<std::endl;
442  }
443 
444 }
445 
446 template<class GM,class ACC,class InputIterator>
448 {
449  IndexType factorId=parent::_storage.pwForwardFactor(parent::_nextPWIndex());
450  if ((parent::_factorProperties.getFunctionType(factorId)==FunctionParameters<GM>::POTTS) && parent::_fastComputation)
451  {
452  parent::_currentUnaryIndex=parent::_next(parent::_currentUnaryIndex);
453  LabelType newSize=parent::_storage.unaryFactors(parent::_currentUnaryIndex).size();
454  parent::_PottsUnaryTransform(newSize,parent::_factorProperties.getFunctionParameters(factorId));
455  std::transform(parent::_currentUnaryFactor.begin(),parent::_currentUnaryFactor.end(),
456  parent::_storage.unaryFactors(parent::_currentUnaryIndex).begin(),
457  parent::_currentUnaryFactor.begin(),plus2ndMul<ValueType>(1.0/parent::_rho));
458  }else
459  parent::_Push();
460 }
461 
462 
463 //===== class SumProdSequenceSolver ========================================
464 
465 
466 template<class GM,class ACC,class InputIterator>
467 class SumProdSolver : public DynamicProgramming<GM,ACC,InputIterator>
468 {
469 public:
471 typedef typename parent::ValueType ValueType;
472 typedef typename parent::IndexType IndexType;
473 typedef typename parent::LabelType LabelType;
476 typedef typename parent::Storage Storage;
480 
481 
482 SumProdSolver(Storage& storage,const FactorProperties& factorProperties,bool fastComputations=true)
483 :parent(storage,factorProperties,fastComputations),_averagingFlag(false){ACC::op(1.0,-1.0,_mul);};
484 void InitMove(ValueType rho){parent::_InitMove(rho,Storage::Direct);};
485 void InitMove(ValueType rho,MoveDirection movedirection){parent::_InitMove(rho,movedirection);};
486 
487 ValueType ComputeObjectiveValue();
488 ValueType MoveBackGetDerivative();
489 ValueType getDerivative()const{return _derivativeValue;}
490 protected:
491 void _Push();//performs a single step of the move
492 void _ExponentiatePWFactor();//updates _currentPWFactor - exponentiation in place
493 void _PushMessagesToVariable();//sums up p/w pencils, updates _currentUnaryFactor=sum and _marginals(begin0+1) += log(_currentUnaryFactor) + _unaryFactor
494 void _PushAndAverage();//additionally to _Push performs estimation of the PW average potentials
495 void _UpdatePWAverage();
497 ValueType _GetAveragedUnaryFactors(ValueType& derivativeBound);
498 void _makeLocalCopyOfPWFactor(LabelType trgsize);//makes a local copy of a p/w factor taking into account the processing order
499 void _InitCurrentUnaryBuffer(IndexType index);
500 
501 ValueType _mul;
503 /*
504  * optimization of computations
505  */
506 
507 UnaryFactor _unaryBuffer;
508 UnaryFactor _copyPWfactor;
510 };
511 
512 
513 //=======================SequenceStorage implementation ===========================================
514 #ifdef TRWS_DEBUG_OUTPUT
515 template<class GM>
516 void SequenceStorage<GM>::PrintTestData(std::ostream& fout)const
517 {
518 fout << "_directIndex:" <<_directIndex;
519 fout << "_pwForwardIndex:" <<_pwForwardIndex;
520 fout << "_unaryFactors:" <<std::endl<<_unaryFactors;
521 fout << "_pwDirection:" << _pwDirection;
522 };
523 #endif
524 
525 template<class GM>
526 SequenceStorage<GM>::SequenceStorage(const GM& masterModel,const VariableToFactorMap& var2FactorMap,
527  const IndexList& variableList,
528  const IndexList& pwFactorList,
529  const IndexList& numOfSequencesPerFactor)//TODO: exchange to the vector of initial values
530 :_masterModel(masterModel),
531  _directIndex(variableList),
532  _pwForwardIndex(pwFactorList),
533  _pwDirection(pwFactorList.size())
534  ,_var2FactorMap(var2FactorMap)
535 {
536  _ConsistencyCheck();
537  AllocateUnaryFactors(&_unaryFactors);
538  _Reset(numOfSequencesPerFactor);//TODO: set weights from a vector
539 }
540 
541 template<class GM>
543 {
544  exception_check((_directIndex.size()-1)==_pwForwardIndex.size(),"DynamicProgramming::_ConsistencyCheck(): (_directIndex.size()-1)!=_pwForwardIndex.size()");
545 
546  LabelType v[2];
547  for (IndexType i=0;i<size()-1;++i)
548  {
549  exception_check(_masterModel[pwForwardFactor(i)].numberOfVariables()==2,"DynamicProgramming::_ConsistencyCheck():factor.numberOfVariables()!=2");
550  _masterModel[pwForwardFactor(i)].variableIndices(&v[0]);
551 
552  if (v[0]==varIndex(i))
553  {
554  exception_check(v[1]==varIndex(i+1),"DynamicProgramming::_ConsistencyCheck(): v[1]!=varIndex(i+1)");
555  _pwDirection[i]=Direct;
556  }
557  else if (v[0]==varIndex(i+1))
558  {
559  exception_check(v[1]==varIndex(i),"DynamicProgramming::_ConsistencyCheck(): v[1]!=varIndex(i)");
560  _pwDirection[i]=Reverse;
561  }
562  else
563  throw std::runtime_error("DynamicProgramming::_ConsistencyCheck(): pairwise factor does not correspond to unaries!");
564  }
565 }
566 
567 template<class GM>
568 void SequenceStorage<GM>::_Reset(const IndexList& numOfSequencesPerFactor)
569 {
570  for (IndexType var=0;var<size();++var)
571  _Reset(var,numOfSequencesPerFactor[var]);
572 };
573 
574 template<class GM>
575 void SequenceStorage<GM>::_Reset(IndexType var,IndexType numOfSequences)
576 {
577  assert(var<size());
578  UnaryFactor& uf=_unaryFactors[var];
579  _masterModel[_var2FactorMap(varIndex(var))].copyValues(uf.begin());
580  transform_inplace(uf.begin(),uf.end(),std::bind2nd(std::multiplies<ValueType>(),1.0/numOfSequences));
581 
582 };
583 
584 template<class GM>
585 void SequenceStorage<GM>::AllocateUnaryFactors(std::vector<UnaryFactor>* pfactors)
586 {
587  pfactors->resize(size());
588  for (size_t i=0;i<pfactors->size();++i)
589  (*pfactors)[i].assign(_masterModel[_var2FactorMap(varIndex(i))].size(),0.0);
590 };
591 
592 template<class GM>
594 {
595  if (dir==Direct)
596  return Reverse;
597  else
598  return Direct;
599 }
600 
601 template<class GM>
602 template<class ITERATOR>
605 {
606  ValueType value=0.0;
607  for (size_t i=0;i<size();++i)
608  {
609  value+=_unaryFactors[i][*labeling];
610  if (i<size()-1)
611  {
612  if (pwDirection(i)==Direct)
613  value+=_masterModel[_pwForwardIndex[i]](labeling);
614  else
615  {
616  std::valarray<LabelType> ind(2);
617  ind[0]=*(labeling+1); ind[1]=*labeling;
618  value+= _masterModel[_pwForwardIndex[i]](labeling);
619  }
620  }
621  ++labeling;
622  }
623  return value;
624 }
625 
626 //========================DynamicProgramming Implementation =============================================
627 template<class GM,class ACC,class InputIterator>
629 
630 template<class GM,class ACC,class InputIterator>
631 DynamicProgramming<GM,ACC,InputIterator>::DynamicProgramming(Storage& storage,const FactorProperties& factorProperties,bool fastComputation)
632 :_fastComputation(fastComputation),
633  _storage(storage),
634  _factorProperties(factorProperties),
635  _objectiveValue(0.0),
636  _rho(1.0),
637  _moveDirection(Storage::Direct),
638  _bInitializationNeeded(true),
639  _currentPWFactor(0),
640  _currentUnaryFactor(0),
641  //_currentUnaryIndex(std::numeric_limits<size_t>::max())
642  _currentUnaryIndex(NaN)
643  {
645 };
646 
647 #ifdef TRWS_DEBUG_OUTPUT
648 template<class GM,class ACC,class InputIterator>
650 {
651 fout << "_marginals:" <<std::endl<<_marginals;
652 fout << "_objectiveValue="<<_objectiveValue<<std::endl;
653 fout << "_rho="<<_rho<<std::endl;
654 fout << "_moveDirection="<< _moveDirection<<std::endl;
655 fout << "_currentPWFactor="<<_currentPWFactor;
656 fout << "_currentUnaryFactor="<<_currentUnaryFactor;
657 fout << "_currentUnaryIndex=" <<_currentUnaryIndex<<std::endl;
658 };
659 #endif
660 
661 template<class GM,class ACC,class InputIterator>
664 {
665  if (dir==Storage::Direct)
666  {
667  assert(begin<_storage.size()-1);
668  return ++begin;
669  }
670  else
671  {
672  assert((begin>0) && (begin<_storage.size()));
673  return --begin;
674  }
675 }
676 
677 template<class GM,class ACC,class InputIterator>
680 {
681  return _core_next(begin,_moveDirection);
682 }
683 
684 template<class GM,class ACC,class InputIterator>
687 {
688  if (_moveDirection==Storage::Direct)
689  return _core_next(begin,Storage::Reverse);
690  else
691  return _core_next(begin,Storage::Direct);
692 }
693 
694 template<class GM,class ACC,class InputIterator>
697 {
698  if (_moveDirection==Storage::Direct)
699  return _currentUnaryIndex;
700  else
701  return _currentUnaryIndex-1;
702 }
703 
704 //makes a local copy of a p/w factor taking into account the processing order
705 template<class GM,class ACC,class InputIterator>
707 {
708 const Factor& f=_storage.masterModel()[_storage.pwForwardFactor(_nextPWIndex())];
709 _currentPWFactor.resize(f.size());
710 if ( ((_moveDirection==Storage::Direct) && (_storage.pwDirection(_nextPWIndex())==Storage::Direct)) ||
711  ((_moveDirection==Storage::Reverse) && (_storage.pwDirection(_nextPWIndex())==Storage::Reverse)) )
712  f.copyValues(_currentPWFactor.begin());
713 else
714  f.copyValuesSwitchedOrder(_currentPWFactor.begin());
715 }
716 
717 //move unaries to fwMessages
718 template<class GM,class ACC,class InputIterator>
720 {
721  LabelType trgsize=_storage.unaryFactors(_next(_currentUnaryIndex)).size();//check asserts of _next first
722 
723  //coping pw factor to the temporary storage
724  _makeLocalCopyOfPWFactor(trgsize);
725  assert(_currentPWFactor.size()==(_currentUnaryFactor.size()*trgsize));
726 
727  if (_rho!=1.0) std::transform(_currentPWFactor.begin(),_currentPWFactor.end(),_currentPWFactor.begin(),std::bind2nd(std::multiplies<ValueType>(),1.0/_rho));
728 
729  _spst.resize(_currentUnaryFactor.size(),trgsize);
730 
731  //increase each pencil of the p/w factor to the value of the marginal
732  for (LabelType i=0;i<_currentUnaryFactor.size();++i)
733  transform_inplace(_spst.beginSrcNC(&_currentPWFactor[0],i),_spst.endSrcNC(&_currentPWFactor[0],i),std::bind2nd(std::plus<ValueType>(),_currentUnaryFactor[i]));
734 }
735 
736 template<class GM,class ACC,class InputIterator>
738 {
739  assert(index < _storage.size());
740  _currentUnaryIndex=index;
741  _currentUnaryFactor.resize(_storage.unaryFactors(_currentUnaryIndex).size());
742  std::copy(_storage.unaryFactors(_currentUnaryIndex).begin(),_storage.unaryFactors(_currentUnaryIndex).end(),_currentUnaryFactor.begin());
743 }
744 
745 template<class T,class Iterator,class Comp>
746  T _MaxNormalize_inplace(Iterator begin, Iterator end, T init,Comp comp)
747  {
748  T max=*std::max_element(begin,end,comp);
749  transform_inplace(begin,end,std::bind2nd(std::minus<T>(),max));
750  return init+max;
751  }
752 
754 //template<class GM,class ACC,class InputIterator>
755 //void DynamicProgramming<GM,ACC,InputIterator>::_ClearMessages(UnaryFactor* pbuffer)
756 //{
757 // LabelType srcsize=_storage.unaryFactors(_previous(_currentUnaryIndex)).size();//check asserts of _previous first
758 //
759 // _spst.resize(srcsize,_currentUnaryFactor.size());
760 //
761 // if (pbuffer==0)
762 // {
763 // for (LabelType i=0;i<_currentUnaryFactor.size();++i)
764 // _currentUnaryFactor[i]+=_MaxNormalize_inplace(_spst.beginTrgNC(&_currentPWFactor[0],i),_spst.endTrgNC(&_currentPWFactor[0],i),(ValueType)0.0,ACC::template ibop<ValueType>);
765 // }
766 // else
767 // {
768 // pbuffer->resize(_currentUnaryFactor.size());
769 // for (LabelType i=0;i<_currentUnaryFactor.size();++i)
770 // _currentUnaryFactor[i]+=(*pbuffer)[i]=_MaxNormalize_inplace(_spst.beginTrgNC(&_currentPWFactor[0],i),_spst.endTrgNC(&_currentPWFactor[0],i),(ValueType)0.0,ACC::template ibop<ValueType>);
771 // }
772 //}
773 
774 //clear bkMessages
775 template<class GM,class ACC,class InputIterator>
777 {
778  LabelType srcsize=_storage.unaryFactors(_previous(_currentUnaryIndex)).size();//check asserts of _previous first
779 
780  _spst.resize(srcsize,_currentUnaryFactor.size());
781 
782  if (pbuffer==0)
783  {
784  for (LabelType i=0;i<_currentUnaryFactor.size();++i)
785  _currentUnaryFactor[i]+=_MaxNormalize_inplace(_spst.beginTrgNC(&_currentPWFactor[0],i),_spst.endTrgNC(&_currentPWFactor[0],i),(ValueType)0.0,ACC::template ibop<ValueType>);
786  }
787  else
788  {
789  pbuffer->resize(_currentUnaryFactor.size());
790  for (LabelType i=0;i<_currentUnaryFactor.size();++i)
791  {
792  (*pbuffer)[i]=(_currentUnaryFactor[i]+=_MaxNormalize_inplace(_spst.beginTrgNC(&_currentPWFactor[0],i),_spst.endTrgNC(&_currentPWFactor[0],i),(ValueType)0.0,ACC::template ibop<ValueType>));
793  //_currentUnaryFactor[i]+=_MaxNormalize_inplace(_spst.beginTrgNC(&_currentPWFactor[0],i),_spst.endTrgNC(&_currentPWFactor[0],i),(ValueType)0.0,ACC::template ibop<ValueType>);
794  //(*pbuffer)[i]=_currentUnaryFactor[i];
795  }
796  }
797 }
798 
799 template<class GM,class ACC,class InputIterator>
801 {
802  //move unaries to fwMessages
803  _PushMessagesToFactor();//updates _currentPWFactor[pencil i]+=_currentUnaryFactor[i]
804  _InitCurrentUnaryBuffer(_next(_currentUnaryIndex));
805  //clear bkMessages
806  _ClearMessages();//updates _currentPWFactor, that each pencil contains 0 and _currUnaryFactor = unaryFactor/rho + pencil normalization
807  _BackUpForwardMarginals();//TODO: check me!
808 }
809 
810 template<class GM,class ACC,class InputIterator>
812 {
813  std::copy(_currentUnaryFactor.begin(),_currentUnaryFactor.end(),_marginals[_currentUnaryIndex].begin());
814 }
815 
816 template<class GM,class ACC,class InputIterator>
818 {
819  UnaryFactor& marginals=_marginals[_currentUnaryIndex];
820  std::transform(_currentUnaryFactor.begin(),_currentUnaryFactor.end(),marginals.begin(),marginals.begin(),std::plus<ValueType>());
821  std::transform(marginals.begin(),marginals.end(),_storage.unaryFactors(_currentUnaryIndex).begin(),marginals.begin(),plus2ndMul<ValueType>(-1.0/_rho));
822 }
823 
824 //performs forward move
825 template<class GM,class ACC,class InputIterator>
827 {
828  if (_bInitializationNeeded)
829  {
830  InitReverseMove();
831  _bInitializationNeeded=false;
832  }
833  //push
834  for (IndexType i=0;i<_storage.size()-1;++i)
835  {
836  _Push();
837  UpdateMarginals();
838  }
839 
840  //_NormalizeMarginals();
841  FinalizeMove();
842 }
843 
847 template<class GM,class ACC,class InputIterator>
849 {
850  if (_bInitializationNeeded)
851  {
852  _InitReverseMoveBack();
853  }
854 
855  _Push();
856  _SumUpBufferToMarginals();
857 }
858 
862 template<class GM,class ACC,class InputIterator>
864 {
865 //push
866  for (IndexType i=0;i<_storage.size()-1;++i)
867  PushBack();
868 
869  FinalizeMove();
870 }
871 
872 template<class GM,class ACC,class InputIterator>
874 {
875  _rho=rho;
876  _moveDirection=movedirection;
877 
878  if (_moveDirection==Storage::Direct)
879  _InitCurrentUnaryBuffer(0);
880  else
881  _InitCurrentUnaryBuffer(_storage.size()-1);
882 
883  _bInitializationNeeded=false;
884  //ComputeObjectiveValue();//initializes _labeling
885 }
886 
887 template<class GM,class ACC,class InputIterator>
889 {
890  _core_InitMoves(rho,movedirection);
891 
892  UpdateMarginals();
893 }
894 
895 template<class GM,class ACC,class InputIterator>
897 {
898  _objectiveValue=ComputeObjectiveValue();
899  _bInitializationNeeded=true;
900 };
901 
902 //template<class InputIterator>
903 template<class GM,class ACC,class InputIterator>
905 {
906  exception_check((LabelType)abs(end-begin)==_storage.unaryFactors(_currentUnaryIndex).size(),"SumProdSequenceTRWSSolver::IncreaseUnaryWeights(): (end-begin)!=unaryFactor.size()");
907 
908  std::transform(begin,end,_storage.ufBegin(_currentUnaryIndex),_storage.ufBegin(_currentUnaryIndex),std::plus<ValueType>());
909  std::transform(_currentUnaryFactor.begin(),_currentUnaryFactor.end(),begin,_currentUnaryFactor.begin(),plus2ndMul<ValueType>(1.0/_rho));
910 }
911 
912 template<class GM,class ACC,class InputIterator>
915 {
916  if (_currentUnaryIndex >= _storage.size()) return NaN;
917 
918  if (_moveDirection==Storage::Direct)
919  return (_currentUnaryIndex==0 ? NaN : _storage.pwForwardFactor(_currentUnaryIndex-1));
920  else
921  return (_currentUnaryIndex==_storage.size()-1 ? NaN : _storage.pwForwardFactor(_currentUnaryIndex));
922 }
923 
924 template<class GM,class ACC,class InputIterator>
927 {
928  if (_currentUnaryIndex >= (IndexType)_storage.size()) return NaN;
929 
930  if (_moveDirection==Storage::Direct)
931  return (_currentUnaryIndex==_storage.size()-1 ? NaN : _storage.pwForwardFactor(_currentUnaryIndex));
932  else
933  return (_currentUnaryIndex==0 ? NaN : _storage.pwForwardFactor(_currentUnaryIndex-1));
934 }
935 
936 template<class T,class InputIterator,class OutputIterator,class Comp >
937 T _MaxNormalize(InputIterator begin, InputIterator end, OutputIterator outBegin, T init,Comp comp)
938 {
939  T max=*std::max_element(begin,end,comp);
940  std::transform(begin,end,outBegin,std::bind2nd(std::minus<T>(),max));
941  return init+max;
942 }
943 
944 template<class Iterator,class T>
945 T _MulNormalize(Iterator begin,Iterator end,T initialValue)
946 {
947  T acc=std::accumulate(begin,end,(T)0.0);
948  std::transform(begin,end,begin,std::bind1st(std::multiplies<T>(),1.0/acc));
949  return initialValue+acc;
950 };
951 
952 //template<class ValueType, class InputIterator, class OutputIterator>
953 //ValueType ComputeLogPartitionAndMarginals(InputIterator _begin,InputIterator _end,
954 // OutputIterator _out,ValueType _mul,ValueType _rho)// _out must be allocated as (_end-_begin)
955 //{
956 // InputIterator begin=_begin,
957 // end=_end;
958 // OutputIterator out_end=_out+(_end-_begin);
959 // //ValueType logPartition= _rho*_MaxNormalize(begin,end,_out,(ValueType)0.0,ACC::template ibop<ValueType>);
960 // ValueType logPartition= _rho*_MaxNormalize(begin,end,_out,(ValueType)0.0,std::greater<ValueType>());
961 // std::transform(_out,out_end,_out,mulAndExp<ValueType>(_mul));
962 // logPartition+=_mul*_rho*(log(std::accumulate(_out,out_end,(ValueType)0.0)));
963 // _MulNormalize(_out,out_end,(ValueType)0);
964 // return logPartition;
965 //}
966 
967 template<class GM,class ACC,class InputIterator>
969 {
970  UnaryFactor& u=*pu;
971  IndexType factorId=parent::getPrevPWId();
972  OPENGM_ASSERT(factorId!=parent::NaN);
973 
974  if ((parent::_factorProperties.getFunctionType(factorId)==FunctionParameters<GM>::POTTS) && parent::_fastComputation)
975  {
976  if (fixedLabel<u.size())
977  u[fixedLabel]-=parent::_factorProperties.getFunctionParameters(factorId)[0];//instead of adding everywhere the same we just subtract the difference
978 // else
979 // transform_inplace(u.begin(),u.end(),std::bind2nd(std::plus<ValueType>(),parent::_factorProperties.getFunctionParameters(factorId)[0]));
980  }else
981  {
982  const typename GM::FactorType& pwfactor=parent::_storage.masterModel()[factorId];
983 
984  OPENGM_ASSERT( (parent::_storage.varIndex(parent::_currentUnaryIndex)==pwfactor.variableIndex(0)) || (parent::_storage.varIndex(parent::_currentUnaryIndex)==pwfactor.variableIndex(1)));
985 
986  IndexType localVarIndx = (parent::_storage.varIndex(parent::_currentUnaryIndex)==pwfactor.variableIndex(0) ? 1 : 0);
987  opengm::ViewFixVariablesFunction<GM> pencil(pwfactor,
988  std::vector<opengm::PositionAndLabel<IndexType,LabelType> >(1,
989  opengm::PositionAndLabel<IndexType,LabelType>(localVarIndx,
990  fixedLabel)));
991 
992  for (LabelType j=0;j<u.size();++j)
993  u[j]+=pencil(&j);
994  }
995 }
996 
997 //========================SumProdSolver Implementation =============================================
998 
999 template<class GM,class ACC,class InputIterator>
1001 {
1002  LabelType srcsize=parent::_marginals[parent::_previous(parent::_currentUnaryIndex)].size();//check asserts of _previous first
1003 
1004  parent::_spst.resize(srcsize,parent::_currentUnaryFactor.size());
1005 
1006  //sum up for each pencil
1007  for (LabelType i=0;i<parent::_currentUnaryFactor.size();++i)
1008  parent::_currentUnaryFactor[i]+=_mul*log(std::accumulate(parent::_spst.beginTrg(&parent::_currentPWFactor[0],i),parent::_spst.endTrg(&parent::_currentPWFactor[0],i),ValueType(0.0)));//TODO: multiply by mul!
1009 }
1010 
1011 //template<class GM,class ACC,class InputIterator>
1012 //void SumProdSolver<GM,ACC,InputIterator>::_UpdatePWAverage()
1013 //{
1014 // std::transform(_unaryBuffer.begin(),_unaryBuffer.end(),parent::_marginals[parent::_currentUnaryIndex].begin(),
1015 // _unaryBuffer.begin(),std::plus<ValueType>());//adding logarithms of the right-hand side
1016 //
1017 // transform_inplace(_unaryBuffer.begin(),_unaryBuffer.end(),std::bind2nd(std::minus<ValueType>(),_getMarginalsLogNormalizer()));//normalize
1018 // transform_inplace(_unaryBuffer.begin(),_unaryBuffer.end(),mulAndExp<ValueType>(_mul));
1019 //
1020 // LabelType srcsize=parent::_marginals[parent::_previous(parent::_currentUnaryIndex)].size();
1021 // parent::_spst.resize(srcsize,parent::_currentUnaryFactor.size());
1022 //
1023 // //sum up for each pencil
1024 // for (LabelType i=0;i<parent::_currentUnaryFactor.size();++i)
1025 // _unaryBuffer[i]*=std::inner_product(parent::_spst.beginTrg(&parent::_currentPWFactor[0],i),
1026 // parent::_spst.endTrg(&parent::_currentPWFactor[0],i),
1027 // parent::_spst.beginTrg(&_copyPWfactor[0],i),
1028 // ValueType(0.0));
1029 //
1030 // _derivativeValue+=std::accumulate(_unaryBuffer.begin(),_unaryBuffer.end(),(ValueType)0.0);//sum up. It is already divided by rho and taken with the correct sign due to _copyPWfactor
1031 //}
1032 
1033 template<class GM,class ACC,class InputIterator>
1035 {
1036  std::transform(_unaryBuffer.begin(),_unaryBuffer.end(),parent::_marginals[parent::_currentUnaryIndex].begin(),
1037  _unaryBuffer.begin(),std::plus<ValueType>());//adding logarithms of the right-hand side
1038  std::transform(_unaryBuffer.begin(),_unaryBuffer.end(),parent::_storage.unaryFactors(parent::_currentUnaryIndex).begin(),_unaryBuffer.begin(),plus2ndMul<ValueType>(-1.0/parent::_rho));
1039 
1040  _MaxNormalize_inplace(_unaryBuffer.begin(),_unaryBuffer.end(),(ValueType)0.0,ACC::template ibop<ValueType>);
1041  transform_inplace(_unaryBuffer.begin(),_unaryBuffer.end(),mulAndExp<ValueType>(_mul));
1042 
1043  //std::cout <<"_unaryBuffer="<< _unaryBuffer;//BSD
1044 
1045  UnaryFactor tmpbuf(_unaryBuffer); //TODO BSD: make it faster if needed
1046 
1047  LabelType srcsize=parent::_marginals[parent::_previous(parent::_currentUnaryIndex)].size();
1048  parent::_spst.resize(srcsize,parent::_currentUnaryFactor.size());
1049 
1050  //sum up for each pencil
1051  for (LabelType i=0;i<parent::_currentUnaryFactor.size();++i)
1052  {
1053  tmpbuf[i]*=std::accumulate(parent::_spst.beginTrg(&parent::_currentPWFactor[0],i),
1054  parent::_spst.endTrg(&parent::_currentPWFactor[0],i),(ValueType)0.0);
1055  _unaryBuffer[i]*=std::inner_product(parent::_spst.beginTrg(&parent::_currentPWFactor[0],i),
1056  parent::_spst.endTrg(&parent::_currentPWFactor[0],i),
1057  parent::_spst.beginTrg(&_copyPWfactor[0],i),
1058  ValueType(0.0));
1059  }
1060 
1061  //std::cout <<"tmpbuf="<< tmpbuf;//BSD
1062 
1063  ValueType acc=(std::accumulate(tmpbuf.begin(),tmpbuf.end(),(ValueType)0.0));
1064  OPENGM_ASSERT(acc>0.0);
1065 
1066  //std::cout << "acc=" << acc <<std::endl;
1067 
1068  acc=1.0/acc;
1069  _derivativeValue+=acc*std::accumulate(_unaryBuffer.begin(),_unaryBuffer.end(),(ValueType)0.0);//sum up. It is already divided by rho and taken with the correct sign due to _copyPWfactor
1070 
1071 }
1072 
1073 template <class T,class ACC> struct thresholdMulAndExp : std::unary_function <T,T> {
1074  thresholdMulAndExp(T threshold):_mul(ACC::template bop<T>(1.0,0.0) ? 1.0 : -1.0),_threshold(threshold){};
1076  {_buf=fabs(x); return (_buf >= _threshold ? 0.0 : exp(-_buf));}
1077 private:
1078  T _mul;
1079  T _threshold;
1080  T _buf;
1081 };
1082 
1083 //template<class GM,class ACC,class InputIterator>
1084 //void SumProdSolver<GM,ACC,InputIterator>::_UpdatePWAverage()
1085 //{
1086 // _unaryBuffer=parent::_currentPWFactor;//TODO: speed-up, if needed
1087 // LabelType trgsize=parent::_storage.unaryFactors(parent::_next(parent::_currentUnaryIndex)).size();
1088 // parent::_spst.resize(parent::_currentUnaryFactor.size(),trgsize);
1089 //
1090 // UnaryFactor& marginals=parent::_marginals[parent::_next(parent::_currentUnaryIndex)];
1091 //
1092 // OPENGM_ASSERT(marginals.size()==trgsize);
1093 //
1094 // for (LabelType i=0;i<trgsize;++i)
1095 // transform_inplace(parent::_spst.beginTrgNC(&_unaryBuffer[0],i)
1096 // ,parent::_spst.endTrgNC(&_unaryBuffer[0],i)
1097 // ,std::bind2nd(std::plus<ValueType>(),marginals[i]));
1098 //
1099 // _MaxNormalize_inplace(_unaryBuffer.begin(),_unaryBuffer.end(),(ValueType)0.0,ACC::template ibop<ValueType>);
1100 // transform_inplace(_unaryBuffer.begin(),_unaryBuffer.end(),thresholdMulAndExp<ValueType,ACC>(-log(std::numeric_limits<ValueType>::epsilon())));
1101 // ValueType acc=std::accumulate(_unaryBuffer.begin(),_unaryBuffer.end(),(ValueType)0.0);
1102 // OPENGM_ASSERT(acc>0);
1103 // std::cout << "pairwise acc=" << acc <<std::endl;
1104 // acc=1.0/acc;
1105 // _derivativeValue+=acc*std::inner_product(_unaryBuffer.begin(),_unaryBuffer.end(),_copyPWfactor.begin(),(ValueType)0.0);
1106 //}
1107 
1108 template<class GM,class ACC,class InputIterator>
1110 {
1111  //move unaries to fwMessages
1112  parent::_PushMessagesToFactor();//updates _currentPWFactor[pencil i]+=_currentUnaryFactor[i]
1113 
1114  //_UpdatePWAverage();
1115 
1116  _InitCurrentUnaryBuffer(parent::_next(parent::_currentUnaryIndex));
1117 
1118  //clear bkMessages
1119  parent::_ClearMessages(&_unaryBuffer);//updates _currentPWFactor, that each pencil contains 0 and _currUnaryFactor = unaryFactor/rho + pencil normalization
1120  //parent::_ClearMessages();
1121 
1122  //exponentiate p/w factor
1123  _ExponentiatePWFactor();//updates _currentPWFactor - exponentiation in place
1124 
1125  _UpdatePWAverage();//here we suppose, that logPartition is already computed, as this has to be a backward move
1126 
1127  //sum up, logarithm and add
1128  _PushMessagesToVariable();// updates _currentUnaryFactor+=log(sum Exp(p/w pencil))
1129 
1130 }
1131 
1132 template<class GM,class ACC,class InputIterator>
1135 {
1136  ValueType unaryAverage=0.0;
1137 
1138 // ValueType oldunary=unaryAverage;//BSD
1139 
1140 
1141  derivativeBound=0;
1142 
1143  for (size_t i=0;i<parent::size();++i)
1144  {
1145  _unaryBuffer.resize(parent::_marginals[i].size());
1146 
1147 // std::cout << "parent::_marginals[i]=" << parent::_marginals[i];//BSD
1148 
1149  //ComputeLogPartitionAndMarginals(parent::_marginals[i].begin(),parent::_marginals[i].end(),_unaryBuffer.begin(),_mul,parent::_rho);
1150  _MaxNormalize(parent::_marginals[i].begin(),parent::_marginals[i].end(),_unaryBuffer.begin(),(ValueType)0.0,ACC::template ibop<ValueType>);
1151  //std::transform(_unaryBuffer.begin(),_unaryBuffer.end(),_unaryBuffer.begin(),mulAndExp<ValueType>(_mul));
1152  std::transform(_unaryBuffer.begin(),_unaryBuffer.end(),_unaryBuffer.begin(),thresholdMulAndExp<ValueType,ACC>(-log(std::numeric_limits<ValueType>::epsilon())));
1153  ValueType acc=std::accumulate(_unaryBuffer.begin(),_unaryBuffer.end(),(ValueType)0.0);
1154  OPENGM_ASSERT(acc>0);
1155 
1157 
1158  //derivativeBound+=log(acc);
1159  derivativeBound+=log(_unaryBuffer.size()-std::count(_unaryBuffer.begin(),_unaryBuffer.end(),(ValueType)0.0));
1160 
1161  acc=1.0/acc;
1162  unaryAverage+=acc*std::inner_product(_unaryBuffer.begin(),_unaryBuffer.end(),parent::_storage.unaryFactors(i).begin(),(ValueType)0.0);
1163 
1164 
1165 // if (fabs(unaryAverage-oldunary) > 0)//BSD
1166 // {
1167 // std::cout << "_objectiveValue=" << parent::_objectiveValue<<std::endl;//BSD
1168 // std::cout << "_getMarginalsLogNormalizer=" << _getMarginalsLogNormalizer()<<std::endl;//BSD
1169 // std::cout << "after exp: _unaryBuffer=" <<_unaryBuffer;//BSD
1170 // std::cout << "parent::_storage.unaryFactors(i)=" <<parent::_storage.unaryFactors(i);//BSD
1171 // std::cout<<"uf="<< i<<", oldunary=" <<oldunary << ", unaryAverage="<< unaryAverage <<std::endl;//BSD
1172 // }
1173 // oldunary=unaryAverage;//BSD
1174  }
1175  return unaryAverage;
1176 }
1177 
1178 
1179 //template<class GM,class ACC,class InputIterator>
1180 //typename SumProdSolver<GM,ACC,InputIterator>::ValueType
1181 //SumProdSolver<GM,ACC,InputIterator>::_GetAveragedUnaryFactors()
1182 //{
1183 // ValueType unaryAverage=0.0;
1184 //
1185 // ValueType oldunary=unaryAverage;//BSD
1186 //
1187 // for (size_t i=0;i<parent::size();++i)
1188 // {
1189 // _unaryBuffer.resize(parent::_marginals[i].size());
1190 //
1191 // std::cout << "parent::_marginals[i]=" << parent::_marginals[i];//BSD
1192 //
1193 // std::transform(parent::_marginals[i].begin(),parent::_marginals[i].end(),_unaryBuffer.begin(),std::bind2nd(std::minus<ValueType>(),_getMarginalsLogNormalizer()));
1194 //
1195 // std::cout << "before exp: _unaryBuffer=" <<_unaryBuffer;//BSD
1196 //
1197 // transform_inplace(_unaryBuffer.begin(),_unaryBuffer.end(),mulAndExp<ValueType>(_mul));
1198 //
1199 // unaryAverage+=std::inner_product(_unaryBuffer.begin(),_unaryBuffer.end(),parent::_storage.unaryFactors(i).begin(),(ValueType)0.0);
1200 //
1201 //
1202 // //if (fabs(unaryAverage-oldunary) > 1e+5)//BSD
1203 // if (fabs(unaryAverage-oldunary) > 0)//BSD
1204 // {
1205 // std::cout << "_objectiveValue=" << parent::_objectiveValue<<std::endl;//BSD
1206 // std::cout << "_getMarginalsLogNormalizer=" << _getMarginalsLogNormalizer()<<std::endl;//BSD
1207 // std::cout << "after exp: _unaryBuffer=" <<_unaryBuffer;//BSD
1208 // std::cout << "parent::_storage.unaryFactors(i)=" <<parent::_storage.unaryFactors(i);//BSD
1209 // std::cout<<"uf="<< i<<", oldunary=" <<oldunary << ", unaryAverage="<< unaryAverage <<std::endl;//BSD
1210 // }
1211 // oldunary=unaryAverage;//BSD
1212 // }
1213 // return unaryAverage;
1214 //}
1215 
1216 template<class GM,class ACC,class InputIterator>
1219 {
1220 if (parent::_bInitializationNeeded)
1221 {
1222  parent::_InitReverseMoveBack();
1223 }
1224 
1225 _averagingFlag=true;
1226 _derivativeValue=0.0;
1227 
1228 ValueType oldderiv=_derivativeValue;//BSD
1229 
1230 for (size_t i=0;i<parent::size()-1;++i)
1231  {
1232  _PushAndAverage();
1233  parent::_SumUpBufferToMarginals();
1234 
1235 // if (fabs(_derivativeValue-oldderiv) > 0)//BSD
1236 // std::cout<<"pw="<<i << ", oldderiv=" <<oldderiv << ", _derivativeValue="<< _derivativeValue <<std::endl;//BSD
1237 // oldderiv=_derivativeValue;//BSD
1238  }
1239 
1240 ValueType derivativeBound;
1241  _derivativeValue+=_GetAveragedUnaryFactors(derivativeBound);
1242 
1243 // if (fabs(_derivativeValue-oldderiv) > 0)//BSD
1244 // std::cout<<"uf"<< ", oldderiv=" <<oldderiv << ", _derivativeValue="<< _derivativeValue <<std::endl;//BSD
1245 
1246  parent::FinalizeMove();
1247  _averagingFlag=false;
1248 
1249 // std::cout << "_dV=" << _derivativeValue << ", parent::GetObjectiveValue()=" << parent::GetObjectiveValue()
1250 // << ", (parent::GetObjectiveValue()-_derivativeValue)=" << (parent::GetObjectiveValue()-_derivativeValue) <<std::endl;//BSD
1251 
1252  _derivativeValue=(parent::GetObjectiveValue()-_derivativeValue)/parent::_rho;
1253 
1254  //std::cout<<"_mul="<< _mul<< ", derivativeBound="<<-derivativeBound<<", _derivativeValue="<<_derivativeValue;//BSD
1255 
1256  ACC::iop(_derivativeValue,_mul*derivativeBound,_derivativeValue);
1257 
1258  //std::cout << ", result="<<_derivativeValue<<std::endl;//BSD
1259 
1260  return _derivativeValue;
1261 }
1262 
1263 template<class GM,class ACC,class InputIterator>
1265 {
1266  parent::_Push();
1267 
1268  //exponentiate p/w factor
1269  _ExponentiatePWFactor();//updates _currentPWFactor - exponentiation in place
1270 
1271  //sum up, logarithm and add
1272  _PushMessagesToVariable();// updates _currentUnaryFactor+=log(sum Exp(p/w pencil))
1273 }
1274 
1275 //exponentiates the temporary p/w factor in place
1276 template<class GM,class ACC,class InputIterator>
1278 {
1279  transform_inplace(parent::_currentPWFactor.begin(),parent::_currentPWFactor.end(),thresholdMulAndExp<ValueType,ACC>(-log(std::numeric_limits<ValueType>::epsilon())));
1280 }
1281 
1282 //uses _currentUnaryFactor as a buffer for computations
1283 template<class GM,class ACC,class InputIterator>
1286 {
1287  typename UnaryFactor::const_iterator begin=parent::_marginals[parent::_currentUnaryIndex].begin(),
1288  end=parent::_marginals[parent::_currentUnaryIndex].end();
1289  parent::_unaryTemp.resize(end-begin);
1290  ValueType logPartition= parent::_rho*_MaxNormalize(begin,end,parent::_unaryTemp.begin(),(ValueType)0.0,ACC::template ibop<ValueType>);
1291  std::transform(parent::_unaryTemp.begin(),parent::_unaryTemp.end(),parent::_unaryTemp.begin(),mulAndExp<ValueType>(_mul));
1292  logPartition+=_mul*parent::_rho*(log(std::accumulate(parent::_unaryTemp.begin(),parent::_unaryTemp.end(),(ValueType)0.0)));
1293  return logPartition;
1294 }
1295 
1296 
1297 template<class GM,class ACC,class InputIterator>
1299 {
1300  parent::_makeLocalCopyOfPWFactor(trgsize);
1301  if (_averagingFlag)
1302  _copyPWfactor=parent::_currentPWFactor;//TODO: optimization may be needed - instead of the memory reallocation just copy in it, as soon as enough space provided
1303 }
1304 
1305 template<class GM,class ACC,class InputIterator>
1307 {
1308  parent::_InitCurrentUnaryBuffer(index);
1309 
1310  if (parent::_rho!=1.0) transform_inplace(parent::_currentUnaryFactor.begin(),parent::_currentUnaryFactor.end(),std::bind2nd(std::multiplies<ValueType>(),1.0/parent::_rho));
1311 }
1312 
1313 };//namespace trws_base
1314 } //namespace opengm
1315 
1316 #endif /* ITERATIVESOLVERTRWS_H_ */
UnaryFactor::iterator ufBegin(IndexType indx)
>const access
void AllocateUnaryFactors(std::vector< UnaryFactor > *pfactors)
IndexType pwForwardFactor(IndexType var) const
IndexType varIndex(IndexType var) const
>non-const access
DynamicProgramming< GM, ACC, InputIterator > parent
The OpenGM namespace.
Definition: config.hxx:43
void exception_check(bool condition, const std::string &str)
Definition: utilities2.hxx:90
T _MaxNormalize(InputIterator begin, InputIterator end, OutputIterator outBegin, T init, Comp comp)
UnaryFactor::iterator ufEnd(IndexType indx)
>non-const access TODO: make a pair of iterators from a single function call
FunctionType getFunctionType(IndexType factorId) const
parent::const_iterators_pair const_iterators_pair
ValueType _GetAveragedUnaryFactors(ValueType &derivativeBound)
subtract it if you want to get normalized log-marginals from non-normalized ones
virtual void Move()
>initializes move, which is reverse to the current one//TODO: remove virtual ?
VariableToFactorMapping< GM > VariableToFactorMap
MaxSumSolver(typename parent::Storage &storage, const FactorProperties &factorProperties, bool fastComputations=true)
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
MoveDirection getMoveDirection() const
returns an external (_gm[.]) pairwise index, which is in front of the current variable. For the first variable this::NaN is returned
virtual void _InitCurrentUnaryBuffer(IndexType index)
virtual ValueType ComputeObjectiveValue()=0
parent::FactorProperties FactorProperties
static MoveDirection ReverseDirection(MoveDirection dir)
InputIterator transform_inplace(InputIterator first, InputIterator last, UnaryOperator op)
Definition: utilities2.hxx:79
T _MulNormalize(Iterator begin, Iterator end, T initialValue)
const UnaryFactor & unaryFactors(IndexType indx) const
virtual void _makeLocalCopyOfPWFactor(LabelType trgsize)
void _PottsUnaryTransform(LabelType newSize, const typename FactorProperties::ParameterStorageType &params)
virtual IndexType getPrevPWId() const
returns an external (_gm[.]) pairwise index, which follows the current variable. For the last variabl...
GraphicalModelType::IndexType IndexType
Definition: inference.hxx:40
void _ClearMessages(UnaryFactor *pbuffer=0)
DynamicProgramming< GM, ACC, InputIterator > parent
const ParameterStorageType & getFunctionParameters(IndexType factorId) const
void _InitMove(ValueType rho, MoveDirection movedirection)
>initializes move, which is reverse to the current one
IndexType _previous(IndexType begin) const
DynamicProgramming(Storage &storage, const FactorProperties &factorProperties, bool fastComputations=true)
virtual void IncreaseUnaryWeights(InputIteratorType begin, InputIteratorType end)
parent::InputIteratorType InputIteratorType
void InitMove(MoveDirection movedirection)
MoveDirection pwDirection(IndexType pwInd) const
SumProdSolver(Storage &storage, const FactorProperties &factorProperties, bool fastComputations=true)
ValueType getDerivative() const
>makes MoveBack and returns derivative w.r.t. _smoothingValue
const_iterators_pair GetMarginals(IndexType indx) const
void _SumUpBackwardEdges(UnaryFactor *u, LabelType fixedLabel) const
std::pair< typename UnaryFactor::const_iterator, typename UnaryFactor::const_iterator > const_iterators_pair
ValueType evaluate(ITERATOR labeling)
void _core_InitMoves(ValueType rho, MoveDirection movedirection)
parent::FactorProperties FactorProperties
virtual IndexType getNextPWId() const
updates marginals in the current node so, that they correspond to the forward (backward) accumulated ...
Funcion that refers to a factor of another GraphicalModel in which some variables are fixed...
IndexType _next(IndexType begin) const
void InitMove(ValueType rho, MoveDirection movedirection)
const_iterators_pair GetMarginals() const
SequenceStorage(const GM &masterModel, const VariableToFactorMap &var2FactorMap, const IndexList &variableList, const IndexList &pwFactorList, const IndexList &numberOfTreesPerFactor)
parent::InputIteratorType InputIteratorType
IndexType _core_next(IndexType begin, MoveDirection dir) const
T _MaxNormalize_inplace(Iterator begin, Iterator end, T init, Comp comp)
void _makeLocalCopyOfPWFactor(LabelType trgsize)
T abs(const T &x)
Definition: opengm.hxx:111