commit 2dbe57d6696dab687fa1675d846425507389e963 Author: Arlo Date: Thu May 2 11:59:51 2024 +0100 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..566430d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "page_rank" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..5e6bdf6 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "page_rank" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..eeeb3a9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,76 @@ +use std::collections::HashMap; + +fn main() { + let mut pages: Graph = Graph::new(); + pages.add_page('A'); + pages.add_page('B'); + pages.add_page('C'); + pages.add_page('D'); + pages.add_page('E'); + + println!("{pages:?}"); + pages.link_page('B', 'A'); + pages.link_page('C', 'B'); + pages.link_page('D', 'C'); + pages.link_page('B', 'D'); + pages.link_page('E', 'D'); + pages.link_page('A', 'E'); + pages.link_page('B', 'E'); + println!("{pages:?}"); + + println!("{:?} -> B", pages.get_links('B')); + let p = pages.clone(); + for page in p.items { + println!("PageRank {page} => {}", pages.page_rank(page, 10)) + } +} + +#[derive(Debug, Clone)] +pub struct Graph { + items: Vec, + links: HashMap>, + pub damping_factor: f64 +} + +impl Graph { + pub fn new() -> Self { + Graph { items: vec![], links: HashMap::new(), damping_factor: 0.85 } + } + + pub fn add_page(&mut self, item: T) { + self.items.push(item); + self.items.sort(); + let index = self.find_item(item); + self.links.insert(index, vec![]); + } + + pub fn link_page(&mut self, item: T, link: T) { + let item = self.find_item(item); + let link = self.find_item(link); + self.add_link(item, link) + } + + fn add_link(&mut self, item_index: usize, link_index: usize) { + self.links.get_mut(&item_index).unwrap().push(link_index); + } + + fn find_item(&self, item: T) -> usize { + self.items.binary_search(&item).unwrap() + } + + pub fn get_links(&self, item: T) -> Vec { + let item = self.find_item(item); + self.links.get(&item).unwrap() + .to_vec().iter().map(|i| self.items[*i]).collect() + } + + pub fn page_rank(&self, item: T, depth: i32) -> f64 { + if depth == 0 { return 0.0; } + + let links = self.get_links(item); + let link_sums: f64 = links.clone().iter().map( + |i| self.page_rank(*i, depth - 1) / self.get_links(*i).len() as f64 + ).sum(); + return (1.0 - self.damping_factor) + self.damping_factor * link_sums + } +} \ No newline at end of file