00001 #pragma once
00002 #ifndef OPENGM_ICM_HXX
00003 #define OPENGM_ICM_HXX
00004
00005 #include <vector>
00006 #include <string>
00007 #include <iostream>
00008
00009 #include "opengm/opengm.hxx"
00010 #include "opengm/inference/visitors/visitor.hxx"
00011 #include "opengm/inference/inference.hxx"
00012 #include "opengm/inference/movemaker.hxx"
00013 #include "opengm/datastructures/buffer_vector.hxx"
00014
00015 namespace opengm {
00016
00020 template<class GM, class ACC>
00021 class ICM : public Inference<GM, ACC>
00022 {
00023 public:
00024 enum MoveType {
00025 SINGLE_VARIABLE = 0,
00026 FACTOR = 1
00027 };
00028 typedef ACC AccumulationType;
00029 typedef GM GraphicalModelType;
00030 OPENGM_GM_TYPE_TYPEDEFS;
00031 typedef Movemaker<GraphicalModelType> MovemakerType;
00032 typedef VerboseVisitor<ICM<GM,ACC> > VerboseVisitorType;
00033 typedef EmptyVisitor<ICM<GM,ACC> > EmptyVisitorType;
00034 typedef TimingVisitor<ICM<GM,ACC> > TimingVisitorType;
00035
00036 class Parameter {
00037 public:
00038 Parameter(
00039 const std::vector<LabelType>& startPoint
00040 )
00041 : moveType_(SINGLE_VARIABLE),
00042 startPoint_(startPoint)
00043 {}
00044
00045 Parameter(
00046 MoveType moveType,
00047 const std::vector<LabelType>& startPoint
00048 )
00049 : moveType_(moveType),
00050 startPoint_(startPoint)
00051 {}
00052
00053 Parameter(
00054 MoveType moveType = SINGLE_VARIABLE
00055 )
00056 : moveType_(moveType),
00057 startPoint_()
00058 {}
00059
00060 MoveType moveType_;
00061 std::vector<LabelType> startPoint_;
00062 };
00063
00064 ICM(const GraphicalModelType&);
00065 ICM(const GraphicalModelType&, const Parameter&);
00066 std::string name() const;
00067 const GraphicalModelType& graphicalModel() const;
00068 InferenceTermination infer();
00069 void reset();
00070 template<class VisitorType>
00071 InferenceTermination infer(VisitorType&);
00072 void setStartingPoint(typename std::vector<LabelType>::const_iterator);
00073 virtual InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const ;
00074 size_t currentMoveType() const;
00075
00076 private:
00077 const GraphicalModelType& gm_;
00078 MovemakerType movemaker_;
00079 Parameter param_;
00080 MoveType currentMoveType_;
00081
00082 };
00083
00084 template<class GM, class ACC>
00085 inline size_t
00086 ICM<GM, ACC>::currentMoveType()const{
00087 return currentMoveType_==SINGLE_VARIABLE?0:1;
00088 }
00089
00090 template<class GM, class ACC>
00091 inline
00092 ICM<GM, ACC>::ICM
00093 (
00094 const GraphicalModelType& gm
00095 )
00096 : gm_(gm),
00097 movemaker_(gm),
00098 param_(Parameter()),
00099 currentMoveType_(SINGLE_VARIABLE) {
00100 }
00101
00102 template<class GM, class ACC>
00103 ICM<GM, ACC>::ICM
00104 (
00105 const GraphicalModelType& gm,
00106 const Parameter& parameter
00107 )
00108 : gm_(gm),
00109 movemaker_(gm),
00110 param_(parameter),
00111 currentMoveType_(SINGLE_VARIABLE)
00112 {
00113 if(parameter.startPoint_.size() == gm.numberOfVariables()) {
00114 movemaker_.initialize(parameter.startPoint_.begin() );
00115 }
00116 else if(parameter.startPoint_.size() != 0) {
00117 throw RuntimeError("unsuitable starting point");
00118 }
00119 }
00120
00121 template<class GM, class ACC>
00122 inline void
00123 ICM<GM, ACC>::reset()
00124 {
00125 if(param_.startPoint_.size() == gm_.numberOfVariables()) {
00126 movemaker_.initialize(param_.startPoint_.begin() );
00127 }
00128 else if(param_.startPoint_.size() != 0) {
00129 throw RuntimeError("unsuitable starting point");
00130 }
00131 else{
00132 movemaker_.reset();
00133 }
00134 }
00135
00136 template<class GM, class ACC>
00137 inline void
00138 ICM<GM,ACC>::setStartingPoint
00139 (
00140 typename std::vector<typename ICM<GM,ACC>::LabelType>::const_iterator begin
00141 ) {
00142 movemaker_.initialize(begin);
00143 }
00144
00145 template<class GM, class ACC>
00146 inline std::string
00147 ICM<GM, ACC>::name() const
00148 {
00149 return "ICM";
00150 }
00151
00152 template<class GM, class ACC>
00153 inline const typename ICM<GM, ACC>::GraphicalModelType&
00154 ICM<GM, ACC>::graphicalModel() const
00155 {
00156 return gm_;
00157 }
00158
00159 template<class GM, class ACC>
00160 inline InferenceTermination
00161 ICM<GM,ACC>::infer()
00162 {
00163 EmptyVisitorType v;
00164 return infer(v);
00165 }
00166
00167
00168 template<class GM, class ACC>
00169 template<class VisitorType>
00170 InferenceTermination ICM<GM,ACC>::infer
00171 (
00172 VisitorType& visitor
00173 )
00174 {
00175 visitor.begin(*this,movemaker_.value(), movemaker_.value());
00176 if(param_.moveType_==SINGLE_VARIABLE ||param_.moveType_==FACTOR) {
00177 bool updates = true;
00178 std::vector<bool> isLocalOptimal(gm_.numberOfVariables());
00179 std::vector<opengm::RandomAccessSet<IndexType> >variableAdjacencyList;
00180 gm_.variableAdjacencyList(variableAdjacencyList);
00181 size_t v=0,s=0,n=0;
00182 while(updates) {
00183 updates = false;
00184 for(v=0; v<gm_.numberOfVariables(); ++v) {
00185 if(isLocalOptimal[v]==false) {
00186 for(s=0; s<gm_.numberOfLabels(v); ++s) {
00187 if(s != movemaker_.state(v)) {
00188 if(AccumulationType::bop(movemaker_.valueAfterMove(&v, &v+1, &s), movemaker_.value())) {
00189 movemaker_.move(&v, &v+1, &s);
00190 for(n=0;n<variableAdjacencyList[v].size();++n) {
00191 isLocalOptimal[variableAdjacencyList[v][n]]=false;
00192 }
00193 updates = true;
00194 visitor(*this,movemaker_.value(), movemaker_.value());
00195 }
00196 }
00197 }
00198 isLocalOptimal[v]=true;
00199 }
00200 }
00201 }
00202 }
00203 if(param_.moveType_==FACTOR) {
00204 currentMoveType_=FACTOR;
00205
00206 bool updates = true;
00207 std::vector<bool> isLocalOptimal(gm_.numberOfFactors(),false);
00208
00209 opengm::BufferVector<LabelType> stateBuffer;
00210 stateBuffer.reserve(10);
00211
00212 size_t f=0,ff=0,v=0;
00213 while(updates) {
00214 updates = false;
00215 for(f=0; f<gm_.numberOfFactors(); ++f) {
00216 if(isLocalOptimal[f]==false && gm_[f].numberOfVariables()>1) {
00217 stateBuffer.clear();
00218 stateBuffer.resize(gm_[f].numberOfVariables());
00219 for(v=0;v<gm_[f].numberOfVariables();++v) {
00220 stateBuffer[v]=movemaker_.state(gm_[f].variableIndex(v));
00221 }
00222 ValueType oldValue=movemaker_.value();
00223 ValueType newValue=movemaker_. template moveOptimally<ACC>(gm_[f].variableIndicesBegin(),gm_[f].variableIndicesEnd());
00224 if(ACC::bop(newValue,oldValue)) {
00225 updates = true ;
00226 visitor(*this,movemaker_.value(), movemaker_.value());
00227 for(v=0;v<gm_[f].numberOfVariables();++v) {
00228 const size_t varIndex=gm_[f].variableIndex(v);
00229 if(stateBuffer[v]!=movemaker_.state(varIndex)) {
00230 for(ff=0;ff<gm_.numberOfFactors(varIndex);++ff) {
00231 isLocalOptimal[gm_.factorOfVariable(varIndex,ff)]=false;
00232 }
00233 }
00234 }
00235 }
00236 isLocalOptimal[f]=true;
00237 }
00238 }
00239 }
00240 }
00241 visitor.end(*this,movemaker_.value(), movemaker_.value());
00242 return NORMAL;
00243 }
00244
00245 template<class GM, class ACC>
00246 inline InferenceTermination
00247 ICM<GM,ACC>::arg
00248 (
00249 std::vector<LabelType>& x,
00250 const size_t N
00251 ) const
00252 {
00253 if(N==1) {
00254 x.resize(gm_.numberOfVariables());
00255 for(size_t j=0; j<x.size(); ++j) {
00256 x[j] = movemaker_.state(j);
00257 }
00258 return NORMAL;
00259 }
00260 else {
00261 return UNKNOWN;
00262 }
00263 }
00264
00265 }
00266
00267 #endif // #ifndef OPENGM_ICM_HXX