source: tags/ms_r18q1/ARBDB/TreeNode.h

Last change on this file was 17110, checked in by westram, 6 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.8 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(NULp),
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    TreeNode *father, *leftson, *rightson;
110    GBT_LEN   leftlen, rightlen;
111    GBDATA   *gb_node;
112    char     *name;
113
114private:
115    bool leaf;
116    bool keeledOver;  // node has group info and tree-root was moved "inside" that group -> group changed meaning (see #735)
117    bool inverseLeft; // (only if keeledOver) true -> left son contains "inverse" of original group; false -> right son dito
118
119    char *remark_branch; // remark_branch normally contains some bootstrap value in format 'xx%'
120                         // if you store other info there, please make sure that this info does not start with digits!!
121                         // Otherwise the tree export routines will not work correctly!
122
123    GBT_LEN& length_ref() { return is_leftson() ? father->leftlen : father->rightlen; }
124    const GBT_LEN& length_ref() const { return const_cast<TreeNode*>(this)->length_ref(); }
125
126    void keelOver(TreeNode *prev, TreeNode *next, double len);
127
128protected:
129    TreeNode*& self_ref() {
130        return is_leftson() ? father->leftson : father->rightson;
131    }
132    void unlink_from_father() {
133        if (father) {
134            self_ref() = NULp;
135            father     = NULp;
136        }
137    }
138
139    char *swap_remark(char *new_remark) {
140        char *result  = remark_branch;
141        remark_branch = new_remark;
142        return result;
143    }
144
145    inline void swap_node_info(TreeNode *other, bool ofKeeledGroups);
146    void fixKeeledOrientation() {
147        if (father->keeledOver) {
148            father->inverseLeft = is_leftson();
149            rt_assert(is_keeled_group());
150        }
151    }
152
153public:
154
155    bool is_leaf() const { return leaf; }
156    void markAsLeaf() {
157        rt_assert(!is_leaf());
158        rt_assert(!leftson && !rightson); // only allowed during setup!
159        leaf = true;
160    }
161
162    DEFINE_READ_ACCESSORS(TreeNode*, get_father,   father);
163    DEFINE_READ_ACCESSORS(TreeNode*, get_leftson,  leftson);
164    DEFINE_READ_ACCESSORS(TreeNode*, get_rightson, rightson);
165
166    // Note: unittests for these attributes are in ../NTREE/ad_trees.cxx@TEST_TreeNode_attributes
167
168    bool is_son_of(const TreeNode *Father) const {
169        return father == Father &&
170            (father->leftson == this || father->rightson == this);
171    }
172    bool is_leftson() const {
173        // left when root is at bottom; see also ../SL/ARB_TREE/ARB_Tree.hxx@is_upper_son
174        gb_assert(is_son_of(get_father())); // do only call with sons!
175        return father->leftson == this;
176    }
177    bool is_rightson() const {
178        gb_assert(is_son_of(get_father())); // do only call with sons!
179        return father->rightson == this;
180    }
181
182    bool is_inside(const TreeNode *subtree) const {
183        return this == subtree || (father && get_father()->is_inside(subtree));
184    }
185    bool is_ancestor_of(const TreeNode *descendant) const {
186        return !is_leaf() && descendant != this && descendant->is_inside(this);
187    }
188    bool in_same_branch_as(const TreeNode *other) const {
189        // returns true if 'this' and 'other' are in ONE branch
190        return this == other || is_ancestor_of(other) || other->is_ancestor_of(this);
191    }
192    bool in_other_branch_than(const TreeNode *other) const {
193        // returns true if 'this' and 'other' are NOT in one branch
194        return !in_same_branch_as(other);
195    }
196    const TreeNode *ancestor_common_with(const TreeNode *other) const;
197    TreeNode *ancestor_common_with(TreeNode *other) { return const_cast<TreeNode*>(ancestor_common_with(const_cast<const TreeNode*>(other))); }
198
199    GBT_LEN get_branchlength() const { return length_ref(); }
200    void set_branchlength(GBT_LEN newlen) {
201        gb_assert(!is_nan_or_inf(newlen));
202        length_ref() = newlen;
203    }
204
205    GBT_LEN get_branchlength_unrooted() const {
206        //! like get_branchlength, but root-edge is treated correctly
207        if (father->is_root_node()) {
208            return father->leftlen+father->rightlen;
209        }
210        return get_branchlength();
211    }
212    void set_branchlength_unrooted(GBT_LEN newlen) {
213        //! like set_branchlength, but root-edge is treated correctly
214        if (father->is_root_node()) {
215            father->leftlen  = newlen/2;
216            father->rightlen = newlen-father->leftlen; // make sure sum equals newlen
217        }
218        else {
219            set_branchlength(newlen);
220        }
221    }
222
223    GBT_LEN sum_child_lengths() const;
224    GBT_LEN root_distance() const {
225        //! returns distance from node to root (including nodes own length)
226        return father ? get_branchlength()+father->root_distance() : 0.0;
227    }
228    GBT_LEN intree_distance_to(const TreeNode *other) const {
229        const TreeNode *ancestor = ancestor_common_with(other);
230        return root_distance() + other->root_distance() - 2*ancestor->root_distance();
231    }
232
233    enum bs100_mode { BS_UNDECIDED, BS_REMOVE, BS_INSERT };
234    bs100_mode toggle_bootstrap100(bs100_mode mode = BS_UNDECIDED); // toggle bootstrap '100%' <-> ''
235    void       remove_bootstrap();                                  // remove bootstrap values from subtree
236
237    void reset_branchlengths();                     // reset branchlengths of subtree to tree_defaults::LENGTH
238    void scale_branchlengths(double factor);
239
240    void bootstrap2branchlen();                     // copy bootstraps to branchlengths
241    void branchlen2bootstrap();                     // copy branchlengths to bootstraps
242
243    GBT_RemarkType parse_bootstrap(double& bootstrap) const {
244        /*! analyse 'remark_branch' and return GBT_RemarkType.
245         * If result is REMARK_BOOTSTRAP, 'bootstrap' contains the bootstrap value
246         */
247        if (!remark_branch) return REMARK_NONE;
248
249        const char *end = NULp;
250        bootstrap       = strtod(remark_branch, (char**)&end);
251
252        bool is_bootstrap = end[0] == '%' && end[1] == 0;
253        return is_bootstrap ? REMARK_BOOTSTRAP : REMARK_OTHER;
254    }
255    const char *get_remark() const { return remark_branch; }
256    void use_as_remark(char *newRemark) { freeset(remark_branch, newRemark); }
257    void set_remark(const char *newRemark) { freedup(remark_branch, newRemark); }
258    void set_bootstrap(double bootstrap) { use_as_remark(GBS_global_string_copy("%i%%", int(bootstrap+0.5))); } // @@@ protect against "100%"?
259    void remove_remark() { use_as_remark(NULp); }
260
261private:
262
263    friend void TreeRoot::change_root(TreeNode *old, TreeNode *newroot);
264
265    TreeRoot *tree_root;
266
267    // ------------------
268    //      functions
269
270    void reorder_subtree(TreeOrder mode);
271
272protected:
273    void set_tree_root(TreeRoot *new_root);
274
275    bool at_root() const {
276        //! return true for root-node and its sons
277        return !father || !father->father;
278    }
279    virtual ~TreeNode() {
280        if (tree_root) {
281            rt_assert(tree_root->get_root_node() == this); // you may only free the root-node or unlinked nodes (i.e. nodes where tree_root is NULp)
282
283            TreeRoot *root = tree_root;
284            root->TreeRoot::change_root(this, NULp);
285            root->delete_by_node();
286        }
287        delete leftson;  gb_assert(!leftson); // cannot use destroy here
288        delete rightson; gb_assert(!rightson);
289
290        unlink_from_father();
291
292        free(name);
293        free(remark_branch);
294    }
295    void destroy()  {
296        rt_assert(knownNonNull(this));
297        TreeRoot *myRoot = get_tree_root();
298        rt_assert(myRoot); // if this fails, you need to use destroy(TreeRoot*), i.e. destroy(TreeNode*, TreeRoot*)
299        myRoot->destroyNode(this);
300    }
301    void destroy(TreeRoot *viaRoot) {
302        rt_assert(knownNonNull(this));
303#if defined(ASSERTION_USED)
304        TreeRoot *myRoot = get_tree_root();
305        rt_assert(!myRoot || myRoot == viaRoot);
306#endif
307        viaRoot->destroyNode(this);
308    }
309
310public:
311    TreeNode(TreeRoot *root) :
312        father(NULp), leftson(NULp), rightson(NULp),
313        leftlen(0.0), rightlen(0.0),
314        gb_node(NULp),
315        name(NULp),
316        leaf(false),
317        keeledOver(false),
318        inverseLeft(false),
319        remark_branch(NULp),
320        tree_root(root)
321    {}
322    static void destroy(TreeNode *that)  { // replacement for destructor
323        if (that) that->destroy();
324    }
325    static void destroy(TreeNode *that, TreeRoot *root) {
326        if (that) that->destroy(root);
327    }
328
329    TreeNode *fixDeletedSon(); // @@@ review (design)
330
331    void unlink_from_DB();
332
333    void announce_tree_constructed() { // @@@ use this function or just call change_root instead?
334        // (has to be) called after tree has been constructed
335        gb_assert(!father); // has to be called with root-node!
336        get_tree_root()->change_root(NULp, this);
337    }
338
339    virtual unsigned get_leaf_count() const = 0;
340    virtual void compute_tree()             = 0;
341
342    void forget_origin() { set_tree_root(NULp); }
343    void forget_relatives() {
344        leftson  = NULp;
345        rightson = NULp;
346        father   = NULp;
347    }
348
349    TreeRoot *get_tree_root() const { return tree_root; }
350
351    const TreeNode *get_root_node() const {
352        if (!tree_root) return NULp; // nodes removed from tree have no root-node
353
354        const TreeNode *root = tree_root->get_root_node();
355        rt_assert(is_inside(root)); // this is not in tree - behavior of get_root_node() changed!
356        return root;
357    }
358    TreeNode *get_root_node() { return const_cast<TreeNode*>(const_cast<const TreeNode*>(this)->get_root_node()); }
359
360    bool is_root_node() const { return get_root_node() == this; }
361    virtual void set_root();
362
363    TreeNode *get_brother() {
364        rt_assert(!is_root_node()); // root node has no brother
365        rt_assert(father);          // this is a removed node (not root, but no father)
366        return is_leftson() ? get_father()->get_rightson() : get_father()->get_leftson();
367    }
368    const TreeNode *get_brother() const {
369        return const_cast<const TreeNode*>(const_cast<TreeNode*>(this)->get_brother());
370    }
371
372    bool has_group_info() const {
373        rt_assert(!is_leaf()); // a leaf never has group info (useless call)
374        return gb_node && name;
375    }
376    TreeNode *keelTarget() {
377        return (has_group_info() && keeledOver) ? (inverseLeft ? get_leftson() : get_rightson()) : NULp;
378    }
379    const TreeNode *keelTarget() const {
380        return const_cast<TreeNode*>(this)->keelTarget();
381    }
382    bool keelsDownGroup(const TreeNode *toSon) const {
383        // returns true if node has a group keeled down 'toSon'
384        return keelTarget() == toSon;
385    }
386    void unkeelGroup() {
387        rt_assert(keelTarget());
388        keeledOver = false;
389    }
390    int keeledStateInfo() const { // keeled-state as stored in database
391        return keeledOver ? (inverseLeft ? 1 : 2) : 0;
392    }
393    void setKeeledState(int keeledState) {
394        keeledOver  = keeledState;
395        inverseLeft = keeledState == 1;
396    }
397
398    bool is_normal_group() const {
399        // returns true when node shall show a "normal" group
400        rt_assert(!is_leaf()); // useless call (a normal group never may occur at leaf)
401        return has_group_info() && !keeledOver;
402    }
403    bool is_keeled_group() const {
404        // returns true when node shall show a "keeled" group.
405        // (i.e. when father has a keeled group oriented towards 'this')
406        return father && father->keelsDownGroup(this);
407    }
408    bool is_clade() const {
409        // return true, if a clickable group shall be displayed in tree
410        // (Note: keeled groups may appear at leafs)
411        return (!is_leaf() && is_normal_group()) || is_keeled_group();
412    }
413
414    const char *get_group_name() const {
415        return
416            !is_leaf() && is_normal_group()
417            ? name
418            : (is_keeled_group() ? father->name : NULp);
419    }
420
421    const TreeNode *find_parent_with_groupInfo(bool skipKeeledBrothers = false) const {
422        const TreeNode *child  = this;
423        const TreeNode *parent = get_father();
424
425        while (parent) {
426            if (parent->has_group_info()) {
427                if (!skipKeeledBrothers) break; // report any group
428
429                const TreeNode *keeled = parent->keelTarget();
430                if (!keeled || keeled == child) break;
431
432                // continue with next parent if keeled to other branch
433            }
434            child  = parent;
435            parent = child->get_father();
436        }
437        return parent;
438    }
439    TreeNode *find_parent_with_groupInfo(bool skipKeeledBrothers = false) {
440        return const_cast<TreeNode*>(const_cast<const TreeNode*>(this)->find_parent_with_groupInfo(skipKeeledBrothers));
441    }
442
443    const TreeNode *find_parent_clade() const {
444        // opposed to find_parent_with_groupInfo this reports only nodes where a group is DISPLAYED
445        // (i.e. in case of keeled groups at son node)
446
447        const TreeNode *parent   = find_parent_with_groupInfo();
448        const TreeNode *myBranch = this;  // me or any ancestor
449        while (parent) {
450            const TreeNode *keeled = parent->keelTarget();
451            if (!keeled) break; // use parent
452
453            if (parent != father && keeled->in_same_branch_as(myBranch)) {
454                parent = keeled; // use keeled
455                break;
456            }
457
458            // either keeled to self, to brother or to brother of some of my ancestors -> step up
459            rt_assert(keeled == this || keeled == get_brother() || keeled->get_brother()->is_ancestor_of(this));
460
461            myBranch = parent;
462            parent   = parent->find_parent_with_groupInfo();
463        }
464
465        rt_assert(implicated(parent, parent->is_clade()));
466
467        return parent;
468    }
469    TreeNode *find_parent_clade() {
470        return const_cast<TreeNode*>(const_cast<const TreeNode*>(this)->find_parent_clade());
471    }
472    int calc_clade_level() const {
473        int             taxLev  = is_clade();
474        const TreeNode *parent  = find_parent_clade();
475        if (parent) taxLev     += parent->calc_clade_level();
476        return taxLev;
477    }
478
479    virtual void swap_sons() {
480        rt_assert(!is_leaf()); // only possible for inner nodes!
481
482        std::swap(leftson, rightson);
483        std::swap(leftlen, rightlen);
484        inverseLeft = !inverseLeft;
485    }
486    void rotate_subtree(); // flip whole subtree ( = recursive swap_sons())
487    void reorder_tree(TreeOrder mode);
488
489    TreeNode *findLeafNamed(const char *wantedName);
490
491    GBT_LEN reset_length_and_bootstrap() {
492        //! remove remark + zero but return branchlen
493        remove_remark();
494        GBT_LEN len = get_branchlength_unrooted();
495        set_branchlength_unrooted(0.0);
496        return len;
497    }
498
499    struct multifurc_limits {
500        double bootstrap;
501        double branchlength;
502        bool   applyAtLeafs;
503        multifurc_limits(double bootstrap_, double branchlength_, bool applyAtLeafs_)
504            : bootstrap(bootstrap_),
505              branchlength(branchlength_),
506              applyAtLeafs(applyAtLeafs_)
507        {}
508    };
509    class LengthCollector;
510
511    void multifurcate();
512    void set_branchlength_preserving(GBT_LEN new_len);
513
514    void multifurcate_whole_tree(const multifurc_limits& below);
515private:
516    void eliminate_and_collect(const multifurc_limits& below, LengthCollector& collect);
517public:
518
519#if defined(PROVIDE_TREE_STRUCTURE_TESTS)
520    Validity is_valid() const;
521#endif // PROVIDE_TREE_STRUCTURE_TESTS
522};
523MARK_NONFINAL_METHOD(TreeNode,void,swap_sons,());
524MARK_NONFINAL_METHOD(TreeNode,void,set_root,());
525
526inline void destroy(TreeNode *that) {
527    TreeNode::destroy(that);
528}
529inline void destroy(TreeNode *that, TreeRoot *root) {
530    TreeNode::destroy(that, root);
531}
532
533// ---------------------------------------------------------------------------------------
534//      macros to overwrite accessors in classes derived from TreeRoot or TreeNode:
535
536#define DEFINE_TREE_ROOT_ACCESSORS(RootType, TreeType)                                  \
537    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_root_node, TreeRoot::get_root_node())
538
539#define DEFINE_TREE_RELATIVES_ACCESSORS(TreeType) \
540    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_father, father); \
541    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_leftson, leftson);  \
542    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_rightson, rightson); \
543    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_brother, TreeNode::get_brother()); \
544    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_root_node, TreeNode::get_root_node());                                      \
545    TreeType *findLeafNamed(const char *wantedName) { return DOWNCAST(TreeType*, TreeNode::findLeafNamed(wantedName)); }
546
547#define DEFINE_TREE_ACCESSORS(RootType, TreeType)                                     \
548    DEFINE_DOWNCAST_ACCESSORS(RootType, get_tree_root, TreeNode::get_tree_root());    \
549    DEFINE_TREE_RELATIVES_ACCESSORS(TreeType)
550
551
552// -------------------------
553//      structure tests
554
555#if defined(PROVIDE_TREE_STRUCTURE_TESTS)
556template <typename TREE>
557inline Validity tree_is_valid(const TREE *tree, bool acceptNULL) {
558    if (tree) return tree->is_valid();
559    return Validity(acceptNULL, "NULp tree");
560}
561#endif
562
563#if defined(AUTO_CHECK_TREE_STRUCTURE)
564#define ASSERT_VALID_TREE(tree)         rt_assert(tree_is_valid(tree, false))
565#define ASSERT_VALID_TREE_OR_NULL(tree) rt_assert(tree_is_valid(tree, true))
566#else
567#define ASSERT_VALID_TREE(tree)
568#define ASSERT_VALID_TREE_OR_NULL(tree)
569#endif // AUTO_CHECK_TREE_STRUCTURE
570
571#if defined(PROVIDE_TREE_STRUCTURE_TESTS) && defined(UNIT_TESTS)
572
573#define TEST_EXPECT_VALID_TREE(tree)                     TEST_VALIDITY(tree_is_valid(tree, false))
574#define TEST_EXPECT_VALID_TREE_OR_NULL(tree)             TEST_VALIDITY(tree_is_valid(tree, true))
575#define TEST_EXPECT_VALID_TREE__BROKEN(tree,why)         TEST_VALIDITY__BROKEN(tree_is_valid(tree, false), why)
576#define TEST_EXPECT_VALID_TREE_OR_NULL__BROKEN(tree,why) TEST_VALIDITY__BROKEN(tree_is_valid(tree, true), why)
577
578#else
579
580#define TEST_EXPECT_VALID_TREE(tree)
581#define TEST_EXPECT_VALID_TREE_OR_NULL(tree)
582#define TEST_EXPECT_VALID_TREE__BROKEN(tree)
583#define TEST_EXPECT_VALID_TREE_OR_NULL__BROKEN(tree)
584
585#endif
586
587// --------------------
588//      SimpleTree
589
590struct SimpleRoot : public TreeRoot {
591    inline SimpleRoot();
592    inline TreeNode *makeNode() const OVERRIDE;
593    inline void destroyNode(TreeNode *node) const OVERRIDE;
594};
595
596class SimpleTree FINAL_TYPE : public TreeNode {
597protected:
598    ~SimpleTree() OVERRIDE {}
599    friend class SimpleRoot;
600public:
601    SimpleTree(SimpleRoot *sroot) : TreeNode(sroot) {}
602
603    // TreeNode interface
604    unsigned get_leaf_count() const OVERRIDE {
605        rt_assert(0); // @@@ impl?
606        return 0;
607    }
608    void compute_tree() OVERRIDE {}
609};
610
611SimpleRoot::SimpleRoot() : TreeRoot(true) {}
612inline TreeNode *SimpleRoot::makeNode() const { return new SimpleTree(const_cast<SimpleRoot*>(this)); }
613inline void SimpleRoot::destroyNode(TreeNode *node) const { delete DOWNCAST(SimpleTree*,node); }
614
615// ----------------------
616//      ARB_edge_type
617
618enum ARB_edge_type {
619    EDGE_TO_ROOT, // edge points towards the root node
620    EDGE_TO_LEAF, // edge points away from the root node
621    ROOT_EDGE, // edge between sons of root node
622};
623
624class ARB_edge {
625    // ARB_edge is a directional edge between two non-root-nodes of the same tree
626    // (can act as iterator for TreeNode)
627
628    TreeNode    *from, *to;
629    ARB_edge_type  type;
630
631    ARB_edge_type detectType() const {
632        rt_assert(to != from);
633        rt_assert(!from->is_root_node());                // edges cannot be at root - use edge between sons of root!
634        rt_assert(!to->is_root_node());
635
636        if (from->father == to) return EDGE_TO_ROOT;
637        if (to->father == from) return EDGE_TO_LEAF;
638
639        rt_assert(from->get_brother() == to);       // no edge exists between 'from' and 'to'
640        rt_assert(to->get_father()->is_root_node());
641        return ROOT_EDGE;
642    }
643
644    GBT_LEN adjacent_distance() const;
645    GBT_LEN length_or_adjacent_distance() const {
646        {
647            GBT_LEN len = length();
648            if (len>0.0) return len;
649        }
650        return adjacent_distance();
651    }
652
653    void virtually_add_or_distribute_length_forward(GBT_LEN len, TreeNode::LengthCollector& collect) const;
654    void virtually_distribute_length_forward(GBT_LEN len, TreeNode::LengthCollector& collect) const;
655public:
656    void virtually_distribute_length(GBT_LEN len, TreeNode::LengthCollector& collect) const; // @@@ hm public :(
657private:
658
659#if defined(UNIT_TESTS) // UT_DIFF
660    friend void TEST_edges();
661#endif
662
663public:
664    ARB_edge(TreeNode *From, TreeNode *To) :
665        from(From),
666        to(To),
667        type(detectType())
668    {}
669    ARB_edge(TreeNode *From, TreeNode *To, ARB_edge_type Type) :
670        from(From),
671        to(To),
672        type(Type)
673    {
674        rt_assert(type == detectType());
675    }
676    ARB_edge(const ARB_edge& otherEdge) :
677        from(otherEdge.from),
678        to(otherEdge.to),
679        type(otherEdge.type)
680    {
681        rt_assert(type == detectType());
682    }
683
684    ARB_edge_type get_type() const { return type; }
685    TreeNode *source() const { return from; }
686    TreeNode *dest() const { return to; }
687
688    TreeNode *son() const  { return type == EDGE_TO_ROOT ? from : to; }
689    TreeNode *other() const  { return type == EDGE_TO_ROOT ? to : from; }
690
691    GBT_LEN length() const {
692        if (type == ROOT_EDGE) return from->get_branchlength() + to->get_branchlength();
693        return son()->get_branchlength();
694    }
695    void set_length(GBT_LEN len)  {
696        if (type == ROOT_EDGE) {
697            from->set_branchlength(len/2);
698            to->set_branchlength(len/2);
699        }
700        else {
701            son()->set_branchlength(len);
702        }
703    }
704    GBT_LEN eliminate() {
705        //! eliminates edge (zeroes length and bootstrap). returns eliminated length.
706        if (type == ROOT_EDGE) {
707            return source()->reset_length_and_bootstrap() + dest()->reset_length_and_bootstrap();
708        }
709        return son()->reset_length_and_bootstrap();
710    }
711
712    ARB_edge inverse() const {
713        return ARB_edge(to, from, ARB_edge_type(type == ROOT_EDGE ? ROOT_EDGE : (EDGE_TO_LEAF+EDGE_TO_ROOT)-type));
714    }
715
716    // iterator functions: endlessly iterate over all edges of tree
717    // - next:        forward  (=towards dest())
718    // - previous:    backward (=back before source())
719    // - counter:     forward descends left  (=upper) son first
720    // - non-counter: forward descends right (=lower) son first
721
722    ARB_edge next() const { // descends rightson first (traverses leaf-edges from bottom to top)
723        if (type == EDGE_TO_ROOT) {
724            rt_assert(from->is_son_of(to));
725            if (from->is_rightson()) return ARB_edge(to, to->get_leftson(), EDGE_TO_LEAF);
726            TreeNode *father = to->get_father();
727            if (father->is_root_node()) return ARB_edge(to, to->get_brother(), ROOT_EDGE);
728            return ARB_edge(to, father, EDGE_TO_ROOT);
729        }
730        if (is_edge_to_leaf()) return inverse();
731        return ARB_edge(to, to->get_rightson(), EDGE_TO_LEAF);
732    }
733    ARB_edge previous() const { // inverse of next(). (traverses leaf-edges from top to bottom)
734        if (type == EDGE_TO_LEAF) {
735            rt_assert(to->is_son_of(from));
736            if (to->is_leftson()) return ARB_edge(from->get_rightson(), from, EDGE_TO_ROOT);
737            TreeNode *father = from->get_father();
738            if (father->is_root_node()) return ARB_edge(from->get_brother(), from, ROOT_EDGE);
739            return ARB_edge(father, from, EDGE_TO_LEAF);
740        }
741        if (is_edge_from_leaf()) return inverse();
742        return ARB_edge(from->get_leftson(), from, EDGE_TO_ROOT);
743    }
744
745    ARB_edge counter_next() const { // descends leftson first (traverses leaf-edges from top to bottom)
746        if (type == EDGE_TO_ROOT) {
747            rt_assert(from->is_son_of(to));
748            if (from->is_leftson()) return ARB_edge(to, to->get_rightson(), EDGE_TO_LEAF);
749            TreeNode *father = to->get_father();
750            if (father->is_root_node()) return ARB_edge(to, to->get_brother(), ROOT_EDGE);
751            return ARB_edge(to, father, EDGE_TO_ROOT);
752        }
753        if (is_edge_to_leaf()) return inverse();
754        return ARB_edge(to, to->get_leftson(), EDGE_TO_LEAF);
755    }
756    ARB_edge counter_previous() const { // inverse of counter_next(). (traverses leaf-edges from bottom to top)
757        if (type == EDGE_TO_LEAF) {
758            rt_assert(to->is_son_of(from));
759            if (to->is_rightson()) return ARB_edge(from->get_leftson(), from, EDGE_TO_ROOT);
760            TreeNode *father = from->get_father();
761            if (father->is_root_node()) return ARB_edge(from->get_brother(), from, ROOT_EDGE);
762            return ARB_edge(father, from, EDGE_TO_LEAF);
763        }
764        if (is_edge_from_leaf()) return inverse();
765        return ARB_edge(from->get_rightson(), from, EDGE_TO_ROOT);
766    }
767
768    static int iteration_count(int leafs_in_tree) {
769        /*! returns number of different edges produced by next() / previous():
770         * - each edge is visited twice (once in each direction)
771         */
772        return leafs_2_edges(leafs_in_tree, UNROOTED) * 2;
773    }
774
775    bool operator == (const ARB_edge& otherEdge) const {
776        return from == otherEdge.from && to == otherEdge.to;
777    }
778    bool operator != (const ARB_edge& otherEdge) const {
779        return !operator == (otherEdge);
780    }
781
782    bool is_edge_to_leaf() const {
783        //! true if edge is leaf edge AND points towards the leaf
784        return dest()->is_leaf();
785    }
786    bool is_edge_from_leaf() const {
787        //! true if edge is leaf edge AND points away from the leaf
788        return source()->is_leaf();
789    }
790    bool is_inner_edge() const {
791        //! true for inner edges
792        return !is_edge_to_leaf() && !is_edge_from_leaf();
793    }
794
795    void set_root() { son()->set_root(); }
796
797    void multifurcate();
798
799};
800
801inline ARB_edge parentEdge(TreeNode *son) {
802    /*! returns edge to father (or to brother for sons of root).
803     * Cannot be called with root-node (but can be called with each end of any ARB_edge)
804     */
805    TreeNode *father = son->get_father();
806    rt_assert(father);
807
808    if (father->is_root_node()) return ARB_edge(son, son->get_brother(), ROOT_EDGE);
809    return ARB_edge(son, father, EDGE_TO_ROOT);
810}
811inline ARB_edge leafEdge(TreeNode *leaf) {
812    rt_assert(leaf->is_leaf());
813    return parentEdge(leaf).inverse();
814}
815
816inline ARB_edge rootEdge(TreeRoot *root) {
817    TreeNode *root_node = root->get_root_node();
818    return ARB_edge(root_node->get_leftson(), root_node->get_rightson(), ROOT_EDGE);
819}
820
821#else
822#error TreeNode.h included twice
823#endif // TREENODE_H
Note: See TracBrowser for help on using the repository browser.