From e3b5d1f7daef1d08659be1d0a1af1536283bf55c Mon Sep 17 00:00:00 2001 From: Antonio De Lucreziis Date: Tue, 22 Oct 2024 21:16:26 +0200 Subject: [PATCH] more refactoring --- examples/configurable/src/main.rs | 4 +- src/{gfa.rs => gfa/mod.rs} | 2 + src/{ => gfa}/parser.rs | 8 +- src/graph_2.rs | 208 +++++++-------- src/graphhhh.rs | 416 ------------------------------ src/lib.rs | 10 +- src/main.rs | 9 +- src/utils.rs | 1 - 8 files changed, 120 insertions(+), 538 deletions(-) rename src/{gfa.rs => gfa/mod.rs} (98%) rename src/{ => gfa}/parser.rs (96%) delete mode 100644 src/graphhhh.rs delete mode 100644 src/utils.rs diff --git a/examples/configurable/src/main.rs b/examples/configurable/src/main.rs index 6cefb79..5ec335d 100644 --- a/examples/configurable/src/main.rs +++ b/examples/configurable/src/main.rs @@ -2,8 +2,6 @@ use std::collections::HashMap; use std::env; use std::time::Instant; -use asd::gfa::{Entry, Orientation}; -use asd::parser; use crossbeam::channel::{unbounded, Receiver, Sender}; use eframe::{run_native, App, CreationContext}; use egui::{CollapsingHeader, Context, Pos2, ScrollArea, Ui}; @@ -11,6 +9,8 @@ use egui_graphs::events::Event; use egui_graphs::{DefaultEdgeShape, DefaultNodeShape, Graph, GraphView}; use fdg_sim::glam::Vec3; use fdg_sim::{ForceGraph, ForceGraphHelper, Simulation, SimulationParameters}; +// use gfa::parser; +// use gfa::{Entry, Orientation}; use petgraph::stable_graph::{DefaultIx, NodeIndex, StableGraph}; use petgraph::Directed; use settings::{SettingsInteraction, SettingsNavigation, SettingsStyle}; diff --git a/src/gfa.rs b/src/gfa/mod.rs similarity index 98% rename from src/gfa.rs rename to src/gfa/mod.rs index f48f376..8a554bc 100644 --- a/src/gfa.rs +++ b/src/gfa/mod.rs @@ -46,3 +46,5 @@ pub enum Entry { segments: Vec<(String, Orientation)>, }, } + +pub mod parser; diff --git a/src/parser.rs b/src/gfa/parser.rs similarity index 96% rename from src/parser.rs rename to src/gfa/parser.rs index 5938c89..6b014f0 100644 --- a/src/parser.rs +++ b/src/gfa/parser.rs @@ -1,4 +1,4 @@ -#![allow(dead_code)] +// #![allow(dead_code)] use std::{ io::{self, BufRead, BufReader, Read}, @@ -126,13 +126,13 @@ fn parse_walk(line: &str) -> Entry { } } -pub fn parse_file>(file: R) -> io::Result> { - let file_lines_count = BufReader::new(std::fs::File::open(file.as_ref())?) +pub fn parse_file(file: &str) -> io::Result> { + let file_lines_count = BufReader::new(std::fs::File::open(file)?) .lines() .progress_count(0) .count() as u64; - let file = std::fs::File::open(file.as_ref())?; + let file = std::fs::File::open(file)?; parse_source(file, file_lines_count) } diff --git a/src/graph_2.rs b/src/graph_2.rs index 5ad7302..3442414 100644 --- a/src/graph_2.rs +++ b/src/graph_2.rs @@ -1,104 +1,104 @@ -use std::{collections::HashMap, io::Read}; - -use crate::{gfa::Entry, parser}; - -pub struct Graph { - nodes: HashMap, - - edges_from: Vec, - edges_to: Vec, -} - -#[derive(Debug)] -pub enum GraphError { - NodeNotFound(String), -} - -impl Graph { - pub fn new() -> Self { - Self { - nodes: HashMap::new(), - edges_from: Vec::new(), - edges_to: Vec::new(), - } - } - - pub fn add_node(&mut self, id: String) { - if self.nodes.contains_key(&id) { - return; - } - - self.nodes.insert(id, self.nodes.len()); - } - - pub fn add_edge(&mut self, from_id: &String, to_id: &String) -> Result<(), GraphError> { - let from = self - .nodes - .get(from_id) - .ok_or(GraphError::NodeNotFound(from_id.clone()))?; - - let to = self - .nodes - .get(to_id) - .ok_or(GraphError::NodeNotFound(to_id.clone()))?; - - self.edges_from.push(*from); - self.edges_to.push(*to); - - Ok(()) - } -} - -#[derive(Debug)] -pub enum LoadGraphError { - IoError(std::io::Error), - GraphError(GraphError), -} - -pub fn load_graph(reader: R, len: u64) -> Result { - println!("Loading graph"); - - let mut graph = Graph::new(); - - let entries = parser::parse_source(reader, len).map_err(|e| LoadGraphError::IoError(e))?; - - let node_count = entries - .iter() - .filter_map(|entry| match entry { - Entry::Segment { id, .. } => Some(id), - _ => None, - }) - .count(); - - println!("Node count: {}", node_count); - - for entry in entries - .iter() - .filter(|entry| matches!(entry, Entry::Link { .. })) - { - if let Entry::Link { - from, - from_orient, - to, - to_orient, - } = entry - { - let node_from = format!("{}{}", from, from_orient); - let node_to = format!("{}{}", to, to_orient); - - graph.add_node(node_from.clone()); - graph.add_node(node_to.clone()); - - graph - .add_edge(&node_from, &node_to) - .expect("Error adding edge"); - graph - .add_edge(&node_to, &node_from) - .expect("Error adding edge"); - } - } - - println!("Loading completed"); - - Ok(graph) -} +// use std::{collections::HashMap, io::Read}; + +// use crate::{gfa::Entry, parser}; + +// pub struct Graph { +// nodes: HashMap, + +// edges_from: Vec, +// edges_to: Vec, +// } + +// #[derive(Debug)] +// pub enum GraphError { +// NodeNotFound(String), +// } + +// impl Graph { +// pub fn new() -> Self { +// Self { +// nodes: HashMap::new(), +// edges_from: Vec::new(), +// edges_to: Vec::new(), +// } +// } + +// pub fn add_node(&mut self, id: String) { +// if self.nodes.contains_key(&id) { +// return; +// } + +// self.nodes.insert(id, self.nodes.len()); +// } + +// pub fn add_edge(&mut self, from_id: &String, to_id: &String) -> Result<(), GraphError> { +// let from = self +// .nodes +// .get(from_id) +// .ok_or(GraphError::NodeNotFound(from_id.clone()))?; + +// let to = self +// .nodes +// .get(to_id) +// .ok_or(GraphError::NodeNotFound(to_id.clone()))?; + +// self.edges_from.push(*from); +// self.edges_to.push(*to); + +// Ok(()) +// } +// } + +// #[derive(Debug)] +// pub enum LoadGraphError { +// IoError(std::io::Error), +// GraphError(GraphError), +// } + +// pub fn load_graph(reader: R, len: u64) -> Result { +// println!("Loading graph"); + +// let mut graph = Graph::new(); + +// let entries = parser::parse_source(reader, len).map_err(|e| LoadGraphError::IoError(e))?; + +// let node_count = entries +// .iter() +// .filter_map(|entry| match entry { +// Entry::Segment { id, .. } => Some(id), +// _ => None, +// }) +// .count(); + +// println!("Node count: {}", node_count); + +// for entry in entries +// .iter() +// .filter(|entry| matches!(entry, Entry::Link { .. })) +// { +// if let Entry::Link { +// from, +// from_orient, +// to, +// to_orient, +// } = entry +// { +// let node_from = format!("{}{}", from, from_orient); +// let node_to = format!("{}{}", to, to_orient); + +// graph.add_node(node_from.clone()); +// graph.add_node(node_to.clone()); + +// graph +// .add_edge(&node_from, &node_to) +// .expect("Error adding edge"); +// graph +// .add_edge(&node_to, &node_from) +// .expect("Error adding edge"); +// } +// } + +// println!("Loading completed"); + +// Ok(graph) +// } diff --git a/src/graphhhh.rs b/src/graphhhh.rs deleted file mode 100644 index fcd3956..0000000 --- a/src/graphhhh.rs +++ /dev/null @@ -1,416 +0,0 @@ -use std::{ - cell::RefCell, - cmp::Ordering, - collections::{BTreeMap, HashMap, HashSet, VecDeque}, - fmt::Debug, - hash::Hash, - rc::Rc, -}; - -use indicatif::{ProgressBar, ProgressIterator}; - -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub enum EdgeType { - TreeEdge, - BackEdge, - ForwardEdge, - CrossEdge, -} - -#[derive(Debug)] -pub struct AdjacencyGraph -where - V: Hash + Eq + Clone, -{ - nodes: HashSet, - adjacencies: HashMap>, -} - -pub struct UndirectedGraph -where - V: Hash + Eq + Clone, -{ - graph: AdjacencyGraph, -} - -#[allow(dead_code)] -impl AdjacencyGraph -where - V: Hash + Eq + Clone + Debug, -{ - pub fn new() -> Self { - AdjacencyGraph { - nodes: HashSet::new(), - adjacencies: HashMap::new(), - } - } - - pub fn add_node(&mut self, node: V) { - // O(1) - self.nodes.insert(node); - } - - pub fn add_edge(&mut self, from: V, to: V) { - // O(1) - self.add_node(from.clone()); - self.add_node(to.clone()); - - // O(1) - self.adjacencies - .entry(from) - .or_insert_with(HashSet::new) - .insert(to); - } - - pub fn get_adjacencies(&self, node: &V) -> Option<&HashSet> { - self.adjacencies.get(node) - } - - pub fn adjacencies(&self) -> &HashMap> { - &self.adjacencies - } - - pub fn nodes(&self) -> &HashSet { - &self.nodes - } - - pub fn edges(&self) -> impl Iterator { - self.adjacencies - .iter() - .flat_map(|(from, tos)| tos.iter().map(move |to| (from, to))) - } - - pub fn opposite(&self) -> AdjacencyGraph<&V> { - let mut opposite = AdjacencyGraph::new(); - - // O(|E|) - for (from, to) in self.edges() { - opposite.add_edge(to, from); - } - - opposite - } - - pub fn undirected(&self) -> UndirectedGraph<&V> { - let mut undirected = AdjacencyGraph::new(); - - // O(|E|) - for (from, to) in self.edges() { - undirected.add_edge(from, to); - undirected.add_edge(to, from); - } - - UndirectedGraph { graph: undirected } - } - - pub fn has_edge(&self, from: &V, to: &V) -> bool { - // O(1) - if let Some(adjacencies) = self.get_adjacencies(from) { - // O(1) - adjacencies.contains(&to.to_owned()) - } else { - false - } - } - - pub fn dfs<'a>(&'a self, node: &'a V) -> impl Iterator + 'a { - let mut visited = HashSet::new(); - let mut stack = VecDeque::from([node]); - - std::iter::from_fn(move || { - while let Some(node) = stack.pop_back() { - if !visited.insert(node.clone()) { - continue; - } - - if let Some(adjacencies) = self.get_adjacencies(node) { - stack.extend(adjacencies); - } - - return Some(node.clone()); - } - - None - }) - } - - /// This computes if this undirected graph is cyclic or not by searching for an oriented cycle in the graph - pub fn is_cyclic(&self) -> bool { - let mut remaining_nodes = self.nodes.iter().collect::>(); - - // let progress_bar = ProgressBar::new(self.nodes.len() as u64); - // let mut visited_count = 0; - - while !remaining_nodes.is_empty() { - let start: &V = remaining_nodes.iter().next().unwrap(); - - // visited_count += 1; - remaining_nodes.remove(start); - // progress_bar.inc(1); - - let mut dfs_visited = HashSet::new(); - let mut stack = VecDeque::new(); - stack.push_back(start); - - // start a new dfs from the current node - while let Some(node) = stack.pop_back() { - if dfs_visited.contains(node) { - // println!("Found cycle after {} nodes", visited_count); - // progress_bar.finish(); - return true; - } - - // visited_count += 1; - remaining_nodes.remove(node); - // progress_bar.inc(1); - - dfs_visited.insert(node.clone()); - - if let Some(adjacencies) = self.get_adjacencies(node) { - stack.extend(adjacencies); - } - } - } - - // println!("Found cycle after {} nodes", visited_count); - // progress_bar.finish(); - false - } - - pub fn shortest_path_matrix(&self) -> HashMap<&V, HashMap<&V, usize>> { - let mut result = HashMap::new(); - - for node in self.nodes.iter() { - let mut distances = HashMap::new(); - let mut visited = HashSet::new(); - let mut queue = VecDeque::from([node]); - - distances.insert(node, 0); - - while let Some(node) = queue.pop_front() { - if visited.contains(node) { - continue; - } - - visited.insert(node.clone()); - - let distance = *distances.get(node).unwrap(); - - if let Some(adjacencies) = self.get_adjacencies(node) { - for adj in adjacencies { - if !distances.contains_key(adj) { - distances.insert(adj, distance + 1); - queue.push_back(adj); - } - } - } - } - - result.insert(node, distances); - } - - result - } - - pub fn compute_ccs(&self) -> Vec> { - let mut visited = HashSet::new(); - let mut result = Vec::new(); - - let op = self.opposite(); - - for node in self - .nodes - .iter() - .progress() - .with_style( - indicatif::ProgressStyle::default_bar() - .template("{prefix} {spinner} [{elapsed_precise}] [{wide_bar}] {pos}/{len}") - .unwrap(), - ) - .with_prefix("computing connected components") - { - if visited.contains(node) { - continue; - } - - let mut cc: HashSet = HashSet::new(); - let mut stack: Vec<&V> = vec![node]; - - while let Some(node) = stack.pop() { - if cc.contains(node) { - continue; - } - - cc.insert(node.clone()); - - if let Some(adjacencies) = self.get_adjacencies(&node) { - for adj in adjacencies { - stack.push(adj); - } - } - - if let Some(adjacencies) = op.get_adjacencies(&node) { - for adj in adjacencies { - stack.push(adj); - } - } - } - - visited.extend(cc.iter().map(|x| x.to_owned())); - result.push(cc.iter().map(|x| x.to_owned()).collect()); - } - - result - } - - pub fn compute_ccs_2(&self) -> Vec> { - let mut cc: HashMap>>> = HashMap::new(); - - for node in self.nodes.iter() { - if cc.contains_key(&node) { - continue; - } - - // println!("All CC: {:?}", cc); - - let new_cc = Rc::new(RefCell::new(HashSet::new())); - - let mut stack: Vec<&V> = vec![node]; - - while let Some(node) = stack.pop() { - // println!("New CC: {:?}", new_cc.borrow()); - - if cc.contains_key(&node) { - // merge the two connected components and go to the next node - - let old_cc: &Rc>> = cc.get(&node).unwrap(); - - // println!( - // "Merging {:?} with {:?} due to link to {:?}", - // new_cc.borrow(), - // old_cc.borrow(), - // node - // ); - - new_cc - .borrow_mut() - .extend(old_cc.borrow().iter().map(|x| x.to_owned())); - - break; - } - - if new_cc.borrow().contains(&node) { - continue; - } - - new_cc.borrow_mut().insert(node.clone()); - - if let Some(adjacencies) = self.get_adjacencies(&node) { - for adj in adjacencies { - stack.push(adj); - } - } - } - - for n in new_cc.borrow().iter() { - cc.insert(n.to_owned(), new_cc.clone()); - } - } - - // extract the unique connected components by pointers - let mut result = Vec::new(); - let mut seen = HashSet::new(); - - for node in self.nodes.iter() { - if seen.contains(node) { - continue; - } - - let cc = cc.get(node).unwrap(); - seen.extend(cc.borrow().iter().map(|x| x.to_owned())); - - result.push(cc.borrow().iter().map(|x| x.to_owned()).collect()); - } - - result - } - - /// This function prints the number of nodes, edges and a histogram of the degrees of the nodes - /// in the graph (computing the degrees might take a long time) - pub fn print_stats(&self) { - let mut vertices_degrees = HashMap::new(); - - for (from, tos) in self - .adjacencies - .iter() - .progress() - .with_style( - indicatif::ProgressStyle::default_bar() - .template("{prefix} {spinner} [{elapsed_precise}] [{wide_bar}] {pos}/{len}") - .unwrap(), - ) - .with_prefix("computing nodes degrees") - { - *vertices_degrees.entry(from).or_insert(0) += tos.len(); - - for to in tos { - *vertices_degrees.entry(to).or_insert(0) += 1; - } - } - - let histogram: BTreeMap = vertices_degrees - .iter() - .map(|(_, degree)| *degree) - .fold(BTreeMap::new(), |mut acc, degree| { - *acc.entry(degree).or_insert(0) += 1; - acc - }); - - println!("Stats:"); - println!("Nodes: {}", self.nodes.len()); - println!("Edges: {}", self.edges().count()); - - println!("Histogram:"); - for (degree, count) in histogram.iter() { - println!("{}: {}", degree, count); - } - } -} - -impl UndirectedGraph -where - V: Hash + Eq + Clone + Debug, -{ - pub fn connected_components(&self) -> Vec> { - let mut visited = HashSet::new(); - let mut result = Vec::new(); - - for node in self.graph.nodes.iter() { - if visited.contains(node) { - continue; - } - - let mut cc: HashSet = HashSet::new(); - let mut stack: Vec<&V> = vec![node]; - - while let Some(node) = stack.pop() { - if cc.contains(node) { - continue; - } - - cc.insert(node.clone()); - - if let Some(adjacencies) = self.graph.get_adjacencies(&node) { - for adj in adjacencies { - stack.push(adj); - } - } - } - - visited.extend(cc.iter().map(|x| x.to_owned())); - result.push(cc.iter().map(|x| x.to_owned()).collect()); - } - - result - } -} diff --git a/src/lib.rs b/src/lib.rs index 79cc1ad..a9fd141 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,4 @@ -pub mod gfa; -pub mod graph; -pub mod graph_2; -pub mod parser; - -mod utils; +// pub mod gfa; +// pub mod graph; +// pub mod graph_2; +// pub mod parser; diff --git a/src/main.rs b/src/main.rs index 240e4ed..7cfda14 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +mod gfa; +mod graph; + use std::{ collections::{BTreeMap, HashMap}, io::{BufRead, BufReader}, @@ -8,10 +11,6 @@ use gfa::{Entry, Orientation}; use graph::AdjacencyGraph; use indicatif::ProgressIterator; -mod gfa; -mod graph; -mod parser; - #[derive(FromArgs, PartialEq, Debug)] /// Strumento CLI per il progetto di Algoritmi e Strutture Dati 2024 struct CliTool { @@ -48,7 +47,7 @@ fn main() -> std::io::Result<()> { let file = std::fs::File::open(show.input)?; - let entries = parser::parse_source(file, file_lines_count)?; + let entries = gfa::parser::parse_source(file, file_lines_count)?; println!("Number of entries: {}", entries.len()); diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index 8b13789..0000000 --- a/src/utils.rs +++ /dev/null @@ -1 +0,0 @@ -