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)
140 std::mt19937
gen(seed);
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));
193 std::mt19937
gen(seed);
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();
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();
819 double hu =
h.find(u);
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.
T & insert(const T &item)
Insert a new item by copy.
void empty() noexcept
empty the list
Generic key-value map implemented on top of a binary search tree.
void next()
Advances the iterator to the next filtered element.
constexpr bool is_empty() const noexcept
Return true if list is empty.
size_t size() const noexcept
Count the number of elements of the list.
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)
iterator end() noexcept
Return an STL-compatible end iterator.
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.
std::pair< First, Second > pair
Alias to std::pair kept for backwards compatibility.
DynList< T > maps(const C &c, Op op)
Classic map operation.
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.