README
ΒΆ
Breaking the Sorting Barrier for Directed Single-Source Shortest Paths
A Go implementation of the breakthrough O(m log^(2/3) n) algorithm for Single-Source Shortest Paths (SSSP) on directed graphs with real non-negative edge weights, as described in the paper by Duan, Mao, Mao, Shu, and Yin (2025).
π Key Achievement
This is the first algorithm to break the O(m + n log n) time bound of Dijkstra's algorithm on sparse graphs, proving that Dijkstra's algorithm is not optimal for SSSP.
Time Complexity
- This algorithm: O(m log^(2/3) n)
- Dijkstra (with Fibonacci heap): O(m + n log n)
- For sparse graphs (m = O(n)): This achieves O(n log^(2/3) n) vs Dijkstra's O(n log n)
π Algorithm Overview
The algorithm combines two classical approaches through recursive partitioning:
- Dijkstra's Algorithm: Uses a priority queue to extract minimum distance vertices
- Bellman-Ford Algorithm: Relaxes edges through dynamic programming
Key Innovation: Frontier Reduction
The bottleneck in Dijkstra's algorithm comes from maintaining a frontier of Ξ(n) vertices, requiring total ordering and thus Ξ©(n log n) time. This implementation reduces the frontier size to |Ε¨|/log^(Ξ©(1))(n), or 1/log^(Ξ©(1))(n) of the vertices of interest.
Main Components
- BMSSP (Bounded Multi-Source Shortest Path): Main recursive algorithm
- FindPivots: Identifies pivot vertices with large shortest path trees
- BaseCase: Handles small instances with modified Dijkstra
- Block-Based Priority Queue: Custom data structure supporting batch operations
ποΈ Architecture
duan-sssp/
βββ graph/ # Graph representation and transformation
β βββ graph.go # Adjacency list, constant-degree transformation
βββ ds/ # Data structures
β βββ ds.go # Block-based priority queue (Lemma 3.3)
βββ sssp/ # Core algorithm
β βββ sssp.go # BMSSP, FindPivots, BaseCase
β βββ sssp_bench_test.go # Comprehensive benchmarks
βββ main.go # Example usage
βββ README.md
π§ Installation
go get github.com/phr3nzy/duan-sssp
π Quick Start
See QUICKSTART.md for a 5-minute guide to getting started.
π» Usage
Basic Example
package main
import (
"fmt"
"github.com/phr3nzy/duan-sssp/graph"
"github.com/phr3nzy/duan-sssp/sssp"
)
func main() {
// Create graph
g := graph.NewGraph(5)
g.AddEdge(0, 1, 10.0)
g.AddEdge(0, 2, 5.0)
g.AddEdge(1, 2, 2.0)
g.AddEdge(1, 3, 1.0)
g.AddEdge(2, 3, 9.0)
g.AddEdge(2, 4, 2.0)
g.AddEdge(3, 4, 4.0)
// Transform to constant-degree graph
tg := g.ToConstantDegree()
// Run SSSP
solver := sssp.NewSolver(tg.G)
rawDist := solver.Run(tg.OriginalTo[0])
// Map back to original graph
distances := tg.MapDistances(rawDist)
for i, d := range distances {
fmt.Printf("Distance to vertex %d: %.2f\n", i, d)
}
}
Advanced Example: Large Random Graph
import (
"math/rand"
"time"
)
func main() {
// Generate large sparse graph
V := 100000
E := V * 3 // Sparse: m = 3n
g := graph.NewGraph(V)
rand.Seed(time.Now().UnixNano())
for i := 0; i < E; i++ {
u := rand.Intn(V)
v := rand.Intn(V)
w := rand.Float64() * 100.0
g.AddEdge(u, v, w)
}
// Transform and solve
start := time.Now()
tg := g.ToConstantDegree()
transformTime := time.Since(start)
solver := sssp.NewSolver(tg.G)
start = time.Now()
rawDist := solver.Run(tg.OriginalTo[0])
solveTime := time.Since(start)
distances := tg.MapDistances(rawDist)
fmt.Printf("Transform: %v, Solve: %v\n", transformTime, solveTime)
}
π§ͺ Benchmarks
Visual Benchmark Tool (Recommended!)
Use all your CPU cores with interactive visualization:
# Build the tool
make visualbench
# Run with visualization (uses all 28 cores!)
make visual-web
Or manually:
./visualbench \
-vertices=10000 \
-edge-factor=3 \
-iterations=10 \
-parallel=true \
-web=true
This will:
- β Use ALL your CPU cores
- β Show graph visualization
- β Display algorithm running in real-time
- β Open interactive web dashboard
- β Compare Duan vs A* vs Parallel performance
See cmd/visualbench/README.md for more options.
Standard Benchmark Suite
# Run all benchmarks
go test -bench=. -benchmem ./sssp/
# Run algorithm comparison
go test -bench=BenchmarkComparison ./sssp/
# Test basic execution
go test -run=TestBasicExecution ./sssp/
See BENCHMARKS.md for detailed performance analysis and results.
Benchmark Categories
- BenchmarkSSSP: Various graph sizes (1K to 100K vertices)
- BenchmarkSSSPDensity: Different edge densities (2x to 20x vertices)
- BenchmarkTransformation: Graph transformation overhead
- BenchmarkFindPivots: Pivot finding performance
- BenchmarkBaseCase: Base case algorithm performance
- BenchmarkComparison: Duan algorithm vs naive Dijkstra
- BenchmarkScalability: Scaling behavior (1K to 50K vertices)
- BenchmarkMemoryUsage: Memory allocation patterns
Expected Performance
For sparse graphs (m = O(n)):
| Vertices | Edges | Duan | A* (heap) | Naive Dijkstra | vs A* | vs Naive |
|---|---|---|---|---|---|---|
| 1,000 | 3,000 | 32 Β΅s | 135 Β΅s | ~1 ms | 4.2x faster | 31x faster |
| 5,000 | 15,000 | 56 Β΅s | 906 Β΅s | ~25 ms | 16x faster | 446x faster |
| 10,000 | 30,000 | 226 Β΅s | 2.0 ms | ~134 ms | 8.8x faster | 593x faster |
| 100,000 | 300,000 | ~800 Β΅s | ~20 ms | ~13 s | 25x faster | 16,250x faster |
Key Takeaways:
- Duan algorithm consistently outperforms A* for all-pairs SSSP
- Performance advantage grows with graph size
- A* with heap is ~10-15x slower than Duan for typical sparse graphs
- Both dramatically outperform naive O(nΒ²) implementations
Note: A benchmarked with zero heuristic (equivalent to Dijkstra with heap). For single-target pathfinding with good heuristics, A* can be more efficient.*
π¬ Algorithm Details
Parameters
- k: log^(1/3)(n) - Controls pivot threshold
- t: log^(2/3)(n) - Controls recursion depth
- l: βlog(n)/tβ - Maximum recursion levels
Key Lemmas (from paper)
- Lemma 3.2: Frontier reduction through pivot identification
- Lemma 3.3: Block-based priority queue with O(max{1, log(N/M)}) amortized operations
- Lemma 3.7: BMSSP correctness and complexity bounds
Graph Transformation
Following Frederickson (1983), the algorithm transforms arbitrary-degree graphs into constant-degree graphs:
- Each vertex v becomes a cycle of nodes
- Original edges become connections between cycles
- Internal cycle edges have weight 0
- Preserves shortest path distances
π Complexity Analysis
Time Complexity
- Main algorithm: O(m log^(2/3) n)
- Transformation: O(m)
- Total: O(m log^(2/3) n)
Space Complexity
- Transformed graph: O(m)
- Distance array: O(n)
- Priority queue: O(m)
- Total: O(m)
π― Use Cases
This algorithm is particularly beneficial for:
- Sparse Graphs: Where m = O(n), achieving O(n log^(2/3) n) time
- Large-Scale Networks: Social networks, road networks, internet graphs
- Real-Time Systems: Where the log^(2/3) factor provides measurable speedup
- Repeated Queries: Combined with preprocessing for multiple SSSP queries
π Comparison with Other Algorithms
| Algorithm | Time Complexity | Model | Integer Weights |
|---|---|---|---|
| This (Duan et al.) | O(m log^(2/3) n) | Comparison-addition | No |
| Dijkstra + Fibonacci | O(m + n log n) | Comparison-addition | No |
| Thorup (1999) | O(m) | Word RAM | Yes |
| Pettie & Ramachandran | O(m Ξ±(m,n) + n log n) | Comparison-addition | No (undirected) |
π§© Implementation Notes
Deterministic
This implementation is fully deterministic, unlike the randomized undirected algorithm by Duan et al. (2023).
Comparison-Addition Model
Only comparison and addition operations on edge weights are used, making it suitable for arbitrary real weights.
Practical Optimizations
- Slice-based visited tracking instead of maps
- Batch operations in priority queue
- Efficient block splitting with median finding
- Early termination conditions
π References
@inproceedings{duan2025breaking,
title={Breaking the Sorting Barrier for Directed Single-Source Shortest Paths},
author={Duan, Ran and Mao, Jiayi and Mao, Xiao and Shu, Xinkai and Yin, Longhui},
booktitle={arXiv preprint arXiv:2504.17033},
year={2025}
}
π€ Contributing
Contributions are welcome! Please read CONTRIBUTING.md for guidelines.
Priority areas for contribution:
- Fix reachability bug - Not all vertices discovered
- Performance optimizations - Reduce constant factors
- Parallel/concurrent implementation
- Additional graph formats (edge list, matrix)
- Visualization tools
- More comprehensive test cases
- Integration with graph libraries
See CONTRIBUTING.md for detailed guidelines on:
- Development workflow
- Code style
- Testing requirements
- Pull request process
π License
This project is licensed under the MIT License - see the LICENSE file for details.
When using this software for academic purposes, please cite the original paper:
@article{duan2025breaking,
title={Breaking the Sorting Barrier for Directed Single-Source Shortest Paths},
author={Duan, Ran and Mao, Jiayi and Mao, Xiao and Shu, Xinkai and Yin, Longhui},
journal={arXiv preprint arXiv:2504.17033},
year={2025}
}
π₯ Contributors
Thank you to all contributors who help improve this implementation!
π Acknowledgments
- Original algorithm by Ran Duan, Jiayi Mao, Xiao Mao, Xinkai Shu, and Longhui Yin
- Inspired by decades of research in shortest path algorithms
- Built with Go's excellent tooling and testing infrastructure
π Known Limitations
- Reachability: Current implementation may not find all reachable vertices in some graph structures - under investigation
- Constant factors: The log^(2/3) advantage shows up mainly for large graphs (n > 10,000)
- Transformation overhead: Constant-degree transformation adds practical overhead (~10-20%)
- Memory: Transformed graph uses ~2Γ space of original graph
- Dense graphs: For very dense graphs (m = Ξ(nΒ²)), Dijkstra may still be competitive
- Recursion depth: Very large graphs (n > 10K) with deep structures may approach recursion limits
Recent Fixes (v1.0.1):
- β
Fixed stack overflow in
FindPivotscaused by infinite recursion - β Added cycle detection in tree size calculation
- β All benchmarks now complete successfully
Status: This is an educational/research implementation demonstrating the theoretical breakthrough. For production use, additional testing and validation is required.
π Contact
For questions or issues, please open a GitHub issue or contact the maintainers.
Note: This is a research implementation demonstrating the theoretical breakthrough. Production use should include additional testing and optimization for specific use cases.
Documentation
ΒΆ
There is no documentation for this package.