docs: complete the bilingual module docs for the ops and sim layers
This commit is contained in:
parent
b4f61085ce
commit
57316092eb
|
|
@ -1,7 +1,5 @@
|
|||
//! Resource modeling for satellite operations.
|
||||
//!
|
||||
//! 卫星运行的资源建模。
|
||||
//!
|
||||
//! A resource is anything a task can occupy: a satellite, a ground station, a
|
||||
//! transmitter, an onboard recorder. This crate models the two things a
|
||||
//! scheduler needs to know about one: when it is available, and how much of
|
||||
|
|
@ -34,6 +32,23 @@
|
|||
//! assert!(resource.is_available_over(120.0, 80.0));
|
||||
//! assert!(!resource.is_available_over(150.0, 100.0));
|
||||
//! ```
|
||||
//!
|
||||
//! 卫星运行的资源建模。
|
||||
//!
|
||||
//! 资源是任务可以占用的任何东西:一颗卫星、一座地面站、一台发射机、一台星载
|
||||
//! 记录器。本 crate 为调度器需要了解的关于它的两件事建模:它何时可用,以及一个
|
||||
//! 任务消耗它多少。
|
||||
//!
|
||||
//! 可用性表达为单一时间轴上互不相交的区间集合,称为窗口。在某瞬时有窗口包含该
|
||||
//! 瞬时,资源即可用。这些窗口可来自任何地方:`apsis-access` 中的可见性分析为
|
||||
//! 地面站产生它们,操作员则手工录入维护时段。
|
||||
//!
|
||||
//! 容量是一个正数,其含义由调用方定义。一次只能运行一项观测的卫星容量为一;记录
|
||||
//! 器的容量以兆比特计;功率母线的以瓦特计。两个任务只有在它们的需求合起来超过
|
||||
//! 容量时才冲突,这使同一个类型既能表达独占资源也能表达共享资源。
|
||||
//!
|
||||
//! 时间以距调用方所选原点的秒数计,故同一模型可服务于场景时钟、流逝时间与儒略日
|
||||
//! 偏移。
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
//! Schedule representation and evaluation.
|
||||
//!
|
||||
//! 调度的表示与评估。
|
||||
//!
|
||||
//! A schedule is the answer a scheduler produces: for each task, when it runs
|
||||
//! and on which resources. This crate holds that answer and evaluates it.
|
||||
//! It does not decide the placements, which is the job of `apsis-scheduler`;
|
||||
|
|
@ -32,6 +30,18 @@
|
|||
//! assert_eq!(schedule.len(), 1);
|
||||
//! assert!(schedule.is_placed(TaskId::new(0)));
|
||||
//! ```
|
||||
//!
|
||||
//! 调度的表示与评估。
|
||||
//!
|
||||
//! 调度是调度器所产生的答案:对每个任务,它何时运行以及在哪些资源上运行。本
|
||||
//! crate 保存该答案并评估它。它不决定放置,那是 `apsis-scheduler` 的事;把二者
|
||||
//! 分开,使一个调度可以从文件读取、由调度器产生,或手工书写,并以相同方式评估。
|
||||
//!
|
||||
//! 一处放置记录任务、其开始时间,以及它所持有的资源。放置时各资源会针对任务的需求
|
||||
//! 检查,故调度无法描述一个运行在它并未请求的资源上的任务。
|
||||
//!
|
||||
//! 评估报告操作员对已完成计划所问的:放置了多少任务、每种资源在其最繁忙时被用去
|
||||
//! 多少,以及可用时间实际花去多少。这些数字正是规划器在候选调度之间比较的。
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
//! Scheduling algorithms for satellite task planning.
|
||||
//!
|
||||
//! 卫星任务规划的调度算法。
|
||||
//!
|
||||
//! A scheduler takes a list of tasks and a set of resources and produces a
|
||||
//! schedule. This crate provides a greedy scheduler and the pieces needed to
|
||||
//! build others.
|
||||
|
|
@ -41,6 +39,23 @@
|
|||
//! assert_eq!(result.schedule.len(), 1);
|
||||
//! assert!(result.is_complete());
|
||||
//! ```
|
||||
//!
|
||||
//! 卫星任务规划的调度算法。
|
||||
//!
|
||||
//! 调度器接收任务列表与资源集合,产生一个调度。本 crate 提供一个贪心调度器以及
|
||||
//! 构建其他调度器所需的构件。
|
||||
//!
|
||||
//! 带资源约束的调度一般是难解的:判定是否每个任务都放得下是一个装箱问题,它是
|
||||
//! NP 难的。卫星规划问题规模小,有数百个任务而非数百万个,但对例行的规划周期而言,
|
||||
//! 精确搜索仍不切实际。故此处的调度器是贪心启发式。
|
||||
//!
|
||||
//! 该算法把任务排序,并把每个放到其全部资源同时空闲的最早时间。任务按加权价值递减
|
||||
//! 的次序考虑,这是一个好的启发式:最有价值的工作先被放置,最不有价值的填充剩余
|
||||
//! 空隙。强制任务不论其价值都先放置,因为一个必须运行的任务比任何可以运行的任务
|
||||
//! 都值更多。
|
||||
//!
|
||||
//! 结果不保证最优,且本 crate 报告它无法放置的内容而非无声丢弃,使操作员能看到该
|
||||
//! 计划的代价。
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
//! Task modeling for satellite operations.
|
||||
//!
|
||||
//! 卫星运行的任务建模。
|
||||
//!
|
||||
//! A task is a unit of work that a scheduler places on a set of resources. It
|
||||
//! carries everything a scheduler needs to decide whether and where to run
|
||||
//! it: how long it takes, when it may run, which resources it needs and in
|
||||
|
|
@ -35,6 +33,19 @@
|
|||
//! assert_eq!(task.requirements.len(), 2);
|
||||
//! assert!(task.is_valid());
|
||||
//! ```
|
||||
//!
|
||||
//! 卫星运行的任务建模。
|
||||
//!
|
||||
//! 任务是调度器放置到一组资源上的工作单元。它携带调度器决定是否运行它、在哪里
|
||||
//! 运行它所需的一切:耗时多久、何时可以运行、需要哪些资源及多少量,以及它值多少。
|
||||
//!
|
||||
//! 一个任务在其整个时长内同时需要它的全部资源。这是观测所具有的模型:取数期间
|
||||
//! 卫星与地面站必须都可用。需要按序使用资源的任务,表达为两个由
|
||||
//! [`PrecedenceGraph`] 中先后约束连接的任务,该约束说一个任务必须在另一个开始
|
||||
//! 之前完成。
|
||||
//!
|
||||
//! 任务一旦构建便不可变。调度器赋给它的状态分开保存在调度中,使同一个任务可以
|
||||
//! 被考虑用于多处放置而不被修改。
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
//! Simulation event types and event queue.
|
||||
//!
|
||||
//! 仿真事件类型与事件队列。
|
||||
//!
|
||||
//! A discrete-event simulation advances by jumping from one event to the
|
||||
//! next rather than by stepping through every instant. This crate provides
|
||||
//! the queue that makes that possible: a priority queue ordered by time,
|
||||
|
|
@ -31,6 +29,19 @@
|
|||
//! assert_eq!(event.time, 5.0);
|
||||
//! assert_eq!(event.payload, "first");
|
||||
//! ```
|
||||
//!
|
||||
//! 仿真事件类型与事件队列。
|
||||
//!
|
||||
//! 离散事件仿真通过从一个事件跳到下一个来推进,而不是逐步走过每个瞬时。本 crate
|
||||
//! 提供使之成为可能的队列:一个按时间排序的优先队列,并在落在同一瞬时的各事件之间
|
||||
//! 有明确定义的次序。
|
||||
//!
|
||||
//! 该并列打破规则比它初看更重要。为同一瞬时调度的两个事件必须以可重复的次序投递,
|
||||
//! 否则仿真每次运行都会产生不同结果,与另一实现的交叉核对也不可能。故每个事件携带
|
||||
//! 一个在调度时赋予的序号,时间相等的事件按该序号排序,故该次序即它们被调度的次序。
|
||||
//! 这是每个离散事件仿真器所用的约定。
|
||||
//!
|
||||
//! 时间以距仿真起点的秒数计,故队列对日历与时标一无所知。
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
//! Simulation output recording.
|
||||
//!
|
||||
//! 仿真输出记录。
|
||||
//!
|
||||
//! A simulation produces more output than a caller can act on at once: event
|
||||
//! times, the values a model computes as it runs, and the warnings it raises.
|
||||
//! This crate collects those into one trace, so that a run can be examined
|
||||
|
|
@ -34,6 +32,22 @@
|
|||
//! assert_eq!(recorder.trace().value_of("altitude"), Some(550.0));
|
||||
//! let _ = RecordKind::Warning;
|
||||
//! ```
|
||||
//!
|
||||
//! 仿真输出记录。
|
||||
//!
|
||||
//! 一次仿真产生的输出多到调用方无法一次全部处理:事件时刻、模型运行时计算的值,以及
|
||||
//! 它提出的警告。本 crate 把这些收集进一条轨迹,使一次运行可以在结束后被检视,而不
|
||||
//! 只在发生时。
|
||||
//!
|
||||
//! 一条记录有一个时刻、一个类别、一个标签与一个值。时刻是作出该记录时的仿真瞬时,
|
||||
//! 这正是使轨迹可排序、可与事件日志连接的原因。类别区分了调用方通常想分辨的三件事:
|
||||
//! 模型作出的观测、它决定的变更,以及它想揭示的警告。标签指明该值所关于的内容,而
|
||||
//! 值是一个单数,这覆盖了一次仿真所记录的绝大多数内容,而不强加调用方必须设计的
|
||||
//! 模式。
|
||||
//!
|
||||
//! 轨迹保持记录在它们被作出的次序,而非时间次序。该区别要紧:处理器可能先为它刚
|
||||
//! 调度的后续事件记录了一个值,再为它正在处理的事件记录一个值,而模型推理所用的
|
||||
//! 次序值得保留。想要时间次序的调用方用 [`Trace::in_time_order`] 索取。
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
//! Scenario definition and loading.
|
||||
//!
|
||||
//! 场景的定义与加载。
|
||||
//!
|
||||
//! A scenario is a simulation's initial conditions: the resources a plan may
|
||||
//! use, the tasks it must place, the precedence constraints between those
|
||||
//! tasks, and the limits the run should respect. It is the input a run is
|
||||
|
|
@ -58,6 +56,42 @@
|
|||
//! assert_eq!(scenario.tasks().len(), 1);
|
||||
//! assert_eq!(scenario.validate(), Ok(()));
|
||||
//! ```
|
||||
//!
|
||||
//! 场景的定义与加载。
|
||||
//!
|
||||
//! 场景是一次仿真的初始条件:计划可用的资源、必须放置的任务、这些任务之间的先后
|
||||
//! 约束,以及运行应遵守的限制。它是一次运行所据以构建的输入,把它保存在一处意味着
|
||||
//! 一次运行可以从单一描述复现,而不必从散落的参数重建。
|
||||
//!
|
||||
//! 本 crate 提供两种构建方式。构建器方法是 Rust 代码所用的,它们在每次添加时就检查。
|
||||
//! 文本格式是存储的场景所用的,[`Scenario::parse`] 把它读回。二者一致:用
|
||||
//! [`Scenario::to_text`] 写出的场景解析回相等的场景,故场景可以被存储、编辑并重新
|
||||
//! 加载而不漂移。
|
||||
//!
|
||||
//! 文本格式是面向行的,且不携带第三方依赖。空行与第一个非空格字符为 `#` 的行被忽略。
|
||||
//! 其余每一行是一个关键字后接其参数:
|
||||
//!
|
||||
//! ```text
|
||||
//! scenario leo downlink
|
||||
//! epoch 0
|
||||
//! time_limit 3600
|
||||
//! event_limit 1000000
|
||||
//!
|
||||
//! resource 0 capacity 1
|
||||
//! window 0 0 600
|
||||
//! window 0 1200 1800
|
||||
//!
|
||||
//! task 0 duration 60
|
||||
//! task_window 0 100 1000
|
||||
//! task_priority 0 5
|
||||
//! task_mandatory 0 true
|
||||
//! require 0 0 1
|
||||
//!
|
||||
//! precedence 0 1
|
||||
//! ```
|
||||
//!
|
||||
//! `epoch` 是仿真时钟的起始时刻,单位为秒。`time_limit` 与 `event_limit` 是两个运行
|
||||
//! 限制;任一个都可省略,那会使该限制不被设置。
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
//! Discrete-event simulation engine.
|
||||
//!
|
||||
//! 离散事件仿真引擎。
|
||||
//!
|
||||
//! The engine advances a clock by jumping from one event to the next. It
|
||||
//! holds the event queue, the current simulation time, and the statistics a
|
||||
//! caller needs to judge a run. What an event means is the caller's: it
|
||||
|
|
@ -40,6 +38,20 @@
|
|||
//! assert_eq!(outcome.executed, 2);
|
||||
//! assert_eq!(engine.now(), 20.0);
|
||||
//! ```
|
||||
//!
|
||||
//! 离散事件仿真引擎。
|
||||
//!
|
||||
//! 引擎通过从一个事件跳到下一个来推进时钟。它保存事件队列、当前仿真时刻,以及调用方
|
||||
//! 判断一次运行所需的统计。一个事件意味着什么由调用方定义:它提供一个接收该事件并可
|
||||
//! 再调度更多事件的处理器,而引擎只负责排序各次调用。
|
||||
//!
|
||||
//! 引擎保持仿真确定。同一瞬时的事件按它们被调度的次序投递,这是事件队列所保证的,故
|
||||
//! 相同输入的一次运行产生相同输出。这正是使结果可复现、与另一实现的交叉核对有意义的
|
||||
//! 原因。
|
||||
//!
|
||||
//! 引擎因四种原因之一停止,报告为一个 [`StopReason`]:队列排空、仿真达到其时限、
|
||||
//! 调用方请求它停止,或达到事件上限。后两者存在,是为了让永远调度事件的模型无法无界
|
||||
//! 运行。
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
//! Simulation facade that integrates the simulation layer.
|
||||
//!
|
||||
//! 整合仿真层的仿真门面。
|
||||
//!
|
||||
//! This crate is the single entry point to the simulation layer. It ties the
|
||||
//! four pieces together: a [`Scenario`] describes the initial conditions, the
|
||||
//! ops layer plans it, the engine runs the resulting timeline, and a
|
||||
|
|
@ -51,6 +49,26 @@
|
|||
//! assert_eq!(starts, 1);
|
||||
//! assert_eq!(report.outcome.executed, 2);
|
||||
//! ```
|
||||
//!
|
||||
//! 整合仿真层的仿真门面。
|
||||
//!
|
||||
//! 本 crate 是仿真层的单一入口。它把四部分联系起来:[`Scenario`] 描述初始条件,
|
||||
//! ops 层为其作计划,引擎运行所得时间线,[`Recorder`] 收集该运行所产生的。
|
||||
//!
|
||||
//! 调用方所遵循的序列很短:
|
||||
//!
|
||||
//! 1. [`Simulation::prepare`] 检查场景并为其作计划,产生一个调度。
|
||||
//! 2. [`Simulation::start`] 把该调度转为由开始与结束事件构成的时间线,并交回一个
|
||||
//! [`Session`]。
|
||||
//! 3. [`Session::run`] 驱动引擎,在每个事件处调用一个处理器,并返回一个
|
||||
//! [`RunReport`],其中含有引擎结果与轨迹。
|
||||
//!
|
||||
//! 该计划是贪心启发式,在 `apsis-scheduler` 中有述,故一次运行可能留下未放置的任务。
|
||||
//! 门面报告这一点而非隐藏它:[`Simulation::plan`] 公开完整规划结果,而
|
||||
//! [`Simulation::has_full_plan`] 直接回答那个常见的问题。
|
||||
//!
|
||||
//! 时间线是调度而非物理模型。任务开始时触发一个开始事件,结束时触发一个结束事件,
|
||||
//! 这正是调用方随时间记录状态所需的;处理器提供该运行所需的任何物理或簿记。
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue