Skip to content

Commit 552a82a

Browse files
authored
Final fix to DFS iter (#54)
* finally fix dfs * bump ver
1 parent fa896aa commit 552a82a

File tree

2 files changed

+25
-34
lines changed

2 files changed

+25
-34
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "safety-net"
3-
version = "0.2.9"
3+
version = "0.2.10"
44
edition = "2024"
55
license = "MIT OR Apache-2.0"
66

src/netlist.rs

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1781,12 +1781,13 @@ pub mod iter {
17811781
}
17821782

17831783
/// A stack that can check contains in roughly O(1) time.
1784-
struct Stack<T: std::hash::Hash + PartialEq + Eq + Clone> {
1784+
#[derive(Clone)]
1785+
struct Walk<T: std::hash::Hash + PartialEq + Eq + Clone> {
17851786
stack: Vec<T>,
17861787
counter: HashMap<T, usize>,
17871788
}
17881789

1789-
impl<T> Stack<T>
1790+
impl<T> Walk<T>
17901791
where
17911792
T: std::hash::Hash + PartialEq + Eq + Clone,
17921793
{
@@ -1804,24 +1805,14 @@ pub mod iter {
18041805
*self.counter.entry(item).or_insert(0) += 1;
18051806
}
18061807

1807-
/// Pops the top element from the stack
1808-
fn pop(&mut self) -> Option<T> {
1809-
if let Some(item) = self.stack.pop() {
1810-
if let Some(count) = self.counter.get_mut(&item) {
1811-
*count -= 1;
1812-
if *count == 0 {
1813-
self.counter.remove(&item);
1814-
}
1815-
}
1816-
Some(item)
1817-
} else {
1818-
None
1819-
}
1808+
/// Returns true if the stack shows a cycle
1809+
fn contains_cycle(&self) -> bool {
1810+
self.counter.values().any(|&count| count > 1)
18201811
}
18211812

1822-
/// Checks if the stack contains the given element
1823-
fn contains(&self, item: &T) -> bool {
1824-
self.counter.contains_key(item)
1813+
/// Returns a reference to the last element in the stack
1814+
fn last(&self) -> Option<&T> {
1815+
self.stack.last()
18251816
}
18261817
}
18271818

@@ -1845,7 +1836,7 @@ pub mod iter {
18451836
/// ```
18461837
pub struct DFSIterator<'a, I: Instantiable> {
18471838
netlist: &'a Netlist<I>,
1848-
stack: Stack<NetRef<I>>,
1839+
stacks: Vec<Walk<NetRef<I>>>,
18491840
visited: HashSet<usize>,
18501841
cycles: bool,
18511842
}
@@ -1856,11 +1847,11 @@ pub mod iter {
18561847
{
18571848
/// Create a new DFS iterator for the netlist starting at `from`.
18581849
pub fn new(netlist: &'a Netlist<I>, from: NetRef<I>) -> Self {
1859-
let mut s = Stack::new();
1850+
let mut s = Walk::new();
18601851
s.push(from);
18611852
Self {
18621853
netlist,
1863-
stack: s,
1854+
stacks: vec![s],
18641855
visited: HashSet::new(),
18651856
cycles: false,
18661857
}
@@ -1899,25 +1890,25 @@ pub mod iter {
18991890
type Item = NetRef<I>;
19001891

19011892
fn next(&mut self) -> Option<Self::Item> {
1902-
if let Some(item) = self.stack.pop() {
1903-
let uw = item.clone().unwrap();
1893+
if let Some(walk) = self.stacks.pop() {
1894+
let item = walk.last().cloned();
1895+
let uw = item.clone().unwrap().unwrap();
19041896
let index = uw.borrow().get_index();
19051897
if self.visited.insert(index) {
19061898
let operands = &uw.borrow().operands;
19071899
for operand in operands.iter().flatten() {
1908-
self.stack
1909-
.push(NetRef::wrap(self.netlist.index_weak(&operand.root())));
1900+
let mut new_walk = walk.clone();
1901+
new_walk.push(NetRef::wrap(self.netlist.index_weak(&operand.root())));
1902+
if !new_walk.contains_cycle() {
1903+
self.stacks.push(new_walk);
1904+
} else {
1905+
self.cycles = true;
1906+
}
19101907
}
1911-
} else {
1912-
self.cycles = true;
1908+
return item;
19131909
}
19141910

1915-
return if self.stack.contains(&item) {
1916-
self.cycles = true;
1917-
self.next()
1918-
} else {
1919-
Some(item)
1920-
};
1911+
return self.next();
19211912
}
19221913

19231914
None

0 commit comments

Comments
 (0)