53#include <gtest/gtest.h>
92 return arc->get_info();
97 arc->get_info() = 0.0;
129 for (
int i = 0; i < n; ++i)
130 nodes.push_back(
g.insert_node(i));
132 for (
int i = 0; i < n - 1; ++i)
144 for (
int i = 0; i < n; ++i)
145 nodes.push_back(
g.insert_node(i));
147 for (
int i = 0; i < n; ++i)
148 for (
int j = 0; j < n; ++j)
164 nodes.push_back(
g.insert_node(0));
165 nodes.push_back(
g.insert_node(1));
166 nodes.push_back(
g.insert_node(2));
167 nodes.push_back(
g.insert_node(3));
179 nodes.push_back(
g.insert_node(0));
180 nodes.push_back(
g.insert_node(1));
181 nodes.push_back(
g.insert_node(2));
195 std::uniform_real_distribution<double>
probDist(0.0, 1.0);
198 for (
int i = 0; i < n; ++i)
199 nodes.push_back(
g.insert_node(i));
201 for (
int i = 0; i < n; ++i)
202 for (
int j = 0; j < n; ++j)
210 const double INF = std::numeric_limits<double>::infinity();
211 int n =
nodes.size();
214 std::vector<std::vector<double>> dist(n, std::vector<double>(n, INF));
216 for (
int i = 0; i < n; ++i)
222 auto arc = it.get_curr();
223 auto src =
g.get_src_node(arc);
224 auto tgt =
g.get_tgt_node(arc);
225 int i = src->get_info();
226 int j = tgt->get_info();
227 double w = arc->get_info();
233 for (
int k = 0;
k < n; ++
k)
234 for (
int i = 0; i < n; ++i)
235 for (
int j = 0; j < n; ++j)
236 if (dist[i][
k] != INF && dist[
k][j] != INF)
237 if (dist[i][
k] + dist[
k][j] < dist[i][j])
238 dist[i][j] = dist[i][
k] + dist[
k][j];
241 std::map<std::pair<int, int>,
double> result;
242 for (
int i = 0; i < n; ++i)
243 for (
int j = 0; j < n; ++j)
244 if (dist[i][j] != INF)
245 result[{i, j}] = dist[i][j];
256 createPathGraph(3, 2.0);
267 createNegativeWeightGraph();
277 createNegativeCycleGraph();
287 createNegativeWeightGraph();
292 auto weights =
bf.compute_nodes_weights();
298 for (
auto node :
nodes)
308 createNegativeCycleGraph();
320 createPathGraph(4, 1.0);
340 createNegativeWeightGraph();
377 createNegativeCycleGraph();
386 createNegativeWeightGraph();
397 ASSERT_NE(entry,
nullptr) <<
"Missing entry for (" << i <<
", " << j <<
")";
399 <<
"Distance mismatch for (" << i <<
", " << j <<
")";
433 createNegativeWeightGraph();
436 auto weights =
bf.compute_nodes_weights();
441 auto arc = it.get_curr();
442 auto u = g.get_src_node(arc);
443 auto v = g.get_tgt_node(arc);
444 double w = arc->get_info();
456 <<
"Reweighted edge should be non-negative: w=" <<
w
457 <<
", h(u)=" <<
hu <<
", h(v)=" <<
hv
466 createNegativeWeightGraph();
470 auto weights =
bf.compute_nodes_weights();
477 for (
auto it = g.get_node_it(); it.has_curr(); it.next())
479 auto orig = it.get_curr();
487 auto arc = it.get_curr();
488 auto u = g.get_src_node(arc);
489 auto v = g.get_tgt_node(arc);
490 double w = arc->get_info();
516 createCompleteGraph(5, 1.0, 10.0);
524 int n =
nodes.size();
525 for (
int i = 0; i < n; ++i)
526 for (
int j = 0; j < n; ++j)
528 <<
"Path from " << i <<
" to " << j <<
" should exist";
534 createSparseGraph(10, 0.3, 1.0, 10.0);
539 for (
int i = 0; i < (
int)
nodes.size(); ++i)
551 nodes.push_back(g.insert_node(0));
561 nodes.push_back(g.insert_node(0));
562 nodes.push_back(g.insert_node(1));
572 nodes.push_back(g.insert_node(0));
573 nodes.push_back(g.insert_node(1));
585 nodes.push_back(g.insert_node(0));
596 nodes.push_back(g.insert_node(0));
607 nodes.push_back(g.insert_node(0));
608 nodes.push_back(g.insert_node(1));
623 createCompleteGraph(20, 1.0, 100.0);
632 for (
size_t i = 1; i <
nodes.size(); ++i)
635 bf.get_min_path(
nodes[i], path);
643 createCompleteGraph(100, 1.0, 100.0);
648 auto start = std::chrono::high_resolution_clock::now();
652 auto weights =
bf.compute_nodes_weights();
654 auto mid = std::chrono::high_resolution_clock::now();
659 auto end = std::chrono::high_resolution_clock::now();
661 auto bfTime = std::chrono::duration_cast<std::chrono::milliseconds>(
mid - start);
662 auto totalTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
664 std::cout <<
"Bellman-Ford time: " <<
bfTime.count() <<
" ms\n";
665 std::cout <<
"Total time: " <<
totalTime.count() <<
" ms\n";
673 nodes.push_back(g.insert_node(0));
674 nodes.push_back(g.insert_node(1));
675 nodes.push_back(g.insert_node(2));
676 nodes.push_back(g.insert_node(3));
705 bf.paint_spanning_tree(
nodes[0]);
724 createNegativeWeightGraph();
745 createNegativeCycleGraph();
752 if (!
cycle.is_empty())
756 EXPECT_GE(
cycle.size(), 2) <<
"Cycle should have at least 2 nodes";
763 nodes.push_back(g.insert_node(0));
764 nodes.push_back(g.insert_node(1));
765 nodes.push_back(g.insert_node(2));
790 createNegativeWeightGraph();
799 h =
bf.compute_nodes_weights();
801 catch (
const std::domain_error&)
803 FAIL() <<
"Unexpected negative cycle in test graph";
812 auto arc = it.get_curr();
813 auto u = g.get_src_node(arc);
814 auto v = g.get_tgt_node(arc);
815 double w = arc->get_info();
820 double hv =
h.find(v);
832 for (
size_t i = 0; i <
nodes.size(); ++i)
837 for (
size_t j = 0; j <
nodes.size(); ++j)
867 auto arc = it.get_curr();
880 <<
"Distance mismatch for pair (" <<
pair.first <<
", " <<
pair.second <<
"): "
881 <<
"Johnson=" << dist <<
", Floyd=" << it->second;
890 ::testing::InitGoogleTest(&
argc,
argv);
Bellman-Ford algorithm for single-source shortest paths.
Dijkstra's shortest path algorithm.
Johnson's algorithm for all-pairs shortest paths.
WeightedDigraph::Node Node
Bellman-Ford algorithm for shortest paths with negative weights.
Generic directed graph (digraph) wrapper template.
typename BaseGraph::Arc Arc
typename BaseGraph::Node Node
Spanning tree calculation of all shortest paths from a given node according to Dijkstra's algorithm.
void paint_min_paths_tree(const GT &g, typename GT::Node *start)
Paints on graph g the spanning tree of all shortest paths starting from start.
Generic key-value map implemented on top of a binary search tree.
Pair * insert(const Key &key, const Data &data)
Insert a key-value pair.
Data & find(const Key &key)
Find the value associated with key.
void next()
Advances the iterator to the next filtered element.
Johnson's algorithm for all-pairs shortest paths.
bool is_empty() const noexcept
Return true if the path is empty.
void createSparseGraph(int n, double edgeProbability=0.2, double minWeight=1.0, double maxWeight=10.0, unsigned seed=42)
std::map< std::pair< int, int >, double > computeFloydWarshall()
std::vector< Node * > nodes
void createPathGraph(int n, double weight=1.0)
void createNegativeWeightGraph()
void createNegativeCycleGraph()
void createCompleteGraph(int n, double minWeight=1.0, double maxWeight=10.0, unsigned seed=42)
static Geom_Number dist2(const Point &a, const Point &b)
DynArray< Graph::Node * > nodes
TEST_F(JohnsonTest, BellmanFordBasic)
Main namespace for Aleph-w library functions.
Itor2 copy(Itor1 sourceBeg, const Itor1 &sourceEnd, Itor2 destBeg)
Copy elements from one range to another.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::pair< First, Second > pair
Alias to std::pair kept for backwards compatibility.
Filtered iterator on all the arcs of a graph.
Arc of graph implemented with double-linked adjacency lists.
Node belonging to a graph implemented with a double linked adjacency list.
Distance_Type operator()(Arc *arc) const
static void set_zero(Arc *arc)
void set_weight(Arc *arc, Distance_Type w)
Generic graph and digraph implementations.
Utility algorithms and operations for graphs.