///|
/// 仿真实验配置
pub(all) struct ExpConfig {
until : Double
seed : Int
params : Map[String, Double]
} derive(Debug, ToJson)
///|
/// 从 JSON 反序列化 ExpConfig
impl FromJson for ExpConfig with fn from_json(json, path) {
match json {
Json::Object(map) =>
{
until: @json.from_json(map["until"], path=path.add_key("until")),
seed: @json.from_json(map["seed"], path=path.add_key("seed")),
params: @json.from_json(map["params"], path=path.add_key("params")),
}
_ => raise @json.JsonDecodeError::JsonDecodeError((path, "expected object"))
}
}
///|
/// 仿真实验结果
pub(all) struct ExpResult {
config : ExpConfig
final_time : Double
event_count : Int
metrics : Map[String, Double]
} derive(Debug, ToJson)
///|
/// 从 JSON 反序列化 ExpResult
impl FromJson for ExpResult with fn from_json(json, path) {
match json {
Json::Object(map) =>
{
config: @json.from_json(map["config"], path=path.add_key("config")),
final_time: @json.from_json(
map["final_time"],
path=path.add_key("final_time"),
),
event_count: @json.from_json(
map["event_count"],
path=path.add_key("event_count"),
),
metrics: @json.from_json(map["metrics"], path=path.add_key("metrics")),
}
_ => raise @json.JsonDecodeError::JsonDecodeError((path, "expected object"))
}
}
///|
/// 仿真快照
///
/// 捕获仿真环境状态,可用于断点回滚。
pub(all) struct Snapshot {
time : Double
event_count : Int
env_snapshot : @core.EnvSnapshot
} derive(Debug, ToJson)
///|
/// 从 JSON 反序列化 Snapshot
impl FromJson for Snapshot with fn from_json(json, path) {
match json {
Json::Object(map) =>
{
time: @json.from_json(map["time"], path=path.add_key("time")),
event_count: @json.from_json(
map["event_count"],
path=path.add_key("event_count"),
),
env_snapshot: @json.from_json(
map["env_snapshot"],
path=path.add_key("env_snapshot"),
),
}
_ => raise @json.JsonDecodeError::JsonDecodeError((path, "expected object"))
}
}
///|
/// 创建实验配置
pub fn new_config(until~ : Double, seed? : Int = 0) -> ExpConfig {
{ until, seed, params: Map([]) }
}
///|
/// 向配置添加参数
pub fn ExpConfig::set_param(
self : ExpConfig,
key : String,
value~ : Double,
) -> Unit {
self.params[key] = value
}
///|
/// 运行单次仿真实验
///
/// 创建仿真环境并运行至终止时间,返回实验结果。
/// `event_count` 为仿真过程中注册的事件总数。
pub fn run_experiment(config : ExpConfig) -> ExpResult {
let env = @core.new_env(until=config.until)
env.run()
{
config,
final_time: env.now(),
event_count: env.event_count(),
metrics: Map([]),
}
}
///|
/// 批量运行多个实验配置
pub fn batch_run(configs : Array[ExpConfig]) -> Array[ExpResult] {
let results : Array[ExpResult] = []
for cfg in configs {
results.push(run_experiment(cfg))
}
results
}
///|
/// 保存仿真快照
///
/// 捕获当前仿真时间、事件数与环境内部状态,可用于 `rollback`。
pub fn snapshot(env : @core.SimulationEnv) -> Snapshot {
{
time: env.now(),
event_count: env.event_count(),
env_snapshot: env.snapshot(),
}
}
///|
/// 断点回滚:从快照恢复环境状态
///
/// 恢复仿真时钟、环境状态、ID 计数器。
/// 注意:事件队列与回调不恢复,回滚后需重新调度后续事件。
pub fn rollback(env : @core.SimulationEnv, snap : Snapshot) -> Unit {
env.restore(snap.env_snapshot)
}
///|
/// 参数遍历:生成一组参数变化的配置
pub fn param_sweep(
base~ : ExpConfig,
param_name~ : String,
values~ : Array[Double],
) -> Array[ExpConfig] {
let configs : Array[ExpConfig] = []
for v in values {
let cfg = new_config(until=base.until, seed=base.seed)
cfg.set_param(param_name, value=v)
for k, val in base.params {
cfg.set_param(k, value=val)
}
configs.push(cfg)
}
configs
}
///|
/// 将 ExpConfig 序列化为 JSON 字符串
pub fn ExpConfig::to_json_string(self : ExpConfig) -> String {
@json.to_json(self).stringify(indent=2)
}
///|
/// 从 JSON 字符串反序列化 ExpConfig
pub fn ExpConfig::from_json_string(s : String) -> ExpConfig raise {
@json.from_json(@json.parse(s))
}
///|
/// 将 ExpResult 序列化为 JSON 字符串
pub fn ExpResult::to_json_string(self : ExpResult) -> String {
@json.to_json(self).stringify(indent=2)
}
///|
/// 从 JSON 字符串反序列化 ExpResult
pub fn ExpResult::from_json_string(s : String) -> ExpResult raise {
@json.from_json(@json.parse(s))
}
///|
/// 将 Snapshot 序列化为 JSON 字符串
pub fn Snapshot::to_json_string(self : Snapshot) -> String {
@json.to_json(self).stringify(indent=2)
}
///|
/// 从 JSON 字符串反序列化 Snapshot
pub fn Snapshot::from_json_string(s : String) -> Snapshot raise {
@json.from_json(@json.parse(s))
}