more refactoring

main
Antonio De Lucreziis 2 months ago
parent 37bc313f20
commit e3b5d1f7da

@ -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};

@ -46,3 +46,5 @@ pub enum Entry {
segments: Vec<(String, Orientation)>,
},
}
pub mod parser;

@ -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<R: AsRef<str>>(file: R) -> io::Result<Vec<Entry>> {
let file_lines_count = BufReader::new(std::fs::File::open(file.as_ref())?)
pub fn parse_file(file: &str) -> io::Result<Vec<Entry>> {
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)
}

@ -1,104 +1,104 @@
use std::{collections::HashMap, io::Read};
use crate::{gfa::Entry, parser};
pub struct Graph {
nodes: HashMap<String, usize>,
edges_from: Vec<usize>,
edges_to: Vec<usize>,
}
#[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<R: Read>(reader: R, len: u64) -> Result<Graph, LoadGraphError> {
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<String, usize>,
// edges_from: Vec<usize>,
// edges_to: Vec<usize>,
// }
// #[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<R: Read>(reader: R, len: u64) -> Result<Graph, LoadGraphError> {
// 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)
// }

@ -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<V>
where
V: Hash + Eq + Clone,
{
nodes: HashSet<V>,
adjacencies: HashMap<V, HashSet<V>>,
}
pub struct UndirectedGraph<V>
where
V: Hash + Eq + Clone,
{
graph: AdjacencyGraph<V>,
}
#[allow(dead_code)]
impl<V> AdjacencyGraph<V>
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<V>> {
self.adjacencies.get(node)
}
pub fn adjacencies(&self) -> &HashMap<V, HashSet<V>> {
&self.adjacencies
}
pub fn nodes(&self) -> &HashSet<V> {
&self.nodes
}
pub fn edges(&self) -> impl Iterator<Item = (&V, &V)> {
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<Item = V> + '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::<HashSet<_>>();
// 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<Vec<V>> {
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<V> = 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<Vec<V>> {
let mut cc: HashMap<V, Rc<RefCell<HashSet<V>>>> = 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<RefCell<HashSet<V>>> = 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<usize, usize> = 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<V> UndirectedGraph<V>
where
V: Hash + Eq + Clone + Debug,
{
pub fn connected_components(&self) -> Vec<Vec<V>> {
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<V> = 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
}
}

@ -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;

@ -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());

Loading…
Cancel
Save