source: tags/ms_r17q2/ARBDB/TreeNode.h

Last change on this file was 15876, checked in by westram, 7 years ago
  • reintegrates 'fix' into 'trunk'
    • automatically deletes field 'group_name' at root of tree
      • done while loading tree
      • provides workaround for #753
  • adds: log:branches/fix@15870:15875
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.3 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : TreeNode.h                                         //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Coded by Ralf Westram (coder@reallysoft.de) in December 2013   //
7//   Institute of Microbiology (Technical University Munich)        //
8//   http://www.arb-home.de/                                        //
9//                                                                  //
10// ================================================================ //
11
12#ifndef TREENODE_H
13#define TREENODE_H
14
15#ifndef ARBDBT_H
16#include "arbdbt.h"
17#endif
18#ifndef _GLIBCXX_ALGORITHM
19#include <algorithm>
20#endif
21
22#define rt_assert(cond) arb_assert(cond)
23
24#if defined(DEBUG) || defined(UNIT_TESTS) // UT_DIFF
25# define PROVIDE_TREE_STRUCTURE_TESTS
26#endif
27#if defined(DEVEL_RALF) && defined(PROVIDE_TREE_STRUCTURE_TESTS)
28# define AUTO_CHECK_TREE_STRUCTURE // Note: dramatically slows down most tree operations
29#endif
30
31class TreeRoot;
32class TreeNode;
33class ARB_edge;
34
35enum TreeOrder { // contains bit values!
36    ORDER_BIG_DOWN      = 1, // bit 0 set -> big branches down
37    ORDER_BIG_TO_EDGE   = 2, // bit 1 set -> big branches to edge
38    ORDER_BIG_TO_CENTER = 4, // bit 2 set -> big branches to center
39    ORDER_ALTERNATING   = 8, // bit 3 set -> alternate bit 0
40
41    // user visible orders:
42    BIG_BRANCHES_TO_TOP      = 0,
43    BIG_BRANCHES_TO_BOTTOM   = ORDER_BIG_DOWN,
44    BIG_BRANCHES_TO_EDGE     = ORDER_BIG_TO_EDGE,
45    BIG_BRANCHES_TO_CENTER   = ORDER_BIG_TO_CENTER,
46    BIG_BRANCHES_ALTERNATING = ORDER_BIG_TO_CENTER|ORDER_ALTERNATING,
47};
48
49#define DEFINE_READ_ACCESSORS(TYPE, ACCESS, MEMBER)     \
50    TYPE ACCESS() { return MEMBER; }                    \
51    const TYPE ACCESS() const { return MEMBER; }
52
53class TreeRoot : virtual Noncopyable {
54    TreeNode *rootNode;            // root node of the tree
55    bool      deleteWithNodes;
56
57protected:
58    void predelete() {
59        // should be called from dtor of derived class defining makeNode/destroyNode
60        if (rootNode) {
61            destroyNode(rootNode);
62            rt_assert(!rootNode);
63        }
64    }
65public:
66    explicit TreeRoot(bool deleteWithNodes_)
67        : rootNode(NULL),
68          deleteWithNodes(deleteWithNodes_)
69    {
70        /*! Create a TreeRoot for a TreeNode.
71         * Purpose:
72         * - act as TreeNode factory
73         * - place to store the current rootNode
74         * - place to store other tree related information by deriving from TreeRoot
75         *
76         * @param nodeMaker_ heap-copy of a RootedTreeNodeFactory, will be deleted when this is destructed
77         * @param deleteWithNodes_ true -> delete TreeRoot when the rootNode gets destroyed (TreeRoot needs to be a heap-copy in that case)
78         *
79         * Ressource handling of the tree structure is quite difficult (and error-prone).
80         * There are two common use-cases:
81         * 1. TreeRoot is owned by some other object/scope
82         *    - pass false for deleteWithNodes_
83         *    - you may or may not destroy (parts of) the TreeNode manually
84         * 2. TreeRoot is owned by the TreeNode
85         *    - pass true for deleteWithNodes_
86         *    - when the rootNode gets destroyed, the TreeRoot will be destroyed as well
87         */
88    }
89    virtual ~TreeRoot();
90    virtual void change_root(TreeNode *old, TreeNode *newroot);
91
92    void delete_by_node() {
93        if (deleteWithNodes) {
94            rt_assert(!rootNode);
95            delete this;
96        }
97    }
98
99    virtual TreeNode *makeNode() const             = 0;
100    virtual void destroyNode(TreeNode *node) const = 0;
101
102    DEFINE_READ_ACCESSORS(TreeNode*, get_root_node, rootNode);
103
104    ARB_edge find_innermost_edge();
105};
106MARK_NONFINAL_METHOD(TreeRoot,void,change_root,(TreeNode*,TreeNode*));
107
108struct TreeNode : virtual Noncopyable {
109    bool      is_leaf;
110    TreeNode *father, *leftson, *rightson;
111    GBT_LEN   leftlen, rightlen;
112    GBDATA   *gb_node;
113    char     *name;
114
115private:
116    char *remark_branch; // remark_branch normally contains some bootstrap value in format 'xx%'
117                         // if you store other info there, please make sure that this info does not start with digits!!
118                         // Otherwise the tree export routines will not work correctly!
119
120    GBT_LEN& length_ref() { return is_leftson() ? father->leftlen : father->rightlen; }
121    const GBT_LEN& length_ref() const { return const_cast<TreeNode*>(this)->length_ref(); }
122
123protected:
124    TreeNode*& self_ref() {
125        return is_leftson() ? father->leftson : father->rightson;
126    }
127    void unlink_from_father() {
128        if (father) {
129            self_ref() = NULL;
130            father     = NULL;
131        }
132    }
133
134    char *swap_remark(char *new_remark) {
135        char *result  = remark_branch;
136        remark_branch = new_remark;
137        return result;
138    }
139
140public:
141
142    DEFINE_READ_ACCESSORS(TreeNode*, get_father,   father);
143    DEFINE_READ_ACCESSORS(TreeNode*, get_leftson,  leftson);
144    DEFINE_READ_ACCESSORS(TreeNode*, get_rightson, rightson);
145
146    bool is_son_of(const TreeNode *Father) const {
147        return father == Father &&
148            (father->leftson == this || father->rightson == this);
149    }
150    bool is_leftson() const {
151        gb_assert(is_son_of(get_father())); // do only call with sons!
152        return father->leftson == this;
153    }
154    bool is_rightson() const {
155        gb_assert(is_son_of(get_father())); // do only call with sons!
156        return father->rightson == this;
157    }
158
159    bool is_inside(const TreeNode *subtree) const {
160        return this == subtree || (father && get_father()->is_inside(subtree));
161    }
162    bool is_anchestor_of(const TreeNode *descendant) const {
163        return !is_leaf && descendant != this && descendant->is_inside(this);
164    }
165    const TreeNode *ancestor_common_with(const TreeNode *other) const;
166    TreeNode *ancestor_common_with(TreeNode *other) { return const_cast<TreeNode*>(ancestor_common_with(const_cast<const TreeNode*>(other))); }
167
168    GBT_LEN get_branchlength() const { return length_ref(); }
169    void set_branchlength(GBT_LEN newlen) {
170        gb_assert(!is_nan_or_inf(newlen));
171        length_ref() = newlen;
172    }
173
174    GBT_LEN get_branchlength_unrooted() const {
175        //! like get_branchlength, but root-edge is treated correctly
176        if (father->is_root_node()) {
177            return father->leftlen+father->rightlen;
178        }
179        return get_branchlength();
180    }
181    void set_branchlength_unrooted(GBT_LEN newlen) {
182        //! like set_branchlength, but root-edge is treated correctly
183        if (father->is_root_node()) {
184            father->leftlen  = newlen/2;
185            father->rightlen = newlen-father->leftlen; // make sure sum equals newlen
186        }
187        else {
188            set_branchlength(newlen);
189        }
190    }
191
192    GBT_LEN sum_child_lengths() const;
193    GBT_LEN root_distance() const {
194        //! returns distance from node to root (including nodes own length)
195        return father ? get_branchlength()+father->root_distance() : 0.0;
196    }
197    GBT_LEN intree_distance_to(const TreeNode *other) const {
198        const TreeNode *ancestor = ancestor_common_with(other);
199        return root_distance() + other->root_distance() - 2*ancestor->root_distance();
200    }
201
202    enum bs100_mode { BS_UNDECIDED, BS_REMOVE, BS_INSERT };
203    bs100_mode toggle_bootstrap100(bs100_mode mode = BS_UNDECIDED); // toggle bootstrap '100%' <-> ''
204    void       remove_bootstrap();                                  // remove bootstrap values from subtree
205
206    void reset_branchlengths();                     // reset branchlengths of subtree to tree_defaults::LENGTH
207    void scale_branchlengths(double factor);
208
209    void bootstrap2branchlen();                     // copy bootstraps to branchlengths
210    void branchlen2bootstrap();                     // copy branchlengths to bootstraps
211
212    GBT_RemarkType parse_bootstrap(double& bootstrap) const {
213        /*! analyse 'remark_branch' and return GBT_RemarkType.
214         * If result is REMARK_BOOTSTRAP, 'bootstrap' contains the bootstrap value
215         */
216        if (!remark_branch) return REMARK_NONE;
217
218        const char *end = 0;
219        bootstrap       = strtod(remark_branch, (char**)&end);
220
221        bool is_bootstrap = end[0] == '%' && end[1] == 0;
222        return is_bootstrap ? REMARK_BOOTSTRAP : REMARK_OTHER;
223    }
224    const char *get_remark() const { return remark_branch; }
225    void use_as_remark(char *newRemark) { freeset(remark_branch, newRemark); }
226    void set_remark(const char *newRemark) { freedup(remark_branch, newRemark); }
227    void set_bootstrap(double bootstrap) { use_as_remark(GBS_global_string_copy("%i%%", int(bootstrap+0.5))); } // @@@ protect against "100%"?
228    void remove_remark() { use_as_remark(NULL); }
229
230private:
231
232    friend void TreeRoot::change_root(TreeNode *old, TreeNode *newroot);
233
234    TreeRoot *tree_root;
235
236    // ------------------
237    //      functions
238
239    void reorder_subtree(TreeOrder mode);
240
241protected:
242    void set_tree_root(TreeRoot *new_root);
243
244    bool at_root() const {
245        //! return true for root-node and its sons
246        return !father || !father->father;
247    }
248    virtual ~TreeNode() {
249        if (tree_root) {
250            rt_assert(tree_root->get_root_node() == this); // you may only free the root-node or unlinked nodes (i.e. such with tree_root==NULL)
251
252            TreeRoot *root = tree_root;
253            root->TreeRoot::change_root(this, NULL);
254            root->delete_by_node();
255        }
256        delete leftson;  gb_assert(!leftson); // cannot use destroy here
257        delete rightson; gb_assert(!rightson);
258
259        unlink_from_father();
260
261        free(name);
262        free(remark_branch);
263    }
264    void destroy()  {
265        rt_assert(knownNonNull(this));
266        TreeRoot *myRoot = get_tree_root();
267        rt_assert(myRoot); // if this fails, you need to use destroy(TreeRoot*), i.e. destroy(TreeNode*, TreeRoot*)
268        myRoot->destroyNode(this);
269    }
270    void destroy(TreeRoot *viaRoot) {
271        rt_assert(knownNonNull(this));
272#if defined(ASSERTION_USED)
273        TreeRoot *myRoot = get_tree_root();
274        rt_assert(!myRoot || myRoot == viaRoot);
275#endif
276        viaRoot->destroyNode(this);
277    }
278
279public:
280    TreeNode(TreeRoot *root)
281        : is_leaf(false),
282          father(NULL), leftson(NULL), rightson(NULL),
283          leftlen(0.0), rightlen(0.0),
284          gb_node(NULL),
285          name(NULL),
286          remark_branch(NULL),
287          tree_root(root)
288    {}
289    static void destroy(TreeNode *that)  { // replacement for destructor
290        if (that) that->destroy();
291    }
292    static void destroy(TreeNode *that, TreeRoot *root) {
293        if (that) that->destroy(root);
294    }
295
296    TreeNode *fixDeletedSon(); // @@@ review (design)
297
298    void unlink_from_DB();
299
300    void announce_tree_constructed() { // @@@ use this function or just call change_root instead?
301        // (has to be) called after tree has been constructed
302        gb_assert(!father); // has to be called with root-node!
303        get_tree_root()->change_root(NULL, this);
304    }
305
306    virtual unsigned get_leaf_count() const = 0;
307    virtual void compute_tree()             = 0;
308
309    void forget_origin() { set_tree_root(NULL); }
310    void forget_relatives() {
311        leftson  = NULL;
312        rightson = NULL;
313        father   = NULL;
314    }
315
316    TreeRoot *get_tree_root() const { return tree_root; }
317
318    const TreeNode *get_root_node() const {
319        if (!tree_root) return NULL; // nodes removed from tree have no root-node
320
321        const TreeNode *root = tree_root->get_root_node();
322        rt_assert(is_inside(root)); // this is not in tree - behavior of get_root_node() changed!
323        return root;
324    }
325    TreeNode *get_root_node() { return const_cast<TreeNode*>(const_cast<const TreeNode*>(this)->get_root_node()); }
326
327    bool is_root_node() const { return get_root_node() == this; }
328    virtual void set_root();
329
330    TreeNode *get_brother() {
331        rt_assert(!is_root_node()); // root node has no brother
332        rt_assert(father);          // this is a removed node (not root, but no father)
333        return is_leftson() ? get_father()->get_rightson() : get_father()->get_leftson();
334    }
335    const TreeNode *get_brother() const {
336        return const_cast<const TreeNode*>(const_cast<TreeNode*>(this)->get_brother());
337    }
338
339    bool is_named_group() const {
340        rt_assert(!is_leaf); // checking whether a leaf is a group
341        return gb_node && name;
342    }
343    const char *get_group_name() const {
344        return is_named_group() ? name : NULL;
345    }
346    TreeNode *find_parent_group() {
347        TreeNode *parent = get_father();
348        while (parent && !parent->is_named_group()) {
349            parent = parent->get_father();
350        }
351        return parent;
352    }
353    const TreeNode *find_parent_group() const {
354        return const_cast<const TreeNode*>(const_cast<TreeNode*>(this)->find_parent_group());
355    }
356    int calculate_tax_level() const {
357        int             taxLev  = is_named_group();
358        const TreeNode *parent  = find_parent_group();
359        if (parent) taxLev     += parent->calculate_tax_level();
360        return taxLev;
361    }
362
363    virtual void swap_sons() {
364        rt_assert(!is_leaf); // @@@ if never fails -> remove condition below
365        if (!is_leaf) {
366            std::swap(leftson, rightson);
367            std::swap(leftlen, rightlen);
368        }
369    }
370    void rotate_subtree(); // flip whole subtree ( = recursive swap_sons())
371    void reorder_tree(TreeOrder mode);
372
373    TreeNode *findLeafNamed(const char *wantedName);
374
375    GBT_LEN reset_length_and_bootstrap() {
376        //! remove remark + zero but return branchlen
377        remove_remark();
378        GBT_LEN len = get_branchlength_unrooted();
379        set_branchlength_unrooted(0.0);
380        return len;
381    }
382
383    struct multifurc_limits {
384        double bootstrap;
385        double branchlength;
386        bool   applyAtLeafs;
387        multifurc_limits(double bootstrap_, double branchlength_, bool applyAtLeafs_)
388            : bootstrap(bootstrap_),
389              branchlength(branchlength_),
390              applyAtLeafs(applyAtLeafs_)
391        {}
392    };
393    class LengthCollector;
394
395    void multifurcate();
396    void set_branchlength_preserving(GBT_LEN new_len);
397
398    void multifurcate_whole_tree(const multifurc_limits& below);
399private:
400    void eliminate_and_collect(const multifurc_limits& below, LengthCollector& collect);
401public:
402
403#if defined(PROVIDE_TREE_STRUCTURE_TESTS)
404    Validity is_valid() const;
405#endif // PROVIDE_TREE_STRUCTURE_TESTS
406};
407MARK_NONFINAL_METHOD(TreeNode,void,swap_sons,());
408MARK_NONFINAL_METHOD(TreeNode,void,set_root,());
409
410inline void destroy(TreeNode *that) {
411    TreeNode::destroy(that);
412}
413inline void destroy(TreeNode *that, TreeRoot *root) {
414    TreeNode::destroy(that, root);
415}
416
417// ---------------------------------------------------------------------------------------
418//      macros to overwrite accessors in classes derived from TreeRoot or TreeNode:
419
420#define DEFINE_TREE_ROOT_ACCESSORS(RootType, TreeType)                                  \
421    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_root_node, TreeRoot::get_root_node())
422
423#define DEFINE_TREE_RELATIVES_ACCESSORS(TreeType) \
424    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_father, father); \
425    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_leftson, leftson);  \
426    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_rightson, rightson); \
427    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_brother, TreeNode::get_brother()); \
428    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_root_node, TreeNode::get_root_node());                                      \
429    TreeType *findLeafNamed(const char *wantedName) { return DOWNCAST(TreeType*, TreeNode::findLeafNamed(wantedName)); }
430
431#define DEFINE_TREE_ACCESSORS(RootType, TreeType)                                     \
432    DEFINE_DOWNCAST_ACCESSORS(RootType, get_tree_root, TreeNode::get_tree_root());    \
433    DEFINE_TREE_RELATIVES_ACCESSORS(TreeType)
434
435
436// -------------------------
437//      structure tests
438
439#if defined(PROVIDE_TREE_STRUCTURE_TESTS)
440template <typename TREE>
441inline Validity tree_is_valid(const TREE *tree, bool acceptNULL) {
442    if (tree) return tree->is_valid();
443    return Validity(acceptNULL, "NULL tree");
444}
445#endif
446
447#if defined(AUTO_CHECK_TREE_STRUCTURE)
448#define ASSERT_VALID_TREE(tree)         rt_assert(tree_is_valid(tree, false))
449#define ASSERT_VALID_TREE_OR_NULL(tree) rt_assert(tree_is_valid(tree, true))
450#else
451#define ASSERT_VALID_TREE(tree)
452#define ASSERT_VALID_TREE_OR_NULL(tree)
453#endif // AUTO_CHECK_TREE_STRUCTURE
454
455#if defined(PROVIDE_TREE_STRUCTURE_TESTS) && defined(UNIT_TESTS)
456
457#define TEST_EXPECT_VALID_TREE(tree)                     TEST_VALIDITY(tree_is_valid(tree, false))
458#define TEST_EXPECT_VALID_TREE_OR_NULL(tree)             TEST_VALIDITY(tree_is_valid(tree, true))
459#define TEST_EXPECT_VALID_TREE__BROKEN(tree,why)         TEST_VALIDITY__BROKEN(tree_is_valid(tree, false), why)
460#define TEST_EXPECT_VALID_TREE_OR_NULL__BROKEN(tree,why) TEST_VALIDITY__BROKEN(tree_is_valid(tree, true), why)
461
462#else
463
464#define TEST_EXPECT_VALID_TREE(tree)
465#define TEST_EXPECT_VALID_TREE_OR_NULL(tree)
466#define TEST_EXPECT_VALID_TREE__BROKEN(tree)
467#define TEST_EXPECT_VALID_TREE_OR_NULL__BROKEN(tree)
468
469#endif
470
471// --------------------
472//      SimpleTree
473
474struct SimpleRoot : public TreeRoot {
475    inline SimpleRoot();
476    inline TreeNode *makeNode() const OVERRIDE;
477    inline void destroyNode(TreeNode *node) const OVERRIDE;
478};
479
480class SimpleTree FINAL_TYPE : public TreeNode {
481protected:
482    ~SimpleTree() OVERRIDE {}
483    friend class SimpleRoot;
484public:
485    SimpleTree(SimpleRoot *sroot) : TreeNode(sroot) {}
486
487    // TreeNode interface
488    unsigned get_leaf_count() const OVERRIDE {
489        rt_assert(0); // @@@ impl?
490        return 0;
491    }
492    void compute_tree() OVERRIDE {}
493};
494
495SimpleRoot::SimpleRoot() : TreeRoot(true) {}
496inline TreeNode *SimpleRoot::makeNode() const { return new SimpleTree(const_cast<SimpleRoot*>(this)); }
497inline void SimpleRoot::destroyNode(TreeNode *node) const { delete DOWNCAST(SimpleTree*,node); }
498
499// ----------------------
500//      ARB_edge_type
501
502enum ARB_edge_type {
503    EDGE_TO_ROOT, // edge points towards the root node
504    EDGE_TO_LEAF, // edge points away from the root node
505    ROOT_EDGE, // edge between sons of root node
506};
507
508class ARB_edge {
509    // ARB_edge is a directional edge between two non-root-nodes of the same tree
510    // (can act as iterator for TreeNode)
511
512    TreeNode    *from, *to;
513    ARB_edge_type  type;
514
515    ARB_edge_type detectType() const {
516        rt_assert(to != from);
517        rt_assert(!from->is_root_node());                // edges cannot be at root - use edge between sons of root!
518        rt_assert(!to->is_root_node());
519
520        if (from->father == to) return EDGE_TO_ROOT;
521        if (to->father == from) return EDGE_TO_LEAF;
522
523        rt_assert(from->get_brother() == to);       // no edge exists between 'from' and 'to'
524        rt_assert(to->get_father()->is_root_node());
525        return ROOT_EDGE;
526    }
527
528    GBT_LEN adjacent_distance() const;
529    GBT_LEN length_or_adjacent_distance() const {
530        {
531            GBT_LEN len = length();
532            if (len>0.0) return len;
533        }
534        return adjacent_distance();
535    }
536
537    void virtually_add_or_distribute_length_forward(GBT_LEN len, TreeNode::LengthCollector& collect) const;
538    void virtually_distribute_length_forward(GBT_LEN len, TreeNode::LengthCollector& collect) const;
539public:
540    void virtually_distribute_length(GBT_LEN len, TreeNode::LengthCollector& collect) const; // @@@ hm public :(
541private:
542
543#if defined(UNIT_TESTS) // UT_DIFF
544    friend void TEST_edges();
545#endif
546
547public:
548    ARB_edge(TreeNode *From, TreeNode *To) :
549        from(From),
550        to(To),
551        type(detectType())
552    {}
553    ARB_edge(TreeNode *From, TreeNode *To, ARB_edge_type Type) :
554        from(From),
555        to(To),
556        type(Type)
557    {
558        rt_assert(type == detectType());
559    }
560    ARB_edge(const ARB_edge& otherEdge) :
561        from(otherEdge.from),
562        to(otherEdge.to),
563        type(otherEdge.type)
564    {
565        rt_assert(type == detectType());
566    }
567
568    ARB_edge_type get_type() const { return type; }
569    TreeNode *source() const { return from; }
570    TreeNode *dest() const { return to; }
571
572    TreeNode *son() const  { return type == EDGE_TO_ROOT ? from : to; }
573    TreeNode *other() const  { return type == EDGE_TO_ROOT ? to : from; }
574
575    GBT_LEN length() const {
576        if (type == ROOT_EDGE) return from->get_branchlength() + to->get_branchlength();
577        return son()->get_branchlength();
578    }
579    void set_length(GBT_LEN len)  {
580        if (type == ROOT_EDGE) {
581            from->set_branchlength(len/2);
582            to->set_branchlength(len/2);
583        }
584        else {
585            son()->set_branchlength(len);
586        }
587    }
588    GBT_LEN eliminate() {
589        //! eliminates edge (zeroes length and bootstrap). returns eliminated length.
590        if (type == ROOT_EDGE) {
591            return source()->reset_length_and_bootstrap() + dest()->reset_length_and_bootstrap();
592        }
593        return son()->reset_length_and_bootstrap();
594    }
595
596    ARB_edge inverse() const {
597        return ARB_edge(to, from, ARB_edge_type(type == ROOT_EDGE ? ROOT_EDGE : (EDGE_TO_LEAF+EDGE_TO_ROOT)-type));
598    }
599
600    // iterator functions: endlessly iterate over all edges of tree
601    // - next:        forward  (=towards dest())
602    // - previous:    backward (=back before source())
603    // - counter:     forward descends left  (=upper) son first
604    // - non-counter: forward descends right (=lower) son first
605
606    ARB_edge next() const { // descends rightson first (traverses leaf-edges from bottom to top)
607        if (type == EDGE_TO_ROOT) {
608            rt_assert(from->is_son_of(to));
609            if (from->is_rightson()) return ARB_edge(to, to->get_leftson(), EDGE_TO_LEAF);
610            TreeNode *father = to->get_father();
611            if (father->is_root_node()) return ARB_edge(to, to->get_brother(), ROOT_EDGE);
612            return ARB_edge(to, father, EDGE_TO_ROOT);
613        }
614        if (is_edge_to_leaf()) return inverse();
615        return ARB_edge(to, to->get_rightson(), EDGE_TO_LEAF);
616    }
617    ARB_edge previous() const { // inverse of next(). (traverses leaf-edges from top to bottom)
618        if (type == EDGE_TO_LEAF) {
619            rt_assert(to->is_son_of(from));
620            if (to->is_leftson()) return ARB_edge(from->get_rightson(), from, EDGE_TO_ROOT);
621            TreeNode *father = from->get_father();
622            if (father->is_root_node()) return ARB_edge(from->get_brother(), from, ROOT_EDGE);
623            return ARB_edge(father, from, EDGE_TO_LEAF);
624        }
625        if (is_edge_from_leaf()) return inverse();
626        return ARB_edge(from->get_leftson(), from, EDGE_TO_ROOT);
627    }
628
629    ARB_edge counter_next() const { // descends leftson first (traverses leaf-edges from top to bottom)
630        if (type == EDGE_TO_ROOT) {
631            rt_assert(from->is_son_of(to));
632            if (from->is_leftson()) return ARB_edge(to, to->get_rightson(), EDGE_TO_LEAF);
633            TreeNode *father = to->get_father();
634            if (father->is_root_node()) return ARB_edge(to, to->get_brother(), ROOT_EDGE);
635            return ARB_edge(to, father, EDGE_TO_ROOT);
636        }
637        if (is_edge_to_leaf()) return inverse();
638        return ARB_edge(to, to->get_leftson(), EDGE_TO_LEAF);
639    }
640    ARB_edge counter_previous() const { // inverse of counter_next(). (traverses leaf-edges from bottom to top)
641        if (type == EDGE_TO_LEAF) {
642            rt_assert(to->is_son_of(from));
643            if (to->is_rightson()) return ARB_edge(from->get_leftson(), from, EDGE_TO_ROOT);
644            TreeNode *father = from->get_father();
645            if (father->is_root_node()) return ARB_edge(from->get_brother(), from, ROOT_EDGE);
646            return ARB_edge(father, from, EDGE_TO_LEAF);
647        }
648        if (is_edge_from_leaf()) return inverse();
649        return ARB_edge(from->get_rightson(), from, EDGE_TO_ROOT);
650    }
651
652    static int iteration_count(int leafs_in_tree) {
653        /*! returns number of different edges produced by next() / previous():
654         * - each edge is visited twice (once in each direction)
655         */
656        return leafs_2_edges(leafs_in_tree, UNROOTED) * 2;
657    }
658
659    bool operator == (const ARB_edge& otherEdge) const {
660        return from == otherEdge.from && to == otherEdge.to;
661    }
662    bool operator != (const ARB_edge& otherEdge) const {
663        return !operator == (otherEdge);
664    }
665
666    bool is_edge_to_leaf() const {
667        //! true if edge is leaf edge AND points towards the leaf
668        return dest()->is_leaf;
669    }
670    bool is_edge_from_leaf() const {
671        //! true if edge is leaf edge AND points away from the leaf
672        return source()->is_leaf;
673    }
674    bool is_inner_edge() const {
675        //! true for inner edges
676        return !is_edge_to_leaf() && !is_edge_from_leaf();
677    }
678
679    void set_root() { son()->set_root(); }
680
681    void multifurcate();
682
683};
684
685inline ARB_edge parentEdge(TreeNode *son) {
686    /*! returns edge to father (or to brother for sons of root).
687     * Cannot be called with root-node (but can be called with each end of any ARB_edge)
688     */
689    TreeNode *father = son->get_father();
690    rt_assert(father);
691
692    if (father->is_root_node()) return ARB_edge(son, son->get_brother(), ROOT_EDGE);
693    return ARB_edge(son, father, EDGE_TO_ROOT);
694}
695inline ARB_edge leafEdge(TreeNode *leaf) {
696    rt_assert(leaf->is_leaf);
697    return parentEdge(leaf).inverse();
698}
699
700inline ARB_edge rootEdge(TreeRoot *root) {
701    TreeNode *root_node = root->get_root_node();
702    return ARB_edge(root_node->get_leftson(), root_node->get_rightson(), ROOT_EDGE);
703}
704
705#else
706#error TreeNode.h included twice
707#endif // TREENODE_H
Note: See TracBrowser for help on using the repository browser.