1use std::iter::{once, repeat};
2use adic::AdicInteger;
3use petgraph::{
4 graph::{EdgeIndex, NodeIndex},
5 visit::{EdgeRef, NodeRef},
6 Directed, Graph
7};
8
9use crate::{AdicShapeError, DisplayShape};
10use super::{
11 element::{AdicEl, PathDInstruction, PathEl},
12 Direction,
13};
14
15
16type GoldBranchChoices = Vec<u32>;
18type Coordinate = (f64, f64);
19
20use Direction::{Left, Right, Up, Down};
21
22
23pub type TreeGraph = Graph<TreeNode, TreeEdge, Directed>;
24
25
26#[derive(Debug, Clone)]
27#[doc = ""]
41#[doc = "<style>"]
42#[doc = include_str!("../../img/rustdoc.css")]
43#[doc = "</style>"]
44#[doc = ""]
45#[doc = include_str!("../../img/tree-shape-example.svg")]
46#[doc = ""]
47pub struct TreeShape {
48 p: u32,
50 options: TreeShapeOptions,
52 position: TreePosition,
54 graph: TreeGraph,
56 root_idx: NodeIndex<u32>,
58 dangling_idx: Option<NodeIndex<u32>>,
60 gold_branches: Vec<GoldBranchChoices>,
62}
63
64
65#[derive(Debug, Clone, Copy)]
66pub struct TreeShapeOptions {
68 pub direction: Direction,
70 pub dangling_direction: Option<Direction>,
72 pub viewbox_width: u32,
74 pub viewbox_height: u32,
76}
77
78impl Default for TreeShapeOptions {
79 fn default() -> Self {
80 TreeShapeOptions {
81 direction: Up,
82 dangling_direction: Some(Right),
83 viewbox_width: 100,
84 viewbox_height: 100,
85 }
86 }
87}
88
89
90#[derive(Debug, Clone, Copy)]
91pub struct TreePosition {
93 pub center: Coordinate,
95}
96
97
98impl TreeShape {
99
100 pub fn full_tree(
112 p: u32,
113 depth: usize,
114 options: TreeShapeOptions,
115 ) -> Result<Self, AdicShapeError> {
116
117 let TreeShapeOptions { direction, dangling_direction, .. } = options;
118
119 let (mut graph, root_idx, dangling_idx) = create_tree_graph(p, depth, direction, dangling_direction)?;
120
121 let width = f64::from(options.viewbox_width);
122 let height = f64::from(options.viewbox_height);
123 adjust_size(&mut graph, direction, width, height);
124
125 Ok(Self {
126 p,
127 position: TreePosition {
128 center: (0.5*width, 0.5*height),
129 },
130 graph,
131 root_idx,
132 dangling_idx,
133 options,
134 gold_branches: vec![],
135 })
136
137 }
138
139 pub fn adic_number_full_tree(
151 adic_data: &impl AdicInteger,
152 depth: usize,
153 options: TreeShapeOptions,
154 ) -> Result<Self, AdicShapeError> {
155
156 let p = adic_data.p();
157 let TreeShapeOptions { direction, dangling_direction, .. } = options;
158
159 let (mut graph, root_idx, dangling_idx) = create_tree_graph(p, depth, direction, dangling_direction)?;
160
161 let width = f64::from(options.viewbox_width);
162 let height = f64::from(options.viewbox_height);
163 adjust_size(&mut graph, direction, width, height);
164
165 Ok(Self {
166 p,
167 position: TreePosition {
168 center: (0.5*width, 0.5*height),
169 },
170 graph,
171 root_idx,
172 dangling_idx,
173 options,
174 gold_branches: vec![adic_data.digits().take(depth).copied().collect()]
175 })
176
177 }
178
179 pub fn zoomed_tree(
184 adic_data: &impl AdicInteger,
185 depth: usize,
186 options: TreeShapeOptions,
187 ) -> Result<Self, AdicShapeError> {
188
189 let p = adic_data.p();
190 let TreeShapeOptions { direction, dangling_direction, .. } = options;
191
192 let (mut graph, root_idx, dangling_idx) = create_zoomed_tree_graph(adic_data.clone(), depth, direction, dangling_direction)?;
193
194 let width = f64::from(options.viewbox_width);
195 let height = f64::from(options.viewbox_height);
196 adjust_size(&mut graph, direction, width, height);
197
198 Ok(Self {
199 p,
200 position: TreePosition {
201 center: (0.5*width, 0.5*height),
202 },
203 graph,
204 root_idx,
205 dangling_idx,
206 options,
207 gold_branches: vec![adic_data.digits().take(depth).copied().collect()]
208 })
209
210 }
211
212
213 pub fn p(&self) -> u32 {
215 self.p
216 }
217
218 pub fn center(&self) -> (f64, f64) {
220 self.position.center
221 }
222
223 fn tree_instructions(&self) -> Result<Vec<PathDInstruction>, AdicShapeError> {
228
229 let mut instructions = vec![];
230 for e in self.graph.edge_references() {
231 let source = self.graph.node_weight(e.source()).ok_or(AdicShapeError::PetGraph)?;
232 let target = self.graph.node_weight(e.target()).ok_or(AdicShapeError::PetGraph)?;
233 instructions.push(PathDInstruction::Move((source.x, source.y)));
234 instructions.push(PathDInstruction::Line((target.x, target.y)));
235 }
236
237 Ok(instructions)
238
239 }
240
241
242 fn gold_branch_instructions(&self) -> Result<Vec<Vec<PathDInstruction>>, AdicShapeError> {
247
248 let mut all_instructions = vec![];
249 for gold_branch_choices in &self.gold_branches {
250
251 let (mut node_id, choices) = if let Some(dangling_idx) = self.dangling_idx {
252 let mut choices = vec![0];
253 choices.extend(gold_branch_choices);
254 (dangling_idx, choices)
255 } else {
256 (self.root_idx, gold_branch_choices.clone())
257 };
258
259 let mut instructions = vec![];
260 for gold_choice in choices.into_iter().chain(repeat(0)) {
261 let mut edges = self.graph.edges(node_id);
262 let gold_edge = edges.find(|e| e.weight().branch_choice == gold_choice);
263 if let Some(ge) = gold_edge {
264 node_id = ge.target().id();
265 let source = self.graph.node_weight(ge.source()).ok_or(AdicShapeError::PetGraph)?;
266 let target = self.graph.node_weight(ge.target()).ok_or(AdicShapeError::PetGraph)?;
267 instructions.push(PathDInstruction::Move((source.x, source.y)));
268 instructions.push(PathDInstruction::Line((target.x, target.y)));
269 } else {
270 break;
271 }
272 }
273 all_instructions.push(instructions);
274
275 }
276
277 Ok(all_instructions)
278
279 }
280
281}
282
283impl DisplayShape for TreeShape {
284
285 fn adic_els(&self) -> impl Iterator<Item=AdicEl> {
287
288 let tree_ins = self.tree_instructions().expect("tree instructions should succeed");
290 let tree_path = AdicEl::Path(PathEl{
291 class: Some("tree-path".to_string()),
292 d: tree_ins
293 });
294 let gold_paths = self.gold_branch_instructions()
299 .expect("gold branch instructions should succeed")
300 .into_iter()
301 .map(
302 |gold_ins| AdicEl::Path(PathEl{
303 class: Some("gold-path".to_string()),
304 d: gold_ins
305 })
306 )
307 .collect::<Vec<_>>();
308
309 once(tree_path)
311 .chain(gold_paths)
313
314 }
315
316 fn default_class(&self) -> String {
317 "adic-tree".to_string()
318 }
319
320 fn viewbox_width(&self) -> u32 {
321 self.options.viewbox_width
322 }
323 fn viewbox_height(&self) -> u32 {
324 self.options.viewbox_height
325 }
326}
327
328
329#[derive(Debug, Clone)]
330pub struct TreeNode {
332 pub x: f64,
334 pub y: f64,
336 pub depth: isize,
338}
339
340#[derive(Debug, Clone)]
341pub struct TreeEdge {
343 pub branch_choice: u32,
345}
346
347
348fn adjust_size(graph: &mut TreeGraph, direction: Direction, width: f64, height: f64) {
350 match direction {
351 Up | Down => {
352 graph.node_weights_mut().for_each(|n| {
353 n.x = width * n.x;
354 n.y = height * n.y;
355 });
356 },
357 Left | Right => {
358 graph.node_weights_mut().for_each(|n| {
359 n.x = width * n.x;
360 n.y = height * n.y;
361 });
362 },
363 }
364}
365
366
367fn create_tree_graph(
372 p: u32,
373 depth: usize,
374 direction: Direction,
375 dangling_direction: Option<Direction>
376) -> Result<(TreeGraph, NodeIndex, Option<NodeIndex>), AdicShapeError> {
377
378 let mut graph = Graph::new();
379 let (root_length, reg_length) = calc_branch_lengths(p, depth, dangling_direction)?;
380 let (root_idx, dangling_idx) = root_tree(&mut graph, direction, dangling_direction, root_length)?;
381
382 let mut cur_branch_point = root_idx;
383 let mut cur_branch_choice = 0;
384 let mut cur_width = 1.;
385 let mut cur_node = graph.node_weight(cur_branch_point).ok_or(AdicShapeError::PetGraph)?;
386 let mut cur_edge_set: Vec<EdgeIndex> = vec![];
387 'tree_pos_loop: loop {
388
389 if cur_node.depth < depth.try_into()? {
391
392 let adjust_choice = ((f64::from(cur_branch_choice) + 0.5) / f64::from(p) - 0.5) * cur_width;
393 let adjust_depth = reg_length;
394
395 let (new_idx, edge_idx) = add_relative_branch(
396 &mut graph, cur_branch_point, cur_branch_choice,
397 direction, adjust_choice, adjust_depth,
398 )?;
399
400 cur_branch_point = new_idx;
401 cur_branch_choice = 0;
402 cur_width = cur_width / f64::from(p);
403 cur_node = graph.node_weight(new_idx).ok_or(AdicShapeError::PetGraph)?;
404 cur_edge_set.push(edge_idx);
405
406 }
407 else {
409
410 while (cur_node.depth >= depth.try_into()?) || (cur_branch_choice == p - 1) {
411
412 if cur_node.depth == 0 {
414 break 'tree_pos_loop;
415 }
416
417 let old_edge_idx = cur_edge_set.pop().ok_or(AdicShapeError::PetGraph)?;
418 cur_branch_point = graph.edge_endpoints(old_edge_idx).ok_or(AdicShapeError::PetGraph)?.0;
419 cur_branch_choice = graph.edge_weight(old_edge_idx).ok_or(AdicShapeError::PetGraph)?.branch_choice;
420 cur_width = cur_width * f64::from(p);
421
422 cur_node = graph.node_weight(cur_branch_point).ok_or(AdicShapeError::PetGraph)?;
423
424 }
425
426 cur_branch_choice += 1;
427
428 }
429
430 }
431
432 Ok((graph, root_idx, dangling_idx))
433
434}
435
436
437fn create_zoomed_tree_graph(
442 adic_data: impl AdicInteger,
443 depth: usize,
444 direction: Direction,
445 dangling_direction: Option<Direction>
446) -> Result<(TreeGraph, NodeIndex, Option<NodeIndex>), AdicShapeError> {
447
448 let p = adic_data.p();
449
450 let mut graph = Graph::new();
451 let (root_length, reg_length) = calc_branch_lengths(p, depth, dangling_direction)?;
452 let (root_idx, dangling_idx) = root_tree(&mut graph, direction, dangling_direction, root_length)?;
453
454 let mut next_branch_point = root_idx;
455 let mut next_choice_pos = 0.5;
456 let choices = adic_data.into_digits().chain(repeat(0)).take(depth-1);
457 for (num_digit, choice) in choices.into_iter().enumerate() {
458
459 let cur_branch_point = next_branch_point;
460 let cur_choice_pos = next_choice_pos;
461 next_choice_pos = (f64::from(choice) + 0.5) / f64::from(p);
462 let branch_width = 1.;
463 let branch_length = reg_length;
464 let unchosen_width_scale = 0.4;
465 let unchosen_length_scale = 0.6;
466 let twig_width_scale = 0.05;
467 let twig_length_scale = 0.2;
468
469 for branch in (0..p) {
471
472 let new_width = branch_width * if branch == choice { 1. } else { unchosen_width_scale };
474 let new_length = branch_length * if branch == choice { 1. } else { unchosen_length_scale };
475
476 let adjust_choice = ((f64::from(branch) + 0.5) / f64::from(p) - 0.5) * new_width;
477 let adjust_choice = adjust_choice + if branch == choice {
478 (0.5 - cur_choice_pos)
479 } else {
480 let main_branch_adjust = unchosen_length_scale * (next_choice_pos - cur_choice_pos);
481 let choice_adjust = (0.5 * f64::from(p-1) - f64::from(choice)) / f64::from(p) * branch_width * unchosen_width_scale;
482 main_branch_adjust + choice_adjust
483 };
484 let adjust_depth = new_length;
485
486 let (next_idx, _edge_idx) = add_relative_branch(
487 &mut graph, cur_branch_point, branch,
488 direction, adjust_choice, adjust_depth,
489 )?;
490
491 if branch == choice {
493
494 if num_digit + 2 == depth {
495 for twig_choice in (0..p) {
497 let final_choice_pos = cur_choice_pos;
498 let twig_width = branch_width * twig_width_scale;
499 let adjust_choice = ((f64::from(twig_choice) + 0.5) / f64::from(p) - 0.5) * twig_width;
500 let adjust_choice = adjust_choice + twig_width * (0.5 - final_choice_pos);
501 let adjust_depth = branch_length * twig_length_scale;
502 let (_leaf_idx, _twig_idx) = add_relative_branch(
503 &mut graph, next_idx, twig_choice,
504 direction, adjust_choice, adjust_depth,
505 )?;
506 }
507 } else {
508 next_branch_point = next_idx;
509 }
510
511 } else {
512
513 for twig_choice in (0..p) {
514
515 let adjust_choice = ((f64::from(twig_choice) + 0.5) / f64::from(p) - 0.5) * branch_width * twig_width_scale;
516 let adjust_depth = branch_length * twig_length_scale;
517 let (_leaf_idx, _twig_idx) = add_relative_branch(
518 &mut graph, next_idx, twig_choice,
519 direction, adjust_choice, adjust_depth,
520 )?;
521
522 }
523
524 }
525
526 }
527
528 }
529
530 Ok((graph, root_idx, dangling_idx))
531
532}
533
534
535fn calc_branch_lengths(
540 p: u32, num_levels: usize, dangling_direction: Option<Direction>
541) -> Result<(f64, f64), AdicShapeError> {
542 let f64_levels = f64::from(u32::try_from(num_levels)?);
543 if dangling_direction.is_some() {
544 let root_length = 2. / (2. + (f64::from(p) - 1.) * f64_levels);
549 let reg_length = (1. - root_length) / f64_levels;
550 Ok((root_length, reg_length))
551 } else {
552 let root_length = 0.;
553 let reg_length = 1. / f64_levels;
554 Ok((root_length, reg_length))
555 }
556}
557
558fn root_tree(
563 graph: &mut TreeGraph, direction: Direction, dangling_direction: Option<Direction>,
564 root_length: f64,
565) -> Result<(NodeIndex, Option<NodeIndex>), AdicShapeError> {
566
567 if let Some(root_direction) = dangling_direction {
568
569 let (x1, y1, x2, y2) = root_node_pos(direction, root_direction, root_length)?;
570
571 let some_dangling_idx = graph.add_node(TreeNode {
572 x: x1, y: y1, depth: -1,
573 });
574 let dangling_idx = Some(some_dangling_idx);
575 let root_idx = graph.add_node(TreeNode{
576 x: x2, y: y2, depth: 0,
577 });
578 graph.add_edge(some_dangling_idx, root_idx, TreeEdge{
579 branch_choice: 0,
580 });
581 Ok((root_idx, dangling_idx))
582
583 } else {
584
585 let (x, y) = match direction {
587 Up => (0.5, 1.),
588 Down => (0.5, 0.),
589 Left => (1., 0.5),
590 Right => (0., 0.5),
591 };
592 let root_idx = graph.add_node(TreeNode{
593 x, y, depth: 0,
594 });
595 Ok((root_idx, None))
596
597 }
598
599}
600
601fn root_node_pos(
607 direction: Direction, root_direction: Direction, root_length: f64
608) -> Result<(f64, f64, f64, f64), AdicShapeError> {
609 let pos = match (direction, root_direction) {
612 (Up, Left) => (0., 1., 0.5, 1. - root_length),
613 (Up, Down) => (0.5, 1., 0.5, 1. - root_length),
614 (Up, Right) => (1., 1., 0.5, 1. - root_length),
615 (Down, Left) => (0., 0., 0.5, root_length),
616 (Down, Up) => (0.5, 0., 0.5, root_length),
617 (Down, Right) => (1., 0., 0.5, root_length),
618 (Left, Up) => (1., 0., 1. - root_length, 0.5),
619 (Left, Right) => (1., 0.5, 1. - root_length, 0.5),
620 (Left, Down) => (1., 1., 1. - root_length, 0.5),
621 (Right, Up) => (0., 0., root_length, 0.5),
622 (Right, Left) => (0., 0.5, root_length, 0.5),
623 (Right, Down) => (0., 1., root_length, 0.5),
624 _ => {
625 return Err(AdicShapeError::ImproperConfig(
626 "Cannot have a dangling root in the same direction as the tree's growth".to_string()
627 ));
628 }
629 };
630 Ok(pos)
631}
632
633
634fn add_relative_branch(
641 graph: &mut TreeGraph, origin_idx: NodeIndex, branch_choice: u32, direction: Direction,
642 adjust_choice: f64, adjust_depth: f64,
643) -> Result<(NodeIndex, EdgeIndex), AdicShapeError> {
644 let origin_bp = graph.node_weight(origin_idx).ok_or(AdicShapeError::PetGraph)?;
645 let (new_x, new_y) = match direction {
646 Up => (origin_bp.x + adjust_choice, origin_bp.y - adjust_depth),
647 Down => (origin_bp.x - adjust_choice, origin_bp.y + adjust_depth),
648 Left => (origin_bp.x - adjust_depth, origin_bp.y - adjust_choice),
649 Right => (origin_bp.x + adjust_depth, origin_bp.y + adjust_choice),
650 };
651
652 let new_idx = graph.add_node(TreeNode{
654 x: new_x, y: new_y,
655 depth: origin_bp.depth + 1,
656 });
657 let edge_idx = graph.add_edge(origin_idx, new_idx, TreeEdge {
658 branch_choice,
659 });
660 Ok((new_idx, edge_idx))
661}
662
663
664
665#[cfg(test)]
666mod test {
667 use adic::uadic;
668 use super::{TreeShape, TreeShapeOptions};
669
670 #[test]
671 fn correct_numbers() {
672
673 let shape_options = TreeShapeOptions::default();
674
675 let tree_shape = TreeShape::full_tree(5, 6, shape_options).unwrap();
676 assert_eq!(5, tree_shape.p);
677 assert_eq!(0, tree_shape.gold_branches.len());
678
679 let adic_data = uadic!(5, [3, 2, 4, 1, 4, 1, 2]);
680 let tree_shape = TreeShape::adic_number_full_tree(&adic_data, 6, shape_options).unwrap();
681 assert_eq!(5, tree_shape.p);
682 assert_eq!(1, tree_shape.gold_branches.len());
683
684 let gold_branch = &tree_shape.gold_branches[0];
685 assert_eq!(6, gold_branch.len());
686 assert_eq!(3, gold_branch[0]);
687 assert_eq!(2, gold_branch[1]);
688 assert_eq!(4, gold_branch[2]);
689 assert_eq!(1, gold_branch[3]);
690 assert_eq!(4, gold_branch[4]);
691 assert_eq!(1, gold_branch[5]);
692
693 let adic_data = uadic!(5, [3, 2, 4, 1, 4, 1, 2]);
694 let tree_shape = TreeShape::zoomed_tree(&adic_data, 6, shape_options).unwrap();
695 assert_eq!(5, tree_shape.p);
696 assert_eq!(1, tree_shape.gold_branches.len());
697
698 let gold_branch = &tree_shape.gold_branches[0];
699 assert_eq!(6, gold_branch.len());
700 assert_eq!(3, gold_branch[0]);
701 assert_eq!(2, gold_branch[1]);
702 assert_eq!(4, gold_branch[2]);
703 assert_eq!(1, gold_branch[3]);
704 assert_eq!(4, gold_branch[4]);
705 assert_eq!(1, gold_branch[5]);
706
707 }
708
709 #[test]
710 fn correct_bounds() {
711
712 let shape_options = TreeShapeOptions::default();
713
714 let tree_shape = TreeShape::full_tree(5, 6, shape_options).unwrap();
715 assert!(0. <= tree_shape.graph.node_weights().map(|nw| nw.x).min_by(f64::total_cmp).unwrap());
716 assert!(100. >= tree_shape.graph.node_weights().map(|nw| nw.x).max_by(f64::total_cmp).unwrap());
717 assert!(0. <= tree_shape.graph.node_weights().map(|nw| nw.y).min_by(f64::total_cmp).unwrap());
718 assert!(100. >= tree_shape.graph.node_weights().map(|nw| nw.y).max_by(f64::total_cmp).unwrap());
719
720 let adic_data = uadic!(5, [3, 2, 4, 1, 4, 1, 2]);
721 let tree_shape = TreeShape::adic_number_full_tree(&adic_data, 6, shape_options).unwrap();
722 assert!(0. <= tree_shape.graph.node_weights().map(|nw| nw.x).min_by(f64::total_cmp).unwrap());
723 assert!(100. >= tree_shape.graph.node_weights().map(|nw| nw.x).max_by(f64::total_cmp).unwrap());
724 assert!(0. <= tree_shape.graph.node_weights().map(|nw| nw.y).min_by(f64::total_cmp).unwrap());
725 assert!(100. >= tree_shape.graph.node_weights().map(|nw| nw.y).max_by(f64::total_cmp).unwrap());
726
727 let adic_data = uadic!(5, [3, 2, 4, 1, 4, 1, 2]);
728 let tree_shape = TreeShape::zoomed_tree(&adic_data, 6, shape_options).unwrap();
729 assert!(0. <= tree_shape.graph.node_weights().map(|nw| nw.x).min_by(f64::total_cmp).unwrap());
730 assert!(100. >= tree_shape.graph.node_weights().map(|nw| nw.x).max_by(f64::total_cmp).unwrap());
731 assert!(0. <= tree_shape.graph.node_weights().map(|nw| nw.y).min_by(f64::total_cmp).unwrap());
732 assert!(100. >= tree_shape.graph.node_weights().map(|nw| nw.y).max_by(f64::total_cmp).unwrap());
733
734 }
735
736 #[test]
737 fn graph_stats() {
738
739 let shape_options = TreeShapeOptions::default();
740
741 let tree_shape = TreeShape::full_tree(5, 4, shape_options).unwrap();
742 let expected_num_branches = 625 + 125 + 25 + 5 + 1;
743 assert_eq!(expected_num_branches + 1, tree_shape.graph.node_count());
744 assert_eq!(expected_num_branches, tree_shape.graph.edge_count());
745 assert_eq!(625 + 125 + 25 + 5 + 1 + 1, tree_shape.graph.node_count());
746 assert_eq!(625 + 125 + 25 + 5 + 1, tree_shape.graph.edge_count());
747 assert_eq!(1, tree_shape.graph.node_weights().filter(|nw| nw.depth == -1).count());
748 assert_eq!(1, tree_shape.graph.node_weights().filter(|nw| nw.depth == 0).count());
749 assert_eq!(5, tree_shape.graph.node_weights().filter(|nw| nw.depth == 1).count());
750 assert_eq!(25, tree_shape.graph.node_weights().filter(|nw| nw.depth == 2).count());
751 assert_eq!(125, tree_shape.graph.node_weights().filter(|nw| nw.depth == 3).count());
752 assert_eq!(625, tree_shape.graph.node_weights().filter(|nw| nw.depth == 4).count());
753 assert_eq!((expected_num_branches-1)/5 + 1, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 0).count());
754 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 1).count());
755 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 2).count());
756 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 3).count());
757 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 4).count());
758
759 let adic_data = uadic!(5, [3, 2, 4, 1, 4, 1, 2]);
760 let tree_shape = TreeShape::adic_number_full_tree(&adic_data, 4, shape_options).unwrap();
761 let expected_num_branches = 625 + 125 + 25 + 5 + 1;
762 assert_eq!(expected_num_branches + 1, tree_shape.graph.node_count());
763 assert_eq!(expected_num_branches, tree_shape.graph.edge_count());
764 assert_eq!(1, tree_shape.graph.node_weights().filter(|nw| nw.depth == -1).count());
765 assert_eq!(1, tree_shape.graph.node_weights().filter(|nw| nw.depth == 0).count());
766 assert_eq!(5, tree_shape.graph.node_weights().filter(|nw| nw.depth == 1).count());
767 assert_eq!(25, tree_shape.graph.node_weights().filter(|nw| nw.depth == 2).count());
768 assert_eq!(125, tree_shape.graph.node_weights().filter(|nw| nw.depth == 3).count());
769 assert_eq!(625, tree_shape.graph.node_weights().filter(|nw| nw.depth == 4).count());
770 assert_eq!((expected_num_branches-1)/5 + 1, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 0).count());
771 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 1).count());
772 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 2).count());
773 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 3).count());
774 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 4).count());
775
776 let adic_data = uadic!(5, [3, 2, 4, 1, 4, 1, 2]);
777 let tree_shape = TreeShape::zoomed_tree(&adic_data, 4, shape_options).unwrap();
778 let expected_num_branches = 5 + 20 + 5 + 20 + 5 + 20 + 5 + 1;
779 assert_eq!(expected_num_branches + 1, tree_shape.graph.node_count());
780 assert_eq!(expected_num_branches, tree_shape.graph.edge_count());
781 assert_eq!(1, tree_shape.graph.node_weights().filter(|nw| nw.depth == -1).count());
782 assert_eq!(1, tree_shape.graph.node_weights().filter(|nw| nw.depth == 0).count());
783 assert_eq!(5, tree_shape.graph.node_weights().filter(|nw| nw.depth == 1).count());
784 assert_eq!(20 + 5, tree_shape.graph.node_weights().filter(|nw| nw.depth == 2).count());
785 assert_eq!(20 + 5, tree_shape.graph.node_weights().filter(|nw| nw.depth == 3).count());
786 assert_eq!(20 + 5, tree_shape.graph.node_weights().filter(|nw| nw.depth == 4).count());
787 assert_eq!((expected_num_branches-1)/5 + 1, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 0).count());
788 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 1).count());
789 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 2).count());
790 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 3).count());
791 assert_eq!((expected_num_branches-1)/5, tree_shape.graph.edge_weights().filter(|ew| ew.branch_choice == 4).count());
792
793 }
794
795}