use crate::packed::PackedTask;
use crate::search::{plan, search_from, PlanResult, SearchCfg};
const SLICE0: usize = 50_000;
pub struct Outcome {
pub ops: Option<Vec<usize>>,
pub evaluated: usize,
pub winner: Option<&'static str>,
}
pub fn solve(task: &PackedTask, threads: usize, cfg: SearchCfg) -> Outcome {
let names: [&'static str; 4] = ["ladder", "lama", "bfs-w3", "bfs-w1"];
let mut alive = [true; 4];
let mut pool = cfg.max_eval;
let mut evaluated = 0usize;
let mut round = 0u32;
while pool > 0 && alive.iter().any(|&a| a) {
let slice = (SLICE0 << round).min(pool);
for (m, &name) in names.iter().enumerate() {
if !alive[m] || pool == 0 {
continue;
}
let budget = slice.min(pool);
let (ops, used, proven_unsolvable) = run_member(task, m, threads, cfg, budget);
evaluated += used;
pool = pool.saturating_sub(used.max(1));
if let Some(ops) = ops {
return Outcome {
ops: Some(ops),
evaluated,
winner: Some(name),
};
}
if proven_unsolvable {
return Outcome {
ops: None,
evaluated,
winner: None,
};
}
if used < budget {
alive[m] = false;
}
}
round += 1;
}
Outcome {
ops: None,
evaluated,
winner: None,
}
}
fn run_member(
task: &PackedTask,
member: usize,
threads: usize,
cfg: SearchCfg,
budget: usize,
) -> (Option<Vec<usize>>, usize, bool) {
match member {
0 => {
let o = plan(
task,
threads,
SearchCfg {
max_eval: budget,
..cfg
},
true,
);
(o.ops, o.evaluated.max(1), false)
}
1 => match crate::lama::search(task, threads, budget, &[]) {
Some((ops, ev)) => (Some(ops), ev.max(1), false),
None => (None, budget, false), },
_ => {
let wh = if member == 2 { 3.0 } else { 1.0 };
match search_from(
task,
&task.initial(),
&task.goal_pos,
&task.goal_num,
None,
f64::INFINITY,
threads,
SearchCfg::from_weights(1.0, wh, Some(budget)),
&[],
None,
None,
) {
PlanResult::Plan { ops, evaluated, .. } => (Some(ops), evaluated.max(1), false),
PlanResult::Unsolvable { evaluated, capped } => (None, evaluated.max(1), !capped),
}
}
}
}