bmssp is a Go implementation of the Bounded Multi-Source Shortest Path (BMSSP) algorithm, as described in the paper:
Breaking the Sorting Barrier for Directed Single-Source Shortest Paths
Ran Duan, Jiayi Mao, Xiao Mao, Xinkai Shu, Longhui Yin
arXiv:2504.17033
This algorithm solves the Single-Source Shortest Path (SSSP) problem on directed graphs with non-negative real edge weights in
- Advanced Algorithm: Implements the recursive BMSSP structure with pivot selection as described in the paper.
- Sparse Graph Optimization: Designed to outperform standard Dijkstra on large, sparse graphs.
- Gonum Integration: Includes an adapter for the popular gonum/graph library, allowing easy integration with existing Go implementations.
-
Hybrid Approach: Automatically falls back to highly optimized Dijkstra for small graphs (
$N < 1000$ ) to minimize overhead.
go get github.com/deicod/bmsspUse the native bmssp.Graph for maximum performance with dense integer indices.
package main
import (
"fmt"
"github.com/deicod/bmssp"
)
func main() {
// Create a graph with 5 vertices
g := bmssp.NewGraph(5)
// Add edges: u -> v (weight)
g.AddEdge(0, 1, 4.0)
g.AddEdge(0, 2, 2.0)
g.AddEdge(1, 2, 5.0)
g.AddEdge(1, 3, 10.0)
g.AddEdge(2, 3, 3.0)
g.AddEdge(3, 4, 1.0)
// Create solver
solver := bmssp.NewSolver(g)
// Find shortest path from vertex 0 to 4
dist, path := solver.Solve(0, 4)
fmt.Printf("Shortest Distance: %f\n", dist)
fmt.Printf("Path: %v\n", path)
}If you are using gonum/graph, you can use the built-in adapter.
package main
import (
"fmt"
"log"
"github.com/deicod/bmssp"
"gonum.org/v1/gonum/graph/simple"
)
func main() {
// Create a simple weighted directed graph
g := simple.NewWeightedDirectedGraph(0, 0)
n1 := g.NewNode()
n2 := g.NewNode()
g.AddNode(n1)
g.AddNode(n2)
// Add weighted edge
g.SetWeightedEdge(g.NewWeightedEdge(n1, n2, 42.0))
// Solve using BMSSP
dist, path, err := bmssp.SolveGonum(g, n1.ID(), n2.ID())
if err != nil {
log.Fatal(err)
}
fmt.Printf("Distance: %f\n", dist)
fmt.Printf("Path IDs: %v\n", path)
}The paper's algorithm achieves a time complexity of
-
$n$ : Number of vertices -
$m$ : Number of edges
This is achieved by avoiding the global sorting bottleneck of Dijkstra's algorithm (using a global priority queue). Instead, BMSSP maintains vertices in approximate order using block-based buckets and sorts them only when necessary ("lazy sorting") within recursive subproblems defined by selected "pivot" vertices.
The implementation follows the paper's structure:
- Pivot Selection: Identifies strategic vertices to partition the search space.
- Frontier Management: Uses the block-based D0/D1 structure with batch prepends and block pulls.
- Recursive Solving: A divide-and-conquer approach that solves subproblems with tighter distance bounds.
- Constant-Degree Reduction: Applies the cycle-based transformation from §2 for BMSSP runs and maps paths back to original vertices.
For small graphs or base cases of the recursion, a bounded version of Dijkstra's algorithm is used.
MIT