chore: stop tracking .claude/, keep agent tooling local
The vendored agent skills under .claude/ are development tooling, not part of the library: nothing there is compiled, imported, or published. Tracking them also meant redistributing third-party skill content, and six of the nine bundled skill directories carried no upstream LICENSE file — a claim docs/THIRD_PARTY.md made but the tree did not back up.
Untrack the directory, widen the ignore rule from .claude/worktrees/ to .claude/, and rewrite THIRD_PARTY.md §2 to record the tooling as local-only and explicitly not redistributed.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9
京公网安备 11010802047560号
petgraph for MoonBit
English | 中文
Rust petgraph 库的 MoonBit 移植——快速、灵活的 图数据结构与算法,支持任意结点/边数据的有向图与无向图。
@graph—— 邻接表Graph[N, E](有向 & 无向),带类型化的NodeId/EdgeId、 邻居与边引用遍历、边查找、map/filter_map/retain_*变换,以及稳定的 swap-remove 语义。@unionfind—— 并查集(按秩合并 + 路径压缩)。@visit—— 遍历器Dfs、Bfs、DfsPostOrder、Topo,事件驱动的depth_first_search,以及可与上述全部遍历器组合使用的视图适配器Reversed、NodeFiltered、EdgeFiltered与UndirectedAdaptor。@algo—— 35 个算法:最短路径(Dijkstra、A*、Bellman–Ford、Floyd–Warshall、 Johnson、SPFA、双向 Dijkstra、k 最短路径)、连通性(强连通分量、割点、桥、支配树、 凝聚图、二分图判定)、生成树与 Steiner 树、最大流(Ford–Fulkerson、Dinic)、 匹配(贪心与 Gabow 带花树算法)、着色、极大团、简单路径枚举、反馈弧集,以及 DAG 传递归约。@dot—— 导出 Graphviz DOT 用于可视化。未移植的部分:petgraph 的其他图表示(
StableGraph、GraphMap、MatrixGraph、Csr、adj::List)、其 serde 支持,以及 graph6 / DOT 解析器。当前的范围边界见docs/TODO.md。项目目标
提供一个清晰、地道、充分测试的 MoonBit 图库,其行为与 petgraph 一致,并配备持续集成、 文档与可复现的示例。架构与 Rust→MoonBit 的适配取舍见
docs/DESIGN.md。安装
这是一个标准的 MoonBit 模块。把它作为依赖加入你的项目:
然后在你所在包的
moon.pkg里按需导入子包:从源码构建本仓库:
使用
构建一张图、运行算法、查看结果。下面这个示例会作为测试套件的一部分被编译并运行。
用
@dot+ Graphviz 渲染后,上面这张无向图看起来是这样:图中每个椭圆是一个结点(标签是结点权重,本例设为其下标
0–3),每条连线是一条 无向边(标签是边权,这里都是1)。这正是上面构建的四元环0–1–2–3–0:从结点0出发的dijkstra距离为{0: 0, 1: 1, 2: 2, 3: 1},而min_spanning_tree会保留 4 条边 中的 3 条——丢弃环上的一条边。把图导出为 Graphviz DOT 以便可视化:
遍历与环检测:
计算最大流:
通过视图适配器遍历一张图——
Reversed沿反方向走边,而不必构造一份反向副本;由于它实现了 与Graph相同的NeighborSourcetrait,因此适用于所有遍历器:支持的接口
本库拆分为若干聚焦的子包,按需导入即可。下面采用 MoonBit 记法:
~表示带标签参数,?表示可选参数或Option结果,raise表示可能抛出受检错误。@graph—— 图数据结构Graph::new()/Graph::new_undirected()、Graph::with_capacity(nodes, edges),以及from_edges(pairs)/from_edges_undirected(pairs)——从(src, dst)下标对构建Graph[Int, Unit]。add_node(w) -> NodeId、add_edge(a, b, w) -> EdgeId、update_edge(a, b, w)(新增或覆盖)、remove_node(n) -> N?、remove_edge(e) -> E?(swap-remove,返回被删权重)、set_node_weight/set_edge_weight、clear、clear_edges、reverse。node_count、edge_count、is_directed、node_weight(n) -> N?、edge_weight(e) -> E?、edge_endpoints(e) -> (NodeId, NodeId)?、find_edge(a, b) -> EdgeId?、find_edge_undirected、contains_edge。Iter):node_ids() -> Iter[NodeId]、edge_ids() -> Iter[EdgeId]、node_weights() -> Iter[N]、edge_weights() -> Iter[E]、neighbors(n)/neighbors_directed(n, dir)/neighbors_undirected(n) -> Iter[NodeId]、edges_directed(n, dir) -> Iter[EdgeId]、externals(dir) -> Iter[NodeId](源点 / 汇点)。edges(n) -> Iter[EdgeRef[E]](端点已归一化,source恒为n,无向边 也是如此——正是这一点让带权算法在无向图上保持正确)、edge_references() -> Iter[EdgeRef[E]](所有边,端点按存储形式给出)、edges_connecting(a, b) -> Iter[EdgeId]。map(node_map, edge_map)/filter_map(node_map, edge_map)构建权重类型不同的新图,retain_nodes(pred)/retain_edges(pred)就地过滤,extend_with_edges(pairs)、into_nodes_edges()。first_edge(n, dir) -> EdgeId?、next_edge(e, dir) -> EdgeId?。NodeId/EdgeId(::new、::index)、EdgeRef[E](id/source/target/weight)、Direction(Outgoing/Incoming、.opposite())、Directedness,以及遍历与算法所泛化依赖的NeighborSourcetrait。@unionfind—— 并查集(按秩合并 + 路径压缩)UnionFind::new(n)/new_empty()、new_set() -> Int(追加一个元素)。union(a, b) -> Bool、same_set(a, b) -> Bool、find(x) -> Int、into_labeling() -> Array[Int],以及带边界检查、返回Option的try_union/try_same_set/try_find。@visit—— 遍历Dfs、Bfs、DfsPostOrder、Topo:::new(graph[, start]),随后.next(graph) -> NodeId?;用reset/move_to重启。泛化于任意NeighborSource。每个遍历器还提供.iter(graph) -> Iter[NodeId]和.walker(graph) -> Walker,便于以迭代器方式驱动,而不必手写next循环。depth_first_search(graph, starts, visitor)—— 事件驱动的 DFS;visitor收到一个DfsEvent(Discover/TreeEdge/BackEdge/CrossForwardEdge/Finish), 返回一个Control(Continue/Prune/Break)。NeighborSource,因此所有遍历器与所有以NeighborSource泛化的算法都能原样作用其上,并且它们彼此之间还可以组合:Reversed(g)—— 交换Outgoing/Incoming。NodeFiltered::from_fn(g, pred)—— 隐藏不满足pred的结点。EdgeFiltered::from_fn(g, pred)—— 隐藏不满足pred的边;因为需要边的标识, 所以只对具体的Graph[N, E]生效。UndirectedAdaptor(g)—— 把有向图当作无向图呈现。VisitMap—— 以NodeId为键、可复用的已访问集合。@algo—— 算法dijkstra(g, start~, goal?, edge_cost~) -> Map[NodeId, K]、astar(g, start~, is_goal~, edge_cost~, estimate_cost~) -> (K, Array[NodeId])?、bellman_ford(g, source~, edge_cost~) -> BellmanFordPaths[K] raise NegativeCycle、spfa(基于队列的 Bellman–Ford)、bidirectional_dijkstra、k_shortest_path、find_negative_cycle(g, source~, edge_cost~) -> Array[NodeId]?。floyd_warshall、johnson(Bellman–Ford 势能 + 逐源点 Dijkstra,因此允许负权边)。toposort(g) -> Array[NodeId] raise Cycle、is_cyclic_directed(g)、is_cyclic_undirected(g)、greedy_feedback_arc_set(g) -> Array[EdgeId]。connected_components(g) -> Int、kosaraju_scc(g)/tarjan_scc(g) -> Array[Array[NodeId]]、condensation(g, make_acyclic)、articulation_points(g)、bridges(g)、has_path_connecting(g, a, b, space?)、is_bipartite_undirected(g, start)、simple_fast(g, root) -> Dominators(Cooper–Harvey–Kennedy 支配树)。min_spanning_tree(g, edge_cost~) -> Array[EdgeId](Kruskal)、min_spanning_tree_prim(g, edge_cost~)(Prim)、steiner_tree(g, terminals, edge_cost~)(Kou 近似算法)。ford_fulkerson(g, source~, destination~, edge_cost~)与dinics(...),均返回(max_flow, per_edge_flows)。greedy_matching(g)与maximum_matching(g)(Gabow 带花树算法, 在一般非二分图上同样正确),返回一个Matching,提供mate/contains_edge/is_perfect/edges/nodes。maximal_cliques(g)(带枢轴的 Bron–Kerbosch)、all_simple_paths/all_simple_paths_multi(惰性)、dsatur_coloring(g) -> (Map[NodeId, Int], Int)。dag_to_toposorted_adjacency_list、dag_transitive_reduction_closure。Measuretrait(zero/add/compare)。 需要饱和的「不可达」值、带溢出检查的松弛或减法的算法——Floyd–Warshall、Johnson、 两个最大流算法、Steiner——使用BoundedMeasure : Measure(max_value/checked_add/sub)。两个 trait 都已为Int与Double实现。@dot—— Graphviz 导出to_dot(g, config?) -> String(要求N : Show、E : Show);config是DotConfig标志数组:NodeIndexLabel、EdgeIndexLabel、EdgeNoLabel、NodeNoLabel、GraphContentOnly。to_dot只生成 DOT 字符串;要渲染成图片需要安装 Graphviz(例如apt-get install graphviz),再把字符串 通过dot渲染:或把字符串贴到在线查看器,例如 GraphvizOnline。
从 Rust petgraph 迁移
本移植的 API 高度贴合 petgraph——大多数名字完全一致,petgraph 代码几乎原样可读。 只有少数几处为顺应 MoonBit 惯用法做了有意的调整。完全一致的命名
@graph:Graph::new/new_undirected/with_capacity/from_edges;add_node/add_edge/update_edge/remove_node/remove_edge;node_weight/edge_weight/edge_endpoints/find_edge/find_edge_undirected/contains_edge/node_count/edge_count/is_directed/externals/reverse;neighbors/neighbors_directed/neighbors_undirected。@algo:dijkstra、astar、bellman_ford、spfa、floyd_warshall、johnson、k_shortest_path、bidirectional_dijkstra、find_negative_cycle、toposort、is_cyclic_directed、is_cyclic_undirected、greedy_feedback_arc_set、connected_components、kosaraju_scc、tarjan_scc、condensation、articulation_points、bridges、simple_fast、has_path_connecting、is_bipartite_undirected、min_spanning_tree、min_spanning_tree_prim、steiner_tree、ford_fulkerson、dinics、greedy_matching、maximum_matching、maximal_cliques、dsatur_coloring、all_simple_paths、all_simple_paths_multi、dag_transitive_reduction_closure。@visit:Dfs、Bfs、DfsPostOrder、Topo、depth_first_search、DfsEvent、Control、Reversed、NodeFiltered、EdgeFiltered、Direction::{Outgoing, Incoming}。@unionfind:UnionFind——union/find/find_mut/new_set/into_labeling。有意的差异
NodeIndex/EdgeIndexNodeId/EdgeId(保留.index())node_indices()/edge_indices()node_ids()/edge_ids()NodeId改名Neighbors、NodeIndices等)Iter[T]for x in …用法完全一致toposort -> Result<_, Cycle>toposort(…) raise Cycletry … catch捕获bellman_ford -> Result<_, NegativeCycle>… raise NegativeCycleTy类型参数(Directed/Undirected)new与new_undirected二选一Measure/FloatMeasure/PositiveMeasure/BoundedMeasureMeasure与BoundedMeasure(Int、Double)GraphBase/IntoNeighbors/Visitable/ …(18 个 trait)pub(open) trait NeighborSourceEdgeReference(借用)EdgeRef[E](拥有所有权的结构体,derive(Debug))min_spanning_tree -> Iterator<Element>-> Array[EdgeId]steiner_tree -> StableGraph-> Array[EdgeId]StableGraphdinics在source == destination时挂死文档
docs/DESIGN.md—— 架构与设计决策(英文)。docs/TESTING.md—— 测试方式说明(英文)。docs/TODO.md—— 范围与迁移进度(英文)。docs/THIRD_PARTY.md—— 上游 petgraph 的署名、许可证, 以及被参考内容的范围(英文)。中文文档:
docs/测试文档.md—— 详细测试文档(用例清单、覆盖率、缺陷修复)。docs/开发报告.md—— 开发报告(目标、设计决策、流程、问题与复现)。许可证
采用 MIT 或 Apache-2.0 双重许可,与上游 petgraph 保持一致。