feat(router): Start implementing route pruning support

This commit is contained in:
Daniel S. 2019-09-28 15:41:25 +02:00
parent 0107cf2f8e
commit 88a0378dfe
2 changed files with 38 additions and 25 deletions

View file

@ -114,7 +114,7 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> {
py: Python<'static>,
hops: Vec<String>,
range: f32,
prune: Option<(usize,f64)>,
prune: Option<(usize, f32)>,
mode: String,
primary: bool,
permute: bool,

View file

@ -57,7 +57,7 @@ pub struct RouteOpts {
pub keep_last: bool,
pub factor: Option<f32>,
pub mode: Mode,
pub prune: Option<(usize,f64)>,
pub prune: Option<(usize, f32)>,
pub systems: Vec<SysEntry>,
pub callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
}
@ -193,8 +193,7 @@ pub struct Router {
range: f32,
primary_only: bool,
path: PathBuf,
prune: Option<(usize,f64)>,
prune_map: FnvHashMap<u32, (usize,f64)>,
prune: Option<(usize, f32)>,
callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
}
@ -202,7 +201,7 @@ impl Router {
pub fn new(
path: &PathBuf,
range: f32,
prune: Option<(usize,f64)>,
prune: Option<(usize, f32)>,
primary_only: bool,
callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
) -> Result<Self, String> {
@ -249,7 +248,6 @@ impl Router {
path: path.clone(),
callback,
prune,
prune_map: FnvHashMap::default()
};
println!(
"{} Systems loaded in {}",
@ -307,7 +305,6 @@ impl Router {
path,
callback,
prune: None,
prune_map: FnvHashMap::default()
},
))
}
@ -320,10 +317,9 @@ impl Router {
self.points_in_sphere(&sys.pos, sys.mult * r)
}
fn valid(&self, sys: &System, src: &System, dst: &System) -> bool {
fn valid(&self, sys: &System) -> bool {
let scoopable = self.scoopable.contains(&sys.id);
return scoopable;
// TODO: check prune map
}
pub fn best_multiroute(
@ -379,6 +375,14 @@ impl Router {
for pair in waypoints.windows(2) {
match pair {
[src, dst] => {
let d_total=dist(&src.pos,&dst.pos);
println!("Plotting route from [{}] to [{}]...", src.system, dst.system);
println!(
"Jump Range: {} Ly, Distance: {} Ly, Estimated Jumps: {}",
range,
d_total,
d_total / range
);
let block = match mode {
Mode::BFS => self.route_bfs(&src, &dst, range)?,
Mode::Greedy => self.route_greedy(&src, &dst, range)?,
@ -510,7 +514,7 @@ impl Router {
}
queue.extend(
self.neighbours(&sys, range)
.filter(|&nb| (self.valid(nb, &src, &dst) || (nb.id == goal_sys.id)))
.filter(|&nb| (self.valid(nb) || (nb.id == goal_sys.id)))
.filter(|&nb| seen.insert(nb.id))
.map(|nb| {
prev.insert(nb.id, sys);
@ -583,11 +587,11 @@ impl Router {
let mut prev = FnvHashMap::default();
let mut seen = FnvHashSet::default();
let mut found = false;
let mut queue: Vec<(f32, f32, usize, &System)> = Vec::new();
queue.push((-goal_sys.mult, start_sys.distp(goal_sys), 0, &start_sys));
let mut queue: Vec<(f32, usize, &System)> = Vec::new();
queue.push((start_sys.distp(goal_sys), 0, &start_sys));
seen.insert(start_sys.id);
while !(queue.is_empty() || found) {
while let Some((_, _, depth, sys)) = queue.pop() {
while let Some((_, depth, sys)) = queue.pop() {
if t_last.elapsed().as_millis() > 100 {
t_last = Instant::now();
state.depth = depth;
@ -611,7 +615,7 @@ impl Router {
}
queue.extend(
self.neighbours(&sys, range)
.filter(|&nb| (self.valid(nb, &src, &dst) || (nb.id == goal_sys.id)))
.filter(|&nb| (self.valid(nb) || (nb.id == goal_sys.id)))
.filter(|&nb| seen.insert(nb.id))
.map(|nb| {
prev.insert(nb.id, sys);
@ -619,10 +623,10 @@ impl Router {
if d_g < d_rem {
d_rem = d_g;
}
(-nb.mult, d_g, depth + 1, nb)
(d_g, depth + 1, nb)
}),
);
queue.sort_by(|a, b| fcmp(a.0, b.0).then(fcmp(a.1, b.1)));
queue.sort_by(|a, b| fcmp(a.0, b.0).then(a.1.cmp(&b.1)));
queue.reverse();
}
}
@ -786,6 +790,7 @@ impl Router {
range: f32,
) -> Result<Vec<System>, String> {
println!("Running BFS");
let min_improvement = self.prune.map(|v| (v.0,v.1*range)).unwrap_or_else(|| (0,0.0));
let src_name = start_sys.system.clone();
let dst_name = goal_sys.system.clone();
let d_total = dist(&start_sys.pos, &goal_sys.pos);
@ -804,15 +809,9 @@ impl Router {
system: start_sys.system.clone(),
body: start_sys.body.clone(),
};
println!("Plotting route from {} to {}...", src_name, dst_name);
println!(
"Jump Range: {} Ly, Distance: {} Ly, Estimated Jumps: {}",
range,
d_total,
d_total / range
);
let total = self.tree.size() as f32;
let mut prev = FnvHashMap::default();
let mut prev: FnvHashMap<u32, &System> = FnvHashMap::default();
let mut prune_map: FnvHashMap<u32, (usize, f32)> = FnvHashMap::default();
let mut seen = FnvHashSet::default();
let mut depth = 0;
let mut found = false;
@ -847,10 +846,24 @@ impl Router {
};
t_last = Instant::now();
}
if self.prune.is_some() {
let best_dist = if let Some(p_sys) = prev.get(&sys.id) {
dist2(&p_sys.pos, &goal_sys.pos).min(
prune_map
.get(&p_sys.id)
.map(|v| v.1)
.unwrap_or(std::f32::MAX),
)
} else {
dist2(&sys.pos, &goal_sys.pos)
};
prune_map.insert(sys.id, (depth, best_dist));
}
// TODO: check improvement, if too small: continue
queue_next.extend(
self.neighbours(&sys, range)
.filter(|&nb| {
(self.valid(nb, &start_sys, &goal_sys) || (nb.id == goal_sys.id))
(self.valid(nb) || (nb.id == goal_sys.id))
})
.filter(|&nb| seen.insert(nb.id))
.map(|nb| {