sat.hxx
Go to the documentation of this file.00001 #pragma once
00002 #ifndef OPENGM_INFERENCE_SAT_HXX
00003 #define OPENGM_INFERENCE_SAT_HXX
00004
00005 #include <iostream>
00006 #include <vector>
00007
00008 #include <boost/config.hpp>
00009 #include <boost/graph/strong_components.hpp>
00010 #include <boost/graph/adjacency_list.hpp>
00011 #include <boost/foreach.hpp>
00012
00013 #include "opengm/inference/inference.hxx"
00014 #include "opengm/operations/and.hxx"
00015 #include "opengm/operations/or.hxx"
00016 #include "opengm/inference/visitors/visitor.hxx"
00017
00018 namespace opengm {
00019
00023 template<class GM>
00024 class SAT : Inference<GM, opengm::Or> {
00025 public:
00026 typedef opengm::Or AccumulationType;
00027 typedef GM GraphicalModelType;
00028 OPENGM_GM_TYPE_TYPEDEFS;
00029
00030 struct Parameter {};
00031
00032 SAT(const GraphicalModelType&, const Parameter& = Parameter());
00033 std::string name() const;
00034 const GraphicalModelType& graphicalModel() const;
00035 InferenceTermination infer();
00036 template<class VISITOR>
00037 InferenceTermination infer(VISITOR &);
00038 virtual void reset();
00039 ValueType value() const;
00040 typedef VerboseVisitor<SAT<GM> > VerboseVisitorType;
00041 typedef TimingVisitor<SAT<GM> > TimingVisitorType;
00042 typedef EmptyVisitor<SAT<GM> > EmptyVisitorType;
00043 private:
00044 const GraphicalModelType& gm_;
00045 std::vector<int> component_;
00046 };
00047
00048 template<class GM>
00049 inline SAT<GM>::SAT
00050 (
00051 const GraphicalModelType& gm,
00052 const Parameter& para
00053 )
00054 : gm_(gm)
00055 {
00056 if(!NO_DEBUG) {
00057 OPENGM_ASSERT(gm_.factorOrder() <= 2);
00058 OPENGM_ASSERT(typeid(OperatorType) == typeid(opengm::And));
00059 for(size_t i=0; i<gm_.numberOfVariables();++i) {
00060 OPENGM_ASSERT(gm_.numberOfLabels(i) == 2);
00061 }
00062 }
00063 }
00064 template<class GM>
00065 void
00066 inline SAT<GM>::reset()
00067 {
00068 }
00069
00070 template<class GM>
00071 inline std::string
00072 SAT<GM>::name() const
00073 {
00074 return "2Sat";
00075 }
00076
00077 template<class GM>
00078 inline const GM&
00079 SAT<GM>::graphicalModel() const
00080 {
00081 return gm_;
00082 }
00083
00084 template<class GM>
00085 InferenceTermination
00086 SAT<GM>::infer() {
00087 EmptyVisitorType v;
00088 return infer(v);
00089 }
00090
00091 template<class GM>
00092 template<class VISITOR>
00093 InferenceTermination
00094 SAT<GM>::infer
00095 (
00096 VISITOR & visitor
00097 ) {
00098 typedef std::pair<int, int> clause;
00099 typedef boost::adjacency_list<> Graph;
00100
00101 Graph g(gm_.numberOfVariables() * 2);
00102 for(size_t f=0; f<gm_.numberOfFactors(); ++f) {
00103 if(gm_[f].numberOfVariables() != 2) {
00104 throw RuntimeError("This implementation of the 2-SAT solver supports only factors of order 2.");
00105 }
00106 std::vector<size_t> vec(2);
00107 for(vec[0]=0; vec[0]<2; ++vec[0]) {
00108 for(vec[1]=0; vec[1]<2; ++vec[1]) {
00109 if(!gm_[f](vec.begin())) {
00110 const int v1=gm_[f].variableIndex(0)+(1-vec[0])*gm_.numberOfVariables();
00111 const int nv1=gm_[f].variableIndex(0)+(0+vec[0])*gm_.numberOfVariables();
00112 const int v2=gm_[f].variableIndex(1)+(1-vec[1])*gm_.numberOfVariables();
00113 const int nv2=gm_[f].variableIndex(1)+(0+vec[1])*gm_.numberOfVariables();
00114 boost::add_edge(nv1,v2,g);
00115 boost::add_edge(nv2,v1,g);
00116 }
00117 }
00118 }
00119 }
00120 component_.resize(num_vertices(g));
00121 strong_components(g,&component_[0]);
00122 return NORMAL;
00123 }
00124
00125 template<class GM>
00126 inline typename GM::ValueType
00127 SAT<GM>::value() const
00128 {
00129 bool satisfied = true;
00130 for(IndexType i=0; i<gm_.numberOfVariables(); i++) {
00131 if(component_[i] == component_[i+gm_.numberOfVariables()]) {
00132 satisfied = false;
00133 }
00134 }
00135 return satisfied;
00136 }
00137
00138 }
00139
00140 #endif // #ifndef OPENGM_INFERENCE_SAT_HXX
00141