Skip to content

Commit 873a0f6

Browse files
authored
DFS fix (#51)
* dfs fix * bump ver
1 parent 486ff43 commit 873a0f6

File tree

2 files changed

+64
-13
lines changed

2 files changed

+64
-13
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.6"
3+
version = "0.2.7"
44
edition = "2024"
55
license = "MIT OR Apache-2.0"
66

src/netlist.rs

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,7 +1637,7 @@ pub mod iter {
16371637
use super::{
16381638
Connection, DrivenNet, InputPort, Instantiable, Net, NetRef, Netlist, Operand, WeakIndex,
16391639
};
1640-
use std::collections::HashSet;
1640+
use std::collections::{HashMap, HashSet};
16411641
/// An iterator over the nets in a netlist
16421642
pub struct NetIterator<'a, I: Instantiable> {
16431643
netlist: &'a Netlist<I>,
@@ -1772,6 +1772,51 @@ pub mod iter {
17721772
}
17731773
}
17741774

1775+
/// A stack that can check contains in roughly O(1) time.
1776+
struct Stack<T: std::hash::Hash + PartialEq + Eq + Clone> {
1777+
stack: Vec<T>,
1778+
counter: HashMap<T, usize>,
1779+
}
1780+
1781+
impl<T> Stack<T>
1782+
where
1783+
T: std::hash::Hash + PartialEq + Eq + Clone,
1784+
{
1785+
/// Create a new, empty Stack.
1786+
fn new() -> Self {
1787+
Self {
1788+
stack: Vec::new(),
1789+
counter: HashMap::new(),
1790+
}
1791+
}
1792+
1793+
/// Inserts an element into the stack
1794+
fn push(&mut self, item: T) {
1795+
self.stack.push(item.clone());
1796+
*self.counter.entry(item).or_insert(0) += 1;
1797+
}
1798+
1799+
/// Pops the top element from the stack
1800+
fn pop(&mut self) -> Option<T> {
1801+
if let Some(item) = self.stack.pop() {
1802+
if let Some(count) = self.counter.get_mut(&item) {
1803+
*count -= 1;
1804+
if *count == 0 {
1805+
self.counter.remove(&item);
1806+
}
1807+
}
1808+
Some(item)
1809+
} else {
1810+
None
1811+
}
1812+
}
1813+
1814+
/// Checks if the stack contains the given element
1815+
fn contains(&self, item: &T) -> bool {
1816+
self.counter.contains_key(item)
1817+
}
1818+
}
1819+
17751820
/// A depth-first iterator over the circuit nodes in a netlist
17761821
/// # Examples
17771822
///
@@ -1792,7 +1837,7 @@ pub mod iter {
17921837
/// ```
17931838
pub struct DFSIterator<'a, I: Instantiable> {
17941839
netlist: &'a Netlist<I>,
1795-
stack: Vec<NetRef<I>>,
1840+
stack: Stack<NetRef<I>>,
17961841
visited: HashSet<usize>,
17971842
cycles: bool,
17981843
}
@@ -1803,9 +1848,11 @@ pub mod iter {
18031848
{
18041849
/// Create a new DFS iterator for the netlist starting at `from`.
18051850
pub fn new(netlist: &'a Netlist<I>, from: NetRef<I>) -> Self {
1851+
let mut s = Stack::new();
1852+
s.push(from);
18061853
Self {
18071854
netlist,
1808-
stack: vec![from],
1855+
stack: s,
18091856
visited: HashSet::new(),
18101857
cycles: false,
18111858
}
@@ -1847,16 +1894,20 @@ pub mod iter {
18471894
if let Some(item) = self.stack.pop() {
18481895
let uw = item.clone().unwrap();
18491896
let index = uw.borrow().get_index();
1850-
if !self.visited.insert(index) {
1851-
self.cycles = true;
1852-
return self.next();
1853-
}
1854-
let operands = &uw.borrow().operands;
1855-
for operand in operands.iter().flatten() {
1856-
self.stack
1857-
.push(NetRef::wrap(self.netlist.index_weak(&operand.root())));
1897+
if self.visited.insert(index) {
1898+
let operands = &uw.borrow().operands;
1899+
for operand in operands.iter().flatten() {
1900+
self.stack
1901+
.push(NetRef::wrap(self.netlist.index_weak(&operand.root())));
1902+
}
18581903
}
1859-
return Some(item);
1904+
1905+
return if self.stack.contains(&item) {
1906+
self.cycles = true;
1907+
self.next()
1908+
} else {
1909+
Some(item)
1910+
};
18601911
}
18611912

18621913
None

0 commit comments

Comments
 (0)