Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Commit 2438a01

Browse files
author
Hendrik van Antwerpen
committed
Use arenas for cycle detectors
1 parent 6fbc49a commit 2438a01

File tree

1 file changed

+75
-50
lines changed

1 file changed

+75
-50
lines changed

stack-graphs/src/cycles.rs

Lines changed: 75 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,17 @@
3030
//! any time.
3131
3232
use std::collections::HashMap;
33-
use std::collections::VecDeque;
3433

3534
use smallvec::SmallVec;
3635

3736
use crate::arena::Handle;
37+
use crate::arena::List;
38+
use crate::arena::ListArena;
3839
use crate::graph::Edge;
3940
use crate::graph::Node;
4041
use crate::graph::StackGraph;
4142
use crate::partial::PartialPath;
4243
use crate::partial::PartialPaths;
43-
use crate::paths::Extend;
4444
use crate::paths::Path;
4545
use crate::stitching::Database;
4646
use crate::stitching::OwnedOrDatabasePath;
@@ -140,51 +140,65 @@ where
140140

141141
#[derive(Clone)]
142142
pub struct EdgeAppendingCycleDetector {
143-
edges: VecDeque<Edge>,
143+
edges: List<Edge>,
144144
}
145145

146-
pub struct AppendedEdges {}
147-
148-
impl AppendedEdges {
149-
pub fn new() -> Self {
150-
Self {}
151-
}
152-
}
146+
pub type AppendedEdges = ListArena<Edge>;
153147

