andres::graph
greedy-fixation.hxx
1 #pragma once
2 
3 #include <cstddef>
4 #include <iterator>
5 #include <vector>
6 #include <algorithm>
7 #include <stack>
8 #include <unordered_map>
9 #include <unordered_set>
10 #include <queue>
11 
12 #include "andres/partition.hxx"
13 
14 namespace andres {
15 namespace graph {
16 namespace multicut {
17 
20 template<typename GRAPH, typename EVA, typename ELA>
22  const GRAPH& graph,
23  EVA const& edge_values,
24  ELA& edge_labels
25 )
26 {
27  class DynamicGraph
28  {
29  public:
30  DynamicGraph(size_t n) :
31  vertices_(n), cut_edges_(n)
32  {}
33 
34  bool edgeExists(size_t a, size_t b) const
35  {
36  return !vertices_[a].empty() && vertices_[a].find(b) != vertices_[a].end();
37  }
38 
39  std::unordered_map<size_t, typename EVA::value_type> const& getAdjacentVertices(size_t v) const
40  {
41  return vertices_[v];
42  }
43 
44  typename EVA::value_type getEdgeWeight(size_t a, size_t b) const
45  {
46  return vertices_[a].at(b);
47  }
48 
49  bool isCutEdge(size_t a, size_t b) const
50  {
51  return !cut_edges_[a].empty() && cut_edges_[a].find(b) != cut_edges_[a].end();
52  }
53 
54  void markEdgeCut(size_t a, size_t b)
55  {
56  cut_edges_[a].insert(b);
57  cut_edges_[b].insert(a);
58  }
59 
60  void removeVertex(size_t v)
61  {
62  for (auto& p : vertices_[v])
63  {
64  vertices_[p.first].erase(v);
65  cut_edges_[p.first].erase(v);
66  }
67 
68  vertices_[v].clear();
69  cut_edges_[v].clear();
70  }
71 
72  void setEdgeWeight(size_t a, size_t b, typename EVA::value_type w)
73  {
74  vertices_[a][b] = w;
75  vertices_[b][a] = w;
76  }
77 
78  private:
79  std::vector<std::unordered_set<size_t>> cut_edges_;
80  std::vector<std::unordered_map<size_t, typename EVA::value_type>> vertices_;
81  };
82 
83  struct Edge
84  {
85  Edge(size_t _a, size_t _b, typename EVA::value_type _w)
86  {
87  if (_a > _b)
88  std::swap(_a, _b);
89 
90  a = _a;
91  b = _b;
92 
93  w = _w;
94  }
95 
96  size_t a;
97  size_t b;
98  size_t edition;
99  typename EVA::value_type w;
100 
101  bool operator <(Edge const& other) const
102  {
103  return fabs(w) < fabs(other.w);
104  }
105  };
106 
107  std::vector<std::unordered_map<size_t, size_t>> edge_editions(graph.numberOfVertices());
108  (graph.numberOfVertices());
109 
110  DynamicGraph original_graph_cp(graph.numberOfVertices());
111  std::priority_queue<Edge> Q;
112 
113  for (size_t i = 0; i < graph.numberOfEdges(); ++i)
114  {
115  auto a = graph.vertexOfEdge(i, 0);
116  auto b = graph.vertexOfEdge(i, 1);
117 
118  original_graph_cp.setEdgeWeight(a, b, edge_values[i]);
119 
120  auto e = Edge(a, b, edge_values[i]);
121  e.edition = ++edge_editions[e.a][e.b];
122 
123  Q.push(e);
124  }
125 
126  andres::Partition<size_t> partition(graph.numberOfVertices());
127 
128  while (!Q.empty())
129  {
130  auto edge = Q.top();
131  Q.pop();
132 
133  if (!original_graph_cp.edgeExists(edge.a, edge.b) || edge.edition < edge_editions[edge.a][edge.b])
134  continue;
135 
136  if (edge.w > typename EVA::value_type() && !original_graph_cp.isCutEdge(edge.a, edge.b))
137  {
138  auto stable_vertex = edge.a;
139  auto merge_vertex = edge.b;
140 
141  if (original_graph_cp.getAdjacentVertices(stable_vertex).size() < original_graph_cp.getAdjacentVertices(merge_vertex).size())
142  std::swap(stable_vertex, merge_vertex);
143 
144  partition.merge(stable_vertex, merge_vertex);
145 
146  for (auto& p : original_graph_cp.getAdjacentVertices(merge_vertex))
147  {
148  if (p.first == stable_vertex)
149  continue;
150 
151  typename EVA::value_type t = typename EVA::value_type();
152 
153  if (original_graph_cp.edgeExists(stable_vertex, p.first))
154  t = original_graph_cp.getEdgeWeight(stable_vertex, p.first);
155 
156  if (original_graph_cp.isCutEdge(merge_vertex, p.first))
157  original_graph_cp.markEdgeCut(stable_vertex, p.first);
158 
159  original_graph_cp.setEdgeWeight(stable_vertex, p.first, p.second + t);
160 
161  auto e = Edge(stable_vertex, p.first, p.second + t);
162  e.edition = ++edge_editions[e.a][e.b];
163 
164  Q.push(e);
165  }
166 
167  original_graph_cp.removeVertex(merge_vertex);
168  }
169  else if (edge.w < typename EVA::value_type())
170  original_graph_cp.markEdgeCut(edge.a, edge.b);
171  }
172 
173  for (size_t i = 0; i < graph.numberOfEdges(); ++i)
174  edge_labels[i] = partition.find(graph.vertexOfEdge(i, 0)) == partition.find(graph.vertexOfEdge(i, 1)) ? 0 : 1;
175 }
176 
177 } // namespace multicut
178 } // namespace graph
179 } // namespace andres