Generic MoonBit trajectory, replay, sequence sampling, offline dataset, and reinforcement-learning training utilities.
moon add hmyhmyhmyss/moontrajectory
moon test
moon run cmd/mainimport hmyhmyhmyss/moontrajectory as traj
fn main {
let episode = traj.Episode::new()
.push(traj.Transition::non_terminal("s0", "left", 1.0, "s1"))
.push(traj.Transition::terminal("s1", "right", 5.0, "s2"))
let buffer : traj.ReplayBuffer[String, String] = traj.ReplayBuffer::new(1024)
let _ = buffer.extend_episode(episode)
let report = buffer.report()
println("steps=\{report.size()}, reward=\{report.total_reward()}")
}moon check --deny-warn
moon test --deny-warn
moon fmt --check
moon info
moon run cmd/main| 文件 | 职责 |
|---|---|
| trajectory.mbt | Transition、Episode 和基础回报计算 |
| trajectory_analysis.mbt | 校验、统计、bootstrap 与 episode 特征 |
| replay_buffer.mbt | 均匀经验回放 |
| prioritized_replay.mbt | 优先级经验回放 |
| sequence_sampling.mbt | 固定长度序列、padding 和 mask |
| dataset.mbt | 离线轨迹数据集 |
| training_targets.mbt | TD、GAE、折扣 targets 和 batch |
| evaluation.mbt | 评估报告和直方图 |
| episode_windows.mbt | RNN/序列模型窗口 |
| batch_ops.mbt | 通用批处理和数值操作 |
| benchmarks.mbt | 确定性工作负载 fixture |
| replay_analytics.mbt | 回放统计和优先级诊断 |
| cmd/main | 可直接运行的 smoke demo |
pub struct BatchCursor {
total : Int
batch_size : Int
position : Int
}pub struct BenchmarkCase {
name : String
episodes : Int
steps_per_episode : Int
reward_scale : Double
}fn BenchmarkCase::new(name : String, episodes : Int, steps_per_episode : Int, reward_scale : Double) -> BenchmarkCasepub struct Episode[S, A] {
transitions : Array[Transition[S, A]]
terminated : Bool
truncated : Bool
total_reward : Double
}fn[S, A] Episode::n_step_transitions(self : Episode[S, A], n : Int, gamma : Double) -> Array[Transition[S, A]]fn[S, A] Episode::windows(self : Episode[S, A], length : Int, stride : Int) -> Array[EpisodeWindow[S, A]]pub struct EvaluationReport {
episodes : Int
total_steps : Int
total_reward : Double
mean_reward : Double
best_reward : Double
worst_reward : Double
terminated : Int
truncated : Int
}pub struct ExponentialSchedule {
initial : Double
final_value : Double
decay_steps : Int
}fn ExponentialSchedule::new(initial : Double, final_value : Double, decay_steps : Int) -> ExponentialSchedulepub struct LinearSchedule {
start : Double
end : Double
duration : Int
}pub struct PrioritizedReplayBuffer[S, A] {
capacity : Int
len : Int
head : Int
data : Array[Transition[S, A]?]
priorities : Array[Double]
max_priority : Double
alpha : Double
beta : Double
epsilon : Double
}fn[S, A] PrioritizedReplayBuffer::clear(self : PrioritizedReplayBuffer[S, A]) -> PrioritizedReplayBuffer[S, A]fn[S, A] PrioritizedReplayBuffer::count_priority_at_least(self : PrioritizedReplayBuffer[S, A], threshold : Double) -> Intfn[S, A] PrioritizedReplayBuffer::effective_priority_sum(self : PrioritizedReplayBuffer[S, A]) -> Doublefn[S, A] PrioritizedReplayBuffer::extend_episode(self : PrioritizedReplayBuffer[S, A], episode : Episode[S, A]) -> Intfn[S, A] PrioritizedReplayBuffer::get(self : PrioritizedReplayBuffer[S, A], logical_index : Int) -> (Transition[S, A], Double)?fn[S, A] PrioritizedReplayBuffer::priority_at(self : PrioritizedReplayBuffer[S, A], index : Int) -> Double?fn[S, A] PrioritizedReplayBuffer::priority_distribution(self : PrioritizedReplayBuffer[S, A]) -> Array[Double]fn[S, A] PrioritizedReplayBuffer::push(self : PrioritizedReplayBuffer[S, A], transition : Transition[S, A], priority? : Double) -> Intfn[S, A] PrioritizedReplayBuffer::sample_batch(self : PrioritizedReplayBuffer[S, A], batch_size : Int, seed : Int) -> Array[PrioritizedSample[S, A]]fn[S, A] PrioritizedReplayBuffer::to_array(self : PrioritizedReplayBuffer[S, A]) -> Array[Transition[S, A]]fn[S, A] PrioritizedReplayBuffer::update_priority(self : PrioritizedReplayBuffer[S, A], logical_index : Int, priority : Double) -> Boolfn[S, A] PrioritizedReplayBuffer::with_params(capacity : Int, alpha : Double, beta : Double, epsilon : Double) -> PrioritizedReplayBuffer[S, A]pub struct PrioritizedSample[S, A] {
index : Int
priority : Double
probability : Double
weight : Double
transition : Transition[S, A]
}pub struct ReplayBuffer[S, A] {
capacity : Int
len : Int
head : Int
data : Array[Transition[S, A]?]
}fn[S, A] ReplayBuffer::all_sequences(self : ReplayBuffer[S, A], sequence_length : Int) -> Array[SequenceSample[S, A]]fn[S, A] ReplayBuffer::reward_histogram(self : ReplayBuffer[S, A], lower : Double, upper : Double, buckets : Int) -> Array[Int]fn[S, A] ReplayBuffer::sample_batch(self : ReplayBuffer[S, A], batch_size : Int, seed : Int) -> Array[ReplaySample[S, A]]fn[S, A] ReplayBuffer::sample_sequences(self : ReplayBuffer[S, A], batch_size : Int, sequence_length : Int, seed : Int, allow_padding : Bool) -> Array[SequenceSample[S, A]]fn[S, A] ReplayBuffer::sequence(self : ReplayBuffer[S, A], start : Int, sequence_length : Int, pad : Bool) -> SequenceSample[S, A]fn[S, A] ReplayBuffer::valid_sequence_starts(self : ReplayBuffer[S, A], sequence_length : Int, allow_padding : Bool) -> Array[Int]pub struct ReplayReport {
size : Int
capacity : Int
occupancy : Double
terminal_count : Int
total_reward : Double
mean_reward : Double
minimum_reward : Double
maximum_reward : Double
}pub struct ReplayRng {
state : Int
}pub struct RewardStats {
count : Int
sum : Double
mean : Double
minimum : Double
maximum : Double
positive_count : Int
negative_count : Int
zero_count : Int
}pub struct SequenceSample[S, A] {
start : Int
transitions : Array[Transition[S, A]?]
mask : Array[Bool]
}fn[S, A] TrajectoryDataset::add_unchecked(self : TrajectoryDataset[S, A], episode : Episode[S, A]) -> Unitfn[S, A] TrajectoryDataset::append(self : TrajectoryDataset[S, A], other : TrajectoryDataset[S, A]) -> Unitfn[S, A] TrajectoryDataset::count_with_reward_at_least(self : TrajectoryDataset[S, A], threshold : Double) -> Intfn[S, A] TrajectoryDataset::discounted_returns(self : TrajectoryDataset[S, A], gamma : Double) -> Array[Double]fn[S, A] TrajectoryDataset::drop_episodes(self : TrajectoryDataset[S, A], count : Int) -> TrajectoryDataset[S, A]fn[S, A] TrajectoryDataset::episode_reward_range(self : TrajectoryDataset[S, A]) -> (Double, Double)?fn[S, A] TrajectoryDataset::filter_by_length(self : TrajectoryDataset[S, A], minimum : Int, maximum : Int) -> TrajectoryDataset[S, A]fn[S, A] TrajectoryDataset::filter_by_reward(self : TrajectoryDataset[S, A], minimum : Double, maximum : Double) -> TrajectoryDataset[S, A]fn[S, A] TrajectoryDataset::from_episodes(episodes : Array[Episode[S, A]]) -> TrajectoryDataset[S, A]fn[S, A] TrajectoryDataset::sample_episodes(self : TrajectoryDataset[S, A], count : Int, seed : Int) -> Array[Episode[S, A]]fn[S, A] TrajectoryDataset::split_at(self : TrajectoryDataset[S, A], first_count : Int) -> (TrajectoryDataset[S, A], TrajectoryDataset[S, A])fn[S, A] TrajectoryDataset::take_episodes(self : TrajectoryDataset[S, A], count : Int) -> Array[Episode[S, A]]pub struct Transition[S, A] {
state : S
action : A
reward : Double
next_state : S
done : Bool
}fn[S, A] Transition::new(state : S, action : A, reward : Double, next_state : S, done : Bool) -> Transition[S, A]fn[S, A] Transition::non_terminal(state : S, action : A, reward : Double, next_state : S) -> Transition[S, A]fn[S, A] Transition::terminal(state : S, action : A, reward : Double, next_state : S) -> Transition[S, A]pub struct WarmupCosineSchedule {
warmup_steps : Int
total_steps : Int
maximum : Double
minimum : Double
}fn WarmupCosineSchedule::new(warmup_steps : Int, total_steps : Int, maximum : Double, minimum : Double) -> WarmupCosineSchedulefn[S, A] generate_benchmark_dataset(case : BenchmarkCase, state : S, action : A) -> TrajectoryDataset[S, A]Generic MoonBit trajectory, replay, sequence sampling, offline dataset, and reinforcement-learning training utilities.