154148
impl EdgeAppendingCycleDetector {
155149
pub fn new() -> Self {
156150
Self {
157-
edges: vec![].into(),
151+
edges: List::empty(),
158152
}
159153
}
160154

161155
pub fn append_edge(
162156
&mut self,
163157
graph: &StackGraph,
164158
partials: &mut PartialPaths,
165-
_edges: &mut AppendedEdges,
159+
appended_edges: &mut AppendedEdges,
166160
edge: Edge,
167161
) -> Result<(), ()> {
168162
let end_node = edge.sink;
169-
self.edges.push(edge);
163+
self.edges.push_front(appended_edges, edge);
170164

171165
let mut cyclic_path = PartialPath::from_node(graph, partials, end_node);
172-
let mut last_idx = self.edges.len();
173-
for idx in (0..last_idx).rev() {
174-
let edge = self.edges[idx];
175-
if edge.source != cyclic_path.end_node {
176-
continue;
166+
let mut index = self.edges;
167+
let mut edges = self.edges;
168+
loop {
169+
// find loop point
170+
let mut count = 0usize;
171+
loop {
172+
match index.pop_front(appended_edges) {
173+
Some(edge) => {
174+
count += 1;
175+
if edge.source == end_node {
176+
break;
177+
}
178+
}
179+
None => return Ok(()),
180+
}
181+
}
182+
183+
// get prefix edges
184+
let mut prefix_edges = List::empty();
185+
for _ in 0..count {
186+
prefix_edges.push_front(appended_edges, *edges.pop_front(appended_edges).unwrap());
177187
}
178188

179-
let mut prefix_path = PartialPath::from_node(graph, partials, edge.source);
180-
for idx in idx..last_idx {
181-
let edge = self.edges[idx];
189+
// build prefix path
190+
let mut prefix_path = PartialPath::from_node(graph, partials, end_node);
191+
while let Some(edge) = prefix_edges.pop_front(appended_edges) {
182192
prefix_path
183193
.resolve_to(graph, partials, edge.source)
184194
.unwrap();
185-
prefix_path.append(graph, partials, edge).unwrap();
195+
prefix_path.append(graph, partials, *edge).unwrap();
186196
}
187-
last_idx = idx;
197+
198+
// build cyclic path
199+
prefix_path
200+
.resolve_to(graph, partials, cyclic_path.start_node)
201+
.unwrap();
188202
prefix_path.ensure_no_overlapping_variables(partials, &cyclic_path);
189203
prefix_path
190204
.concatenate(graph, partials, &cyclic_path)
@@ -195,8 +209,6 @@ impl EdgeAppendingCycleDetector {
195209
return Err(());
196210
}
197211
}
198-
199-
Ok(())
200212
}
201213
}
202214

@@ -205,59 +217,74 @@ impl EdgeAppendingCycleDetector {
205217

206218
#[derive(Clone)]
207219
pub struct PartialPathAppendingCycleDetector {
208-
paths: VecDeque<OwnedOrDatabasePath>,
220+
paths: List<OwnedOrDatabasePath>,
209221
}
210222

211-
pub struct AppendedPartialPaths {}
212-
213-
impl AppendedPartialPaths {
214-
pub fn new() -> Self {
215-
Self {}
216-
}
217-
}
223+
pub type AppendedPartialPaths = ListArena<OwnedOrDatabasePath>;
218224

219225
impl PartialPathAppendingCycleDetector {
220226
pub fn from_partial_path(
221227
_graph: &StackGraph,
222228
_partials: &mut PartialPaths,
223229
_db: &mut Database,
224-
_paths: &mut AppendedPartialPaths,
230+
appended_paths: &mut AppendedPartialPaths,
225231
path: OwnedOrDatabasePath,
226232
) -> Self {
227-
Self {
228-
paths: vec![path].into(),
229-
}
233+
let mut paths = List::empty();
234+
paths.push_front(appended_paths, path);
235+
Self { paths }
230236
}
231237

232238
pub fn append_partial_path(
233239
&mut self,
234240
graph: &StackGraph,
235241
partials: &mut PartialPaths,
236242
db: &Database,
237-
_paths: &mut AppendedPartialPaths,
243+
appended_paths: &mut AppendedPartialPaths,
238244
path: OwnedOrDatabasePath,
239245
) -> Result<(), ()> {
240246
let end_node = path.get(db).end_node;
241-
self.paths.push(path);
247+
self.paths.push_front(appended_paths, path);
242248

243249
let mut cyclic_path = PartialPath::from_node(graph, partials, end_node);
244-
let mut last_idx = self.paths.len();
245-
for idx in (0..last_idx).rev() {
246-
let path = self.paths[idx].get(db);
247-
if path.start_node != cyclic_path.end_node {
248-
continue;
250+
let mut index = self.paths;
251+
let mut paths = self.paths;
252+
loop {
253+
// find loop point
254+
let mut count = 0usize;
255+
loop {
256+
match index.pop_front(appended_paths) {
257+
Some(path) => {
258+
count += 1;
259+
if path.get(db).start_node == end_node {
260+
break;
261+
}
262+
}
263+
None => return Ok(()),
264+
}
265+
}
266+
267+
// get prefix paths
268+
let mut prefix_paths = List::empty();
269+
for _ in 0..count {
270+
prefix_paths.push_front(
271+
appended_paths,
272+
paths.pop_front(appended_paths).unwrap().clone(),
273+
);
249274
}
250275

251-
let mut prefix_path = path.clone();
252-
for idx in (idx + 1)..last_idx {
253-
let path = self.paths[idx].get(db);
276+
// build prefix path
277+
let mut prefix_path = PartialPath::from_node(graph, partials, end_node);
278+
while let Some(path) = prefix_paths.pop_front(appended_paths) {
279+
let path = path.get(db);
254280
prefix_path
255281
.resolve_to(graph, partials, path.start_node)
256282
.unwrap();
257283
prefix_path.ensure_no_overlapping_variables(partials, path);
258284
prefix_path.concatenate(graph, partials, path).unwrap();
259285
}
260-
last_idx = idx;
286+
287+
// build cyclic path
261288
prefix_path
262289
.resolve_to(graph, partials, cyclic_path.start_node)
263290
.unwrap();
@@ -271,7 +298,5 @@ impl PartialPathAppendingCycleDetector {
271298
return Err(());
272299
}
273300
}
274-
275-
Ok(())
276301
}
277302
}

0 commit comments

Comments
 (0)