refactor: centralize graph traversal logic in walk

Refactor `leavable` and `reachable` to eliminate duplicated graph traversal logic by mutually delegating via `WalkState`. `leavable` now returns `self.walk(graph).is_some()`, while `reachable` delegates to the inverted `direct` state's `leavable` check. This centralizes kmer extension and visited-state validation in `walk`, simplifying control flow and reducing code duplication.
This commit is contained in:
Eric Coissac
2026-06-06 04:41:53 +02:00
parent 952a21eef8
commit 95b3461405
+3 -49
View File
@@ -189,58 +189,12 @@ impl WalkState {
} }
pub fn leavable(&self, graph: &GraphDeBruijn) -> bool { pub fn leavable(&self, graph: &GraphDeBruijn) -> bool {
WalkState { self.walk(graph).is_some()
kmer: self.kmer,
node: self.node,
direct: !self.direct,
}
.reachable(graph)
} }
pub fn reachable(&self, graph: &GraphDeBruijn) -> bool { pub fn reachable(&self, graph: &GraphDeBruijn) -> bool {
if self.direct { WalkState { kmer: self.kmer, node: self.node, direct: !self.direct }
if self.node.can_extend_left() { .leavable(graph)
let next = self.kmer.into_kmer().push_left(self.node.left_nuc());
let cnext = next.canonical();
let dnext = next.raw() == cnext.raw();
let next_node = Node(
graph
.nodes
.get(&cnext)
.unwrap()
.load(std::sync::atomic::Ordering::Relaxed),
);
!next_node.is_visited()
&& if dnext {
next_node.can_extend_right()
} else {
next_node.can_extend_left()
}
} else {
false
}
} else {
if self.node.can_extend_right() {
let next = self.kmer.into_kmer().push_right(self.node.right_nuc());
let cnext = next.canonical();
let dnext = next.raw() == cnext.raw();
let next_node = Node(
graph
.nodes
.get(&cnext)
.unwrap()
.load(std::sync::atomic::Ordering::Relaxed),
);
!next_node.is_visited()
&& if dnext {
next_node.can_extend_left()
} else {
next_node.can_extend_right()
}
} else {
false
}
}
} }
pub fn walk(&self, graph: &GraphDeBruijn) -> Option<WalkState> { pub fn walk(&self, graph: &GraphDeBruijn) -> Option<WalkState> {