feat(directed): Customizable CH(CCH,Dibbelt 2014)——权重换绑 13–19× 于 CH 重建
- src/directed/cch.mbt:度量无关最小度贪心收缩 + 弦图补全一次成型, 换权只跑 basic customization(下三角 relax,无堆无搜索),查询同 CH 双向向上 Dijkstra 含 stall-on-demand - OSM 实测(benches/results/cch-osm-20260706.md):换权成本北京 1.90 s vs CH 全量重建 25.3 s(13.4×)、厦门 18.8×;查询相对双向 Dijkstra 4.4–7.9×(比 CH 慢 3.9–5.9×,论文已知取舍,诚实归档) - 守卫:差分 PBT 100 迭代(含换权 recustomize 再对拍)+ OSM 厦门 8 组守卫 + bench 全量对拍(原权/扰动权各一轮均一致) - 文档同步:双语 README 第 38 项、paper-to-code §4.7、slides/QA/ video_script/backlog/开发文章 7→8 种前沿算法 - 三后端 2161/2161 全绿 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
0eda5603da
commit
060fd43f41
|
|
@ -187,7 +187,7 @@ The current local guard passes with one environment warning: `moon publish
|
|||
|
||||
## Algorithm Catalog
|
||||
|
||||
当前已落地 **30 种经典图/路径算法** 与 **7 种前沿算法**。
|
||||
当前已落地 **30 种经典图/路径算法** 与 **8 种前沿算法**。
|
||||
CH / ALT / Hub Labeling 已有生产级稠密快路径变体(`src/directed/`)
|
||||
并附真实 OSM 路网基准证据(北京驾车网:CH 相对双向 Dijkstra
|
||||
**46×**,HL 距离查询 **0.44 µs(14304×)**,PHAST 一到全 SSSP
|
||||
|
|
@ -235,6 +235,7 @@ CH **16–25×**,RPHAST 目标子集限定再提 **6.9–9.8×**,见
|
|||
| 35 | 🔥 PHAST (一到全 SSSP) | [`src/directed/phast.mbt`](./src/directed/phast.mbt) | ✅ OSM 实测 6.15× | [Delling, Goldberg, Nowatzyk & Werneck 2011](https://doi.org/10.1109/IPDPS.2011.89) |
|
||||
| 36 | 🔥 Many-to-many 距离表 | [`src/directed/many_to_many.mbt`](./src/directed/many_to_many.mbt) | ✅ OSM 实测 16–25× | [Knopp, Sanders, Schultes, Schulz & Wagner 2007](https://doi.org/10.1137/1.9781611972870.4) |
|
||||
| 37 | 🔥 RPHAST (目标子集限定) | [`src/directed/rphast.mbt`](./src/directed/rphast.mbt) | ✅ OSM 实测 6.9–9.8× | [Delling, Goldberg, Nowatzyk & Werneck 2011](https://doi.org/10.1109/IPDPS.2011.89) |
|
||||
| 38 | 🔥 Customizable CH (CCH) | [`src/directed/cch.mbt`](./src/directed/cch.mbt) | ✅ OSM 实测换权 13–19× | [Dibbelt, Strasser & Wagner 2014](https://doi.org/10.1007/978-3-319-07959-2_24) |
|
||||
|
||||
> ✅ v0.0.1 = 源码 + 单元测试 + PBT 已合入主干
|
||||
> ✅ v0.0.2 = 新增算法(Prim / DAG-SP / 桥与割点 / 双向 Dijkstra),源码 + 单元测试已合入主干
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File scripts\release_guard.ps1
|
|||
|
||||
## 算法目录
|
||||
|
||||
当前已落地 **30 种经典图 / 路径算法** 与 **7 种前沿算法**。
|
||||
当前已落地 **30 种经典图 / 路径算法** 与 **8 种前沿算法**。
|
||||
CH / ALT / Hub Labeling 已有生产级稠密快路径变体(`src/directed/`)
|
||||
并附真实 OSM 路网基准证据(北京驾车网:CH 相对双向 Dijkstra
|
||||
**46×**,HL 距离查询 **0.44 µs(14304×)**,PHAST 一到全 SSSP
|
||||
|
|
@ -181,6 +181,7 @@ CH **16–25×**,RPHAST 目标子集限定再提 **6.9–9.8×**,见
|
|||
| 35 | 🔥 PHAST(一到全 SSSP) | `src/directed/phast.mbt` | ✅ OSM 实测 6.15× | Delling, Goldberg, Nowatzyk & Werneck 2011 |
|
||||
| 36 | 🔥 Many-to-many 距离表 | `src/directed/many_to_many.mbt` | ✅ OSM 实测 16–25× | Knopp, Sanders, Schultes, Schulz & Wagner 2007 |
|
||||
| 37 | 🔥 RPHAST(目标子集限定) | `src/directed/rphast.mbt` | ✅ OSM 实测 6.9–9.8× | Delling, Goldberg, Nowatzyk & Werneck 2011 |
|
||||
| 38 | 🔥 Customizable CH(CCH) | `src/directed/cch.mbt` | ✅ OSM 实测换权 13–19× | Dibbelt, Strasser & Wagner 2014 |
|
||||
|
||||
> 🔥 = **Rust `pathfinding` crate 未实现的独家算法**
|
||||
> 🧪 experimental = 源码与测试已存在,但 API / 性能证据尚未冻结
|
||||
|
|
|
|||
|
|
@ -0,0 +1,179 @@
|
|||
// osm_cch_bench.mbt —— 真实 OSM 路网上的 Customizable CH 基准。
|
||||
//
|
||||
// CCH 的卖点不是查询更快(其骨架无 witness 剪枝、比 CH 密),而是
|
||||
// **换权重只需 customization 而非整套重建**。本基准量三件事:
|
||||
// 1. 度量无关构建耗时(一次性,可跨权重复用);
|
||||
// 2. customization 耗时(换权成本)vs CH 全量重建耗时(对比项);
|
||||
// 3. CCH 查询耗时 vs CH / 双向 Dijkstra(代价全量对拍护栏,含换权
|
||||
// 后再 customize 的第二轮对拍)。
|
||||
// 执行约定与 osm_alt_bench.mbt 一致(预热/采样/中位数)。
|
||||
|
||||
///|
|
||||
/// 单数据集采集主体:返回 Markdown 证据。
|
||||
fn run_osm_cch_benchmark_on(
|
||||
dataset : String,
|
||||
n : Int,
|
||||
edge_count : Int,
|
||||
payload : Array[String],
|
||||
qcount : Int,
|
||||
warmup : Int,
|
||||
samples : Int,
|
||||
) -> String {
|
||||
let (g, rg) = build_osm_weighted_csr(n, edge_count, payload)
|
||||
let qrng = Lcg::new(query_seed_int)
|
||||
let queries : Array[(Int, Int)] = []
|
||||
for _ in 0..<qcount {
|
||||
queries.push((qrng.next() % n, qrng.next() % n))
|
||||
}
|
||||
// CH 全量重建耗时(换权时 CH 的必付成本,对比项)。
|
||||
let mut ch_opt : @dir.ContractionHierarchy? = None
|
||||
let ch_pre_us = elapsed(fn() {
|
||||
ch_opt = Some(@dir.ContractionHierarchy::build(g))
|
||||
})
|
||||
let ch = ch_opt.unwrap()
|
||||
// CCH 度量无关构建(含首次 customize)。
|
||||
let mut cch_opt : @dir.CustomizableCch? = None
|
||||
let cch_build_us = elapsed(fn() {
|
||||
cch_opt = Some(@dir.CustomizableCch::build(g))
|
||||
})
|
||||
let cch = cch_opt.unwrap()
|
||||
// 换权成本:customization 单独计时(中位数)。
|
||||
let cust_samples = collect_samples(warmup, samples, fn() { cch.customize(g) })
|
||||
let cust_med = csr_bench_median(cust_samples)
|
||||
// 代价全量对拍护栏(原权重)。
|
||||
let cf = @dir.SearchCtx::new(n)
|
||||
let cb = @dir.SearchCtx::new(n)
|
||||
let mut parity_ok = true
|
||||
for q in queries {
|
||||
let (s, t) = q
|
||||
let a = @dir.dijkstra_bidirectional_ctx(g, rg, cf, cb, s, t)
|
||||
match (a, cch.query_dist(s, t), ch.query(s, t)) {
|
||||
(Some((_, x)), Some(y), Some((_, z))) =>
|
||||
if x.to_int64() != y || x != z {
|
||||
parity_ok = false
|
||||
}
|
||||
(None, None, None) => ()
|
||||
_ => parity_ok = false
|
||||
}
|
||||
}
|
||||
// 查询耗时:双向 Dijkstra / CH / CCH。
|
||||
let sink : Array[Int64] = [0L]
|
||||
let dij_samples = collect_samples(warmup, samples, fn() {
|
||||
for q in queries {
|
||||
match @dir.dijkstra_bidirectional_ctx(g, rg, cf, cb, q.0, q.1) {
|
||||
Some((_, c)) => sink[0] = sink[0] + c.to_int64()
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
})
|
||||
let ch_samples = collect_samples(warmup, samples, fn() {
|
||||
for q in queries {
|
||||
match ch.query(q.0, q.1) {
|
||||
Some((_, c)) => sink[0] = sink[0] + c.to_int64()
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
})
|
||||
let cch_samples = collect_samples(warmup, samples, fn() {
|
||||
for q in queries {
|
||||
match cch.query_dist(q.0, q.1) {
|
||||
Some(c) => sink[0] = sink[0] + c
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
})
|
||||
let dij_med = csr_bench_median(dij_samples)
|
||||
let ch_med = csr_bench_median(ch_samples)
|
||||
let cch_med = csr_bench_median(cch_samples)
|
||||
let qd = qcount.to_double()
|
||||
// 换权重(全边权 ×3+7 扰动)后 customize,再对拍守卫语义。
|
||||
let edges2 : Array[(Int, Int, Int)] = []
|
||||
let mask = (1L << 21) - 1L
|
||||
for u in 0..<n {
|
||||
let stop = g.offsets[u + 1]
|
||||
for ei = g.offsets[u]; ei < stop; ei = ei + 1 {
|
||||
let pe = g.packed[ei]
|
||||
let v = (pe & mask).to_int()
|
||||
let w = (pe >> 21).to_int()
|
||||
edges2.push((u, v, w * 3 + 7))
|
||||
}
|
||||
}
|
||||
let g2 = @dir.WeightedCsr::from_edges(n, edges2)
|
||||
let rg2edges : Array[(Int, Int, Int)] = []
|
||||
for e in edges2 {
|
||||
rg2edges.push((e.1, e.0, e.2))
|
||||
}
|
||||
let rg2 = @dir.WeightedCsr::from_edges(n, rg2edges)
|
||||
let recust_us = elapsed(fn() { cch.customize(g2) })
|
||||
let mut parity2_ok = true
|
||||
for q in queries {
|
||||
let (s, t) = q
|
||||
let a = @dir.dijkstra_bidirectional_ctx(g2, rg2, cf, cb, s, t)
|
||||
match (a, cch.query_dist(s, t)) {
|
||||
(Some((_, x)), Some(y)) => if x.to_int64() != y { parity2_ok = false }
|
||||
(None, None) => ()
|
||||
_ => parity2_ok = false
|
||||
}
|
||||
}
|
||||
cch.customize(g)
|
||||
let tb = @infra_text.TextBuilder::new()
|
||||
tb.push_str("### \{dataset}(节点 \{n},边 \{edge_count})CCH\n\n")
|
||||
tb.push_str(
|
||||
"- 代价对拍一致(原权重): \{parity_ok}; 换权重后: \{parity2_ok}\n",
|
||||
)
|
||||
tb.push_str(
|
||||
"- CH 全量重建: \{ch_pre_us / 1.0e3} ms; CCH 度量无关构建(含首次 customize): \{cch_build_us / 1.0e3} ms\n",
|
||||
)
|
||||
tb.push_str(
|
||||
"- **customization(换权成本)中位: \{cust_med / 1.0e3} ms(相对 CH 重建 \{ch_pre_us / cust_med}×)**; 实测换权再绑: \{recust_us / 1.0e3} ms\n",
|
||||
)
|
||||
tb.push_str(
|
||||
"- 每查询中位: 双向 Dijkstra \{dij_med / qd} µs; CH \{ch_med / qd} µs; CCH \{cch_med / qd} µs(相对双向 Dijkstra \{dij_med / cch_med}×、相对 CH \{cch_med / ch_med}× 慢因子)\n",
|
||||
)
|
||||
if !parity_ok || !parity2_ok {
|
||||
tb.push_str(
|
||||
"\n**警告:代价对拍存在不一致,数字无效。**\n",
|
||||
)
|
||||
}
|
||||
tb.build()
|
||||
}
|
||||
|
||||
///|
|
||||
test "bench: collect real OSM road-network CCH artifacts" (b : @bench.T) {
|
||||
let xm_md = run_osm_cch_benchmark_on(
|
||||
"厦门驾车网", osm_xiamen_node_count, osm_xiamen_edge_count, osm_xiamen_payload,
|
||||
osm_bench_queries, csr_bench_warmup, csr_bench_samples,
|
||||
)
|
||||
let bj_md = run_osm_cch_benchmark_on(
|
||||
"北京驾车网", osm_beijing_node_count, osm_beijing_edge_count, osm_beijing_payload,
|
||||
osm_bench_queries, csr_bench_warmup, csr_bench_samples,
|
||||
)
|
||||
println("===OSM_CCH_EVIDENCE_BEGIN===")
|
||||
println(xm_md)
|
||||
println(bj_md)
|
||||
println("===OSM_CCH_EVIDENCE_END===")
|
||||
b.bench(name="osm_cch_artifacts_emitted", fn() {
|
||||
b.keep(xm_md.length() + bj_md.length())
|
||||
})
|
||||
}
|
||||
|
||||
///|
|
||||
test "guard: 真实 OSM 路网 CCH 代价对拍(前 8 组,含换权 customize)" {
|
||||
let (g, rg) = build_osm_weighted_csr(
|
||||
osm_xiamen_node_count, osm_xiamen_edge_count, osm_xiamen_payload,
|
||||
)
|
||||
let cch = @dir.CustomizableCch::build(g)
|
||||
let cf = @dir.SearchCtx::new(osm_xiamen_node_count)
|
||||
let cb = @dir.SearchCtx::new(osm_xiamen_node_count)
|
||||
let qrng = Lcg::new(query_seed_int)
|
||||
for _ in 0..<8 {
|
||||
let s = qrng.next() % osm_xiamen_node_count
|
||||
let t = qrng.next() % osm_xiamen_node_count
|
||||
let a = @dir.dijkstra_bidirectional_ctx(g, rg, cf, cb, s, t)
|
||||
match (a, cch.query_dist(s, t)) {
|
||||
(Some((_, x)), Some(y)) => assert_eq(x.to_int64(), y)
|
||||
(None, None) => ()
|
||||
_ => abort("reachability mismatch")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# Customizable CH(CCH)真实 OSM 路网证据(2026-07-06)
|
||||
|
||||
采集命令(与 osm_alt/ch 系列同口径:预热 3、采样 12、中位数、全查询代价对拍护栏):
|
||||
|
||||
```bash
|
||||
moon bench --target native -p benches/advanced_bench -f osm_cch_bench.mbt
|
||||
```
|
||||
|
||||
实现:`src/directed/cch.mbt`(Dibbelt, Strasser, Wagner 2014)。度量无关
|
||||
最小度贪心收缩 + 弦图补全一次成型,之后换权只跑 basic customization
|
||||
(下三角 relax,无堆无搜索),查询同 CH 双向向上 Dijkstra(含 stall)。
|
||||
|
||||
## 采集结果(原样粘贴)
|
||||
|
||||
### 厦门驾车网(节点 23925,边 54151)CCH
|
||||
|
||||
- 代价对拍一致(原权重): true; 换权重后: true
|
||||
- CH 全量重建: 2110.014022 ms; CCH 度量无关构建(含首次 customize): 363.730591 ms
|
||||
- **customization(换权成本)中位: 112.46901 ms(相对 CH 重建 18.760848183868607×)**; 实测换权再绑: 112.641383 ms
|
||||
- 每查询中位: 双向 Dijkstra 649.5853541666667 µs; CH 37.903656250000004 µs; CCH 147.80785416666666 µs(相对双向 Dijkstra 4.394795918180375×、相对 CH 3.899567186652783× 慢因子)
|
||||
|
||||
### 北京驾车网(节点 163501,边 406591)CCH
|
||||
|
||||
- 代价对拍一致(原权重): true; 换权重后: true
|
||||
- CH 全量重建: 25311.87677 ms; CCH 度量无关构建(含首次 customize): 5968.030457999999 ms
|
||||
- **customization(换权成本)中位: 1895.7728155 ms(相对 CH 重建 13.35174582262597×)**; 实测换权再绑: 1919.576763 ms
|
||||
- 每查询中位: 双向 Dijkstra 6131.049677083334 µs; CH 131.81360416666666 µs; CCH 780.2530208333334 µs(相对双向 Dijkstra 7.857771150357343×、相对 CH 5.9193664096064955× 慢因子)
|
||||
|
||||
## 结论(诚实口径)
|
||||
|
||||
- **换权成本(CCH 的卖点)**:北京 1.90 s vs CH 全量重建 25.3 s(**13.4×**),
|
||||
厦门 112 ms vs 2.11 s(**18.8×**)。适用于交通拥堵/自定义代价等频繁换权场景。
|
||||
- **度量无关构建**(一次性、可跨权重复用)也比 CH 重建快:北京 6.0 s、厦门 0.36 s。
|
||||
- **查询侧比 CH 慢 3.9–5.9×**(北京 780 µs vs 132 µs)——basic customization
|
||||
的骨架无 witness 剪枝、比 CH 密,这是 CCH 论文已知的取舍;相对双向
|
||||
Dijkstra 仍有 4.4–7.9× 加速。若查询占主导且权重稳定应选 CH/HL。
|
||||
- 正确性:48 组查询与双向 Dijkstra 全量对拍一致(原权重与 ×3+7 扰动换权后
|
||||
各一轮),另有 `src/directed/cch_test.mbt` 100 迭代差分 PBT(含换权
|
||||
recustomize 再对拍)与厦门网 8 组守卫测试。
|
||||
|
|
@ -129,7 +129,7 @@ Official contest page: <https://www.moonbitlang.cn/2026-scc>
|
|||
- Evidence: `docs/verification/paper-to-code-advanced.md` — CH (Geisberger 2008) / JPS (Harabor & Grastien 2011) / ALT (Goldberg & Harrelson 2005), paper construct → code lines → tests, plus documented departures (witness budget, uniform-cost JPS); production variants in section 4 add HL / PHAST / RPHAST / many-to-many traceability, and stall-on-demand is now implemented in `src/directed/ch.mbt`.
|
||||
- [x] Prepare defense assets.
|
||||
- Acceptance: slides, script, Q&A, and offline demo all reflect the current repository instead of future plans.
|
||||
- Evidence: `docs/presentation/slides.md`, `docs/presentation/video_script.md`, and `docs/rehearsal/qa.md` refreshed (2026-07-05) to cite measured OSM speedups and archived artifacts instead of hedged future-work language; bilingual READMEs list all 37 algorithms with identical status columns.
|
||||
- Evidence: `docs/presentation/slides.md`, `docs/presentation/video_script.md`, and `docs/rehearsal/qa.md` refreshed (2026-07-05) to cite measured OSM speedups and archived artifacts instead of hedged future-work language; bilingual READMEs list all 38 algorithms with identical status columns (CCH added 2026-07-06, `benches/results/cch-osm-20260706.md`).
|
||||
|
||||
## Next Attack Order
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ pub fn dijkstra[N, W](start, successors: (N) -> Array[(N, W)], goal) -> (Array[N
|
|||
| 图结构 | Kruskal / Connected Components / Tarjan SCC / Topo Sort | 已实现并测试 |
|
||||
| 流与匹配 | Edmonds-Karp / Kuhn-Munkres | 已实现并测试 |
|
||||
| 组合路径 | Bidirectional BFS / IDA* / Yen | 已实现并测试 |
|
||||
| 前沿方向 | CH / JPS / ALT / Hub Labeling / PHAST / RPHAST / many-to-many | 生产级实现 + OSM 真实路网实测(北京:CH 46×、HL 14304×)+ 论文追踪 |
|
||||
| 前沿方向 | CH / JPS / ALT / Hub Labeling / PHAST / RPHAST / many-to-many / CCH | 生产级实现 + OSM 真实路网实测(北京:CH 46×、HL 14304×、CCH 换权 13.4×)+ 论文追踪 |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -263,7 +263,7 @@ let result = ch_query(graph, source, target)
|
|||
| 可执行文档 | crate docs / tests | README.mbt.md 可由 `moon test` 执行 |
|
||||
| 合约验证 | 无内建证明链路 | runtime proof predicates 已测试 |
|
||||
| 多后端 | Rust native / wasm 需额外链路 | MoonBit wasm-gc / js / native CI 目标 |
|
||||
| 前沿算法 | 无 CH/HL/PHAST 等路网 SOTA | 7 种已实现,OSM 实测证据归档(benches/results/ch-osm-20260705.md) |
|
||||
| 前沿算法 | 无 CH/HL/PHAST 等路网 SOTA | 8 种已实现(含 CCH 权重换绑),OSM 实测证据归档(benches/results/ch-osm-20260705.md、cch-osm-20260706.md) |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
| 2:20-3:10 | README 即测试 | 运行 `moon test README.mbt.md`,说明 README 示例不是截图而是黑盒测试。 | 终端 + README |
|
||||
| 3:10-4:10 | Proof predicates | 展示 `src/proofs/bfs_proof.mbt` 与 `src/proofs/bfs_proof_test.mbt`,解释 runtime minimality witness。 | 代码高亮 |
|
||||
| 4:10-5:00 | 质量保障 | 运行 `scripts\acceptance.ps1 -SkipCoverage`,展示 check/fmt/test/doc/audit 链路。 | 终端录屏 |
|
||||
| 5:00-5:45 | 高级算法 | 展示 7 种前沿路网算法(CH/ALT/HL/PHAST/RPHAST/m2m/JPS)与 OSM 真实路网实测归档(北京 CH 46×、HL 0.44 µs/14304×)。 | PPT + benches/results |
|
||||
| 5:00-5:45 | 高级算法 | 展示 8 种前沿路网算法(CH/ALT/HL/PHAST/RPHAST/m2m/CCH/JPS)与 OSM 真实路网实测归档(北京 CH 46×、HL 0.44 µs/14304×、CCH 换权 13.4×)。 | PPT + benches/results |
|
||||
| 5:45-6:30 | 对标与差异化 | 对标 Rust pathfinding:MoonBit 原生、多后端、README doctest、runtime predicates、release evidence。 | 表格页 |
|
||||
| 6:30-7:00 | 路线图与结尾 | 下一步是边界回归、双语文档/答辩打磨、OSM benchmark 与 playground 取舍。 | 路线图页 |
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File scripts\acceptance.ps1 -Sk
|
|||
|
||||
### 对标与差异化 (5:45-6:30)
|
||||
|
||||
> “和 Rust pathfinding 对标,我避免使用无法一次证明的绝对化说法。当前能证明的差异化是:MoonBit 原生、多后端目标、README 可执行、runtime proof predicates、中英文文档、7 种前沿路网算法的生产级 MoonBit 实现、OSM 真实路网实测归档(北京 CH 46×、HL 14304×)、跨语言等价负载对比基础设施与 release readiness evidence。未验证的外部语言绑定不当作当前事实。”
|
||||
> “和 Rust pathfinding 对标,我避免使用无法一次证明的绝对化说法。当前能证明的差异化是:MoonBit 原生、多后端目标、README 可执行、runtime proof predicates、中英文文档、8 种前沿路网算法的生产级 MoonBit 实现(含 CCH 权重秒级换绑)、OSM 真实路网实测归档(北京 CH 46×、HL 14304×)、跨语言等价负载对比基础设施与 release readiness evidence。未验证的外部语言绑定不当作当前事实。”
|
||||
|
||||
### 路线图与结尾 (6:30-7:00)
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
> 2. successor function 风格适合 AI Agent 生成调用代码,也适合真实项目把数组、Map 或外部数据源接入。
|
||||
> 3. `README.mbt.md` 可被 `moon test` 执行,文档不是静态宣传页。
|
||||
> 4. runtime proof predicates 让路径合法性、代价一致性、BFS minimality 变成可运行检查。
|
||||
> 5. 7 种前沿路网算法(CH / ALT / HL / PHAST / RPHAST / m2m / JPS)Rust pathfinding 均未提供,且附真实 OSM 路网实测证据(北京 CH 46×、HL 14304×)。
|
||||
> 5. 8 种前沿路网算法(CH / ALT / HL / PHAST / RPHAST / m2m / CCH / JPS)Rust pathfinding 均未提供,且附真实 OSM 路网实测证据(北京 CH 46×、HL 14304×、CCH 换权 13.4×)。
|
||||
> 6. 跨语言等价工作负载对比基础设施(`bench_rust/` + 逐位一致随机源 + 黄金交叉校验)把“和 Rust 比”变成可复现命令而非口号。
|
||||
>
|
||||
> 也就是说,我的差异化不是“语言换皮”,而是把 MoonBit 的多后端、可执行文档和未来证明链路组合成一个可交付库。
|
||||
|
|
|
|||
|
|
@ -147,6 +147,22 @@ OSM 实测每对相对逐对 CH 北京 16.0× / 厦门 24.8×。
|
|||
- **ALT 生产级(`src/directed/alt.mbt`)**:farthest 选点 + 节点主序
|
||||
布局 + INF 统一截断保证下界可采纳一致;OSM 北京 6.6×。
|
||||
|
||||
### 4.7 Customizable CH 生产级(`src/directed/cch.mbt`)
|
||||
|
||||
- **论文**:Dibbelt, Strasser & Wagner 2014(Customizable Route Planning
|
||||
in Road Networks 谱系)。
|
||||
- **实现要点**:度量无关最小度贪心收缩 + 弦图补全一次成型
|
||||
(`CustomizableCch::build`);换权只跑 basic customization——按
|
||||
rank 升序下三角 relax(`customize`,无堆无搜索);查询与 CH 同款
|
||||
双向向上 Dijkstra 含 stall-on-demand(`query_dist`)。
|
||||
- **测试**:`src/directed/cch_test.mbt` 差分 PBT 100 迭代(含同拓扑
|
||||
换权重 recustomize 再对拍);`benches/advanced_bench/osm_cch_bench.mbt`
|
||||
厦门网 8 组守卫。
|
||||
- **OSM 实测**(`benches/results/cch-osm-20260706.md`):换权成本北京
|
||||
1.90 s vs CH 全量重建 25.3 s(**13.4×**)、厦门 **18.8×**;查询比 CH
|
||||
慢 3.9–5.9×(论文已知取舍,无 witness 剪枝骨架更密),相对双向
|
||||
Dijkstra 仍 4.4–7.9×。
|
||||
|
||||
---
|
||||
|
||||
## 5. 取舍与已知边界(答辩 Q&A 素材)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ NetworkX,而 MoonBit 在本项目之前没有对应基础设施。
|
|||
而是真实 OSM 路网上可测量的数量级加速;
|
||||
3. **可信度**:每个声明都有可复现证据,每个优化都有差分测试守卫。
|
||||
|
||||
最终交付:**30 种经典算法 + 7 种前沿路网算法**,三后端
|
||||
最终交付:**30 种经典算法 + 8 种前沿路网算法**,三后端
|
||||
(native / wasm-gc / js)2158 项测试全绿,真实北京驾车路网上
|
||||
距离查询从双向 Dijkstra 的 6.3 ms 压到 Hub Labeling 的
|
||||
**0.44 µs(14304×)**。
|
||||
|
|
@ -135,7 +135,7 @@ PHAST(Delling 2011)把一到全查询拆成向上 Dijkstra + rank 降序
|
|||
的用例标注并排除。方法学声明、机器信息与两套工具链版本全部写进
|
||||
报告工件(`benches/results/latest-rust-comparison.{md,json}`)。
|
||||
|
||||
差异化不在"语言换皮",而在 Rust `pathfinding` 未提供的 7 种
|
||||
差异化不在"语言换皮",而在 Rust `pathfinding` 未提供的 8 种
|
||||
前沿路网算法,以及 MoonBit 的多后端一键部署(同一份算法代码
|
||||
驱动 native 基准与浏览器 playground)。
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,375 @@
|
|||
// cch.mbt —— Customizable Contraction Hierarchies(Dibbelt, Strasser,
|
||||
// Wagner 2014)。
|
||||
//
|
||||
// CH 的预处理把「收缩序 + 捷径拓扑」与「边权」耦合在一起:权重一变
|
||||
// (交通拥堵、限行、自定义代价)就要整套重建(OSM 北京 ~24.6 s)。
|
||||
// CCH 把两者解耦:
|
||||
// 1. **度量无关阶段**(一次性):只看拓扑,按最小度贪心序收缩,
|
||||
// 对被删节点的存活邻居对补骨架边(弦图补全,不做 witness 搜索
|
||||
// ——没有权重可搜);
|
||||
// 2. **customization**(每次换权,毫秒~秒级):把原图权写进骨架
|
||||
// 边的上/下行两个方向,再按 rank 升序枚举每个节点的上邻三角
|
||||
// 做下三角 relax,使上行图恢复最短路保持性;
|
||||
// 3. **查询**:与 CH 相同的双向「向上」Dijkstra(含 stall-on-
|
||||
// demand),距离与原图 Dijkstra 一致。
|
||||
//
|
||||
// 语义由差分 PBT(含换权重再 customize 再对拍)与 OSM 全量对拍守卫。
|
||||
|
||||
///|
|
||||
/// CCH 产物:度量无关骨架(拓扑 + 收缩序)与当前 customize 的权。
|
||||
/// 骨架边按低 rank 端点分桶存高 rank 邻居(上邻表,按节点编号有序,
|
||||
/// 供三角枚举二分定位),每条骨架边带两个可换绑方向权。
|
||||
pub struct CustomizableCch {
|
||||
n : Int
|
||||
/// rank[v] = 收缩序(越大越重要)。
|
||||
rank : Array[Int]
|
||||
/// rank 升序节点序(customization 处理序)。
|
||||
ord : Array[Int]
|
||||
/// 上邻 CSR:fo[u]..fo[u+1] 为低端点 u 的高 rank 邻居(按编号有序)。
|
||||
fo : Array[Int]
|
||||
ft : Array[Int]
|
||||
/// 上行方向权 u→v(customize 写入;INF_DIST = 无原图对应)。
|
||||
fw : Array[Int64]
|
||||
/// 下行方向权 v→u。
|
||||
gw : Array[Int64]
|
||||
// 查询暂存(代戳懒失效,单线程复用)。
|
||||
df : Array[Int64]
|
||||
db : Array[Int64]
|
||||
sf : Array[Int]
|
||||
sb : Array[Int]
|
||||
mut gen : Int
|
||||
hf : RadixHeap
|
||||
hb : RadixHeap
|
||||
}
|
||||
|
||||
///|
|
||||
/// 有序数组二分查 target,返回下标或 -1。
|
||||
fn cch_bsearch(ft : Array[Int], lo0 : Int, hi0 : Int, target : Int) -> Int {
|
||||
let mut lo = lo0
|
||||
let mut hi = hi0
|
||||
while lo < hi {
|
||||
let mid = lo + (hi - lo) / 2
|
||||
let t = ft[mid]
|
||||
if t == target {
|
||||
return mid
|
||||
} else if t < target {
|
||||
lo = mid + 1
|
||||
} else {
|
||||
hi = mid
|
||||
}
|
||||
}
|
||||
-1
|
||||
}
|
||||
|
||||
///|
|
||||
/// 度量无关构建:最小度贪心懒更新收缩 + 弦图补全,随后用 g 的权做
|
||||
/// 首次 customization。拓扑只依赖 g 的边集(方向合并为无向骨架)。
|
||||
pub fn CustomizableCch::build(g : WeightedCsr) -> CustomizableCch {
|
||||
let n = g.node_count()
|
||||
let mask = (1L << NODE_BITS) - 1L
|
||||
// 无向骨架邻接:每节点有序邻居表(二分去重/删除)。
|
||||
let adj : Array[Array[Int]] = []
|
||||
for _ in 0..<n {
|
||||
adj.push([])
|
||||
}
|
||||
fn adj_insert(a : Array[Int], v : Int) -> Unit {
|
||||
let mut lo = 0
|
||||
let mut hi = a.length()
|
||||
while lo < hi {
|
||||
let mid = lo + (hi - lo) / 2
|
||||
if a[mid] == v {
|
||||
return
|
||||
} else if a[mid] < v {
|
||||
lo = mid + 1
|
||||
} else {
|
||||
hi = mid
|
||||
}
|
||||
}
|
||||
a.insert(lo, v)
|
||||
}
|
||||
|
||||
fn adj_remove(a : Array[Int], v : Int) -> Unit {
|
||||
let mut lo = 0
|
||||
let mut hi = a.length()
|
||||
while lo < hi {
|
||||
let mid = lo + (hi - lo) / 2
|
||||
if a[mid] == v {
|
||||
let _ = a.remove(mid)
|
||||
return
|
||||
} else if a[mid] < v {
|
||||
lo = mid + 1
|
||||
} else {
|
||||
hi = mid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for u in 0..<n {
|
||||
let stop = g.offsets[u + 1]
|
||||
for ei = g.offsets[u]; ei < stop; ei = ei + 1 {
|
||||
let v = (g.packed[ei] & mask).to_int()
|
||||
if v != u {
|
||||
adj_insert(adj[u], v)
|
||||
adj_insert(adj[v], u)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 最小度贪心(懒更新:pop 后度数变了就按当前度重新入队)。
|
||||
let rank = Array::make(n, -1)
|
||||
let ord = Array::make(n, 0)
|
||||
let heap = RadixHeap::new()
|
||||
heap.reset(0L)
|
||||
for v in 0..<n {
|
||||
heap.push((adj[v].length().to_int64() << NODE_BITS) | v.to_int64())
|
||||
}
|
||||
// 收缩时定稿的上邻表(v 收缩瞬间的存活邻居即其全部高 rank 邻居)。
|
||||
let ups : Array[Array[Int]] = []
|
||||
for _ in 0..<n {
|
||||
ups.push([])
|
||||
}
|
||||
let mut next_rank = 0
|
||||
let mut edge_total = 0
|
||||
while heap.len > 0 {
|
||||
let enc = heap.pop()
|
||||
let v = (enc & mask).to_int()
|
||||
if rank[v] >= 0 {
|
||||
continue
|
||||
}
|
||||
let deg = adj[v].length()
|
||||
if (enc >> NODE_BITS).to_int() != deg {
|
||||
heap.push((deg.to_int64() << NODE_BITS) | v.to_int64())
|
||||
continue
|
||||
}
|
||||
rank[v] = next_rank
|
||||
ord[next_rank] = v
|
||||
next_rank = next_rank + 1
|
||||
let nbrs = adj[v]
|
||||
edge_total = edge_total + nbrs.length()
|
||||
for i = 0; i < nbrs.length(); i = i + 1 {
|
||||
ups[v].push(nbrs[i])
|
||||
}
|
||||
// 弦图补全:存活邻居两两连边,并把 v 从各邻接表中摘除。
|
||||
for i = 0; i < nbrs.length(); i = i + 1 {
|
||||
let a = nbrs[i]
|
||||
adj_remove(adj[a], v)
|
||||
for j = i + 1; j < nbrs.length(); j = j + 1 {
|
||||
let b = nbrs[j]
|
||||
adj_insert(adj[a], b)
|
||||
adj_insert(adj[b], a)
|
||||
}
|
||||
}
|
||||
adj[v].clear()
|
||||
}
|
||||
// 上邻 CSR(ups[v] 收缩时即有序,直接铺平)。
|
||||
let fo = Array::make(n + 1, 0)
|
||||
for v in 0..<n {
|
||||
fo[v + 1] = fo[v] + ups[v].length()
|
||||
}
|
||||
let ft = Array::make(edge_total, 0)
|
||||
for v in 0..<n {
|
||||
let base = fo[v]
|
||||
let uv = ups[v]
|
||||
for i = 0; i < uv.length(); i = i + 1 {
|
||||
ft[base + i] = uv[i]
|
||||
}
|
||||
}
|
||||
let cch = {
|
||||
n,
|
||||
rank,
|
||||
ord,
|
||||
fo,
|
||||
ft,
|
||||
fw: Array::make(edge_total, INF_DIST),
|
||||
gw: Array::make(edge_total, INF_DIST),
|
||||
df: Array::make(n, 0L),
|
||||
db: Array::make(n, 0L),
|
||||
sf: Array::make(n, 0),
|
||||
sb: Array::make(n, 0),
|
||||
gen: 0,
|
||||
hf: RadixHeap::new(),
|
||||
hb: RadixHeap::new(),
|
||||
}
|
||||
cch.customize(g)
|
||||
cch
|
||||
}
|
||||
|
||||
///|
|
||||
/// 换绑权重:把 g 的边权写进骨架(拓扑必须与 build 时同边集),再做
|
||||
/// basic customization——按 rank 升序对每个节点的上邻对做下三角
|
||||
/// relax,恢复上行图的最短路保持性。O(骨架三角数),无堆无搜索。
|
||||
pub fn CustomizableCch::customize(
|
||||
self : CustomizableCch,
|
||||
g : WeightedCsr,
|
||||
) -> Unit {
|
||||
let mask = (1L << NODE_BITS) - 1L
|
||||
let fw = self.fw
|
||||
let gw = self.gw
|
||||
let ft = self.ft
|
||||
let fo = self.fo
|
||||
for ei = 0; ei < fw.length(); ei = ei + 1 {
|
||||
fw[ei] = INF_DIST
|
||||
gw[ei] = INF_DIST
|
||||
}
|
||||
// 原图权注入:u→v 落在骨架边 {u,v} 的对应方向上(保留更小权)。
|
||||
for u in 0..<self.n {
|
||||
let stop = g.offsets[u + 1]
|
||||
for ei = g.offsets[u]; ei < stop; ei = ei + 1 {
|
||||
let pe = g.packed[ei]
|
||||
let v = (pe & mask).to_int()
|
||||
if v == u {
|
||||
continue
|
||||
}
|
||||
let w = pe >> NODE_BITS
|
||||
if self.rank[u] < self.rank[v] {
|
||||
let idx = cch_bsearch(ft, fo[u], fo[u + 1], v)
|
||||
if fw[idx] > w {
|
||||
fw[idx] = w
|
||||
}
|
||||
} else {
|
||||
let idx = cch_bsearch(ft, fo[v], fo[v + 1], u)
|
||||
if gw[idx] > w {
|
||||
gw[idx] = w
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 下三角 relax:三角 {x,u,v}(rank x < u < v),经 x 的两跳收紧
|
||||
// 骨架边 {u,v} 的两个方向。
|
||||
for oi = 0; oi < self.n; oi = oi + 1 {
|
||||
let x = self.ord[oi]
|
||||
let stop = fo[x + 1]
|
||||
for i = fo[x]; i < stop; i = i + 1 {
|
||||
let a = ft[i]
|
||||
for j = i + 1; j < stop; j = j + 1 {
|
||||
let b = ft[j]
|
||||
let (u, eu, v, ev) = if self.rank[a] < self.rank[b] {
|
||||
(a, i, b, j)
|
||||
} else {
|
||||
(b, j, a, i)
|
||||
}
|
||||
let idx = cch_bsearch(ft, fo[u], fo[u + 1], v)
|
||||
// u→x→v 收紧上行 u→v;v→x→u 收紧下行 v→u。
|
||||
let up = gw[eu] + fw[ev]
|
||||
if up < fw[idx] {
|
||||
fw[idx] = up
|
||||
}
|
||||
let dn = gw[ev] + fw[eu]
|
||||
if dn < gw[idx] {
|
||||
gw[idx] = dn
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///|
|
||||
/// 点对点距离查询:双向「向上」Dijkstra(前向走上行权、后向走下行
|
||||
/// 权,均含 stall-on-demand),会合取 min。不可达返回 `None`。语义
|
||||
/// 与 `dijkstra_csr` 的 s→t 距离一致。
|
||||
pub fn CustomizableCch::query_dist(
|
||||
self : CustomizableCch,
|
||||
start : Int,
|
||||
target : Int,
|
||||
) -> Int64? {
|
||||
if start < 0 || start >= self.n || target < 0 || target >= self.n {
|
||||
return None
|
||||
}
|
||||
self.gen = self.gen + 1
|
||||
let gen = self.gen
|
||||
let mask = (1L << NODE_BITS) - 1L
|
||||
let df = self.df
|
||||
let db = self.db
|
||||
let sf = self.sf
|
||||
let sb = self.sb
|
||||
let fo = self.fo
|
||||
let ft = self.ft
|
||||
let fw = self.fw
|
||||
let gw = self.gw
|
||||
let hf = self.hf
|
||||
let hb = self.hb
|
||||
hf.reset(0L)
|
||||
hb.reset(0L)
|
||||
df[start] = 0L
|
||||
sf[start] = gen
|
||||
hf.push(start.to_int64())
|
||||
db[target] = 0L
|
||||
sb[target] = gen
|
||||
hb.push(target.to_int64())
|
||||
let mut mu = INF_DIST
|
||||
while hf.len > 0 || hb.len > 0 {
|
||||
let ff = if hf.len > 0 { hf.peek() >> NODE_BITS } else { INF_DIST }
|
||||
let fb = if hb.len > 0 { hb.peek() >> NODE_BITS } else { INF_DIST }
|
||||
if ff >= mu && fb >= mu {
|
||||
break
|
||||
}
|
||||
if ff <= fb {
|
||||
let enc = hf.pop()
|
||||
let u = (enc & mask).to_int()
|
||||
let du = enc >> NODE_BITS
|
||||
if du > df[u] {
|
||||
continue
|
||||
}
|
||||
let stop = fo[u + 1]
|
||||
// stall-on-demand:更高 rank 上邻 v 经下行 v→u 更短则免松弛。
|
||||
let mut stalled = false
|
||||
for ei = fo[u]; ei < stop; ei = ei + 1 {
|
||||
let v = ft[ei]
|
||||
if sf[v] == gen && df[v] + gw[ei] < du {
|
||||
stalled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if stalled {
|
||||
continue
|
||||
}
|
||||
if sb[u] == gen && du + db[u] < mu {
|
||||
mu = du + db[u]
|
||||
}
|
||||
for ei = fo[u]; ei < stop; ei = ei + 1 {
|
||||
let v = ft[ei]
|
||||
let nd = du + fw[ei]
|
||||
if nd < INF_DIST && (sf[v] != gen || nd < df[v]) {
|
||||
df[v] = nd
|
||||
sf[v] = gen
|
||||
hf.push((nd << NODE_BITS) | v.to_int64())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let enc = hb.pop()
|
||||
let u = (enc & mask).to_int()
|
||||
let du = enc >> NODE_BITS
|
||||
if du > db[u] {
|
||||
continue
|
||||
}
|
||||
let stop = fo[u + 1]
|
||||
let mut stalled = false
|
||||
for ei = fo[u]; ei < stop; ei = ei + 1 {
|
||||
let v = ft[ei]
|
||||
if sb[v] == gen && db[v] + fw[ei] < du {
|
||||
stalled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if stalled {
|
||||
continue
|
||||
}
|
||||
if sf[u] == gen && du + df[u] < mu {
|
||||
mu = du + df[u]
|
||||
}
|
||||
for ei = fo[u]; ei < stop; ei = ei + 1 {
|
||||
let v = ft[ei]
|
||||
let nd = du + gw[ei]
|
||||
if nd < INF_DIST && (sb[v] != gen || nd < db[v]) {
|
||||
db[v] = nd
|
||||
sb[v] = gen
|
||||
hb.push((nd << NODE_BITS) | v.to_int64())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if mu >= INF_DIST {
|
||||
None
|
||||
} else {
|
||||
Some(mu)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
// cch_test.mbt —— Customizable CH 黑盒测试:距离与 Dijkstra 差分 PBT,
|
||||
// 核心场景是**换权重后 customize 再对拍**(CCH 相对 CH 的价值所在)。
|
||||
|
||||
///|
|
||||
test "CustomizableCch basic: chain with recustomization" {
|
||||
let edges : Array[(Int, Int, Int)] = [
|
||||
(0, 1, 2),
|
||||
(1, 2, 3),
|
||||
(2, 3, 4),
|
||||
(0, 3, 10),
|
||||
]
|
||||
let g = @directed.WeightedCsr::from_edges(4, edges)
|
||||
let cch = @directed.CustomizableCch::build(g)
|
||||
assert_true(cch.query_dist(0, 3) is Some(9L))
|
||||
assert_true(cch.query_dist(3, 0) is None)
|
||||
assert_true(cch.query_dist(2, 2) is Some(0L))
|
||||
// 换权重(同拓扑):直连边变便宜,链路变贵。
|
||||
let edges2 : Array[(Int, Int, Int)] = [
|
||||
(0, 1, 20),
|
||||
(1, 2, 30),
|
||||
(2, 3, 40),
|
||||
(0, 3, 10),
|
||||
]
|
||||
let g2 = @directed.WeightedCsr::from_edges(4, edges2)
|
||||
cch.customize(g2)
|
||||
assert_true(cch.query_dist(0, 3) is Some(10L))
|
||||
assert_true(cch.query_dist(0, 2) is Some(50L))
|
||||
}
|
||||
|
||||
///|
|
||||
test "CustomizableCch differential PBT vs dijkstra (100 iterations, 含换权重 customize 再对拍)" {
|
||||
let rng = @infra_pbt.rng_new(0xCC_47AC7UL)
|
||||
for iter in 0..<100 {
|
||||
let n = 2 + rng.next_below(50)
|
||||
let m = rng.next_below(n * 3)
|
||||
let us : Array[Int] = []
|
||||
let vs : Array[Int] = []
|
||||
let edges : Array[(Int, Int, Int)] = []
|
||||
for _ in 0..<m {
|
||||
let u = rng.next_below(n)
|
||||
let mut v = rng.next_below(n)
|
||||
if v == u {
|
||||
v = (u + 1) % n
|
||||
}
|
||||
us.push(u)
|
||||
vs.push(v)
|
||||
edges.push(
|
||||
(
|
||||
u,
|
||||
v,
|
||||
if iter % 3 == 2 {
|
||||
1 + rng.next_below(60) + 2000
|
||||
} else {
|
||||
1 + rng.next_below(60)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
let g = @directed.WeightedCsr::from_edges(n, edges)
|
||||
let cch = @directed.CustomizableCch::build(g)
|
||||
let ctx = @directed.SearchCtx::new(n)
|
||||
for _q in 0..<6 {
|
||||
let s = rng.next_below(n)
|
||||
let t = rng.next_below(n)
|
||||
let expect = @directed.dijkstra_indexed_ctx(g, ctx, s, t)
|
||||
let got = cch.query_dist(s, t)
|
||||
match (expect, got) {
|
||||
(Some((_, ec)), Some(gc)) => assert_eq(gc, ec.to_int64())
|
||||
(None, None) => ()
|
||||
_ => abort("reachability mismatch (initial customize)")
|
||||
}
|
||||
}
|
||||
// 同拓扑换权重:只跑 customize(不重建),再与 Dijkstra 对拍。
|
||||
let edges2 : Array[(Int, Int, Int)] = []
|
||||
for i = 0; i < m; i = i + 1 {
|
||||
edges2.push((us[i], vs[i], 1 + rng.next_below(500)))
|
||||
}
|
||||
let g2 = @directed.WeightedCsr::from_edges(n, edges2)
|
||||
cch.customize(g2)
|
||||
for _q in 0..<6 {
|
||||
let s = rng.next_below(n)
|
||||
let t = rng.next_below(n)
|
||||
let expect = @directed.dijkstra_indexed_ctx(g2, ctx, s, t)
|
||||
let got = cch.query_dist(s, t)
|
||||
match (expect, got) {
|
||||
(Some((_, ec)), Some(gc)) => assert_eq(gc, ec.to_int64())
|
||||
(None, None) => ()
|
||||
_ => abort("reachability mismatch (recustomize)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -132,6 +132,26 @@ pub fn ContractionHierarchy::query(Self, Int, Int) -> (Array[Int], Int)?
|
|||
pub fn ContractionHierarchy::rphast_query(Self, RphastTargets, Int, Array[Int64]) -> Unit
|
||||
pub fn ContractionHierarchy::rphast_targets(Self, Array[Int]) -> RphastTargets
|
||||
|
||||
pub struct CustomizableCch {
|
||||
n : Int
|
||||
rank : Array[Int]
|
||||
ord : Array[Int]
|
||||
fo : Array[Int]
|
||||
ft : Array[Int]
|
||||
fw : Array[Int64]
|
||||
gw : Array[Int64]
|
||||
df : Array[Int64]
|
||||
db : Array[Int64]
|
||||
sf : Array[Int]
|
||||
sb : Array[Int]
|
||||
mut gen : Int
|
||||
hf : RadixHeap
|
||||
hb : RadixHeap
|
||||
}
|
||||
pub fn CustomizableCch::build(WeightedCsr) -> Self
|
||||
pub fn CustomizableCch::customize(Self, WeightedCsr) -> Unit
|
||||
pub fn CustomizableCch::query_dist(Self, Int, Int) -> Int64?
|
||||
|
||||
type EncodedHeap
|
||||
|
||||
pub struct HubLabels {
|
||||
|
|
|
|||
Loading…
Reference in New Issue