Add weight parameter for Dijkstra's algorithm, add unweighted variants (unused)

This commit is contained in:
2026-05-07 17:15:34 +02:00
parent 6fe3acb306
commit 726e7691ea
2 changed files with 37 additions and 12 deletions
+31 -6
View File
@@ -27,12 +27,13 @@ pub struct DijkstraResult<V: Copy> {
pub predecessors: VertexMap<V, Option<V>>, pub predecessors: VertexMap<V, Option<V>>,
} }
pub fn dijkstra<G>(graph: &G, source: G::Vertex) -> DijkstraResult<G::Vertex> pub fn dijkstra<G, W>(graph: &G, source: G::Vertex, weight: W) -> DijkstraResult<G::Vertex>
where where
G: GraphTopology, G: GraphTopology,
W: Fn(G::Edge) -> u32,
{ {
let mut predecessors = graph.vertex_map(None); let mut predecessors = graph.vertex_map(None);
let distances = dijkstra_impl(graph, source, |neighbor, predecessor| { let distances = dijkstra_impl(graph, source, weight, |neighbor, predecessor| {
predecessors[neighbor] = Some(predecessor); predecessors[neighbor] = Some(predecessor);
}); });
DijkstraResult { DijkstraResult {
@@ -41,21 +42,44 @@ where
} }
} }
pub fn dijkstra_distances<G>(graph: &G, source: G::Vertex) -> VertexMap<G::Vertex, Option<u32>> pub fn dijkstra_unweighted<G>(graph: &G, source: G::Vertex) -> DijkstraResult<G::Vertex>
where where
G: GraphTopology, G: GraphTopology,
{ {
dijkstra_impl(graph, source, |_, _| {}) dijkstra(graph, source, |_| 1)
} }
// TODO: Add a way to provide custom edge weights for Dijkstra's algorithm. pub fn dijkstra_distances<G, W>(
fn dijkstra_impl<G, F>(
graph: &G, graph: &G,
source: G::Vertex, source: G::Vertex,
weight: W,
) -> VertexMap<G::Vertex, Option<u32>>
where
G: GraphTopology,
W: Fn(G::Edge) -> u32,
{
dijkstra_impl(graph, source, weight, |_, _| {})
}
pub fn dijkstra_distances_unweighted<G>(
graph: &G,
source: G::Vertex,
) -> VertexMap<G::Vertex, Option<u32>>
where
G: GraphTopology,
{
dijkstra_distances(graph, source, |_| 1)
}
fn dijkstra_impl<G, W, F>(
graph: &G,
source: G::Vertex,
weight: W,
mut on_relax: F, mut on_relax: F,
) -> VertexMap<G::Vertex, Option<u32>> ) -> VertexMap<G::Vertex, Option<u32>>
where where
G: GraphTopology, G: GraphTopology,
W: Fn(G::Edge) -> u32,
F: FnMut(G::Vertex, G::Vertex), F: FnMut(G::Vertex, G::Vertex),
{ {
let mut distances = graph.vertex_map(None); let mut distances = graph.vertex_map(None);
@@ -69,6 +93,7 @@ where
while let Some(v) = heap.pop() { while let Some(v) = heap.pop() {
for neighbor in graph.neighbors(v.vertex) { for neighbor in graph.neighbors(v.vertex) {
// TODO: Use custom edge weights in Dijkstra's algorithm.
let edge_weight = 1; let edge_weight = 1;
let new_distance = distances[v.vertex].unwrap() + edge_weight; let new_distance = distances[v.vertex].unwrap() + edge_weight;
if match distances[neighbor] { if match distances[neighbor] {
+6 -6
View File
@@ -6,7 +6,7 @@ use grapherity::traits::GraphTopology;
fn dijkstra_single_vertex() { fn dijkstra_single_vertex() {
let mut graph = AppendGraph::new(); let mut graph = AppendGraph::new();
let v1 = graph.add_vertex(); let v1 = graph.add_vertex();
let result = algorithms::dijkstra(&graph, v1); let result = algorithms::dijkstra_unweighted(&graph, v1);
assert_eq!( assert_eq!(
result.distances[v1], result.distances[v1],
Some(0), Some(0),
@@ -23,7 +23,7 @@ fn dijkstra_disconnected() {
let mut graph = AppendGraph::new(); let mut graph = AppendGraph::new();
let v1 = graph.add_vertex(); let v1 = graph.add_vertex();
let v2 = graph.add_vertex(); let v2 = graph.add_vertex();
let result = algorithms::dijkstra(&graph, v1); let result = algorithms::dijkstra_unweighted(&graph, v1);
assert_eq!( assert_eq!(
result.distances[v1], result.distances[v1],
Some(0), Some(0),
@@ -46,7 +46,7 @@ fn dijkstra_disconnected() {
#[test] #[test]
fn dijkstra() { fn dijkstra() {
let (graph, vertices) = make_test_graph(); let (graph, vertices) = make_test_graph();
let result = algorithms::dijkstra(&graph, vertices[0]); let result = algorithms::dijkstra_unweighted(&graph, vertices[0]);
let expected_distances_from_v0 = [ let expected_distances_from_v0 = [
Some(0), Some(0),
Some(1), Some(1),
@@ -90,7 +90,7 @@ fn dijkstra() {
fn dijkstra_distances_single_vertex() { fn dijkstra_distances_single_vertex() {
let mut graph = AppendGraph::new(); let mut graph = AppendGraph::new();
let v1 = graph.add_vertex(); let v1 = graph.add_vertex();
let distances = algorithms::dijkstra_distances(&graph, v1); let distances = algorithms::dijkstra_distances_unweighted(&graph, v1);
assert_eq!( assert_eq!(
distances[v1], distances[v1],
Some(0), Some(0),
@@ -103,7 +103,7 @@ fn dijkstra_distances_disconnected() {
let mut graph = AppendGraph::new(); let mut graph = AppendGraph::new();
let v1 = graph.add_vertex(); let v1 = graph.add_vertex();
let v2 = graph.add_vertex(); let v2 = graph.add_vertex();
let distances = algorithms::dijkstra_distances(&graph, v1); let distances = algorithms::dijkstra_distances_unweighted(&graph, v1);
assert_eq!( assert_eq!(
distances[v1], distances[v1],
Some(0), Some(0),
@@ -118,7 +118,7 @@ fn dijkstra_distances_disconnected() {
#[test] #[test]
fn dijkstra_distances() { fn dijkstra_distances() {
let (graph, vertices) = make_test_graph(); let (graph, vertices) = make_test_graph();
let distances = algorithms::dijkstra_distances(&graph, vertices[0]); let distances = algorithms::dijkstra_distances_unweighted(&graph, vertices[0]);
let expected_distances_from_v0 = [ let expected_distances_from_v0 = [
Some(0), Some(0),
Some(1), Some(1),