added working ALT
This commit is contained in:
parent
7d657b7222
commit
b11eef1cf7
8 changed files with 167 additions and 80 deletions
78
src/alt.rs
78
src/alt.rs
|
|
@ -12,6 +12,11 @@ pub struct Landmark {
|
|||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct LandmarkSet {
|
||||
pub landmarks: Vec<Landmark>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LandmarkBestSet<'a> {
|
||||
pub landmark_set: &'a LandmarkSet,
|
||||
pub best_size: usize,
|
||||
best_landmarks: Vec<usize>,
|
||||
}
|
||||
|
|
@ -24,7 +29,7 @@ impl Landmark {
|
|||
};
|
||||
landmark.node = node;
|
||||
|
||||
#[derive(Eq)]
|
||||
#[derive(Eq, PartialEq)]
|
||||
struct DijkstraElement {
|
||||
index: u32,
|
||||
cost: EdgeCost,
|
||||
|
|
@ -44,40 +49,23 @@ impl Landmark {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq for DijkstraElement {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.cost == other.cost
|
||||
}
|
||||
}
|
||||
|
||||
let mut heap = BinaryHeap::new();
|
||||
heap.push(DijkstraElement {
|
||||
cost: 0,
|
||||
index: landmark.node.index,
|
||||
});
|
||||
|
||||
let mut counter = 0;
|
||||
|
||||
while let Some(DijkstraElement { index, cost }) = heap.pop() {
|
||||
// the heap does not support "update" operations, so we
|
||||
// insert elements again and if they come out of the heap but have
|
||||
// been processed earlier we simply skip them.
|
||||
if landmark.distances[index as usize] <= cost {
|
||||
if cost > landmark.distances[index as usize] {
|
||||
continue;
|
||||
};
|
||||
|
||||
counter += 1;
|
||||
|
||||
if counter % 1000 == 0 {
|
||||
println!("Finished {} nodes", counter);
|
||||
}
|
||||
|
||||
landmark.distances[index as usize] = cost;
|
||||
|
||||
let edge_start = graph.edge_offsets[index as usize] as usize;
|
||||
let edge_end = graph.edge_offsets[(index + 1) as usize] as usize;
|
||||
|
||||
for edge in graph.edges[edge_start..edge_end].iter() {
|
||||
for edge in graph.get_edges(index as NodeId) {
|
||||
let new_cost = cost + edge.cost;
|
||||
|
||||
if new_cost < landmark.distances[edge.neighbor as usize] {
|
||||
|
|
@ -86,11 +74,11 @@ impl Landmark {
|
|||
index: edge.neighbor,
|
||||
cost: new_cost,
|
||||
});
|
||||
landmark.distances[edge.neighbor as usize] = new_cost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now the shortest paths to all reachable nodes is calculated.
|
||||
// now the costs to all reachable nodes is calculated.
|
||||
|
||||
landmark
|
||||
}
|
||||
|
|
@ -103,18 +91,28 @@ impl Landmark {
|
|||
let l_to = self.distances[to];
|
||||
let l_from = self.distances[from];
|
||||
|
||||
if l_to == EdgeCost::MAX {
|
||||
0
|
||||
if l_to == EdgeCost::MAX || l_from == EdgeCost::MAX {
|
||||
EdgeCost::MAX
|
||||
} else {
|
||||
l_to.saturating_sub(l_from)
|
||||
// since we are working on an undirected graph we can
|
||||
// use the distances once from and once to the landmark.
|
||||
// This leads to l_to - l_from and l_from - l_to (as signed subtractions)
|
||||
// which except for the sign are the same value.
|
||||
// We can simply take the bigger one, which is handled
|
||||
// nicely the abs() function
|
||||
let distance = (l_to as i64 - l_from as i64).abs() as EdgeCost;
|
||||
//println!(
|
||||
// "distance from {} to {} via landmark {} is at least {}",
|
||||
// from, to, self.node.index, distance
|
||||
//);
|
||||
distance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LandmarkSet {
|
||||
pub fn random_set(size: usize, best_size: usize, graph: &GridGraph) -> Self {
|
||||
pub fn random_set(size: usize, graph: &GridGraph) -> Self {
|
||||
let mut set = LandmarkSet::default();
|
||||
set.best_size = best_size;
|
||||
|
||||
let nodes = graph.get_random_nodes(size);
|
||||
|
||||
|
|
@ -125,11 +123,13 @@ impl LandmarkSet {
|
|||
|
||||
set
|
||||
}
|
||||
}
|
||||
|
||||
impl LandmarkBestSet<'_> {
|
||||
pub fn select_best(&mut self, from: NodeId, to: NodeId) {
|
||||
let mut results = vec![];
|
||||
|
||||
for (index, landmark) in self.landmarks.iter().enumerate() {
|
||||
for (index, landmark) in self.landmark_set.landmarks.iter().enumerate() {
|
||||
results.push((index, landmark.estimate(from, to)));
|
||||
}
|
||||
|
||||
|
|
@ -143,18 +143,28 @@ impl LandmarkSet {
|
|||
}
|
||||
|
||||
pub fn estimate(&self, from: NodeId, to: NodeId) -> EdgeCost {
|
||||
|
||||
let mut distance = 0;
|
||||
|
||||
for index in &self.best_landmarks {
|
||||
distance = distance.max(self.landmarks[*index].estimate(from, to));
|
||||
};
|
||||
let candidate = self.landmark_set.landmarks[*index].estimate(from, to);
|
||||
|
||||
if distance == 0 {
|
||||
distance = EdgeCost::MAX;
|
||||
if candidate == EdgeCost::MAX {
|
||||
continue;
|
||||
}
|
||||
|
||||
distance = distance.max(candidate)
|
||||
}
|
||||
|
||||
distance
|
||||
//println!("calculated estimate {:?} for {} to {}", distance, from, to);
|
||||
|
||||
distance
|
||||
}
|
||||
|
||||
pub fn new<'a>(best_size: usize, landmark_set: &'a LandmarkSet) -> LandmarkBestSet<'a> {
|
||||
LandmarkBestSet {
|
||||
best_size,
|
||||
landmark_set,
|
||||
best_landmarks: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue