Graph.cpp
Go to the documentation of this file.
1 //=============================================================================
2 // Copyright (C) 2021-2024 Wageningen University - All Rights Reserved
3 // Author: Gonzalo Mier
4 // BSD-3 License
5 //=============================================================================
6 
7 #include <numeric>
8 #include <algorithm>
10 
11 namespace f2c::types {
12 
13 Graph& Graph::addDirectedEdge(size_t from, size_t to, int64_t cost) {
14  this->edges_[from][to] = cost;
15  if (this->shortest_paths_.size() > 0) {
16  this->shortest_paths_.clear();
17  }
18  return *this;
19 }
20 
21 Graph& Graph::addEdge(size_t i, size_t j, int64_t cost) {
22  return this->addDirectedEdge(i, j, cost).addDirectedEdge(j, i, cost);
23 }
24 
25 
26 Graph& Graph::removeDirectedEdge(size_t from, size_t to) {
27  if (this->edges_.count(from) == 0 || this->edges_.at(from).count(to) == 0) {
28  return *this;
29  }
30  this->edges_.at(from).erase(to);
31  return *this;
32 }
33 Graph& Graph::removeEdge(size_t i, size_t j) {
34  return this->removeDirectedEdge(i, j).removeDirectedEdge(j, i);
35 }
36 
37 size_t Graph::numNodes() const {
38  return this->edges_.size();
39 }
40 
41 size_t Graph::numEdges() const {
42  return std::accumulate(this->edges_.begin(), this->edges_.end(), 0,
43  [](int sum, const auto& e) {return sum + e.second.size();});
44 }
45 
47  return this->edges_;
48 }
49 
50 std::vector<size_t> Graph::getEdgesFrom(size_t s) const {
51  if (this->edges_.count(s) == 0) {
52  return {};
53  }
54  std::vector<size_t> connections;
55  for (auto&& i : this->edges_.at(s)) {
56  connections.emplace_back(i.first);
57  }
58  return connections;
59 }
60 
61 int64_t Graph::getCostFromEdge(size_t from, size_t to, int64_t INF) const {
62  if (this->edges_.count(from) == 0 || this->edges_.at(from).count(to) == 0) {
63  return INF;
64  }
65  return this->edges_.at(from).at(to);
66 }
67 
68 std::vector<std::vector<size_t>> Graph::allPathsBetween(
69  size_t from, size_t to) const {
70  std::vector<bool> visited(this->numNodes(), false);
71  std::vector<std::vector<size_t>> routes(1);
72  int route_index = 0;
73  this->DFS(from, to, routes, visited, route_index);
74  routes.erase(std::remove_if(routes.begin(), routes.end(),
75  [&to] (const std::vector<size_t> x) {
76  return (x.size() < 1 || x.back() != to);
77  }), routes.end());
78  return routes;
79 }
80 
82  size_t from, size_t to,
83  std::vector<std::vector<size_t>>& routes,
84  std::vector<bool>& visited,
85  int& route_index) const {
86  routes.emplace_back(routes[route_index]);
87  routes.back().emplace_back(from);
88  int i_route = routes.size() - 1;
89  if (from != to) {
90  visited[from] = true;
91  for (auto&& i : this->getEdgesFrom(from)) {
92  if (!visited[i]) {
93  this->DFS(i, to, routes, visited, i_route);
94  }
95  }
96  visited[from] = false;
97  }
98 }
99 
100 std::vector<std::vector<pair_vec_size__int>>
102  const size_t N = this->numNodes();
103  std::vector<std::vector<int64_t>> dist(N, std::vector<int64_t>(N, INF));
104  std::vector<std::vector<int64_t>> next(N, std::vector<int64_t>(N, -1));
105 
106 
107  // Initialize distances and paths for direct connections
108  for (const auto& src : this->edges_) {
109  for (const auto& dest : src.second) {
110  dist[src.first][dest.first] = dest.second;
111  next[src.first][dest.first] = dest.first;
112  }
113  dist[src.first][src.first] = 0;
114  }
115 
116 
117  // Floyd-Warshall
118  for (size_t k = 0; k < N; ++k) {
119  for (size_t i = 0; i < N; ++i) {
120  for (size_t j = 0; j < N; ++j) {
121  if (dist[i][k] < INF && \
122  dist[k][j] < INF && \
123  dist[i][j] > dist[i][k] + dist[k][j]) {
124  dist[i][j] = dist[i][k] + dist[k][j];
125  next[i][j] = next[i][k];
126  }
127  }
128  }
129  }
130 
131 
132  // Reconstruct paths
133  std::vector<std::vector<pair_vec_size__int>>
134  paths(N, std::vector<pair_vec_size__int>(N));
135  for (size_t i = 0; i < N; ++i) {
136  for (size_t j = 0; j < N; ++j) {
137  if (i != j && next[i][j] != -1) {
138  std::vector<size_t> path = {i};
139  size_t current = i;
140  while (current != j) {
141  current = next[current][j];
142  path.push_back(current);
143  }
144  paths[i][j] = std::make_pair(path, dist[i][j]);
145  } else if (i != j && next[i][j] == -1) {
146  paths[i][j].second = INF;
147  }
148  }
149  }
150  this->shortest_paths_ = std::move(paths);
151  return this->shortest_paths_;
152 }
153 
154 std::vector<size_t> Graph::shortestPath(size_t from, size_t to, int64_t INF) {
155  if (this->numNodes() > 0 && this->shortest_paths_.size() == 0) {
156  this->shortestPathsAndCosts(INF);
157  }
158  return this->shortest_paths_[from][to].first;
159 }
160 
161 int64_t Graph::shortestPathCost(size_t from, size_t to, int64_t INF) {
162  if (this->numNodes() > 0 && this->shortest_paths_.size() == 0) {
163  this->shortestPathsAndCosts(INF);
164  }
165  return this->shortest_paths_[from][to].second;
166 }
167 
168 } // namespace f2c::types
169 
170 
f2c::types
Types used by fields2cover library.
Definition: Cell.h:20
f2c::types::Graph::edges_
map_to_map_to_int edges_
Definition: Graph.h:58
2_objective_functions.path
path
Definition: 2_objective_functions.py:88
f2c::types::Graph::shortestPath
std::vector< size_t > shortestPath(size_t from, size_t to, int64_t INF=1e15)
Definition: Graph.cpp:154
f2c::types::Graph::getEdges
map_to_map_to_int getEdges() const
Definition: Graph.cpp:46
f2c::types::Graph::shortestPathsAndCosts
std::vector< std::vector< pair_vec_size__int > > shortestPathsAndCosts(int64_t INF=1e15)
Definition: Graph.cpp:101
f2c::types::Graph::getCostFromEdge
int64_t getCostFromEdge(size_t from, size_t to, int64_t INF=1e15) const
Definition: Graph.cpp:61
f2c::types::map_to_map_to_int
std::unordered_map< size_t, std::unordered_map< size_t, int64_t > > map_to_map_to_int
Definition: Graph.h:20
f2c::types::Graph::shortest_paths_
std::vector< std::vector< pair_vec_size__int > > shortest_paths_
Definition: Graph.h:59
f2c::types::Graph::getEdgesFrom
std::vector< size_t > getEdgesFrom(size_t s) const
Definition: Graph.cpp:50
f2c::types::Graph::addDirectedEdge
Graph & addDirectedEdge(size_t from, size_t to, int64_t cost)
Definition: Graph.cpp:13
f2c::types::Graph::allPathsBetween
std::vector< std::vector< size_t > > allPathsBetween(size_t from, size_t to) const
Definition: Graph.cpp:68
f2c::types::Graph
Definition: Graph.h:23
Graph.h
f2c::types::Graph::numNodes
size_t numNodes() const
Definition: Graph.cpp:37
f2c::types::Graph::removeEdge
Graph & removeEdge(size_t i, size_t j)
Definition: Graph.cpp:33
f2c::types::Graph::addEdge
Graph & addEdge(size_t i, size_t j, int64_t cost)
Definition: Graph.cpp:21
f2c::types::Graph::numEdges
size_t numEdges() const
Definition: Graph.cpp:41
f2c::types::Graph::shortestPathCost
int64_t shortestPathCost(size_t from, size_t to, int64_t INF=1e15)
Definition: Graph.cpp:161
f2c::types::Graph::DFS
void DFS(size_t from, size_t to, std::vector< std::vector< size_t >> &routes, std::vector< bool > &visited, int &route_index) const
Definition: Graph.cpp:81
f2c::types::Graph::removeDirectedEdge
Graph & removeDirectedEdge(size_t from, size_t to)
Definition: Graph.cpp:26


fields2cover
Author(s):
autogenerated on Fri Apr 25 2025 02:18:31