From fa43bab6156fedb789da7ac02a8af513dadf9778 Mon Sep 17 00:00:00 2001 From: "Kevin R. Thornton" Date: Thu, 1 Dec 2022 10:59:04 -0800 Subject: [PATCH] doc: book chapter on edge differences Move some tests from tree.rs to tests/ --- book/src/SUMMARY.md | 1 + book/src/tree_sequence_edge_diffs.md | 19 +++++++++++ src/trees.rs | 50 ---------------------------- tests/book_trees.rs | 42 +++++++++++++++++++++++ 4 files changed, 62 insertions(+), 50 deletions(-) create mode 100644 book/src/tree_sequence_edge_diffs.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 33096beb6..1a632f927 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -13,6 +13,7 @@ - [Initialization from a table collection](./tree_sequence_from_table_collection.md) - [Iterating over trees](./tree_sequence_iterate_trees.md) - [Working with trees](./tree_sequence_tree.md) + - [Edge differences](./tree_sequence_edge_diffs.md) - [Miscellaneous operations](./tree_sequence_miscellaneous.md) * [Metadata](./metadata.md) diff --git a/book/src/tree_sequence_edge_diffs.md b/book/src/tree_sequence_edge_diffs.md new file mode 100644 index 000000000..a694f9800 --- /dev/null +++ b/book/src/tree_sequence_edge_diffs.md @@ -0,0 +1,19 @@ +## Iterating over edge differences + +As with [trees](tree_sequence_iterate_trees.md), the API provides a *lending* iterator over edge differences. +Each step of the iterator advances to the next tree in the tree sequence. +For each tree, a standard `Iterator` over removals and insertions is available: + +```rust, noplaygound, ignore +{{#include ../../tests/book_trees.rs:iterate_edge_differences}} +``` + +Edge differences are the basis of efficient algorithms based on the incremental updating of summaries of trees. +The following example co-iterates over edge differences and trees. +The edge differences are used to calculate the parent array for each tree: + +```rust, noplaygound, ignore +{{#include ../../tests/book_trees.rs:iterate_edge_differences_update_parents}} +``` + + diff --git a/src/trees.rs b/src/trees.rs index e31e57e3b..ffde23f2a 100644 --- a/src/trees.rs +++ b/src/trees.rs @@ -873,56 +873,6 @@ pub(crate) mod test_trees { panic!("Expected a tree."); } } - - // TODO: use trybuild to add tests that the iterator - // lifetime is indeed coupled to that of the treeseq - #[test] - fn test_edge_diffs_lending_iterator_num_trees() { - { - let treeseq = treeseq_from_small_table_collection_two_trees(); - let num_nodes: usize = treeseq.nodes().num_rows().try_into().unwrap(); - let mut parents = vec![NodeId::NULL; num_nodes + 1]; - if let Ok(mut ediff_iter) = treeseq.edge_differences_iter() { - let mut tree_iter = treeseq.tree_iterator(0).unwrap(); - let mut ntrees = 0; - while let Some(diffs) = ediff_iter.next() { - let tree = tree_iter.next().unwrap(); - - for edge_out in diffs.edge_removals() { - let p = edge_out.child(); - parents[usize::try_from(p).unwrap()] = NodeId::NULL; - } - - for edge_in in diffs.edge_insertions() { - let c: usize = edge_in.child().try_into().unwrap(); - parents[c] = edge_in.parent(); - } - - assert_eq!(tree.parent_array(), &parents); - ntrees += 1; - } - assert_eq!(ntrees, 2); - } else { - panic!("expected an edge differences iterator"); - } - } - - { - let treeseq = treeseq_from_small_table_collection_two_trees(); - let mut ediff_iter = treeseq.edge_differences_iter().unwrap(); - - let mut ntrees = 0; - while let Some(diffs) = ediff_iter.next() { - if ntrees == 0 { - assert_eq!(diffs.interval(), (0.0.into(), 500.0.into())); - } else { - assert_eq!(diffs.interval(), (500.0.into(), 1000.0.into())); - } - ntrees += 1; - } - assert_eq!(ntrees, 2); - } - } } #[cfg(test)] diff --git a/tests/book_trees.rs b/tests/book_trees.rs index f40e40274..6ffbf4469 100644 --- a/tests/book_trees.rs +++ b/tests/book_trees.rs @@ -142,4 +142,46 @@ fn initialize_from_table_collection() { } } // ANCHOR_END: iterate_node_siblings_via_array_getters + + // ANCHOR: iterate_edge_differences + if let Ok(mut edge_diff_iterator) = treeseq.edge_differences_iter() { + while let Some(diffs) = edge_diff_iterator.next() { + for edge_removal in diffs.edge_removals() { + println!("{}", edge_removal); + } + for edge_insertion in diffs.edge_insertions() { + println!("{}", edge_insertion); + } + } + } else { + panic!("creating edge diffs iterator failed"); + } + // ANCHOR_END: iterate_edge_differences + + // ANCHOR: iterate_edge_differences_update_parents + let num_nodes: usize = treeseq.nodes().num_rows().try_into().unwrap(); + // num_nodes + 1 to reflect a "virtual root" present in + // the tree arrays + let mut parents = vec![NodeId::NULL; num_nodes + 1]; + match treeseq.edge_differences_iter() { + Ok(mut ediff_iter) => match treeseq.tree_iterator(0) { + Ok(mut tree_iter) => { + while let Some(diffs) = ediff_iter.next() { + let tree = tree_iter.next().unwrap(); + for edge_out in diffs.edge_removals() { + let c = edge_out.child(); + parents[c.as_usize()] = NodeId::NULL; + } + for edge_in in diffs.edge_insertions() { + let c = edge_in.child(); + parents[c.as_usize()] = edge_in.parent(); + } + assert_eq!(tree.parent_array(), &parents); + } + } + Err(e) => panic!("error creating tree iter: {:?}", e), + }, + Err(e) => panic!("error creating edge diff iter: {:?}", e), + } + // ANCHOR_END: iterate_edge_differences_update_parents }