00001 #pragma once
00002 #ifndef OPENGM_MINSTCUTBOOST_HXX
00003 #define OPENGM_MINSTCUTBOOST_HXX
00004
00005 #ifndef BOOST_DISABLE_ASSERTS
00006 #define BOOST_DISABLE_ASSERTS
00007 #define USED_BOOST_DISABLE_ASSERTS
00008 #endif
00009
00010 #include <queue>
00011 #include <cassert>
00012
00013 #include <boost/graph/graph_traits.hpp>
00014 #include <boost/graph/one_bit_color_map.hpp>
00015 #include <boost/property_map/property_map.hpp>
00016 #include <boost/typeof/typeof.hpp>
00017
00018 #include <boost/graph/adjacency_list.hpp>
00019 #include <boost/graph/edmonds_karp_max_flow.hpp>
00020 #include <boost/graph/push_relabel_max_flow.hpp>
00021 #include <boost/graph/boykov_kolmogorov_max_flow.hpp>
00022
00023 namespace opengm {
00024
00025 enum BoostMaxFlowAlgorithm {
00026 PUSH_RELABEL, EDMONDS_KARP, KOLMOGOROV
00027 };
00028
00030 template<class NType, class VType, BoostMaxFlowAlgorithm mfalg>
00031 class MinSTCutBoost {
00032 public:
00033
00034 typedef NType node_type;
00035 typedef VType ValueType;
00036 typedef boost::vecS OutEdgeList;
00037 typedef boost::vecS VertexList;
00038 typedef boost::adjacency_list_traits<OutEdgeList, VertexList, boost::directedS> graph_traits;
00039 typedef graph_traits::edge_descriptor edge_descriptor;
00040 typedef graph_traits::vertex_descriptor vertex_descriptor;
00041
00043 struct Edge {
00044 Edge() : capacity(ValueType()), residual(ValueType()), reverse(edge_descriptor())
00045 {}
00046 ValueType capacity;
00047 ValueType residual;
00048 edge_descriptor reverse;
00049 };
00051
00052 typedef boost::adjacency_list<OutEdgeList, VertexList, boost::directedS, size_t, Edge> graph_type;
00053 typedef typename boost::graph_traits<graph_type>::edge_iterator edge_iterator;
00054 typedef typename boost::graph_traits<graph_type>::out_edge_iterator out_edge_iterator;
00055
00056
00057 MinSTCutBoost();
00058 MinSTCutBoost(size_t numberOfNodes, size_t numberOfEdges);
00059 void addEdge(node_type, node_type, ValueType);
00060 void calculateCut(std::vector<bool>&);
00061
00062 private:
00063
00064 graph_type graph_;
00065 size_t numberOfNodes_;
00066 size_t numberOfEdges_;
00067 static const NType S = 0;
00068 static const NType T = 1;
00069 };
00070
00071
00072
00073
00074
00075 template<class NType, class VType, BoostMaxFlowAlgorithm mfalg>
00076 MinSTCutBoost<NType, VType, mfalg>::MinSTCutBoost() {
00077 numberOfNodes_ = 2;
00078 numberOfEdges_ = 0;
00079 }
00080
00081 template<class NType, class VType, BoostMaxFlowAlgorithm mfalg>
00082 MinSTCutBoost<NType, VType, mfalg>::MinSTCutBoost(size_t numberOfNodes, size_t numberOfEdges) {
00083 numberOfNodes_ = numberOfNodes;
00084 numberOfEdges_ = numberOfEdges;
00085 graph_ = graph_type(numberOfNodes_);
00086
00087 }
00088
00089 template<class NType, class VType, BoostMaxFlowAlgorithm mfalg>
00090 void MinSTCutBoost<NType, VType, mfalg>::addEdge(node_type n1, node_type n2, ValueType cost) {
00091 assert(n1 < numberOfNodes_);
00092 assert(n2 < numberOfNodes_);
00093 assert(cost >= 0);
00094 std::pair<edge_descriptor, bool> e = add_edge(n1, n2, graph_);
00095 std::pair<edge_descriptor, bool> er = add_edge(n2, n1, graph_);
00096 graph_[e.first].capacity += cost;
00097 graph_[e.first].reverse = er.first;
00098 graph_[er.first].reverse = e.first;
00099
00100 }
00101
00102 template<class NType, class VType, BoostMaxFlowAlgorithm mfalg>
00103 void MinSTCutBoost<NType, VType, mfalg>::calculateCut(std::vector<bool>& segmentation) {
00104 if (mfalg == KOLMOGOROV) {
00105 std::vector<boost::default_color_type> color(num_vertices(graph_));
00106 std::vector<edge_descriptor> pred(num_vertices(graph_));
00107 std::vector<vertex_descriptor> dist(num_vertices(graph_));
00108 boykov_kolmogorov_max_flow(graph_,
00109 get(&Edge::capacity, graph_),
00110 get(&Edge::residual, graph_),
00111 get(&Edge::reverse, graph_),
00112 &pred[0],
00113 &color[0],
00114 &dist[0],
00115 get(boost::vertex_index, graph_),
00116 S, T
00117 );
00118
00119 segmentation.resize(num_vertices(graph_));
00120 for (size_t j = 2; j < num_vertices(graph_); ++j) {
00121 if (color[j] == boost::black_color || color[j] == boost::gray_color) {
00122 segmentation[j] = false;
00123 } else if (color[j] == boost::white_color) {
00124 segmentation[j] = true;
00125 }
00126 }
00127 }
00128 else if (mfalg == PUSH_RELABEL) {
00129
00130 push_relabel_max_flow(graph_, S, T,
00131 get(&Edge::capacity, graph_),
00132 get(&Edge::residual, graph_),
00133 get(&Edge::reverse, graph_),
00134 get(boost::vertex_index_t(), graph_)
00135 );
00136
00137 segmentation.resize(num_vertices(graph_), true);
00138 segmentation[S] = false;
00139 segmentation[T] = false;
00140 typedef typename boost::property_map<graph_type, boost::vertex_index_t>::type VertexIndexMap;
00141 VertexIndexMap vertexIndexMap = get(boost::vertex_index, graph_);
00142 std::queue<vertex_descriptor> q;
00143 q.push(*(vertices(graph_).first));
00144 while (!q.empty()) {
00145 out_edge_iterator current, end;
00146 tie(current, end) = out_edges(q.front(), graph_);
00147 q.pop();
00148 while (current != end) {
00149 if (graph_[*current].residual > 0) {
00150 vertex_descriptor v = target(*current, graph_);
00151 if (vertexIndexMap[v] > 1 && segmentation[vertexIndexMap[v]] == true) {
00152 segmentation[vertexIndexMap[v]] = false;
00153 q.push(v);
00154 }
00155 }
00156 ++current;
00157 }
00158 }
00159 }
00160 else if (mfalg == EDMONDS_KARP) {
00161 std::vector<boost::default_color_type> color(num_vertices(graph_));
00162 std::vector<edge_descriptor> pred(num_vertices(graph_));
00163 edmonds_karp_max_flow(graph_, S, T,
00164 get(&Edge::capacity, graph_),
00165 get(&Edge::residual, graph_),
00166 get(&Edge::reverse, graph_),
00167 &color[0], &pred[0]
00168 );
00169
00170 segmentation.resize(num_vertices(graph_));
00171 for (size_t j = 2; j < num_vertices(graph_); ++j) {
00172 if (color[j] == boost::black_color) {
00173 segmentation[j] = false;
00174 } else if (color[j] == boost::white_color) {
00175 segmentation[j] = true;
00176 } else {
00177 throw std::runtime_error("At least one vertex is labeled neither black nor white.");
00178 }
00179 }
00180 }
00181 else {
00182 throw std::runtime_error("Unknown MaxFlow-algorithm in MinSTCutBoost.hxx");
00183 }
00184 return;
00185 }
00186
00187 }
00188
00189 #ifdef USED_BOOST_DISABLE_ASSERTS
00190 #undef BOOST_DISABLE_ASSERTS
00191 #undef USED_BOOST_DISABLE_ASSERTS
00192 #endif
00193
00194
00195 #endif // #ifndef OPENGM_MINSTCUTBOOST_HXX