From 5857c44492e2ce157b6d68a30f9e686d66708a0b Mon Sep 17 00:00:00 2001 From: ApsisRS contributors Date: Fri, 2 Oct 2026 01:25:10 +0800 Subject: [PATCH] docs: bilingual comments for mesh and routing --- crates/network/apsis-mesh/src/mesh.rs | 79 +++++++++++++++++++++++ crates/network/apsis-routing/src/route.rs | 64 ++++++++++++++++++ 2 files changed, 143 insertions(+) diff --git a/crates/network/apsis-mesh/src/mesh.rs b/crates/network/apsis-mesh/src/mesh.rs index ac3dfc3..f1bad9b 100644 --- a/crates/network/apsis-mesh/src/mesh.rs +++ b/crates/network/apsis-mesh/src/mesh.rs @@ -4,20 +4,32 @@ use crate::connectivity::{edge_connectivity, reachable_from, strongly_connected_ use apsis_topology::Topology; /// A link whose removal would change the connectivity of the mesh. +/// +/// 一条移除后会改变网格连通性的链路。 #[derive(Debug, Clone, Copy, PartialEq)] pub struct CriticalLink { /// The node the link leaves. + /// + /// 该链路离开的节点。 pub from: usize, /// The node the link arrives at. + /// + /// 该链路到达的节点。 pub to: usize, /// The cost of the link. + /// + /// 该链路的代价。 pub cost: f64, /// The number of components the mesh has after the link is removed. + /// + /// 移除该链路后网格所具有的分量数。 pub components_without: usize, } impl CriticalLink { /// Creates a critical link record. + /// + /// 创建关键链路记录。 pub const fn new(from: usize, to: usize, cost: f64, components_without: usize) -> Self { Self { from, @@ -29,15 +41,25 @@ impl CriticalLink { } /// A summary of the connectivity of a mesh. +/// +/// 网格连通性的摘要。 #[derive(Debug, Clone, PartialEq)] pub struct MeshSummary { /// The number of terminals. + /// + /// 终端的数量。 pub node_count: usize, /// The number of directed links. + /// + /// 有向链路的数量。 pub edge_count: usize, /// The number of components when the links are treated as undirected. + /// + /// 把链路视为无向时的分量数。 pub components: usize, /// The number of strongly connected components. + /// + /// 强连通分量的数量。 pub strongly_connected_components: usize, /// The smallest number of independent paths between any two distinct /// terminals, or `None` when there are fewer than two terminals. @@ -45,6 +67,12 @@ pub struct MeshSummary { /// This is the worst connection in the mesh. A value of one means some /// pair of terminals relies on a single link and the mesh has no /// redundancy anywhere. + /// + /// 任意两个不同终端之间独立路径条数的最小值;终端少于两个时返回 + /// `None`。 + /// + /// 这是网格中最差的连接。值为一意味着某对终端依赖单条链路,网格 + /// 处处都无冗余。 pub minimum_connectivity: Option, } @@ -53,6 +81,11 @@ pub struct MeshSummary { /// The mesh wraps a topology and adds the connectivity measures a mesh /// application needs. It does not own a schedule or a traffic model; those /// belong to the caller. +/// +/// 由链路连接的终端构成的网格。 +/// +/// 网格封装一个拓扑并加入网格应用所需的连通性度量。它不拥有调度或业务 +/// 模型;那些属于调用方。 #[derive(Debug, Clone, PartialEq)] pub struct Mesh { topology: Topology, @@ -60,32 +93,44 @@ pub struct Mesh { impl Mesh { /// Creates a mesh over a topology. + /// + /// 在某拓扑之上创建网格。 pub const fn new(topology: Topology) -> Self { Self { topology } } /// Returns the underlying topology. + /// + /// 返回底层拓扑。 pub const fn topology(&self) -> &Topology { &self.topology } /// Returns the number of terminals. + /// + /// 返回终端的数量。 pub fn node_count(&self) -> usize { self.topology.node_count() } /// Returns the number of links. + /// + /// 返回链路的数量。 pub fn edge_count(&self) -> usize { self.topology.edge_count() } /// Returns `true` when every terminal reaches every other, treating the /// links as undirected. + /// + /// 把链路视为无向时,当每个终端都能到达其余每个终端,返回 `true`。 pub fn is_connected(&self) -> bool { self.topology.is_connected() } /// Returns the terminals reachable from a terminal. + /// + /// 返回自某终端可达的各终端。 pub fn reachable_from(&self, source: usize) -> Vec { reachable_from(&self.topology, source) } @@ -94,6 +139,10 @@ impl Mesh { /// /// Returns `None` when either terminal is out of range or the two are /// the same. + /// + /// 返回两个终端之间独立路径的条数。 + /// + /// 任一终端越界或两者相同时返回 `None`。 pub fn edge_connectivity(&self, source: usize, destination: usize) -> Option { edge_connectivity(&self.topology, source, destination) } @@ -102,6 +151,10 @@ impl Mesh { /// distinct terminals. /// /// Returns `None` when there are fewer than two terminals. + /// + /// 返回任意两个不同终端之间独立路径条数的最小值。 + /// + /// 终端少于两个时返回 `None`。 pub fn minimum_connectivity(&self) -> Option { let node_count = self.topology.node_count(); if node_count < 2 { @@ -134,6 +187,18 @@ impl Mesh { /// Links that are not bridges are omitted, so an empty result means /// every link lies on a cycle and the mesh survives any single link /// failure without splitting. + /// + /// 返回移除后会增加连通分量数的那些链路,把每条链路视为无向。 + /// + /// 它们是网格底层无向图的桥。一条链路只报告一次,即便它有双向, + /// 因为一次失效是整条链路失效而非其中一个方向。 + /// + /// 每个候选通过在两方向移除该链路并比较分量数来发现,这精确但每条 + /// 链路要花一次遍历。对卫星网所呈现的图规模而言这是可接受的,且比 + /// 线性时间的桥查找算法更易验证。 + /// + /// 非桥的链路被省略,故空结果意味着每条链路都在某个环上,网格在 + /// 任何单条链路失效下都不会裂开。 pub fn critical_links(&self) -> Vec { let baseline = self.topology.connected_components(); let mut critical = Vec::new(); @@ -142,6 +207,7 @@ impl Mesh { for edge in self.topology.edges() { // Canonicalize the pair so that the two directions of one link // are considered together and reported once. + // 规范化该点对,使一条链路的两个方向被一并考虑并只报告一次。 let pair = if edge.from <= edge.to { (edge.from, edge.to) } else { @@ -154,6 +220,7 @@ impl Mesh { // Remove the link in every direction in which it is present, // which is what a link failure does. + // 在它出现的每个方向上移除该链路,这正是链路失效所做的。 let mut without = self.topology.clone(); let _ = without.remove_edge(pair.0, pair.1); let _ = without.remove_edge(pair.1, pair.0); @@ -172,6 +239,11 @@ impl Mesh { /// This is the condition for the mesh to have a single link failure /// tolerance, which is the minimum redundancy a network carrying traffic /// without interruption should have. + /// + /// 当网格在任何单条链路失效下都不裂开时返回 `true`。 + /// + /// 这是网格具备单链路失效容错的条件,而这是不中断地承载业务的网络 + /// 应有的最低冗余。 pub fn survives_single_link_failure(&self) -> bool { self.critical_links().is_empty() } @@ -181,11 +253,18 @@ impl Mesh { /// For a mesh of directed links this counts the pieces that can route /// internally. A value above one means some terminals cannot be reached /// from some others. + /// + /// 返回强连通分量的数量。 + /// + /// 对有向链路的网格而言,它统计可各自内部路由的块数。大于一的值 + /// 意味着有些终端无法从另一些到达。 pub fn strongly_connected_components(&self) -> usize { strongly_connected_components(&self.topology) } /// Returns a summary of the mesh connectivity. + /// + /// 返回网格连通性的摘要。 pub fn summarise(&self) -> MeshSummary { MeshSummary { node_count: self.topology.node_count(), diff --git a/crates/network/apsis-routing/src/route.rs b/crates/network/apsis-routing/src/route.rs index 8acd612..218bf61 100644 --- a/crates/network/apsis-routing/src/route.rs +++ b/crates/network/apsis-routing/src/route.rs @@ -4,18 +4,31 @@ /// /// A step records the link traversed and the cost of that link, so a caller /// can attribute a route's total cost to its parts. +/// +/// 路由的一跳。 +/// +/// 一个步骤记录所穿越的链路及其代价,使调用方能把路由的总代价归因于 +/// 各部分。 #[derive(Debug, Clone, Copy, PartialEq)] pub struct RouteStep { /// The node the step leaves. + /// + /// 该步骤离开的节点。 pub from: usize, /// The node the step arrives at. + /// + /// 该步骤到达的节点。 pub to: usize, /// The cost of the link. + /// + /// 该链路的代价。 pub cost: f64, } impl RouteStep { /// Creates a step. + /// + /// 创建一个步骤。 pub const fn new(from: usize, to: usize, cost: f64) -> Self { Self { from, to, cost } } @@ -26,13 +39,24 @@ impl RouteStep { /// The node list includes both endpoints, so a route of one hop has two /// nodes and one step, and a route from a node to itself has one node and no /// steps. +/// +/// 两个节点之间的路由。 +/// +/// 节点列表包含两个端点,故一跳的路由有两个节点和一个步骤,自某节点到 +/// 其自身的路由有一个节点且没有步骤。 #[derive(Debug, Clone, PartialEq)] pub struct Route { /// The nodes in order, from the source to the destination. + /// + /// 按次序排列的节点,从源到目的地。 pub nodes: Vec, /// The links traversed, in order. + /// + /// 按次序穿越的链路。 pub steps: Vec, /// The total cost of the route. + /// + /// 该路由的总代价。 pub cost: f64, } @@ -41,12 +65,18 @@ impl Route { /// /// The cost is taken as the sum of the step costs, so a caller cannot /// make the total disagree with the parts. + /// + /// 由其节点与步骤创建路由。 + /// + /// 代价取各步骤代价之和,故调用方无法使总计与各部分不一致。 pub fn new(nodes: Vec, steps: Vec) -> Self { let cost = steps.iter().map(|step| step.cost).sum(); Self { nodes, steps, cost } } /// Returns the number of hops. + /// + /// 返回跳数。 pub fn hop_count(&self) -> usize { self.steps.len() } @@ -54,6 +84,10 @@ impl Route { /// Returns the source node. /// /// Returns `None` when the route has no nodes. + /// + /// 返回源节点。 + /// + /// 路由没有节点时返回 `None`。 pub fn source(&self) -> Option { self.nodes.first().copied() } @@ -61,6 +95,10 @@ impl Route { /// Returns the destination node. /// /// Returns `None` when the route has no nodes. + /// + /// 返回目的地节点。 + /// + /// 路由没有节点时返回 `None`。 pub fn destination(&self) -> Option { self.nodes.last().copied() } @@ -70,6 +108,11 @@ impl Route { /// The costs are unchanged, because a route reversed traverses the same /// links. This is only correct when every link is present in both /// directions with the same cost, which a caller must ensure. + /// + /// 返回按相反方向穿越的路由。 + /// + /// 各代价不变,因为反转后的路由穿越同样的链路。仅当每条链路都以 + /// 相同代价双向存在时才正确,这一点须由调用方保证。 pub fn reversed(&self) -> Self { let nodes = self.nodes.iter().rev().copied().collect(); let steps = self @@ -82,32 +125,49 @@ impl Route { } /// Returns `true` when the route passes through a node. + /// + /// 当该路由经过某节点时返回 `true`。 pub fn passes_through(&self, node: usize) -> bool { self.nodes.contains(&node) } /// Returns the position of a node in the route, if it is on it. + /// + /// 返回某节点在路由中的位置(若在该路由上)。 pub fn position_of(&self, node: usize) -> Option { self.nodes.iter().position(|candidate| *candidate == node) } } /// A route with the interval over which it is valid. +/// +/// 一条路由及其有效的时段。 #[derive(Debug, Clone, PartialEq)] pub struct RouteLeg { /// The route. + /// + /// 该路由。 pub route: Route, /// The time from which the route is valid, in seconds. + /// + /// 该路由开始有效的时间,单位为秒。 pub start_seconds: f64, /// The time until which the route is valid, in seconds. /// /// This is the time of the topology change that invalidates the route. /// It is infinite when the route is valid for all later times. + /// + /// 该路由保持有效直到的时间,单位为秒。 + /// + /// 这是使该路由失效的拓扑变化的时间。当该路由对其后所有时间都有效 + /// 时它为无穷。 pub end_seconds: f64, } impl RouteLeg { /// Creates a route leg. + /// + /// 创建一段路由。 pub const fn new(route: Route, start_seconds: f64, end_seconds: f64) -> Self { Self { route, @@ -119,6 +179,10 @@ impl RouteLeg { /// Returns the duration for which the route holds, in seconds. /// /// Returns infinity when the route is valid for all later times. + /// + /// 返回该路由保持的时长,单位为秒。 + /// + /// 该路由对其后所有时间都有效时返回无穷。 pub fn duration_seconds(&self) -> f64 { self.end_seconds - self.start_seconds }