use ferroplan::{solve, Options, Plan};
fn read(inst: &str) -> (String, String) {
let base = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../benchmarks/ipc/pref/openstacks"
);
(
std::fs::read_to_string(format!("{base}/domain.pddl")).unwrap(),
std::fs::read_to_string(format!("{base}/{inst}.pddl")).unwrap(),
)
}
fn steps(plan: &Plan) -> Vec<(String, Vec<String>)> {
plan.steps
.iter()
.map(|s| (s.action.clone(), s.args.clone()))
.collect()
}
#[test]
#[ignore = "heavy IPC solve (~2-6 min): ESPC penalty-resolution loop on openstacks/p01. \
Opt-in via `cargo test -- --include-ignored`; CI runs it in release."]
fn espc_openstacks_p01_improves_verifies_and_is_deterministic() {
let (d, p) = read("p01");
std::env::set_var("FF_NO_ESPC", "1");
let base = solve(&d, &p, &Options::default()).unwrap();
std::env::remove_var("FF_NO_ESPC");
let bplan = base.plan.expect("default plan");
let bm = bplan.metric.expect("default metric");
let bv = ferroplan::verify::verify(&d, &p, &steps(&bplan)).unwrap();
assert!(bv.hard_goal_met, "default plan must meet the hard goal");
assert!(
(bv.metric - bm).abs() < 1e-6,
"default reported {bm} != independently verified {}",
bv.metric
);
let o1 = Options {
threads: 1,
..Options::default()
};
let o8 = Options {
threads: 8,
..Options::default()
};
let s1 = solve(&d, &p, &o1).unwrap();
let s8 = solve(&d, &p, &o8).unwrap();
let p1 = s1.plan.expect("espc plan (t1)");
let m1 = p1.metric.expect("espc metric");
let v1 = ferroplan::verify::verify(&d, &p, &steps(&p1)).unwrap();
assert!(v1.hard_goal_met, "espc plan must meet the hard goal");
assert!(
(v1.metric - m1).abs() < 1e-6,
"espc reported {m1} != independently verified {}",
v1.metric
);
assert!(
m1 < bm,
"espc metric {m1} must strictly beat the default {bm}"
);
assert!(
m1 <= 19.0,
"espc openstacks/p01 metric {m1} regressed above the locked 19 \
(partitioned coupling, increment 2)"
);
let p8 = s8.plan.expect("espc plan (t8)");
assert_eq!(
steps(&p1),
steps(&p8),
"espc plan differs across thread counts"
);
assert_eq!(
m1,
p8.metric.expect("espc metric t8"),
"espc metric differs across thread counts"
);
std::env::set_var("FF_ESPC_MONO", "1");
std::env::set_var("FF_ESPC_EVAL_BUDGET", "600000");
let sm = solve(&d, &p, &Options::default()).unwrap();
std::env::remove_var("FF_ESPC_MONO");
std::env::remove_var("FF_ESPC_EVAL_BUDGET");
let pm = sm.plan.expect("espc mono plan");
let mm = pm.metric.expect("espc mono metric");
let vm = ferroplan::verify::verify(&d, &p, &steps(&pm)).unwrap();
assert!(vm.hard_goal_met, "espc mono plan must meet the hard goal");
assert!(
(vm.metric - mm).abs() < 1e-6,
"espc mono reported {mm} != independently verified {}",
vm.metric
);
assert!(
mm <= 63.0,
"espc mono metric {mm} regressed above its 63 compiled-goal floor"
);
}