source: tags/testbuild/SL/ROOTED_TREE/RootedTree.h

Last change on this file was 13127, checked in by westram, 10 years ago
  • do not assert valid sequence state (when checking valid tree) atm
  • added simple topology modification (set root twice + pop) that corrupts valid sequence state
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : RootedTree.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 ROOTEDTREE_H
13#define ROOTEDTREE_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 RootedTree;
33class ARB_edge;
34
35struct RootedTreeNodeFactory { // acts similar to TreeNodeFactory for trees with root
36    virtual ~RootedTreeNodeFactory() {}
37    virtual RootedTree *makeNode(TreeRoot *root) const = 0;
38};
39
40class TreeRoot : public TreeNodeFactory, virtual Noncopyable {
41    RootedTree            *rootNode; // root node of the tree
42    RootedTreeNodeFactory *nodeMaker;
43    bool                   deleteWithNodes;
44
45public:
46    TreeRoot(RootedTreeNodeFactory *nodeMaker_, bool deleteWithNodes_)
47        : rootNode(NULL),
48          nodeMaker(nodeMaker_),
49          deleteWithNodes(deleteWithNodes_)
50    {
51        /*! Create a TreeRoot for a RootedTree.
52         * Purpose:
53         * - act as TreeNodeFactory
54         * - place to store the current rootNode
55         * - place to store other tree related information by deriving from TreeRoot
56         *
57         * @param nodeMaker_ heap-copy of a RootedTreeNodeFactory, will be deleted when this is destructed
58         * @param deleteWithNodes_ true -> delete TreeRoot when the rootNode gets destroyed (TreeRoot needs to be a heap-copy in that case)
59         *
60         * Ressource handling of the tree structure is quite difficult (and error-prone).
61         * There are two common use-cases:
62         * 1. TreeRoot is owned by some other object/scope
63         *    - pass false for deleteWithNodes_
64         *    - you may or may not destroy (parts of) the RootedTree manually
65         * 2. TreeRoot is owned by the RootedTree
66         *    - pass true for deleteWithNodes_
67         *    - when the rootNode gets destroyed, the TreeRoot will be destroyed as well
68         */
69    }
70    virtual ~TreeRoot();
71    virtual void change_root(RootedTree *old, RootedTree *newroot);
72
73    void delete_by_node() {
74        if (deleteWithNodes) {
75            rt_assert(!rootNode);
76            delete this;
77        }
78    }
79
80    // TreeNodeFactory interface
81    inline GBT_TREE *makeNode() const OVERRIDE;
82
83    RootedTree *get_root_node() { return rootNode; }
84    const RootedTree *get_root_node() const { return rootNode; }
85
86    ARB_edge find_innermost_edge();
87};
88
89enum TreeOrder { // contains bit values!
90    ORDER_BIG_DOWN      = 1, // bit 0 set -> big branches down
91    ORDER_BIG_TO_EDGE   = 2, // bit 1 set -> big branches to edge
92    ORDER_BIG_TO_CENTER = 4, // bit 2 set -> big branches to center
93    ORDER_ALTERNATING   = 8, // bit 3 set -> alternate bit 0
94
95    // user visible orders:
96    BIG_BRANCHES_TO_TOP      = 0,
97    BIG_BRANCHES_TO_BOTTOM   = ORDER_BIG_DOWN,
98    BIG_BRANCHES_TO_EDGE     = ORDER_BIG_TO_EDGE,
99    BIG_BRANCHES_TO_CENTER   = ORDER_BIG_TO_CENTER,
100    BIG_BRANCHES_ALTERNATING = ORDER_BIG_TO_CENTER|ORDER_ALTERNATING,
101};
102
103class RootedTree : public GBT_TREE { // derived from Noncopyable
104    friend void TreeRoot::change_root(RootedTree *old, RootedTree *newroot);
105
106    TreeRoot *tree_root;
107
108    // ------------------
109    //      functions
110
111    void reorder_subtree(TreeOrder mode);
112
113protected:
114    void set_tree_root(TreeRoot *new_root);
115
116    bool at_root() const {
117        //! return true for root-node and its sons
118        return !father || !father->father;
119    }
120
121public:
122    RootedTree(TreeRoot *root)
123        : tree_root(root)
124    {}
125    ~RootedTree() OVERRIDE {
126        if (tree_root) {
127            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)
128
129            TreeRoot *root = tree_root;
130            root->TreeRoot::change_root(this, NULL);
131            root->delete_by_node();
132        }
133    }
134
135    void announce_tree_constructed() OVERRIDE {
136        GBT_TREE::announce_tree_constructed();
137        get_tree_root()->change_root(NULL, this);
138    }
139
140    virtual unsigned get_leaf_count() const = 0;
141    virtual void compute_tree()             = 0;
142
143    DEFINE_SIMPLE_TREE_RELATIVES_ACCESSORS(RootedTree);
144
145    void forget_origin() { set_tree_root(NULL); }
146
147    TreeRoot *get_tree_root() const { return tree_root; }
148
149    const RootedTree *get_root_node() const {
150        if (!tree_root) return NULL; // nodes removed from tree have no root-node
151
152        const RootedTree *root = tree_root->get_root_node();
153        rt_assert(is_inside(root)); // this is not in tree - behavior of get_root_node() changed!
154        return root;
155    }
156    RootedTree *get_root_node() { return const_cast<RootedTree*>(const_cast<const RootedTree*>(this)->get_root_node()); }
157
158    bool is_root_node() const { return get_root_node() == this; }
159    virtual void set_root();
160
161    RootedTree *get_brother() {
162        rt_assert(!is_root_node()); // root node has no brother
163        rt_assert(father);          // this is a removed node (not root, but no father)
164        return is_leftson() ? get_father()->get_rightson() : get_father()->get_leftson();
165    }
166    const RootedTree *get_brother() const {
167        return const_cast<const RootedTree*>(const_cast<RootedTree*>(this)->get_brother());
168    }
169
170    bool is_named_group() const {
171        rt_assert(!is_leaf); // checking whether a leaf is a group
172        return gb_node && name;
173    }
174    const char *get_group_name() const {
175        return is_named_group() ? name : NULL;
176    }
177
178    virtual void swap_sons() {
179        rt_assert(!is_leaf); // @@@ if never fails -> remove condition below
180        if (!is_leaf) {
181            std::swap(leftson, rightson);
182            std::swap(leftlen, rightlen);
183        }
184    }
185    void rotate_subtree(); // flip whole subtree ( = recursive swap_sons())
186    void reorder_tree(TreeOrder mode);
187
188    RootedTree *findLeafNamed(const char *wantedName);
189
190    GBT_LEN reset_length_and_bootstrap() {
191        //! remove remark + zero but return branchlen
192        remove_remark();
193        GBT_LEN len = get_branchlength_unrooted();
194        set_branchlength_unrooted(0.0);
195        return len;
196    }
197
198    struct multifurc_limits {
199        double bootstrap;
200        double branchlength;
201        bool   applyAtLeafs;
202        multifurc_limits(double bootstrap_, double branchlength_, bool applyAtLeafs_)
203            : bootstrap(bootstrap_),
204              branchlength(branchlength_),
205              applyAtLeafs(applyAtLeafs_)
206        {}
207    };
208    class LengthCollector;
209
210    void multifurcate();
211    void set_branchlength_preserving(GBT_LEN new_len);
212
213    void multifurcate_whole_tree(const multifurc_limits& below);
214private:
215    void eliminate_and_collect(const multifurc_limits& below, LengthCollector& collect);
216public:
217
218#if defined(PROVIDE_TREE_STRUCTURE_TESTS)
219    void assert_valid() const;
220#endif // PROVIDE_TREE_STRUCTURE_TESTS
221};
222
223inline GBT_TREE *TreeRoot::makeNode() const {
224    return nodeMaker->makeNode(const_cast<TreeRoot*>(this));
225}
226
227// ---------------------------------------------------------------------------------------
228//      macros to overwrite accessors in classes derived from TreeRoot or RootedTree:
229
230#define DEFINE_TREE_ROOT_ACCESSORS(RootType, TreeType)                                  \
231    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_root_node, TreeRoot::get_root_node())
232
233#define DEFINE_TREE_RELATIVES_ACCESSORS(TreeType)                                       \
234    DEFINE_SIMPLE_TREE_RELATIVES_ACCESSORS(TreeType);                                   \
235    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_brother, RootedTree::get_brother());        \
236    DEFINE_DOWNCAST_ACCESSORS(TreeType, get_root_node, RootedTree::get_root_node());    \
237    TreeType *findLeafNamed(const char *wantedName) { return DOWNCAST(TreeType*, RootedTree::findLeafNamed(wantedName)); }
238
239#define DEFINE_TREE_ACCESSORS(RootType, TreeType)                                       \
240    DEFINE_DOWNCAST_ACCESSORS(RootType, get_tree_root, RootedTree::get_tree_root());    \
241    DEFINE_TREE_RELATIVES_ACCESSORS(TreeType)
242
243
244// -------------------------
245//      structure tests
246
247#if defined(PROVIDE_TREE_STRUCTURE_TESTS)
248template <typename TREE>
249inline void assert_tree_has_valid_structure(const TREE *tree, bool IF_ASSERTION_USED(acceptNULL)) {
250    rt_assert(acceptNULL || tree);
251    if (tree) tree->assert_valid();
252}
253#endif
254
255#if defined(AUTO_CHECK_TREE_STRUCTURE)
256#define ASSERT_VALID_TREE(tree)         assert_tree_has_valid_structure(tree, false)
257#define ASSERT_VALID_TREE_OR_NULL(tree) assert_tree_has_valid_structure(tree, true)
258#else
259#define ASSERT_VALID_TREE(tree)
260#define ASSERT_VALID_TREE_OR_NULL(tree)
261#endif // AUTO_CHECK_TREE_STRUCTURE
262
263#if defined(PROVIDE_TREE_STRUCTURE_TESTS) && defined(UNIT_TESTS)
264#define TEST_ASSERT_VALID_TREE(tree)         assert_tree_has_valid_structure(tree, false)
265#define TEST_ASSERT_VALID_TREE_OR_NULL(tree) assert_tree_has_valid_structure(tree, true)
266#else
267#define TEST_ASSERT_VALID_TREE(tree)
268#define TEST_ASSERT_VALID_TREE_OR_NULL(tree)
269#endif
270
271// ----------------------
272//      ARB_edge_type
273
274enum ARB_edge_type {
275    EDGE_TO_ROOT, // edge points towards the root node
276    EDGE_TO_LEAF, // edge points away from the root node
277    ROOT_EDGE, // edge between sons of root node
278};
279
280class ARB_edge {
281    // ARB_edge is a directional edge between two non-root-nodes of the same tree
282
283    RootedTree    *from, *to;
284    ARB_edge_type  type;
285
286    ARB_edge_type detectType() const {
287        rt_assert(to != from);
288        rt_assert(!from->is_root_node());                // edges cannot be at root - use edge between sons of root!
289        rt_assert(!to->is_root_node());
290
291        if (from->father == to) return EDGE_TO_ROOT;
292        if (to->father == from) return EDGE_TO_LEAF;
293
294        rt_assert(from->get_brother() == to);       // no edge exists between 'from' and 'to'
295        rt_assert(to->get_father()->is_root_node());
296        return ROOT_EDGE;
297    }
298
299    GBT_LEN adjacent_distance() const;
300    GBT_LEN length_or_adjacent_distance() const {
301        {
302            GBT_LEN len = length();
303            if (len>0.0) return len;
304        }
305        return adjacent_distance();
306    }
307
308    void virtually_add_or_distribute_length_forward(GBT_LEN len, RootedTree::LengthCollector& collect) const;
309    void virtually_distribute_length_forward(GBT_LEN len, RootedTree::LengthCollector& collect) const;
310public:
311    void virtually_distribute_length(GBT_LEN len, RootedTree::LengthCollector& collect) const; // @@@ hm public :(
312private:
313
314#if defined(UNIT_TESTS) // UT_DIFF
315    friend void TEST_edges();
316#endif
317
318public:
319    ARB_edge(RootedTree *From, RootedTree *To)
320        : from(From)
321        , to(To)
322        , type(detectType())
323    {}
324    ARB_edge(RootedTree *From, RootedTree *To, ARB_edge_type Type)
325        : from(From)
326        , to(To)
327        , type(Type)
328    {
329        rt_assert(type == detectType());
330    }
331    ARB_edge(const ARB_edge& otherEdge)
332        : from(otherEdge.from)
333        , to(otherEdge.to)
334        , type(otherEdge.type)
335    {
336        rt_assert(type == detectType());
337    }
338
339    ARB_edge_type get_type() const { return type; }
340    RootedTree *source() const { return from; }
341    RootedTree *dest() const { return to; }
342
343    RootedTree *son() const  { return type == EDGE_TO_ROOT ? from : to; }
344    RootedTree *other() const  { return type == EDGE_TO_ROOT ? to : from; }
345
346    GBT_LEN length() const {
347        if (type == ROOT_EDGE) return from->get_branchlength() + to->get_branchlength();
348        return son()->get_branchlength();
349    }
350    void set_length(GBT_LEN len)  {
351        if (type == ROOT_EDGE) {
352            from->set_branchlength(len/2);
353            to->set_branchlength(len/2);
354        }
355        else {
356            son()->set_branchlength(len);
357        }
358    }
359    GBT_LEN eliminate() {
360        //! eliminates edge (zeroes length and bootstrap). returns eliminated length.
361        if (type == ROOT_EDGE) {
362            return source()->reset_length_and_bootstrap() + dest()->reset_length_and_bootstrap();
363        }
364        return son()->reset_length_and_bootstrap();
365    }
366
367    ARB_edge inverse() const {
368        return ARB_edge(to, from, ARB_edge_type(type == ROOT_EDGE ? ROOT_EDGE : (EDGE_TO_LEAF+EDGE_TO_ROOT)-type));
369    }
370
371    // iterator functions: endlessly iterate over all edges of tree
372    ARB_edge next() const { // descends rightson first
373        if (type == EDGE_TO_ROOT) {
374            rt_assert(from->is_son_of(to));
375            if (from->is_rightson()) return ARB_edge(to, to->get_leftson(), EDGE_TO_LEAF);
376            RootedTree *father = to->get_father();
377            if (father->is_root_node()) return ARB_edge(to, to->get_brother(), ROOT_EDGE);
378            return ARB_edge(to, father, EDGE_TO_ROOT);
379        }
380        if (at_leaf()) return inverse();
381        return ARB_edge(to, to->get_rightson(), EDGE_TO_LEAF);
382    }
383    ARB_edge otherNext() const { // descends leftson first (slow)
384        if (at_leaf()) return inverse();
385        return next().inverse().next();
386    }
387
388    bool operator == (const ARB_edge& otherEdge) const {
389        return from == otherEdge.from && to == otherEdge.to;
390    }
391
392    bool at_leaf() const {
393        //! true if edge is leaf edge and points towards the leaf
394        return dest()->is_leaf;
395    }
396
397    void set_root() { son()->set_root(); }
398
399    void multifurcate();
400};
401
402inline ARB_edge parentEdge(RootedTree *son) {
403    /*! returns edge to father (or to brother for sons of root).
404     * Cannot be called with root-node (but can be called with each end of any ARB_edge)
405     */
406    RootedTree *father = son->get_father();
407    rt_assert(father);
408
409    if (father->is_root_node()) return ARB_edge(son, son->get_brother(), ROOT_EDGE);
410    return ARB_edge(son, father, EDGE_TO_ROOT);
411}
412
413#else
414#error RootedTree.h included twice
415#endif // ROOTEDTREE_H
Note: See TracBrowser for help on using the repository browser.