Skip to content

Commit

Permalink
Ran formatter and bumped version to v0.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
octavonce committed Mar 24, 2019
1 parent d90ea25 commit a12058b
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 69 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "graphlib"
version = "0.2.1"
version = "0.2.2"
authors = ["Octavian Oncescu <[email protected]>"]
edition = "2018"
repository = "https://github.com/purpleprotocol/graphlib"
Expand Down
49 changes: 26 additions & 23 deletions src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,9 @@ impl<T> Graph<T> {
/// graph.add_edge(&v3, &v4).unwrap();
///
/// assert!(!graph.is_cyclic());
///
///
/// graph.add_edge(&v3, &v1);
///
///
/// assert!(graph.is_cyclic());
/// ```
pub fn is_cyclic(&self) -> bool {
Expand Down Expand Up @@ -667,8 +667,8 @@ impl<T> Graph<T> {
/// ```
pub fn in_neighbors(&self, id: &VertexId) -> VertexIter<'_> {
match self.inbound_table.get(id) {
Some(neighbors) => VertexIter(Box::new(neighbors.iter().map(AsRef::as_ref,),),),
None => VertexIter(Box::new(std::iter::empty(),),),
Some(neighbors) => VertexIter(Box::new(neighbors.iter().map(AsRef::as_ref))),
None => VertexIter(Box::new(std::iter::empty())),
}
}

Expand Down Expand Up @@ -701,9 +701,9 @@ impl<T> Graph<T> {
/// assert_eq!(neighbors[1], &v4);
/// ```
pub fn out_neighbors(&self, id: &VertexId) -> VertexIter<'_> {
match self.outbound_table.get(id,) {
Some(iter) => VertexIter(Box::new(iter.iter().map(AsRef::as_ref,),),),
None => VertexIter(Box::new(std::iter::empty(),),),
match self.outbound_table.get(id) {
Some(iter) => VertexIter(Box::new(iter.iter().map(AsRef::as_ref))),
None => VertexIter(Box::new(std::iter::empty())),
}
}

Expand Down Expand Up @@ -738,12 +738,13 @@ impl<T> Graph<T> {
/// ```
pub fn neighbors(&self, id: &VertexId) -> VertexIter<'_> {
let mut visited = HashSet::new();
let neighbors = self.out_neighbors(id,)
.chain(self.in_neighbors(id,),)
let neighbors = self
.out_neighbors(id)
.chain(self.in_neighbors(id))
//Remove duplicates.
.filter(move |&&v,| visited.insert(v,),);
.filter(move |&&v| visited.insert(v));

VertexIter(Box::new(neighbors,),)
VertexIter(Box::new(neighbors))
}

/// Returns an iterator over the root vertices
Expand Down Expand Up @@ -774,7 +775,7 @@ impl<T> Graph<T> {
/// assert_eq!(roots[0], &v3);
/// ```
pub fn roots(&self) -> VertexIter<'_> {
VertexIter(Box::new(self.roots.iter().map(AsRef::as_ref,),),)
VertexIter(Box::new(self.roots.iter().map(AsRef::as_ref)))
}

/// Returns an iterator over all of the
Expand All @@ -800,7 +801,7 @@ impl<T> Graph<T> {
/// assert_eq!(vertices.len(), 4);
/// ```
pub fn vertices(&self) -> VertexIter<'_> {
VertexIter(Box::new(self.vertices.keys().map(AsRef::as_ref,),),)
VertexIter(Box::new(self.vertices.keys().map(AsRef::as_ref)))
}

/// Returns an iterator over the vertices
Expand All @@ -811,20 +812,20 @@ impl<T> Graph<T> {
/// # #[macro_use] extern crate graphlib; fn main() {
/// use graphlib::Graph;
/// use std::collections::HashSet;
///
///
/// let mut graph: Graph<usize> = Graph::new();
///
///
/// let v1 = graph.add_vertex(0);
/// let v2 = graph.add_vertex(1);
/// let v3 = graph.add_vertex(2);
/// let v4 = graph.add_vertex(3);
///
///
/// graph.add_edge(&v1, &v2).unwrap();
/// graph.add_edge(&v3, &v1).unwrap();
/// graph.add_edge(&v1, &v4).unwrap();
///
///
/// let mut dfs = graph.dfs();
///
///
/// assert_eq!(dfs.next(), Some(&v3));
/// assert_eq!(dfs.next(), Some(&v1));
/// assert!(set![&v2, &v4] == dfs.collect());
Expand Down Expand Up @@ -894,7 +895,7 @@ mod tests {
#[test]
fn dfs() {
let mut graph: Graph<usize> = Graph::new();

let v1 = graph.add_vertex(0);
let v2 = graph.add_vertex(1);
let v3 = graph.add_vertex(2);
Expand All @@ -914,7 +915,7 @@ mod tests {
#[test]
fn dfs_mul_roots() {
let mut graph: Graph<usize> = Graph::new();

let v1 = graph.add_vertex(0);
let v2 = graph.add_vertex(1);
let v3 = graph.add_vertex(2);
Expand All @@ -931,16 +932,18 @@ mod tests {

// Iterate over vertices
let mut dfs = graph.dfs();

for _ in 0..2 {
let v = dfs.next();

if v == Some(&v3) {
assert_eq!(dfs.next(), Some(&v1));
assert!(set![&v2, &v4] == (&mut dfs).take(2).collect());
} else if v == Some(&v5) {
assert_eq!(dfs.next(), Some(&v6));
} else { panic!("Not a root node") }
} else {
panic!("Not a root node")
}
}

assert_eq!(dfs.count(), 0, "There were remaining nodes");
Expand Down
92 changes: 52 additions & 40 deletions src/iterators/dfs.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Copyright 2019 Octavian Oncescu

use crate::graph::Graph;
use crate::vertex_id::VertexId;
use crate::iterators::VertexIter;
use crate::vertex_id::VertexId;

use hashbrown::HashSet;
use std::iter::{Cloned, Chain, Peekable,};
use std::iter::{Chain, Cloned, Peekable};

#[derive(Debug)]
/// Depth-First Iterator
Expand All @@ -26,9 +26,7 @@ pub struct Dfs<'a, T> {

impl<'a, T> Dfs<'a, T> {
pub fn new(graph: &'a Graph<T>) -> Dfs<'_, T> {
let unchecked = graph.roots()
.chain(graph.vertices())
.cloned().peekable();
let unchecked = graph.roots().chain(graph.vertices()).cloned().peekable();

Dfs {
unchecked,
Expand All @@ -41,13 +39,15 @@ impl<'a, T> Dfs<'a, T> {
}

/// Returns true if the iterated graph has a cycle.
///
///
/// # Warning
///
///
/// It is a logic error to use this iterator after calling this function.
pub fn is_cyclic(&mut self,) -> bool {
pub fn is_cyclic(&mut self) -> bool {
//Check for a cached answer.
if self.cached_cyclic { return self.cached_cyclic }
if self.cached_cyclic {
return self.cached_cyclic;
}

//Search until an answer is found.
while self.process_vertex().is_some() {}
Expand All @@ -56,50 +56,56 @@ impl<'a, T> Dfs<'a, T> {
}

/// Processes the next vertex.
///
///
/// Will return None if:
///
///
/// * No vertices are left.
/// * The next vertex forms a cycle.
fn process_vertex(&mut self,) -> Option<&'a VertexId> {
fn process_vertex(&mut self) -> Option<&'a VertexId> {
//We have traversed this partition of the graph, move on.
if self.pending_stack.is_empty() {
//Mark all the grey vertices black.
self.black.extend(self.grey.drain(),);
self.black.extend(self.grey.drain());

//Spliting the borrows for the borrow checker.
let unchecked = &mut self.unchecked;
let black = &self.black;

//Search for an unprocessed vertex.
let next = unchecked.find(move |v,| !black.contains(v));
let next = unchecked.find(move |v| !black.contains(v));

//We found a new vertex.
if let Some(v) = next {
self.pending_stack.push(v);
}
}

//Get the next pending vertex.
self.pending_stack.pop().iter()
//Filter cycles.
.filter_map(|v,| {
//If this vertex forms a cycle do not return it.
if !self.grey.insert(*v) {
self.cached_cyclic = true;

return None
}

//Add all of its neighbours to be processed.
for v in self.iterable.out_neighbors(v) {
//This neighbour forms a cycle don't process it.
if self.grey.contains(v) { self.cached_cyclic = true }
else { self.pending_stack.push(*v) }
}

self.iterable.fetch_id_ref(v)
}).next()
self.pending_stack
.pop()
.iter()
//Filter cycles.
.filter_map(|v| {
//If this vertex forms a cycle do not return it.
if !self.grey.insert(*v) {
self.cached_cyclic = true;

return None;
}

//Add all of its neighbours to be processed.
for v in self.iterable.out_neighbors(v) {
//This neighbour forms a cycle don't process it.
if self.grey.contains(v) {
self.cached_cyclic = true
} else {
self.pending_stack.push(*v)
}
}

self.iterable.fetch_id_ref(v)
})
.next()
}
}

Expand All @@ -112,7 +118,9 @@ impl<'a, T> Iterator for Dfs<'a, T> {
(0, Some(remaining))
}
fn next(&mut self) -> Option<Self::Item> {
(0..self.size_hint().1.unwrap()).filter_map(move |_,| self.process_vertex()).next()
(0..self.size_hint().1.unwrap())
.filter_map(move |_| self.process_vertex())
.next()
}
}

Expand All @@ -136,11 +144,15 @@ mod tests {

assert!(graph.add_edge(&v, &v).is_ok(), "Failed to create cycle");

for _ in 0..100 { graph.add_vertex(0); }
for _ in 0..100 {
graph.add_vertex(0);
}

let mut dfs = graph.dfs();

for _ in 0..99 { dfs.next(); }
for _ in 0..99 {
dfs.next();
}

assert!(dfs.is_cyclic());
}
Expand All @@ -153,9 +165,9 @@ mod tests {
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());

graph.add_edge(&v1, &v2,);
graph.add_edge(&v3, &v2,);
graph.add_edge(&v1, &v2);
graph.add_edge(&v3, &v2);

graph.add_vertex(());

assert!(graph.is_cyclic() == false,);
Expand Down
11 changes: 6 additions & 5 deletions src/iterators/vertices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@
use crate::vertex_id::VertexId;
use std::fmt::Debug;

pub(crate) trait MergedTrait<'a,>: Iterator<Item = &'a VertexId> + Debug {}
pub(crate) trait MergedTrait<'a>: Iterator<Item = &'a VertexId> + Debug {}

impl<'a, T,> MergedTrait<'a,> for T
where T: Iterator<Item = &'a VertexId> + Debug {}
impl<'a, T> MergedTrait<'a> for T where T: Iterator<Item = &'a VertexId> + Debug {}

/// Generic Vertex Iterator.
#[derive(Debug)]
pub struct VertexIter<'a>(pub(crate) Box<dyn 'a + MergedTrait<'a,>>,);
pub struct VertexIter<'a>(pub(crate) Box<dyn 'a + MergedTrait<'a>>);

impl<'a> Iterator for VertexIter<'a> {
type Item = &'a VertexId;

#[inline]
fn next(&mut self) -> Option<Self::Item> { self.0.next() }
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}

0 comments on commit a12058b

Please sign in to comment.