steiner_tree/
tree.rs

1// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5//! Representation of rectilinear trees in the euclidean plane.
6
7use super::hanan_grid::UnitHananGrid;
8use super::iterator_set_operations::{intersection, symmetric_difference};
9use super::marker_types::*;
10use super::rectangle::Rect;
11use super::wirelength_vector::*;
12use super::{HananCoord, Point};
13
14use std::collections::HashSet;
15use std::marker::PhantomData;
16
17use bitvec::prelude::BitVec;
18use itertools::Itertools;
19use std::cmp::Ordering;
20use std::hash::{Hash, Hasher};
21
22/// Representation of a rectilinear tree in the euclidean plane.
23/// The tree is simply represented by the rectilinear line segments.
24///
25/// This datastructure is in canonical form when the edges are sorted.
26/// Two trees in canonical form can be easily compared for equality by checking
27/// the edges for equality.
28///
29/// The implementation of `Tree<Canonical>` guarantees that the tree is in canonical form
30/// after any operation.
31///
32/// The implementation of `Tree<NonCanonical>` (the default) does not make such guarantee
33/// but can do certain operations slightly faster.
34#[derive(Clone, Debug)]
35pub struct Tree<C: CanonicalMarker = NonCanonical> {
36    edges: Vec<TreeEdge>,
37    _is_canonical: PhantomData<C>,
38}
39
40impl PartialEq for Tree<Canonical> {
41    fn eq(&self, other: &Self) -> bool {
42        self.edges.eq(&other.edges)
43    }
44}
45
46impl Eq for Tree<Canonical> {}
47
48impl PartialOrd for Tree<Canonical> {
49    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
50        self.edges.partial_cmp(&other.edges)
51    }
52}
53
54impl Ord for Tree<Canonical> {
55    fn cmp(&self, other: &Self) -> Ordering {
56        self.edges.cmp(&other.edges)
57    }
58}
59
60impl Hash for Tree<Canonical> {
61    fn hash<H: Hasher>(&self, state: &mut H) {
62        self.edges.hash(state)
63    }
64}
65
66impl Tree {
67    /// Create an empty tree.
68    pub fn empty_non_canonical() -> Self {
69        Self {
70            edges: Default::default(),
71            _is_canonical: Default::default(),
72        }
73    }
74}
75
76impl Tree<Canonical> {
77    /// Create an empty tree.
78    pub fn empty_canonical() -> Self {
79        Self {
80            edges: Default::default(),
81            _is_canonical: Default::default(),
82        }
83    }
84
85    /// Create a three from a set of edges.
86    /// Returns an error if the set of edges does not form a tree (i.e. if it has cycles or is not connected).
87    pub fn from_edges(mut edges: Vec<TreeEdge>) -> Result<Self, ()> {
88        edges.sort_unstable();
89
90        let maybe_tree = Tree {
91            edges,
92            _is_canonical: Default::default(),
93        };
94
95        if maybe_tree.is_tree() {
96            Ok(maybe_tree)
97        } else {
98            // Is not a valid tree.
99            Err(())
100        }
101    }
102
103    /// Compute the XOR of the tree edges.
104    /// For two equal trees, the result will be an empty iterator.
105    pub(crate) fn symmetric_difference<'a>(
106        &'a self,
107        other: &'a Self,
108    ) -> impl Iterator<Item = TreeEdge> + 'a {
109        symmetric_difference(self.all_edges(), other.all_edges())
110    }
111}
112
113#[test]
114fn test_tree_from_valid_edges() {
115    let edges = vec![
116        TreeEdge::new((0, 0).into(), EdgeDirection::Right),
117        TreeEdge::new((1, 0).into(), EdgeDirection::Right),
118        TreeEdge::new((1, 0).into(), EdgeDirection::Up),
119        TreeEdge::new((2, 0).into(), EdgeDirection::Right),
120    ];
121
122    let tree = Tree::from_edges(edges);
123    assert!(tree.is_ok())
124}
125
126#[test]
127fn test_tree_from_invalid_edges() {
128    // A cycle:
129    let edges = vec![
130        TreeEdge::new((0, 0).into(), EdgeDirection::Right),
131        TreeEdge::new((0, 0).into(), EdgeDirection::Up),
132        TreeEdge::new((1, 0).into(), EdgeDirection::Up),
133        TreeEdge::new((0, 1).into(), EdgeDirection::Right),
134    ];
135
136    let tree = Tree::from_edges(edges);
137    assert!(tree.is_err())
138}
139
140impl<C: CanonicalMarker> Tree<C> {
141    /// Create an empty tree.
142    pub fn empty() -> Self {
143        Self {
144            edges: vec![],
145            _is_canonical: Default::default(),
146        }
147    }
148
149    pub fn is_empty(&self) -> bool {
150        self.edges.is_empty()
151    }
152
153    pub(crate) fn num_edges(&self) -> usize {
154        self.edges.len()
155    }
156
157    /// Check if the set of edges forms a valid tree, i.e. a single connected and non-cyclic graph.
158    /// An empty graph is also a tree.
159    pub(crate) fn is_tree(&self) -> bool {
160        if self.edges.len() <= 1 {
161            true
162        } else {
163            let mut visited_edges = vec![false; self.edges.len()];
164            let mut front = vec![self.edges[0].start()];
165
166            while let Some(current_node) = front.pop() {
167                // Find adjacent edges of the current node.
168                let mut num_second_visits = 0;
169                for (idx, adjacent_edge) in self.adjacent_edges_with_index(current_node) {
170                    if visited_edges[idx] {
171                        num_second_visits += 1;
172                        if num_second_visits > 1 {
173                            // Visiting the edge the second time. Cycle detected.
174                            // This is not tree.
175                            return false;
176                        }
177                    } else {
178                        // Edge was not yet visited.
179                        visited_edges[idx] = true;
180
181                        // Grow the front.
182                        if adjacent_edge.start() != current_node {
183                            front.push(adjacent_edge.start());
184                        }
185                        if adjacent_edge.end() != current_node {
186                            front.push(adjacent_edge.end());
187                        }
188                    }
189                }
190            }
191
192            true
193        }
194    }
195
196    /// Iterate over all nodes of the tree. A node of degree `d` appears `d` times.
197    fn all_nodes(&self) -> impl Iterator<Item = Point<HananCoord>> + '_ {
198        self.edges
199            .iter()
200            .map(|e| e.start())
201            .chain(self.edges.iter().map(|e| e.end()))
202    }
203
204    pub fn all_edges(&self) -> impl Iterator<Item = TreeEdge> + '_ {
205        self.edges.iter().copied()
206    }
207
208    /// Get all edges adjacent to `p`.
209    pub fn adjacent_edges(&self, p: Point<HananCoord>) -> impl Iterator<Item = TreeEdge> + '_ {
210        self.adjacent_edges_with_index(p).map(|(_, e)| e)
211    }
212
213    /// Get all edges adjacent to `p` and their position in the list of edges.
214    fn adjacent_edges_with_index(
215        &self,
216        p: Point<HananCoord>,
217    ) -> impl Iterator<Item = (usize, TreeEdge)> + '_ {
218        // TODO: There's a faster way than brute-force search when the edges are sorted.
219        self.edges
220            .iter()
221            .copied()
222            .enumerate()
223            .filter(move |(_, e)| e.start() == p || e.end() == p)
224    }
225
226    /// Check if the tree uses this node.
227    pub fn contains_node(&self, p: Point<HananCoord>) -> bool {
228        self.adjacent_edges(p).next().is_some()
229    }
230
231    /// Check if the tree contains this edge.
232    pub fn contains_edge(&self, edge: &TreeEdge) -> bool {
233        if C::is_canonical() {
234            self.edges.binary_search(edge).is_ok()
235        } else {
236            self.edges.iter().find(|e| *e == edge).is_some()
237        }
238    }
239
240    pub fn add_edge(&mut self, edge: TreeEdge) -> &mut Self {
241        {
242            // Check that the tree remains a connected tree after insertion of the edge.
243            // 1) No cycle should be created.
244            // 2) New edge must connect to the tree.
245
246            // Simpler but probably slower:
247            // let has_existing_edge_at_a = self.adjacent_edges(a).next().is_some();
248            // let has_existing_edge_at_b = self.adjacent_edges(b).next().is_some();
249            //
250            // assert!( !(has_existing_edge_at_a && has_existing_edge_at_b), "insertion of this edge creates a cycle");
251            // assert!( (has_existing_edge_at_a || has_existing_edge_at_b) || self.is_empty(), "insertion of this edge creates an unconnected component");
252
253            let a = edge.start();
254            let b = edge.end();
255
256            let mut existing_points = self.all_nodes();
257
258            let contains_a_or_b = existing_points.find(|&p| p == a || p == b);
259            if let Some(found_point) = contains_a_or_b {
260                let other = if found_point == a { b } else { a };
261                let contains_other = existing_points.find(|&p| p == other).is_some();
262                assert!(!contains_other, "insertion of this edge creates a cycle");
263            }
264
265            assert!(
266                contains_a_or_b.is_some() || self.is_empty(),
267                "insertion of this edge creates an unconnected component"
268            );
269        }
270
271        self.add_edge_unchecked(edge)
272    }
273
274    /// Add edge without guarantee that the tree stays a tree.
275    pub(crate) fn add_edge_unchecked(&mut self, edge: TreeEdge) -> &mut Self {
276        if C::is_canonical() {
277            // Insert edge such that the edges remain sorted.
278            match self.edges.binary_search(&edge) {
279                Ok(_) => {
280                    panic!("edge already exists");
281                }
282                Err(pos) => self.edges.insert(pos, edge),
283            }
284
285            debug_assert!(
286                self.edges
287                    .iter()
288                    .zip(self.edges.iter().skip(1))
289                    .all(|(a, b)| a <= b),
290                "edges must remain sorted"
291            );
292        } else {
293            self.edges.push(edge)
294        }
295
296        self
297    }
298
299    pub fn remove_edge(&mut self, edge: TreeEdge) -> &mut Self {
300        let a = edge.start();
301        let b = edge.end();
302
303        dbg!(a, b);
304        let num_adj_a = self.adjacent_edges(a).take(2).count();
305        let num_adj_b = self.adjacent_edges(b).take(2).count();
306        dbg!(num_adj_a, num_adj_b);
307
308        let will_disconnect_tree = num_adj_a > 1 && num_adj_b > 1;
309        assert!(
310            !will_disconnect_tree,
311            "removing this edge disconnects the tree"
312        );
313
314        // Remove the edge.
315        if C::is_canonical() {
316            // Remove edge while preserving the ordering of the other edges.
317            self.edges.retain(|e| e != &edge);
318        } else {
319            // Faster removal of the edge but destroy the ordering.
320            if let Some((index, _)) = self.edges.iter().enumerate().find(|(_, e)| e == &&edge) {
321                self.edges.swap_remove(index);
322            }
323        }
324
325        self
326    }
327
328    pub fn into_canonical_form(mut self) -> Tree<Canonical> {
329        if !C::is_canonical() {
330            self.edges.sort_unstable();
331        }
332        Tree {
333            edges: self.edges,
334            _is_canonical: Default::default(),
335        }
336    }
337
338    pub fn into_non_canonical_form(self) -> Tree<NonCanonical> {
339        Tree {
340            edges: self.edges,
341            _is_canonical: Default::default(),
342        }
343    }
344
345    /// Shift the whole tree by the vector `(dx, dy)`.
346    pub fn translate(&mut self, (dx, dy): (HananCoord, HananCoord)) {
347        self.edges
348            .iter_mut()
349            .for_each(|e| *e = e.translate((dx, dy)))
350    }
351
352    /// Rotate the tree around the origin by 90 degrees counter-clock-wise.
353    pub fn rotate_90ccw(mut self) -> Tree<NonCanonical> {
354        self.edges.iter_mut().for_each(|e| *e = e.rotate_ccw90());
355
356        self.into_non_canonical_form()
357    }
358
359    /// Mirror the tree at the y axis.
360    pub fn mirror_at_y_axis(mut self) -> Tree<NonCanonical> {
361        self.edges
362            .iter_mut()
363            .for_each(|e| *e = e.mirror_at_y_axis());
364
365        self.into_non_canonical_form()
366    }
367
368    /// Merge the other tree into this tree.
369    /// The trees must either intersect in exactly one node or at least one of the trees must be empty.
370    /// Otherwise the result will not be a connected tree, hence an error is returned.
371    pub fn merge(&mut self, other: &Self) -> Result<(), ()> {
372        if self.is_empty() {
373            self.edges = other.edges.clone();
374            return Ok(());
375        }
376
377        if other.is_empty() {
378            return Ok(());
379        }
380
381        // Trees can be merged if their intersection is a non-empty tree (a single node is ok).
382
383        // TODO: Compute intersection with less allocations.
384        let nodes_a: HashSet<_> = self.all_nodes().collect();
385        let num_node_intersections = other.all_nodes().filter(|n| nodes_a.contains(n)).count();
386
387        let intersection_edges: Vec<_> = if C::is_canonical() {
388            // Edges are sorted.
389            intersection(self.all_edges(), other.all_edges()).collect()
390        } else {
391            self.all_edges()
392                .filter(|e| other.contains_edge(e))
393                .collect()
394        };
395
396        let intersection_tree = Tree::from_edges(intersection_edges)?; // Return Err, if intersection is not a tree.
397
398        let additional_edges = other
399            .all_edges()
400            .filter(|e| !intersection_tree.contains_edge(e));
401
402        if num_node_intersections > 0 {
403            if C::is_canonical() {
404                // Join edges while keeping the ordering.
405
406                let new_edges = self.all_edges().merge(additional_edges).collect();
407                self.edges = new_edges;
408
409                Ok(())
410            } else {
411                // Don't maintain ordering of edges.
412                self.edges.extend(additional_edges);
413                Ok(())
414            }
415        } else {
416            dbg!(num_node_intersections);
417            Err(())
418        }
419    }
420
421    /// Compute amount of used edges for each column and row.
422    ///
423    pub(crate) fn compute_wirelength_vector(&self, w: &mut WirelenghtVector) {
424        let (horizontal_edge_count, vertical_edge_count) = w.hv_vectors_mut();
425
426        // let ll = self.bounding_box()
427        //     .unwrap_or(Rect::new((0, 0).into(), (0, 0).into()))
428        //     .lower_left();
429
430        // Check that the nodes in the tree are contained in the upper right quadrant and do not exceed the coordinates covered by the
431        // supplied slices.
432        debug_assert!(self
433            .all_edges()
434            .all(|e| e.start().x >= 0 && e.start().x as usize <= horizontal_edge_count.len()));
435        debug_assert!(self
436            .all_edges()
437            .all(|e| e.start().y >= 0 && e.start().y as usize <= vertical_edge_count.len()));
438
439        self.all_edges().for_each(|e| match e.direction {
440            EdgeDirection::Right => {
441                horizontal_edge_count[e.start().x as usize] += 1;
442            }
443            EdgeDirection::Up => {
444                vertical_edge_count[e.start().y as usize] += 1;
445            }
446        });
447    }
448
449    /// Compute the corners of the minimal bounding box of all tree nodes.
450    /// Returns none if the tree is empty.
451    pub fn bounding_box(&self) -> Option<Rect<HananCoord>> {
452        let mut nodes = self.all_nodes();
453        nodes.next().map(|first_node| {
454            let mut lower_left = first_node;
455            let mut upper_right = first_node;
456
457            for n in nodes {
458                lower_left.x = lower_left.x.min(n.x);
459                lower_left.y = lower_left.y.min(n.y);
460                upper_right.x = upper_right.x.max(n.x);
461                upper_right.y = upper_right.y.max(n.y);
462            }
463
464            Rect::new(lower_left, upper_right)
465        })
466    }
467
468    /// Translate the tree such that the lower left corner of the bounding box is at `(0, 0)`;
469    pub fn translate_to_origin(mut self) -> Self {
470        if let Some(r) = self.bounding_box() {
471            self.translate((-r.lower_left().x, -r.lower_left().y))
472        }
473        self
474    }
475
476    /// Encode the tree as a vector of bits. Each bit is associated with a possible tree edge
477    /// and stores if the edge is present or not.
478    /// This is used for fast computation of the Hamming distance between trees.
479    pub fn to_bitvec(&self) -> BitVec {
480        let bbox = self
481            .bounding_box()
482            .unwrap_or(Rect::new(Point::new(0, 0), Point::new(0, 0)));
483        let ll = bbox.lower_left();
484        let ur = bbox.upper_right();
485        assert!(
486            ll.x >= 0 && ll.y >= 0,
487            "tree must be in upper right quadrant"
488        );
489
490        let bbox = Rect::new(Point::new(0, 0), ur);
491        let grid = UnitHananGrid::new(bbox);
492
493        let mut bits = BitVec::new();
494
495        for p in grid.all_points_spiral() {
496            let horizontal_edge = TreeEdge::new(p, EdgeDirection::Right);
497            let vertical_edge = TreeEdge::new(p, EdgeDirection::Up);
498            bits.push(self.contains_edge(&horizontal_edge));
499            bits.push(self.contains_edge(&vertical_edge));
500        }
501
502        bits
503    }
504}
505
506/// An edge of the tree.
507/// Edges are defined by a point and a direction into positive x or y direction ('right' or 'up').
508/// An edge always has unit length, therefore the end point can be easily computed.
509#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
510pub struct TreeEdge {
511    start: Point<HananCoord>,
512    direction: EdgeDirection,
513}
514
515impl TreeEdge {
516    pub fn new(start: Point<HananCoord>, direction: EdgeDirection) -> Self {
517        Self { start, direction }
518    }
519
520    /// Returns `Err` when the points are not adjacent on the grid.
521    pub fn from_points(a: Point<HananCoord>, b: Point<HananCoord>) -> Result<Self, ()> {
522        let dx = b.x - a.x;
523        let dy = b.y - a.y;
524
525        if dx.abs() + dy.abs() != 1 {
526            Err(())
527        } else {
528            let edge = match (dx, dy) {
529                (1, _) => TreeEdge::new(a, EdgeDirection::Right),
530                (-1, _) => TreeEdge::new(b, EdgeDirection::Right),
531                (_, 1) => TreeEdge::new(a, EdgeDirection::Up),
532                (_, -1) => TreeEdge::new(b, EdgeDirection::Up),
533                _ => unreachable!(),
534            };
535
536            debug_assert!(edge.start() == a || edge.start() == b);
537            debug_assert!(edge.end() == a || edge.end() == b);
538
539            Ok(edge)
540        }
541    }
542
543    pub fn is_vertical(&self) -> bool {
544        self.direction == EdgeDirection::Up
545    }
546
547    pub fn is_horizontal(&self) -> bool {
548        self.direction == EdgeDirection::Right
549    }
550
551    /// Get the start point of the edge.
552    pub fn start(&self) -> Point<HananCoord> {
553        self.start
554    }
555
556    /// Get the end point of the edge.
557    pub fn end(&self) -> Point<HananCoord> {
558        match self.direction {
559            EdgeDirection::Right => Point::new(self.start.x + 1, self.start.y),
560            EdgeDirection::Up => Point::new(self.start.x, self.start.y + 1),
561        }
562    }
563
564    /// Shift the edge by a vector `(dx, dy)`.
565    fn translate(mut self, (dx, dy): (HananCoord, HananCoord)) -> Self {
566        self.start.x += dx;
567        self.start.y += dy;
568        self
569    }
570
571    /// Mirror the edge at the y-axis.
572    fn mirror_at_y_axis(mut self) -> Self {
573        match self.direction {
574            EdgeDirection::Right => {
575                self.start.x = -self.end().x;
576            }
577            EdgeDirection::Up => {
578                self.start.x = -self.start.x;
579            }
580        }
581        self
582    }
583
584    /// Rotate around the origin by 90 degrees counter-clock-wise.
585    fn rotate_ccw90(&self) -> Self {
586        match self.direction {
587            EdgeDirection::Right => Self {
588                start: self.start().rotate_ccw90(),
589                direction: EdgeDirection::Up,
590            },
591            EdgeDirection::Up => Self {
592                start: self.end().rotate_ccw90(),
593                direction: EdgeDirection::Right,
594            },
595        }
596    }
597}
598
599/// Direction into positive x or y direction.
600#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
601pub enum EdgeDirection {
602    /// Horizontal edge, directed in positive x direction.
603    Right,
604    /// Vertical edge, directed in positive y direction.
605    Up,
606}
607
608#[test]
609fn test_mirror_edge() {
610    let e = TreeEdge::new((1, 2).into(), EdgeDirection::Right);
611    let mirrored = e.mirror_at_y_axis();
612
613    let expected = TreeEdge::new((-2, 2).into(), EdgeDirection::Right);
614    assert_eq!(mirrored, expected);
615}
616
617#[test]
618fn test_rotate_edge() {
619    let e = TreeEdge::new((1, 2).into(), EdgeDirection::Right);
620    let rotated = e.rotate_ccw90();
621
622    let expected = TreeEdge::new((-2, 1).into(), EdgeDirection::Up);
623    assert_eq!(rotated, expected);
624}
625
626#[test]
627fn test_rotate_edge_4_times() {
628    let e = TreeEdge::new((1, 2).into(), EdgeDirection::Right);
629    let rotated = e
630        .rotate_ccw90()
631        .rotate_ccw90()
632        .rotate_ccw90()
633        .rotate_ccw90();
634
635    assert_eq!(rotated, e);
636}
637
638#[test]
639fn test_add_edges() {
640    let mut tree = Tree::empty_non_canonical();
641
642    tree.add_edge(TreeEdge::new((0, 0).into(), EdgeDirection::Right))
643        .add_edge(TreeEdge::new((1, 0).into(), EdgeDirection::Right));
644}
645
646#[test]
647fn test_bounding_box() {
648    let mut tree = Tree::empty_non_canonical();
649
650    tree.add_edge(TreeEdge::new((0, 0).into(), EdgeDirection::Right))
651        .add_edge(TreeEdge::new((1, 0).into(), EdgeDirection::Up))
652        .add_edge(TreeEdge::new((1, 1).into(), EdgeDirection::Up))
653        .add_edge(TreeEdge::new((-1, 0).into(), EdgeDirection::Right));
654
655    assert_eq!(
656        tree.bounding_box(),
657        Some(Rect::new((-1, 0).into(), (1, 2).into()))
658    );
659}
660
661#[test]
662fn test_adjacent_edges() {
663    let mut tree = Tree::empty_non_canonical();
664
665    let a = TreeEdge::new((0, 0).into(), EdgeDirection::Right);
666    let b = TreeEdge::new((1, 0).into(), EdgeDirection::Right);
667
668    assert_eq!(tree.adjacent_edges(a.start()).count(), 0);
669    assert_eq!(tree.adjacent_edges(a.end()).count(), 0);
670
671    tree.add_edge(a);
672    tree.add_edge(b);
673
674    assert_eq!(tree.adjacent_edges(a.start()).next(), Some(a));
675    assert_eq!(tree.adjacent_edges(a.end()).count(), 2);
676    assert_eq!(tree.adjacent_edges(b.start()).count(), 2);
677    assert_eq!(tree.adjacent_edges(b.end()).next(), Some(b));
678}
679
680#[test]
681fn test_remove_edges() {
682    let mut tree = Tree::empty_non_canonical();
683    let a = TreeEdge::new((0, 0).into(), EdgeDirection::Right);
684    let b = TreeEdge::new((1, 0).into(), EdgeDirection::Right);
685    let c = TreeEdge::new((2, 0).into(), EdgeDirection::Right);
686
687    tree.add_edge(a)
688        .add_edge(b)
689        .add_edge(c)
690        .remove_edge(a)
691        .remove_edge(c)
692        .remove_edge(b);
693}
694
695#[test]
696#[should_panic]
697fn test_remove_disconnecting_edge() {
698    let mut tree = Tree::empty_non_canonical();
699
700    let a = TreeEdge::new((0, 0).into(), EdgeDirection::Right);
701    let b = TreeEdge::new((1, 0).into(), EdgeDirection::Right);
702    let c = TreeEdge::new((2, 0).into(), EdgeDirection::Right);
703
704    tree.add_edge(a)
705        .add_edge(b)
706        .add_edge(c)
707        // Remove the middle edge.
708        .remove_edge(b);
709}
710
711#[test]
712fn test_canonical_tree_equivalence() {
713    let mut tree1 = Tree::empty_canonical();
714    let mut tree2 = Tree::empty_canonical();
715
716    assert_eq!(tree1, tree2);
717
718    tree1.add_edge(TreeEdge::new((0, 0).into(), EdgeDirection::Right));
719    tree1.add_edge(TreeEdge::new((1, 0).into(), EdgeDirection::Right));
720
721    // Add edges in reverse order.
722    tree2.add_edge(TreeEdge::new((1, 0).into(), EdgeDirection::Right));
723    tree2.add_edge(TreeEdge::new((0, 0).into(), EdgeDirection::Right));
724
725    assert_eq!(tree1, tree2);
726}
727
728#[test]
729#[should_panic]
730fn test_create_unconnected_tree() {
731    let mut tree = Tree::empty_non_canonical();
732    tree.add_edge(TreeEdge::new((0, 0).into(), EdgeDirection::Right));
733    tree.add_edge(TreeEdge::new((2, 0).into(), EdgeDirection::Right));
734}
735
736#[test]
737#[should_panic]
738fn test_create_tree_with_cycle() {
739    let mut tree = Tree::empty_non_canonical();
740    tree.add_edge(TreeEdge::new((0, 0).into(), EdgeDirection::Right));
741    tree.add_edge(TreeEdge::new((0, 0).into(), EdgeDirection::Up));
742    tree.add_edge(TreeEdge::new((1, 0).into(), EdgeDirection::Up));
743    // Close the cycle.
744    tree.add_edge(TreeEdge::new((0, 1).into(), EdgeDirection::Right));
745}
746
747#[test]
748fn test_wirelength_vector() {
749    let mut tree = Tree::empty_non_canonical();
750
751    tree.add_edge(TreeEdge::new((0, 0).into(), EdgeDirection::Right))
752        .add_edge(TreeEdge::new((1, 0).into(), EdgeDirection::Up))
753        .add_edge(TreeEdge::new((1, 1).into(), EdgeDirection::Up))
754        .add_edge(TreeEdge::new((1, 2).into(), EdgeDirection::Up))
755        .add_edge(TreeEdge::new((0, 0).into(), EdgeDirection::Up));
756
757    let mut w = WirelenghtVector::zero(2, 3);
758
759    tree.compute_wirelength_vector(&mut w);
760
761    assert_eq!(w.hv_vectors().0, vec![1, 0]);
762    assert_eq!(w.hv_vectors().1, vec![2, 1, 1]);
763}