00001 #pragma once
00002 #ifndef OPENGM_LOC_HXX
00003 #define OPENGM_LOC_HXX
00004
00005 #include <vector>
00006 #include <algorithm>
00007 #include <string>
00008 #include <iostream>
00009 #include <iomanip>
00010 #include <cstdlib>
00011 #include <cmath>
00012 #include <queue>
00013
00014 #include "opengm/opengm.hxx"
00015 #include "opengm/utilities/random.hxx"
00016 #include "opengm/inference/inference.hxx"
00017 #include "opengm/inference/movemaker.hxx"
00018 #include "opengm/inference/astar.hxx"
00019 #include "opengm/inference/visitors/visitor.hxx"
00020
00021 namespace opengm {
00031 template<class GM, class ACC>
00032 class LOC : public Inference<GM, ACC> {
00033 public:
00034 typedef ACC AccumulationType;
00035 typedef GM GraphicalModelType;
00036 OPENGM_GM_TYPE_TYPEDEFS;
00037 typedef Movemaker<GraphicalModelType> MovemakerType;
00038 typedef VerboseVisitor<LOC<GM, ACC> > VerboseVisitorType;
00039 typedef TimingVisitor<LOC<GM, ACC> > TimingVisitorType;
00040 typedef EmptyVisitor<LOC<GM, ACC> > EmptyVisitorType;
00041
00042 class Parameter {
00043 public:
00050 Parameter
00051 (
00052 double phi = 0.5,
00053 size_t maxRadius = 10,
00054 size_t maxIterations = 0,
00055 size_t aStarThreshold = 10,
00056 const std::vector<LabelType>& startPoint = std::vector<LabelType>()
00057 )
00058 : phi_(phi),
00059 maxRadius_(maxRadius),
00060 maxIterations_(maxIterations),
00061 aStarThreshold_(aStarThreshold),
00062 startPoint_(startPoint)
00063 {}
00065 double phi_;
00067 size_t maxRadius_;
00069 size_t maxIterations_;
00071 size_t aStarThreshold_;
00073 std::vector<LabelType> startPoint_;
00074 };
00075
00076 LOC(const GraphicalModelType&, const Parameter& param = Parameter());
00077 std::string name() const;
00078 const GraphicalModelType& graphicalModel() const;
00079 InferenceTermination infer();
00080 void reset();
00081 template<class VisitorType>
00082 InferenceTermination infer(VisitorType&);
00083 void setStartingPoint(typename std::vector<LabelType>::const_iterator);
00084 InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const;
00085 ValueType value() const;
00086
00087 private:
00088 void getSubgraphVis(const size_t, const size_t, std::vector<size_t>&);
00089 void inline initializeProbabilities(std::vector<double>&);
00090 const GraphicalModelType& gm_;
00091 MovemakerType movemaker_;
00092 Parameter param_;
00093 std::vector<std::vector<size_t> > viAdjacency_;
00094 std::vector<bool> usedVi_;
00095 };
00096
00097 template<class GM, class ACC>
00098 LOC<GM, ACC>::LOC
00099 (
00100 const GraphicalModelType& gm,
00101 const Parameter& parameter
00102 )
00103 : gm_(gm),
00104 movemaker_(gm),
00105 param_(parameter),
00106 viAdjacency_(gm.numberOfVariables()),
00107 usedVi_(gm.numberOfVariables(), false)
00108 {
00109 if(parameter.startPoint_.size() == gm.numberOfVariables())
00110 movemaker_.initialize(parameter.startPoint_.begin());
00111 else if(parameter.startPoint_.size() != 0)
00112 throw RuntimeError("Unsuitable starting point.");
00113
00114 for(size_t f=0;f<gm_.numberOfFactors();++f) {
00115 if(gm_[f].numberOfVariables()>1) {
00116
00117 for(size_t va=0;va<gm_[f].numberOfVariables();++va) {
00118 for(size_t vb=0;vb<gm_[f].numberOfVariables();++vb)
00119 if(va!=vb) {
00120 viAdjacency_[ gm_[f].variableIndex(va)].push_back(gm_[f].variableIndex(vb));
00121 viAdjacency_[ gm_[f].variableIndex(vb)].push_back(gm_[f].variableIndex(va));
00122 }
00123 }
00124 }
00125 }
00126 if(this->param_.maxIterations_==0)
00127 param_.maxIterations_ = gm_.numberOfVariables() *
00128 log(double(gm_.numberOfVariables()))*log(double(gm_.numberOfVariables()));
00129 }
00130
00131 template<class GM, class ACC>
00132 void
00133 LOC<GM, ACC>::reset()
00134 {
00135 if(param_.startPoint_.size() == gm_.numberOfVariables()) {
00136 movemaker_.initialize(param_.startPoint_.begin());
00137 }
00138 else if(param_.startPoint_.size() != 0) {
00139 throw RuntimeError("Unsuitable starting point.");
00140 }
00141 else{
00142 movemaker_.reset();
00143 }
00144 std::fill(usedVi_.begin(),usedVi_.end(),false);
00145
00146
00147
00148 if(this->param_.maxIterations_==0)
00149 param_.maxIterations_ = gm_.numberOfVariables() *
00150 log(double(gm_.numberOfVariables()))*log(double(gm_.numberOfVariables()));
00151 }
00152
00153 template<class GM, class ACC>
00154 inline void
00155 LOC<GM,ACC>::setStartingPoint
00156 (
00157 typename std::vector<typename LOC<GM,ACC>::LabelType>::const_iterator begin
00158 ) {
00159 try{
00160 movemaker_.initialize(begin);
00161 }
00162 catch(...) {
00163 throw RuntimeError("unsuitable starting point");
00164 }
00165 }
00166
00167 template<class GM, class ACC>
00168 inline typename LOC<GM, ACC>::ValueType
00169 LOC<GM, ACC>::value()const
00170 {
00171 return this->movemaker_.value();
00172 }
00173
00174 template<class GM, class ACC>
00175 void inline
00176 LOC<GM, ACC>::initializeProbabilities
00177 (
00178 std::vector<double>& prob
00179 )
00180 {
00181 const double phi = param_.phi_;
00182 if(param_.maxRadius_ < 2) {
00183 param_.maxRadius_ = 2;
00184 }
00185 size_t maxRadius = param_.maxRadius_;
00186 prob.resize(param_.maxRadius_);
00187 for(size_t i=0;i<param_.maxRadius_-1;++i) {
00188 prob[i] = phi * pow((1.0-phi), static_cast<double>(i));
00189 }
00190 prob[maxRadius-1]= pow((1.0-phi), static_cast<double>(param_.maxRadius_));
00191 }
00192
00193 template<class GM, class ACC>
00194 inline std::string
00195 LOC<GM, ACC>::name() const {
00196 return "LOC";
00197 }
00198
00199 template<class GM, class ACC>
00200 inline const typename LOC<GM, ACC>::GraphicalModelType&
00201 LOC<GM, ACC>::graphicalModel() const {
00202 return gm_;
00203 }
00204
00205 template<class GM, class ACC>
00206 void LOC<GM, ACC>::getSubgraphVis
00207 (
00208 const size_t startVi,
00209 const size_t radius,
00210 std::vector<size_t>& vis
00211 ) {
00212 std::fill(usedVi_.begin(),usedVi_.end(),false);
00213 vis.clear();
00214 vis.push_back(startVi);
00215 usedVi_[startVi]=true;
00216 std::queue<size_t> viQueue;
00217 viQueue.push(startVi);
00218 size_t r=0;
00219 while(viQueue.size()!=0 && r<radius) {
00220 size_t cvi=viQueue.front();
00221 viQueue.pop();
00222
00223 for(size_t vni=0;vni<viAdjacency_[cvi].size();++vni) {
00224
00225 const size_t vn=viAdjacency_[cvi][vni];
00226 if(usedVi_[vn]==false) {
00227
00228 usedVi_[vn]=true;
00229
00230 viQueue.push(vn);
00231
00232 vis.push_back(vn);
00233 }
00234 }
00235 ++r;
00236 }
00237 }
00238
00239 template<class GM, class ACC>
00240 inline InferenceTermination
00241 LOC<GM, ACC>::infer() {
00242 EmptyVisitorType v;
00243 return infer(v);
00244 }
00245
00246 template<class GM, class ACC>
00247 template<class VisitorType>
00248 InferenceTermination
00249 LOC<GM, ACC>::infer
00250 (
00251 VisitorType& visitor
00252 ) {
00253 visitor.begin(*this,this->value(),this->bound());
00254
00255 opengm::RandomUniform<size_t> randomVariable(0, gm_.numberOfVariables());
00256 std::vector<double> prob;
00257 this->initializeProbabilities(prob);
00258 opengm::RandomDiscreteWeighted<size_t, double> randomRadius(prob.begin(), prob.end());
00259 std::vector<size_t> subgGraphVi;
00260
00261 for(size_t i=0;i<param_.maxIterations_;++i) {
00262
00263 size_t viStart = randomVariable();
00264
00265 size_t radius=randomRadius()+1;
00266
00267 this->getSubgraphVis(viStart, radius, subgGraphVi);
00268
00269 if(subgGraphVi.size()>param_.aStarThreshold_) {
00270 std::sort(subgGraphVi.begin(), subgGraphVi.end());
00271 typedef typename MovemakerType::SubGmType SubGmType;
00272 typedef opengm::AStar<SubGmType, ACC> SubGmInferenceType;
00273 typedef typename SubGmInferenceType::Parameter SubGmInferenceParameterType;
00274 SubGmInferenceParameterType para;
00275 para.heuristic_ = para.STANDARDHEURISTIC;
00276 std::vector<LabelType> states(std::distance(subgGraphVi.begin(), subgGraphVi.end()));
00277 movemaker_. template proposeMoveAccordingToInference<
00278 SubGmInferenceType,
00279 SubGmInferenceParameterType,
00280 typename std::vector<size_t>::const_iterator,
00281 typename std::vector<LabelType>::iterator
00282 > (para, subgGraphVi.begin(), subgGraphVi.end(), states);
00283 movemaker_.move(subgGraphVi.begin(), subgGraphVi.end(), states.begin());
00284
00285
00286
00287 }
00288 else
00289 movemaker_.template moveOptimally<AccumulationType>(subgGraphVi.begin(), subgGraphVi.end());
00290 visitor(*this,this->value(),this->bound(),radius);
00291 }
00292 visitor.end(*this,this->value(),this->bound());
00293 return NORMAL;
00294 }
00295
00296 template<class GM, class ACC>
00297 inline InferenceTermination
00298 LOC<GM, ACC>::arg
00299 (
00300 std::vector<LabelType>& x,
00301 const size_t N
00302 ) const {
00303 if(N == 1) {
00304 x.resize(gm_.numberOfVariables());
00305 for(size_t j = 0; j < x.size(); ++j) {
00306 x[j] = movemaker_.state(j);
00307 }
00308 return NORMAL;
00309 }
00310 else
00311 return UNKNOWN;
00312 }
00313
00314 }
00315
00316 #endif // #ifndef OPENGM_LOC_HXX
00317