Skip to content

Commit 5a43a38

Browse files
authored
doc: book chapter on edge differences (#417)
Move some tests from tree.rs to tests/
1 parent 1e2bb48 commit 5a43a38

File tree

4 files changed

+62
-50
lines changed

4 files changed

+62
-50
lines changed

book/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- [Initialization from a table collection](./tree_sequence_from_table_collection.md)
1414
- [Iterating over trees](./tree_sequence_iterate_trees.md)
1515
- [Working with trees](./tree_sequence_tree.md)
16+
- [Edge differences](./tree_sequence_edge_diffs.md)
1617
- [Miscellaneous operations](./tree_sequence_miscellaneous.md)
1718

1819
* [Metadata](./metadata.md)

book/src/tree_sequence_edge_diffs.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
## Iterating over edge differences
2+
3+
As with [trees](tree_sequence_iterate_trees.md), the API provides a *lending* iterator over edge differences.
4+
Each step of the iterator advances to the next tree in the tree sequence.
5+
For each tree, a standard `Iterator` over removals and insertions is available:
6+
7+
```rust, noplaygound, ignore
8+
{{#include ../../tests/book_trees.rs:iterate_edge_differences}}
9+
```
10+
11+
Edge differences are the basis of efficient algorithms based on the incremental updating of summaries of trees.
12+
The following example co-iterates over edge differences and trees.
13+
The edge differences are used to calculate the parent array for each tree:
14+
15+
```rust, noplaygound, ignore
16+
{{#include ../../tests/book_trees.rs:iterate_edge_differences_update_parents}}
17+
```
18+
19+

src/trees.rs

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -873,56 +873,6 @@ pub(crate) mod test_trees {
873873
panic!("Expected a tree.");
874874
}
875875
}
876-
877-
// TODO: use trybuild to add tests that the iterator
878-
// lifetime is indeed coupled to that of the treeseq
879-
#[test]
880-
fn test_edge_diffs_lending_iterator_num_trees() {
881-
{
882-
let treeseq = treeseq_from_small_table_collection_two_trees();
883-
let num_nodes: usize = treeseq.nodes().num_rows().try_into().unwrap();
884-
let mut parents = vec![NodeId::NULL; num_nodes + 1];
885-
if let Ok(mut ediff_iter) = treeseq.edge_differences_iter() {
886-
let mut tree_iter = treeseq.tree_iterator(0).unwrap();
887-
let mut ntrees = 0;
888-
while let Some(diffs) = ediff_iter.next() {
889-
let tree = tree_iter.next().unwrap();
890-
891-
for edge_out in diffs.edge_removals() {
892-
let p = edge_out.child();
893-
parents[usize::try_from(p).unwrap()] = NodeId::NULL;
894-
}
895-
896-
for edge_in in diffs.edge_insertions() {
897-
let c: usize = edge_in.child().try_into().unwrap();
898-
parents[c] = edge_in.parent();
899-
}
900-
901-
assert_eq!(tree.parent_array(), &parents);
902-
ntrees += 1;
903-
}
904-
assert_eq!(ntrees, 2);
905-
} else {
906-
panic!("expected an edge differences iterator");
907-
}
908-
}
909-
910-
{
911-
let treeseq = treeseq_from_small_table_collection_two_trees();
912-
let mut ediff_iter = treeseq.edge_differences_iter().unwrap();
913-
914-
let mut ntrees = 0;
915-
while let Some(diffs) = ediff_iter.next() {
916-
if ntrees == 0 {
917-
assert_eq!(diffs.interval(), (0.0.into(), 500.0.into()));
918-
} else {
919-
assert_eq!(diffs.interval(), (500.0.into(), 1000.0.into()));
920-
}
921-
ntrees += 1;
922-
}
923-
assert_eq!(ntrees, 2);
924-
}
925-
}
926876
}
927877

928878
#[cfg(test)]

tests/book_trees.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,46 @@ fn initialize_from_table_collection() {
142142
}
143143
}
144144
// ANCHOR_END: iterate_node_siblings_via_array_getters
145+
146+
// ANCHOR: iterate_edge_differences
147+
if let Ok(mut edge_diff_iterator) = treeseq.edge_differences_iter() {
148+
while let Some(diffs) = edge_diff_iterator.next() {
149+
for edge_removal in diffs.edge_removals() {
150+
println!("{}", edge_removal);
151+
}
152+
for edge_insertion in diffs.edge_insertions() {
153+
println!("{}", edge_insertion);
154+
}
155+
}
156+
} else {
157+
panic!("creating edge diffs iterator failed");
158+
}
159+
// ANCHOR_END: iterate_edge_differences
160+
161+
// ANCHOR: iterate_edge_differences_update_parents
162+
let num_nodes: usize = treeseq.nodes().num_rows().try_into().unwrap();
163+
// num_nodes + 1 to reflect a "virtual root" present in
164+
// the tree arrays
165+
let mut parents = vec![NodeId::NULL; num_nodes + 1];
166+
match treeseq.edge_differences_iter() {
167+
Ok(mut ediff_iter) => match treeseq.tree_iterator(0) {
168+
Ok(mut tree_iter) => {
169+
while let Some(diffs) = ediff_iter.next() {
170+
let tree = tree_iter.next().unwrap();
171+
for edge_out in diffs.edge_removals() {
172+
let c = edge_out.child();
173+
parents[c.as_usize()] = NodeId::NULL;
174+
}
175+
for edge_in in diffs.edge_insertions() {
176+
let c = edge_in.child();
177+
parents[c.as_usize()] = edge_in.parent();
178+
}
179+
assert_eq!(tree.parent_array(), &parents);
180+
}
181+
}
182+
Err(e) => panic!("error creating tree iter: {:?}", e),
183+
},
184+
Err(e) => panic!("error creating edge diff iter: {:?}", e),
185+
}
186+
// ANCHOR_END: iterate_edge_differences_update_parents
145187
}

0 commit comments

Comments
 (0)