feat(router): Start implementing route pruning support
This commit is contained in:
parent
0107cf2f8e
commit
88a0378dfe
2 changed files with 38 additions and 25 deletions
|
@ -114,7 +114,7 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
py: Python<'static>,
|
py: Python<'static>,
|
||||||
hops: Vec<String>,
|
hops: Vec<String>,
|
||||||
range: f32,
|
range: f32,
|
||||||
prune: Option<(usize,f64)>,
|
prune: Option<(usize, f32)>,
|
||||||
mode: String,
|
mode: String,
|
||||||
primary: bool,
|
primary: bool,
|
||||||
permute: bool,
|
permute: bool,
|
||||||
|
|
|
@ -57,7 +57,7 @@ pub struct RouteOpts {
|
||||||
pub keep_last: bool,
|
pub keep_last: bool,
|
||||||
pub factor: Option<f32>,
|
pub factor: Option<f32>,
|
||||||
pub mode: Mode,
|
pub mode: Mode,
|
||||||
pub prune: Option<(usize,f64)>,
|
pub prune: Option<(usize, f32)>,
|
||||||
pub systems: Vec<SysEntry>,
|
pub systems: Vec<SysEntry>,
|
||||||
pub callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
|
pub callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
|
||||||
}
|
}
|
||||||
|
@ -193,8 +193,7 @@ pub struct Router {
|
||||||
range: f32,
|
range: f32,
|
||||||
primary_only: bool,
|
primary_only: bool,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
prune: Option<(usize,f64)>,
|
prune: Option<(usize, f32)>,
|
||||||
prune_map: FnvHashMap<u32, (usize,f64)>,
|
|
||||||
callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
|
callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +201,7 @@ impl Router {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
path: &PathBuf,
|
path: &PathBuf,
|
||||||
range: f32,
|
range: f32,
|
||||||
prune: Option<(usize,f64)>,
|
prune: Option<(usize, f32)>,
|
||||||
primary_only: bool,
|
primary_only: bool,
|
||||||
callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
|
callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
|
||||||
) -> Result<Self, String> {
|
) -> Result<Self, String> {
|
||||||
|
@ -249,7 +248,6 @@ impl Router {
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
callback,
|
callback,
|
||||||
prune,
|
prune,
|
||||||
prune_map: FnvHashMap::default()
|
|
||||||
};
|
};
|
||||||
println!(
|
println!(
|
||||||
"{} Systems loaded in {}",
|
"{} Systems loaded in {}",
|
||||||
|
@ -307,7 +305,6 @@ impl Router {
|
||||||
path,
|
path,
|
||||||
callback,
|
callback,
|
||||||
prune: None,
|
prune: None,
|
||||||
prune_map: FnvHashMap::default()
|
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -320,10 +317,9 @@ impl Router {
|
||||||
self.points_in_sphere(&sys.pos, sys.mult * r)
|
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);
|
let scoopable = self.scoopable.contains(&sys.id);
|
||||||
return scoopable;
|
return scoopable;
|
||||||
// TODO: check prune map
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn best_multiroute(
|
pub fn best_multiroute(
|
||||||
|
@ -379,6 +375,14 @@ impl Router {
|
||||||
for pair in waypoints.windows(2) {
|
for pair in waypoints.windows(2) {
|
||||||
match pair {
|
match pair {
|
||||||
[src, dst] => {
|
[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 {
|
let block = match mode {
|
||||||
Mode::BFS => self.route_bfs(&src, &dst, range)?,
|
Mode::BFS => self.route_bfs(&src, &dst, range)?,
|
||||||
Mode::Greedy => self.route_greedy(&src, &dst, range)?,
|
Mode::Greedy => self.route_greedy(&src, &dst, range)?,
|
||||||
|
@ -510,7 +514,7 @@ impl Router {
|
||||||
}
|
}
|
||||||
queue.extend(
|
queue.extend(
|
||||||
self.neighbours(&sys, range)
|
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))
|
.filter(|&nb| seen.insert(nb.id))
|
||||||
.map(|nb| {
|
.map(|nb| {
|
||||||
prev.insert(nb.id, sys);
|
prev.insert(nb.id, sys);
|
||||||
|
@ -583,11 +587,11 @@ impl Router {
|
||||||
let mut prev = FnvHashMap::default();
|
let mut prev = FnvHashMap::default();
|
||||||
let mut seen = FnvHashSet::default();
|
let mut seen = FnvHashSet::default();
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
let mut queue: Vec<(f32, f32, usize, &System)> = Vec::new();
|
let mut queue: Vec<(f32, usize, &System)> = Vec::new();
|
||||||
queue.push((-goal_sys.mult, start_sys.distp(goal_sys), 0, &start_sys));
|
queue.push((start_sys.distp(goal_sys), 0, &start_sys));
|
||||||
seen.insert(start_sys.id);
|
seen.insert(start_sys.id);
|
||||||
while !(queue.is_empty() || found) {
|
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 {
|
if t_last.elapsed().as_millis() > 100 {
|
||||||
t_last = Instant::now();
|
t_last = Instant::now();
|
||||||
state.depth = depth;
|
state.depth = depth;
|
||||||
|
@ -611,7 +615,7 @@ impl Router {
|
||||||
}
|
}
|
||||||
queue.extend(
|
queue.extend(
|
||||||
self.neighbours(&sys, range)
|
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))
|
.filter(|&nb| seen.insert(nb.id))
|
||||||
.map(|nb| {
|
.map(|nb| {
|
||||||
prev.insert(nb.id, sys);
|
prev.insert(nb.id, sys);
|
||||||
|
@ -619,10 +623,10 @@ impl Router {
|
||||||
if d_g < d_rem {
|
if d_g < d_rem {
|
||||||
d_rem = d_g;
|
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();
|
queue.reverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -786,6 +790,7 @@ impl Router {
|
||||||
range: f32,
|
range: f32,
|
||||||
) -> Result<Vec<System>, String> {
|
) -> Result<Vec<System>, String> {
|
||||||
println!("Running BFS");
|
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 src_name = start_sys.system.clone();
|
||||||
let dst_name = goal_sys.system.clone();
|
let dst_name = goal_sys.system.clone();
|
||||||
let d_total = dist(&start_sys.pos, &goal_sys.pos);
|
let d_total = dist(&start_sys.pos, &goal_sys.pos);
|
||||||
|
@ -804,15 +809,9 @@ impl Router {
|
||||||
system: start_sys.system.clone(),
|
system: start_sys.system.clone(),
|
||||||
body: start_sys.body.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 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 seen = FnvHashSet::default();
|
||||||
let mut depth = 0;
|
let mut depth = 0;
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
|
@ -847,10 +846,24 @@ impl Router {
|
||||||
};
|
};
|
||||||
t_last = Instant::now();
|
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(
|
queue_next.extend(
|
||||||
self.neighbours(&sys, range)
|
self.neighbours(&sys, range)
|
||||||
.filter(|&nb| {
|
.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))
|
.filter(|&nb| seen.insert(nb.id))
|
||||||
.map(|nb| {
|
.map(|nb| {
|
||||||
|
|
Loading…
Reference in a new issue