Implement new graph data structure and dijkstra
This commit is contained in:
parent
778cb6748d
commit
18e54c4ce1
6 changed files with 516 additions and 3 deletions
77
brood/src/commands/path2.rs
Normal file
77
brood/src/commands/path2.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
use std::{
|
||||
fs::File,
|
||||
io::{self, BufReader},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
algo::Dijkstra,
|
||||
data::{info::PageInfo, store},
|
||||
graph::{Graph, NodeIdx},
|
||||
util,
|
||||
};
|
||||
|
||||
pub fn find_index_of_title(pages: &[PageInfo], title: &str) -> NodeIdx {
|
||||
let title = util::normalize_link(title);
|
||||
pages
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, p)| util::normalize_link(&p.title) == title)
|
||||
.map(|(i, _)| NodeIdx::new(i))
|
||||
.expect("invalid title")
|
||||
}
|
||||
|
||||
pub fn resolve_redirects(pages: &[PageInfo], graph: &Graph, mut page: NodeIdx) -> NodeIdx {
|
||||
loop {
|
||||
if pages[page.usize()].redirect {
|
||||
if let Some(next) = graph.edges_for(page).first() {
|
||||
page = *next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path(datafile: &Path, start: &str, goal: &str) -> io::Result<()> {
|
||||
println!(">> Import");
|
||||
let mut databuf = BufReader::new(File::open(datafile)?);
|
||||
let (pages, _links, graph) = store::read_graph(&mut databuf)?;
|
||||
|
||||
println!(">> Locate from and to");
|
||||
let start = resolve_redirects(&pages, &graph, find_index_of_title(&pages, start));
|
||||
let goal = resolve_redirects(&pages, &graph, find_index_of_title(&pages, goal));
|
||||
println!("Start: {:?}", pages[start.usize()].title);
|
||||
println!("Goal: {:?}", pages[goal.usize()].title);
|
||||
|
||||
println!(">> Find path");
|
||||
println!("> Preparing dijkstra");
|
||||
let mut dijkstra = Dijkstra::new(&graph);
|
||||
println!("> Running dijkstra");
|
||||
dijkstra.run(
|
||||
start,
|
||||
|node| node == goal,
|
||||
|source, _edge, _target| !pages[source.usize()].redirect as u32,
|
||||
);
|
||||
|
||||
if dijkstra.cost(goal) == u32::MAX {
|
||||
println!("No path found");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
println!("> Collecting path");
|
||||
let path = dijkstra.path(goal);
|
||||
let cost = dijkstra.cost(goal);
|
||||
println!("Path found (cost {cost}, length {}):", path.len());
|
||||
for page in path {
|
||||
let info = &pages[page.usize()];
|
||||
if info.redirect {
|
||||
println!(" v {:?}", info.title);
|
||||
} else {
|
||||
println!(" - {:?}", info.title);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue