source: tags/ms_r18q1/PARSIMONY/AP_tree_nlen.cxx

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: 45.0 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : AP_tree_nlen.cxx                                  //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Coded by Ralf Westram (coder@reallysoft.de) in Summer 1995    //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#include "ap_tree_nlen.hxx"
13#include "ap_main.hxx"
14
15#include <AP_seq_dna.hxx>
16#include <aw_root.hxx>
17
18using namespace std;
19
20// ---------------------------------
21//      Section base operations:
22// ---------------------------------
23
24AP_UPDATE_FLAGS AP_pars_root::check_update() {
25    // disables load if tree changes in DB
26    // (ignore changes performed in arb_ntree while tree is loaded in arb_pars)
27    AP_UPDATE_FLAGS res = AP_tree_root::check_update();
28    return res == AP_UPDATE_RELOADED ? AP_UPDATE_OK : res;
29}
30
31ostream& operator<<(ostream& out, const AP_tree_nlen *node) {
32    out << ' ';
33
34    if (!node) {
35        out << "NULp";
36    }
37    if (node->is_leaf()) {
38        out << ((void *)node) << '(' << node->name << ')';
39    }
40    else {
41        static int notTooDeep;
42
43        if (notTooDeep) {
44            out << ((void *)node);
45            if (!node->father) out << " (ROOT)";
46        }
47        else {
48            notTooDeep = 1;
49
50            out << "NODE(" << ((void *)node);
51
52            if (!node->father) {
53                out << " (ROOT)";
54            }
55            else {
56                out << ", father=" << node->father;
57            }
58
59            out << ", leftson=" << node->leftson
60                << ", rightson=" << node->rightson
61                << ", edge[0]=" << node->edge[0]
62                << ", edge[1]=" << node->edge[1]
63                << ", edge[2]=" << node->edge[2]
64                << ")";
65
66            notTooDeep = 0;
67        }
68    }
69
70    return out << ' ';
71}
72
73int AP_tree_nlen::unusedEdgeIndex() const {
74    for (int e=0; e<3; e++) if (!edge[e]) return e;
75    return -1;
76}
77
78AP_tree_edge* AP_tree_nlen::edgeTo(const AP_tree_nlen *neighbour) const {
79    for (int e=0; e<3; e++) {
80        if (edge[e] && edge[e]->node[1-index[e]]==neighbour) {
81            return edge[e];
82        }
83    }
84    return NULp;
85}
86
87AP_tree_edge* AP_tree_nlen::nextEdge(const AP_tree_edge *afterThatEdge) const {
88    /*! @return one edge of 'this'
89     *
90     * @param afterThatEdge
91     * - if == NULp -> returns the "first" edge (edge[0])
92     * - otherwise -> returns the next edge following 'afterThatEdge' in the array edge[]
93     */
94    return edge[afterThatEdge ? ((indexOf(afterThatEdge)+1) % 3) : 0];
95}
96
97void AP_tree_nlen::unlinkAllEdges(AP_tree_edge **edgePtr1, AP_tree_edge **edgePtr2, AP_tree_edge **edgePtr3) {
98    ap_assert(edge[0]);
99    ap_assert(edge[1]);
100    ap_assert(edge[2]);
101
102    *edgePtr1 = edge[0]->unlink();
103    *edgePtr2 = edge[1]->unlink();
104    *edgePtr3 = edge[2]->unlink();
105}
106
107void AP_tree_nlen::linkAllEdges(AP_tree_edge *edge1, AP_tree_edge *edge2, AP_tree_edge *edge3) {
108    ap_assert(!edge[0]);
109    ap_assert(!edge[1]);
110    ap_assert(!edge[2]);
111
112    edge1->relink(this, get_father()->get_father() ? get_father() : get_brother());
113    edge2->relink(this, get_leftson());
114    edge3->relink(this, get_rightson());
115}
116
117// -----------------------------
118//      Check tree structure
119
120#if defined(PROVIDE_TREE_STRUCTURE_TESTS)
121
122#if defined(DEBUG)
123#define DUMP_INVALID_SUBTREES
124#endif
125
126#if defined(DEVEL_RALF)
127#define CHECK_CORRECT_INVALIDATION // recombines all up-to-date nodes to find missing invalidations (VERY slow)
128#endif
129
130
131#if defined(DUMP_INVALID_SUBTREES)
132inline void dumpSubtree(const char *msg, const AP_tree_nlen *node) {
133    fprintf(stderr, "%s:\n", msg);
134    char *printable = GBT_tree_2_newick(node, NewickFormat(nSIMPLE|nWRAP), true);
135    fputs(printable, stderr);
136    fputc('\n', stderr);
137    free(printable);
138}
139#endif
140
141inline const AP_tree_edge *edge_between(const AP_tree_nlen *node1, const AP_tree_nlen *node2) {
142    AP_tree_edge *edge_12 = node1->edgeTo(node2);
143
144#if defined(ASSERTION_USED)
145    AP_tree_edge *edge_21 = node2->edgeTo(node1);
146    ap_assert(edge_12 == edge_21); // nodes should agree about their edge
147#endif
148
149    return edge_12;
150}
151
152inline const char *no_valid_edge_between(const AP_tree_nlen *node1, const AP_tree_nlen *node2) {
153    AP_tree_edge *edge_12 = node1->edgeTo(node2);
154    AP_tree_edge *edge_21 = node2->edgeTo(node1);
155
156    if (edge_12 == edge_21) {
157        return edge_12 ? NULp : "edge missing";
158    }
159    return "edge inconsistent";
160}
161
162#if defined(DUMP_INVALID_SUBTREES)
163#define PRINT_BAD_EDGE(msg,node) dumpSubtree(msg,node)
164#else // !defined(DUMP_INVALID_SUBTREES)
165#define PRINT_BAD_EDGE(msg,node) fprintf(stderr, "Warning: %s (at node=%p)\n", (msg), (node))
166#endif
167
168#define SHOW_BAD_EDGE(format,str,node) do{              \
169        char *msg = GBS_global_string_copy(format,str); \
170        PRINT_BAD_EDGE(msg, node);                      \
171        free(msg);                                      \
172    }while(0)
173
174Validity AP_tree_nlen::has_valid_edges() const {
175    Validity valid;
176    if (get_father()) {                     // root has no edges
177        if (get_father()->is_root_node()) { // sons of root have one edge between them
178            if (is_leftson()) { // test root-edge only from one son
179                const char *invalid = no_valid_edge_between(this, get_brother());
180                if (invalid) {
181                    SHOW_BAD_EDGE("root-%s. root", invalid, get_father());
182                    valid = Validity(false, "no valid edge between sons of root");
183                }
184            }
185            const char *invalid = no_valid_edge_between(this, get_father());
186            if (!invalid || !strstr(invalid, "missing")) {
187                SHOW_BAD_EDGE("unexpected edge (%s) between root and son", invalid ? invalid : "valid", this);
188                valid = Validity(false, "unexpected edge between son-of-root and root");
189            }
190        }
191        else {
192            const char *invalid = no_valid_edge_between(this, get_father());
193            if (invalid) {
194                SHOW_BAD_EDGE("son-%s. father", invalid, get_father());
195                SHOW_BAD_EDGE("parent-%s. son", invalid, this);
196                valid = Validity(false, "invalid edge between son and father");
197            }
198        }
199    }
200
201    if (!is_leaf()) {
202        if (valid) valid = get_leftson()->has_valid_edges();
203        if (valid) valid = get_rightson()->has_valid_edges();
204    }
205    return valid;
206}
207
208Validity AP_tree_nlen::sequence_state_valid() const {
209    // if some node has a sequence, all son-nodes have to have sequences!
210
211    Validity valid;
212
213    const AP_combinableSeq *sequence = get_seq();
214    if (sequence) {
215        if (sequence->hasSequence()) {
216            if (!is_leaf()) {
217                bool leftson_hasSequence  = get_leftson()->hasSequence();
218                bool rightson_hasSequence = get_rightson()->hasSequence();
219
220#if defined(DUMP_INVALID_SUBTREES)
221                if (!leftson_hasSequence) dumpSubtree("left subtree has no sequence", get_leftson());
222                if (!rightson_hasSequence) dumpSubtree("right subtree has no sequence", get_rightson());
223                if (!(leftson_hasSequence && rightson_hasSequence)) {
224                    dumpSubtree("while father HAS sequence", this);
225                }
226#endif
227
228                valid = Validity(leftson_hasSequence && rightson_hasSequence, "node has sequence and son w/o sequence");
229
230#if defined(CHECK_CORRECT_INVALIDATION)
231                if (valid) {
232                    // check for missing invalidations
233                    // (if recalculating a node (via combine) does not reproduce the current sequence, it should have been invalidated)
234
235                    AP_combinableSeq *recombined             = sequence->dup();
236                    Mutations         mutations_from_combine = recombined->noncounting_combine_seq(get_leftson()->get_seq(), get_rightson()->get_seq());
237
238                    valid = Validity(recombined->combinedEquals(sequence), "recombining changed existing sequence (missing invalidation?)");
239                    if (valid) {
240                        Mutations expected_mutrate = mutations_from_combine + get_leftson()->mutations + get_rightson()->mutations;
241                        valid = Validity(expected_mutrate == mutations, "invalid mutation_rate");
242                    }
243
244                    delete recombined;
245
246#if defined(DUMP_INVALID_SUBTREES)
247                    if (!valid) {
248                        dumpSubtree(valid.why_not(), this);
249                    }
250#endif
251                }
252#endif
253            }
254        }
255#if defined(ASSERTION_USED)
256        else {
257            if (is_leaf()) ap_assert(sequence->is_bound_to_species()); // can do lazy load if needed
258        }
259#endif
260    }
261
262    if (!is_leaf()) {
263        if (valid) valid = get_leftson()->sequence_state_valid();
264        if (valid) valid = get_rightson()->sequence_state_valid();
265    }
266
267    return valid;
268}
269
270Validity AP_tree_nlen::is_valid() const {
271    ap_assert(knownNonNull(this));
272
273    Validity valid   = AP_tree::is_valid();
274    if (valid) valid = has_valid_edges();
275    if (valid) valid = sequence_state_valid();
276
277    return valid;
278}
279
280#endif // PROVIDE_TREE_STRUCTURE_TESTS
281
282// -------------------------
283//      Tree operations:
284//
285// insert
286// remove
287// swap
288// set_root
289// move
290// costs
291
292
293inline void push_all_upnode_sequences(AP_tree_nlen *nodeBelow) {
294    for  (AP_tree_nlen *upnode = nodeBelow->get_father();
295          upnode;
296          upnode = upnode->get_father())
297    {
298        ap_main->push_node(upnode, SEQUENCE);
299    }
300}
301
302inline void sortOldestFirst(AP_tree_edge **e1, AP_tree_edge **e2) {
303    if ((*e1)->Age() > (*e2)->Age()) {
304        swap(*e1, *e2);
305    }
306}
307
308inline void sortOldestFirst(AP_tree_edge **e1, AP_tree_edge **e2, AP_tree_edge **e3) {
309    sortOldestFirst(e1, e2);
310    sortOldestFirst(e2, e3);
311    sortOldestFirst(e1, e2);
312}
313
314void AP_tree_nlen::initial_insert(AP_tree_nlen *newBrother, AP_pars_root *troot) {
315    // construct initial tree from 'this' and 'newBrother'
316    // (both have to be leafs)
317
318    ap_assert(newBrother);
319    ap_assert(is_leaf());
320    ap_assert(newBrother->is_leaf());
321
322    AP_tree::initial_insert(newBrother, troot);
323    makeEdge(newBrother, this); // build the root edge
324
325    ASSERT_VALID_TREE(this->get_father());
326}
327
328void AP_tree_nlen::insert(AP_tree_nlen *newBrother) {
329    //  inserts 'this' (a new node) at the father-edge of 'newBrother'
330    ap_assert(newBrother);
331
332    ASSERT_VALID_TREE(this);
333    ASSERT_VALID_TREE(newBrother);
334
335    ap_main->push_node(this, STRUCTURE);
336    ap_main->push_node(newBrother, STRUCTURE);
337
338    AP_tree_nlen *brothersFather = newBrother->get_father();
339    if (brothersFather) {
340        ap_main->push_node(brothersFather, BOTH);
341        push_all_upnode_sequences(brothersFather);
342
343        if (brothersFather->get_father()) {
344            AP_tree_edge *oldEdge = newBrother->edgeTo(newBrother->get_father())->unlink();
345            AP_tree::insert(newBrother);
346            oldEdge->relink(get_father(), get_father()->get_father());
347        }
348        else { // insert to son of root
349            AP_tree_nlen *brothersOldBrother = newBrother->get_brother();
350            ap_main->push_node(brothersOldBrother, STRUCTURE);
351
352            AP_tree_edge *oldEdge = newBrother->edgeTo(brothersOldBrother)->unlink();
353            AP_tree::insert(newBrother);
354            oldEdge->relink(get_father(), get_father()->get_brother());
355        }
356
357        makeEdge(this, get_father());
358        makeEdge(get_father(), newBrother);
359
360        ASSERT_VALID_TREE(get_father()->get_father());
361    }
362    else { // insert at root
363        ap_assert(!newBrother->is_leaf()); // either swap 'this' and 'newBrother' or use initial_insert() to construct the initial tree
364
365        AP_tree_nlen *lson = newBrother->get_leftson();
366        AP_tree_nlen *rson = newBrother->get_rightson();
367
368        ap_main->push_node(lson, STRUCTURE);
369        ap_main->push_node(rson, STRUCTURE);
370
371        AP_tree_edge *oldEdge = lson->edgeTo(rson)->unlink();
372
373        AP_tree::insert(newBrother);
374
375        oldEdge->relink(this, newBrother);
376        makeEdge(newBrother, rson);
377        makeEdge(newBrother, lson);
378
379        ASSERT_VALID_TREE(get_father());
380    }
381}
382
383AP_tree_nlen *AP_tree_nlen::REMOVE() {
384    // Removes 'this' and its father from the tree:
385    //
386    //       grandpa                grandpa
387    //           /                    /
388    //          /                    /
389    //    father        =>        brother
390    //       /     \                                            .
391    //      /       \                                           .
392    //   this       brother
393    //
394    // One of the edges is relinked between brother and grandpa.
395    // 'father' is destroyed, 'this' is returned.
396
397    AP_tree_nlen *oldBrother = get_brother();
398
399    ASSERT_VALID_TREE(this);
400
401    ap_assert(father); // can't remove complete tree,
402
403    ap_main->push_node(this, STRUCTURE);
404    ap_main->push_node(oldBrother, STRUCTURE);
405    push_all_upnode_sequences(get_father());
406
407    AP_tree_edge *oldEdge;
408    AP_tree_nlen *grandPa = get_father()->get_father();
409    if (grandPa) {
410        ASSERT_VALID_TREE(grandPa);
411
412        ap_main->push_node(get_father(), BOTH);
413        ap_main->push_node(grandPa, STRUCTURE);
414
415        destroyEdge(edgeTo(get_father())->unlink());
416        destroyEdge(get_father()->edgeTo(oldBrother)->unlink());
417
418        if (grandPa->father) {
419            oldEdge = get_father()->edgeTo(grandPa)->unlink();
420            AP_tree::REMOVE();
421            oldEdge->relink(oldBrother, grandPa);
422        }
423        else { // remove grandson of root
424            AP_tree_nlen *uncle = get_father()->get_brother();
425            ap_main->push_node(uncle, STRUCTURE);
426
427            oldEdge = get_father()->edgeTo(uncle)->unlink();
428            AP_tree::REMOVE();
429            oldEdge->relink(oldBrother, uncle);
430        }
431        ASSERT_VALID_TREE(grandPa);
432    }
433    else {                                          // remove son of root
434        AP_tree_nlen *oldRoot = get_father();
435        ASSERT_VALID_TREE(oldRoot);
436
437        if (oldBrother->is_leaf()) {
438            //           root
439            //            oo
440            //           o  o
441            //          o    o
442            // oldBrother --- this         ----->   NULp
443            //
444            ap_main->push_node(oldRoot, ROOT);
445
446            destroyEdge(edgeTo(oldBrother)->unlink());
447
448#if defined(ASSERTION_USED)
449            AP_pars_root *troot = get_tree_root();
450#endif // ASSERTION_USED
451            AP_tree::REMOVE();
452            ap_assert(!troot->get_root_node()); // tree should have been removed
453        }
454        else {
455            //
456            //           root
457            //            oo                                                              .
458            //           o  o                                     root (=oldBrother)
459            //          o    o                                     oo                      .
460            // oldBrother --- this          ----->                o  o                     .
461            //       /\                                          o    o                    .
462            //      /  \                                     lson ----- rson
463            //     /    \                                                                .
464            //    lson  rson
465            //
466            AP_tree_nlen *lson = oldBrother->get_leftson();
467            AP_tree_nlen *rson = oldBrother->get_rightson();
468
469            ap_assert(lson && rson);
470
471            ap_main->push_node(lson, STRUCTURE);
472            ap_main->push_node(rson, STRUCTURE);
473            ap_main->push_node(oldRoot, ROOT);
474
475            destroyEdge(edgeTo(oldBrother)->unlink());
476            destroyEdge(oldBrother->edgeTo(lson)->unlink());
477
478            oldEdge = oldBrother->edgeTo(rson)->unlink();
479            AP_tree::REMOVE();
480            oldEdge->relink(lson, rson);
481
482            ap_assert(lson->get_tree_root()->get_root_node() == oldBrother);
483            ASSERT_VALID_TREE(oldBrother);
484        }
485    }
486
487    father = NULp;
488    set_tree_root(NULp);
489
490    ASSERT_VALID_TREE(this);
491    return this;
492}
493
494void AP_tree_nlen::swap_sons() {
495    ap_assert(!is_leaf()); // cannot swap sons at leafs
496
497    ap_main->push_node(this, STRUCTURE);
498    AP_tree::swap_sons();
499}
500
501void AP_tree_nlen::swap_assymetric(AP_TREE_SIDE mode) {
502    // mode AP_LEFT exchanges leftson with brother
503    // mode AP_RIGHT exchanges rightson with brother
504
505    // @@@ "NNI" works really bad for keeled groups (fixable?; #785)
506
507    ap_assert(!is_leaf());                          // cannot swap leafs
508    ap_assert(father);                              // cannot swap root (has no brother)
509    ap_assert(mode == AP_LEFT || mode == AP_RIGHT); // illegal mode
510
511    AP_tree_nlen *oldBrother = get_brother();
512    AP_tree_nlen *movedSon   = mode == AP_LEFT ? get_leftson() : get_rightson();
513
514    if (!father->father) {
515        // son of root case
516        // take leftson of brother to exchange with
517
518        if (!oldBrother->is_leaf()) { // swap needed ?
519            AP_tree_nlen *nephew = oldBrother->get_leftson();
520
521            ap_main->push_node(this, BOTH);
522            ap_main->push_node(movedSon, STRUCTURE);
523            ap_main->push_node(get_father(), SEQUENCE);
524            ap_main->push_node(nephew, STRUCTURE);
525            ap_main->push_node(oldBrother, BOTH);
526
527            AP_tree_edge *edge1 = edgeTo(movedSon)->unlink();
528            AP_tree_edge *edge2 = oldBrother->edgeTo(nephew)->unlink();
529
530            if (mode == AP_LEFT) {
531                swap(leftson->father, nephew->father);
532                swap(leftson, oldBrother->leftson);
533            }
534            else {
535                swap(rightson->father, nephew->father);
536                swap(rightson, oldBrother->leftson);
537            }
538
539            edge2->relink(this, nephew);
540            edge1->relink(oldBrother, movedSon);
541
542            if (nephew->gr.mark_sum != movedSon->gr.mark_sum) {
543                get_brother()->recalc_marked_from_sons();
544                this->recalc_marked_from_sons_and_forward_upwards();
545            }
546        }
547    }
548    else {
549        ap_main->push_node(this, BOTH);
550        ap_main->push_node(get_father(), BOTH);
551        ap_main->push_node(oldBrother, STRUCTURE);
552        ap_main->push_node(movedSon, STRUCTURE);
553
554        push_all_upnode_sequences(get_father());
555
556        AP_tree_edge *edge1 = edgeTo(movedSon)->unlink();
557        AP_tree_edge *edge2 = get_father()->edgeTo(oldBrother)->unlink();
558
559        if (mode == AP_LEFT) { // swap leftson with brother
560            swap(leftson->father, oldBrother->father);
561            if (father->leftson == this) {
562                swap(leftson, father->rightson);
563            }
564            else {
565                swap(leftson, father->leftson);
566            }
567        }
568        else { // swap rightson with brother
569            swap(rightson->father, oldBrother->father);
570            if (father->leftson == this) {
571                swap(rightson, father->rightson);
572            }
573            else {
574                swap(rightson, father->leftson);
575            }
576        }
577
578        edge2->relink(this, oldBrother);
579        edge1->relink(get_father(), movedSon);
580
581        if (oldBrother->gr.mark_sum != movedSon->gr.mark_sum) {
582            recalc_marked_from_sons_and_forward_upwards(); // father is done implicit
583        }
584    }
585}
586
587void AP_tree_nlen::set_root() {
588    if (at_root()) return; // already root
589
590    // from this to root buffer the nodes
591    ap_main->push_node(this,  STRUCTURE);
592
593    AP_tree_nlen *son_of_root = NULp; // in previous topology 'this' was contained inside 'son_of_root'
594    AP_tree_nlen *old_root    = NULp;
595    {
596        AP_tree_nlen *pntr;
597        for (pntr = get_father(); pntr->father; pntr = pntr->get_father()) {
598            ap_main->push_node(pntr, BOTH);
599            son_of_root = pntr;
600        }
601        old_root = pntr;
602    }
603
604    ap_assert(son_of_root); // always true
605
606    {
607        AP_tree_nlen *other_son_of_root = son_of_root->get_brother();
608        ap_main->push_node(other_son_of_root, STRUCTURE);
609    }
610
611    ap_main->push_node(old_root, ROOT);
612    AP_tree::set_root();
613
614    for (AP_tree_nlen *node = son_of_root; node ; node = node->get_father()) {
615        node->recalc_marked_from_sons();
616    }
617}
618
619void AP_tree_nlen::moveNextTo(AP_tree_nlen *newBrother, AP_FLOAT rel_pos) {
620    // Note: see http://bugs.arb-home.de/ticket/627#comment:8 for an experimental
621    // replacement of moveNextTo with REMOVE() + insert()
622
623    ap_assert(father);
624    ap_assert(newBrother);
625    ap_assert(newBrother->father);
626    ap_assert(newBrother->father != father); // already there
627    ap_assert(newBrother != father);         // already there
628
629    ASSERT_VALID_TREE(rootNode());
630
631    // push everything that will be modified onto stack
632    ap_main->push_node(this,  STRUCTURE);
633    ap_main->push_node(get_brother(), STRUCTURE);
634
635    if (father->father) {
636        AP_tree_nlen *grandpa = get_father()->get_father();
637
638        ap_main->push_node(get_father(), BOTH);
639
640        if (grandpa->father) {
641            ap_main->push_node(grandpa, BOTH);
642            push_all_upnode_sequences(grandpa);
643        }
644        else { // 'this' is grandson of root
645            ap_main->push_node(grandpa, ROOT);
646            ap_main->push_node(get_father()->get_brother(), STRUCTURE);
647        }
648    }
649    else { // 'this' is son of root
650        ap_main->push_node(get_father(), ROOT);
651
652        if (!get_brother()->is_leaf()) {
653            ap_main->push_node(get_brother()->get_leftson(), STRUCTURE);
654            ap_main->push_node(get_brother()->get_rightson(), STRUCTURE);
655        }
656    }
657
658    ap_main->push_node(newBrother,  STRUCTURE);
659    if (newBrother->father) {
660        AP_tree_nlen *newBrothersFather = newBrother->get_father();
661        ap_main->push_node(newBrothersFather, BOTH);
662        if (!newBrothersFather->father) { // move to son of root
663            ap_main->push_node(newBrother->get_brother(), STRUCTURE);
664        }
665        push_all_upnode_sequences(newBrothersFather);
666    }
667
668    AP_tree_nlen *thisFather        = get_father();
669    AP_tree_nlen *grandFather       = thisFather->get_father();
670    AP_tree_nlen *oldBrother        = get_brother();
671    AP_tree_nlen *newBrothersFather = newBrother->get_father();
672    AP_tree_edge *e1, *e2, *e3;
673
674    if (thisFather==newBrothersFather->get_father()) { // son -> son of brother
675        if (grandFather) {
676            if (grandFather->get_father()) {
677                // covered by test at PARS_main.cxx@COVER3
678                thisFather->unlinkAllEdges(&e1, &e2, &e3);
679                AP_tree_edge *e4 = newBrother->edgeTo(oldBrother)->unlink();
680
681                AP_tree::moveNextTo(newBrother, rel_pos);
682
683                sortOldestFirst(&e1, &e2, &e3);
684                e1->relink(oldBrother, grandFather); // use oldest edge at remove position
685                thisFather->linkAllEdges(e2, e3, e4);
686            }
687            else { // grandson of root -> son of brother
688                // covered by test at PARS_main.cxx@COVER2
689                AP_tree_nlen *uncle = thisFather->get_brother();
690
691                thisFather->unlinkAllEdges(&e1, &e2, &e3);
692                AP_tree_edge *e4 = newBrother->edgeTo(oldBrother)->unlink();
693
694                AP_tree::moveNextTo(newBrother, rel_pos);
695
696                sortOldestFirst(&e1, &e2, &e3);
697                e1->relink(oldBrother, uncle);
698                thisFather->linkAllEdges(e2, e3, e4);
699            }
700        }
701        else { // son of root -> grandson of root
702            // covered by test at PARS_main.cxx@COVER1
703            oldBrother->unlinkAllEdges(&e1, &e2, &e3);
704            AP_tree::moveNextTo(newBrother, rel_pos);
705            thisFather->linkAllEdges(e1, e2, e3);
706        }
707    }
708    else if (grandFather==newBrothersFather) { // son -> brother of father
709        if (grandFather->father) {
710            // covered by test at PARS_main.cxx@COVER4
711            thisFather->unlinkAllEdges(&e1, &e2, &e3);
712            AP_tree_edge *e4 = grandFather->edgeTo(newBrother)->unlink();
713
714            AP_tree::moveNextTo(newBrother, rel_pos);
715
716            sortOldestFirst(&e1, &e2, &e3);
717            e1->relink(oldBrother, grandFather);
718            thisFather->linkAllEdges(e2, e3, e4);
719        }
720        else { // no edges change if we move grandson of root -> son of root
721            AP_tree::moveNextTo(newBrother, rel_pos);
722        }
723    }
724    else {
725        //  now we are sure, the minimal distance
726        //  between 'this' and 'newBrother' is 4 edges
727        //  or if the root-edge is between them, the
728        //  minimal distance is 3 edges
729
730        if (!grandFather) { // son of root
731            oldBrother->unlinkAllEdges(&e1, &e2, &e3);
732            AP_tree_edge *e4 = newBrother->edgeTo(newBrothersFather)->unlink();
733
734            AP_tree::moveNextTo(newBrother, rel_pos);
735
736            sortOldestFirst(&e1, &e2, &e3);
737            e1->relink(oldBrother->get_leftson(), oldBrother->get_rightson()); // new root-edge
738            thisFather->linkAllEdges(e2, e3, e4);   // old root
739        }
740        else if (!grandFather->get_father()) { // grandson of root
741            if (!newBrothersFather->get_father()->get_father()) { // grandson of root -> grandson of root
742                thisFather->unlinkAllEdges(&e1, &e2, &e3);
743                AP_tree_edge *e4 = newBrother->edgeTo(newBrothersFather)->unlink();
744
745                AP_tree::moveNextTo(newBrother, rel_pos);
746
747                sortOldestFirst(&e1, &e2, &e3);
748                e1->relink(oldBrother, newBrothersFather);  // new root-edge
749                thisFather->linkAllEdges(e2, e3, e4);
750            }
751            else {
752                AP_tree_nlen *uncle = thisFather->get_brother();
753
754                thisFather->unlinkAllEdges(&e1, &e2, &e3);
755                AP_tree_edge *e4 = newBrother->edgeTo(newBrothersFather)->unlink();
756
757                AP_tree::moveNextTo(newBrother, rel_pos);
758
759                sortOldestFirst(&e1, &e2, &e3);
760                e1->relink(oldBrother, uncle);
761                thisFather->linkAllEdges(e2, e3, e4);
762            }
763        }
764        else {
765            if (!newBrothersFather->get_father()) { // move to son of root
766                AP_tree_nlen *newBrothersBrother = newBrother->get_brother();
767
768                thisFather->unlinkAllEdges(&e1, &e2, &e3);
769                AP_tree_edge *e4 = newBrother->edgeTo(newBrothersBrother)->unlink();
770
771                AP_tree::moveNextTo(newBrother, rel_pos);
772
773                sortOldestFirst(&e1, &e2, &e3);
774                e1->relink(oldBrother, grandFather);
775                thisFather->linkAllEdges(e2, e3, e4);
776            }
777            else { // simple independent move
778                thisFather->unlinkAllEdges(&e1, &e2, &e3);
779                AP_tree_edge *e4 = newBrother->edgeTo(newBrothersFather)->unlink();
780
781                AP_tree::moveNextTo(newBrother, rel_pos);
782
783                sortOldestFirst(&e1, &e2, &e3);
784                e1->relink(oldBrother, grandFather);
785                thisFather->linkAllEdges(e2, e3, e4);
786            }
787        }
788    }
789
790    ASSERT_VALID_TREE(this);
791    ASSERT_VALID_TREE(rootNode());
792
793    ap_assert(is_leftson());
794    ap_assert(get_brother() == newBrother);
795}
796
797void AP_tree_nlen::unhash_sequence() {
798    /*! removes the parsimony sequence from an inner node
799     * (has no effect for leafs)
800     */
801
802    AP_sequence *sequence = get_seq();
803    if (sequence && !is_leaf()) sequence->forget_sequence();
804}
805
806bool AP_tree_nlen::acceptCurrentState(Level frame_level) {
807    // returns
808    // - true           if the top state has been removed
809    // - false          if the top state was kept/extended for possible revert at lower frame_level
810
811    if (remembered_for_frame != frame_level) {
812        ap_assert(0); // internal control number check failed
813        return false;
814    }
815
816    NodeState *state   = states.pop();
817    bool       removed = true;
818
819    Level next_frame_level   = frame_level-1;
820    Level stored_frame_level = state->frameNr;
821
822    if (!next_frame_level) { // accept() called at top-level
823        delete state;
824    }
825    else if (stored_frame_level == next_frame_level) {
826        // node already is buffered for next_frame_level
827
828        // if the currently accepted state->mode is not completely covered by previous state->mode
829        // => a future revert() would only restore partially
830        // To avoid that, move missing state information to previous NodeState
831        {
832            NodeState     *prev_state = states.top();
833            AP_STACK_MODE  prev_mode  = prev_state->mode;
834            AP_STACK_MODE  common     = AP_STACK_MODE(prev_mode & state->mode);
835
836            if (common != state->mode) {
837                AP_STACK_MODE missing = AP_STACK_MODE(state->mode & ~common); // previous is missing this state information
838
839                ap_assert((prev_mode&missing) == NOTHING);
840                state->move_info_to(*prev_state, missing);
841            }
842        }
843
844        delete state;
845    }
846    else {
847        // keep state for future revert
848        states.push(state);
849        removed = false;
850    }
851    remembered_for_frame = next_frame_level;
852
853    return removed;
854}
855
856
857bool AP_tree_nlen::rememberState(AP_STACK_MODE mode, Level frame_level) {
858    // according to mode
859    // tree_structure or sequence is buffered in the node
860
861    NodeState *store;
862    bool       ret;
863
864    if (is_leaf() && !(STRUCTURE & mode)) return false;    // tips push only structure
865
866    if (remembered_for_frame == frame_level) { // node already has a push (at current frame_level)
867        NodeState *is_stored = states.top();
868
869        if (0 == (mode & ~is_stored->mode)) { // already buffered
870            AP_sequence *sequence = get_seq();
871            if (sequence && (mode & SEQUENCE)) sequence->forget_sequence();
872            return false;
873        }
874        store = is_stored;
875        ret = false;
876    }
877    else { // first push for this node (in current stack frame)
878        store = new NodeState(remembered_for_frame);
879        states.push(store);
880
881        remembered_for_frame = frame_level;
882        ret                  = true;
883    }
884
885    if ((mode & (STRUCTURE|SEQUENCE)) && !(store->mode & (STRUCTURE|SEQUENCE))) {
886        store->mark_sum = gr.mark_sum;
887    }
888    if ((mode & STRUCTURE) && !(store->mode & STRUCTURE)) {
889        store->father    = get_father();
890        store->leftson   = get_leftson();
891        store->rightson  = get_rightson();
892        store->leftlen   = leftlen;
893        store->rightlen  = rightlen;
894        store->root      = get_tree_root();
895        store->gb_node   = gb_node;
896        store->keelState = keeledStateInfo();
897
898        for (int e=0; e<3; e++) {
899            store->edge[e]      = edge[e];
900            store->edgeIndex[e] = index[e];
901        }
902    }
903
904    if (mode & SEQUENCE) {
905        ap_assert(!is_leaf()); // only allowed to push SEQUENCE for inner nodes
906        if (!(store->mode & SEQUENCE)) {
907            AP_sequence *sequence = take_seq();
908            store->sequence       = sequence;
909            store->mutations      = mutations;
910            mutations             = 0;
911        }
912        else {
913            AP_sequence *sequence = get_seq();
914            if (sequence) sequence->forget_sequence();
915        }
916    }
917
918    store->mode = (AP_STACK_MODE)(store->mode|mode);
919
920    return ret;
921}
922
923void NodeState::move_info_to(NodeState& target, AP_STACK_MODE what) {
924    // rescue partial NodeState information
925
926    ap_assert((mode&what)        == what); // this has to contain 'what' is moved
927    ap_assert((target.mode&what) == NOTHING); // target shall not already contain 'what' is moved
928
929    if ((what & (STRUCTURE|SEQUENCE)) && !(target.mode & (STRUCTURE|SEQUENCE))) {
930        target.mark_sum = mark_sum;
931    }
932    if (what & STRUCTURE) {
933        target.father    = father;
934        target.leftson   = leftson;
935        target.rightson  = rightson;
936        target.leftlen   = leftlen;
937        target.rightlen  = rightlen;
938        target.root      = root;
939        target.gb_node   = gb_node;
940        target.keelState = keelState;
941
942        for (int e=0; e<3; e++) {
943            target.edge[e]      = edge[e];
944            target.edgeIndex[e] = edgeIndex[e];
945        }
946    }
947    if (what & SEQUENCE) {
948        target.sequence  = sequence;
949        target.mutations = mutations;
950        sequence         = NULp;
951
952    }
953    // nothing needs to be done for ROOT
954    target.mode = AP_STACK_MODE(target.mode|what);
955}
956
957void AP_tree_nlen::restore_structure(const NodeState& state) {
958    father   = state.father;
959    leftson  = state.leftson;
960    rightson = state.rightson;
961    leftlen  = state.leftlen;
962    rightlen = state.rightlen;
963    set_tree_root(state.root);
964    gb_node  = state.gb_node;
965    setKeeledState(state.keelState);
966
967    gr.mark_sum = state.mark_sum;
968
969    for (int e=0; e<3; e++) {
970        edge[e]  = state.edge[e];
971        index[e] = state.edgeIndex[e];
972        if (edge[e]) {
973            edge[e]->index[index[e]] = e;
974            edge[e]->node[index[e]]  = this;
975        }
976    }
977}
978void AP_tree_nlen::restore_sequence(NodeState& state) {
979    replace_seq(state.sequence);
980    state.sequence = NULp;
981    mutations      = state.mutations;
982    gr.mark_sum    = state.mark_sum;
983}
984void AP_tree_nlen::restore_sequence_nondestructive(const NodeState& state) {
985    replace_seq(state.sequence ? state.sequence->dup() : NULp);
986    mutations = state.mutations;
987}
988void AP_tree_nlen::restore_root(const NodeState& state) {
989    state.root->change_root(state.root->get_root_node(), this);
990}
991
992void AP_tree_nlen::restore(NodeState& state) {
993    //! restore 'this' from NodeState (cheap; only call once for each 'state')
994    AP_STACK_MODE mode = state.mode;
995    if (mode&STRUCTURE) restore_structure(state);
996    if (mode&SEQUENCE) restore_sequence(state);
997    if (ROOT==mode) restore_root(state);
998}
999void AP_tree_nlen::restore_nondestructive(const NodeState& state) {
1000    //! restore 'this' from NodeState (expensive; may be called multiple times for each 'state')
1001    AP_STACK_MODE mode = state.mode;
1002    if (mode&STRUCTURE) restore_structure(state);
1003    if (mode&SEQUENCE) restore_sequence_nondestructive(state);
1004    if (ROOT==mode) restore_root(state);
1005}
1006
1007void AP_tree_nlen::revertToPreviousState(Level IF_ASSERTION_USED(curr_frameLevel), bool& IF_ASSERTION_USED(rootPopped)) { // pop old tree costs
1008    ap_assert(remembered_for_frame == curr_frameLevel); // error in node stack (node wasnt remembered in current frame!)
1009
1010    NodeState *previous = states.pop();
1011#if defined(ASSERTION_USED)
1012    if (previous->mode == ROOT) { // @@@ remove test code later
1013        ap_assert(!rootPopped); // only allowed once
1014        rootPopped = true;
1015    }
1016#endif
1017    restore(*previous);
1018
1019    remembered_for_frame = previous->frameNr;
1020    delete previous;
1021}
1022
1023void AP_tree_nlen::parsimony_rec(char *mutPerSite) {
1024    AP_combinableSeq *sequence = get_seq();
1025
1026    if (is_leaf()) {
1027        ap_assert(sequence); // tree w/o aliview?
1028        sequence->ensure_sequence_loaded();
1029    }
1030    else {
1031        if (!sequence) {
1032            sequence = set_seq(get_tree_root()->get_seqTemplate()->dup());
1033            ap_assert(sequence);
1034        }
1035
1036        if (!sequence->hasSequence()) {
1037            AP_tree_nlen *lson = get_leftson();
1038            AP_tree_nlen *rson = get_rightson();
1039
1040            ap_assert(lson);
1041            ap_assert(rson);
1042
1043            lson->parsimony_rec(mutPerSite);
1044            rson->parsimony_rec(mutPerSite);
1045
1046            AP_combinableSeq *lseq = lson->get_seq();
1047            AP_combinableSeq *rseq = rson->get_seq();
1048
1049            ap_assert(lseq);
1050            ap_assert(rseq);
1051
1052            Mutations mutations_for_combine = sequence->combine_seq(lseq, rseq, mutPerSite);
1053            mutations                   = lson->mutations + rson->mutations + mutations_for_combine;
1054        }
1055    }
1056}
1057
1058Mutations AP_tree_nlen::costs(char *mutPerSite) {
1059    // returns costs of a tree ( = number of mutations)
1060
1061    ap_assert(get_tree_root()->get_seqTemplate());  // forgot to set_seqTemplate() ?  (previously returned 0.0 in this case)
1062    ap_assert(sequence_state_valid());
1063
1064    parsimony_rec(mutPerSite);
1065    return mutations;
1066}
1067
1068Mutations AP_tree_nlen::nn_interchange_rec(EdgeSpec whichEdges, AP_BL_MODE mode) {
1069    if (!father) {
1070        return rootEdge()->nni_rec(whichEdges, mode, NULp, true);
1071    }
1072    if (!father->father) {
1073        AP_tree_edge *e = rootEdge();
1074        return e->nni_rec(whichEdges, mode, e->otherNode(this), false);
1075    }
1076    return edgeTo(get_father())->nni_rec(whichEdges, mode, get_father(), false);
1077}
1078
1079CONSTEXPR_INLINE AP_TREE_SIDE idx2side(const int idx) {
1080    return idx&1 ? AP_RIGHT : AP_LEFT;
1081}
1082
1083bool AP_tree_edge::kl_rec(const KL_params& KL, const int rec_depth, Mutations pars_best) {
1084    /*! does K.L. recursion
1085     * @param KL                parameters defining how recursion is done
1086     * @param rec_depth         current recursion depth (starts with 0)
1087     * @param pars_best         current parsimony value of topology
1088     */
1089
1090    ap_assert(!is_leaf_edge());
1091    if (rec_depth >= KL.max_rec_depth) return false;
1092
1093    ap_assert(implicated(rec_depth>0, kl_visited));
1094
1095    int           order[8];
1096    AP_tree_edge *descend[8];
1097
1098    {
1099        if (rec_depth == 0) {
1100            descend[0] = this;
1101            descend[2] = NULp;
1102            descend[4] = NULp;
1103            descend[6] = NULp;
1104        }
1105        else {
1106            AP_tree_nlen *son    = sonNode();
1107            AP_tree_nlen *notSon = otherNode(son); // brother or father
1108
1109            descend[0] = notSon->nextEdge(this);
1110            descend[2] = notSon->nextEdge(descend[0]);
1111
1112            ap_assert(descend[2] != this);
1113
1114            descend[4] = son->nextEdge(this);
1115            descend[6] = son->nextEdge(descend[4]);
1116
1117            ap_assert(descend[6] != this);
1118        }
1119
1120        descend[1] = descend[0];
1121        descend[3] = descend[2];
1122        descend[5] = descend[4];
1123        descend[7] = descend[6];
1124    }
1125
1126    // ---------------------------------
1127    //      detect parsimony values
1128
1129    ap_main->remember(); // @@@ i think this is unneeded. better reset root after all done in caller
1130    set_root();
1131    rootNode()->costs();
1132
1133    int rec_width_dynamic = 0;
1134    int visited_subtrees  = 0;
1135    int better_subtrees   = 0;
1136
1137    Mutations pars[8]; // eight parsimony values (produced by 2*swap_assymetric at each adjacent edge)
1138
1139#if defined(ASSERTION_USED)
1140    int forbidden_descends = 0;
1141#endif
1142    {
1143        AP_FLOAT schwellwert = KL.thresFunctor.calculate(rec_depth); // @@@ skip if not needed
1144        for (int i = 0; i < 8; i++) {
1145            order[i] = i;
1146            AP_tree_edge * const subedge = descend[i];
1147
1148            if (subedge                  &&
1149                !subedge->is_leaf_edge() &&
1150                !subedge->kl_visited     &&
1151                (!KL.stopAtFoldedGroups || !subedge->next_to_folded_group())
1152                )
1153            {
1154                ap_main->remember();
1155                subedge->sonNode()->swap_assymetric(idx2side(i));
1156                pars[i] = rootNode()->costs();
1157                if (pars[i] < pars_best) {
1158                    better_subtrees++;
1159                    pars_best = pars[i]; // @@@ do not overwrite yet; store and overwrite when done with this loop
1160                }
1161                if (pars[i] < schwellwert) {
1162                    rec_width_dynamic++;
1163                }
1164                ap_main->revert();
1165                visited_subtrees++;
1166            }
1167            else {
1168                pars[i] = -1;
1169#if defined(ASSERTION_USED)
1170                if (subedge && subedge->kl_visited) {
1171                    forbidden_descends++;
1172                }
1173#endif
1174            }
1175        }
1176    }
1177
1178    // bubblesort pars[]+order[], such that pars[0] contains best (=smallest) parsimony value
1179    {
1180        for (int i=7, t=0; t<i; t++) { // move negative (=unused) parsimony values to the end
1181            if (pars[t] <0) {
1182                pars[t]  = pars[i];
1183                order[t] = i;
1184                t--;
1185                i--;
1186            }
1187        }
1188
1189        for (int t = visited_subtrees - 1; t > 0; t--) {
1190            bool bubbled = false;
1191            for (int i = 0; i < t; i++) {
1192                if (pars[i] > pars[i+1]) {
1193                    std::swap(order[i], order[i+1]);
1194                    std::swap(pars[i],  pars[i+1]);
1195                    bubbled = true;
1196                }
1197            }
1198            if (!bubbled) break;
1199        }
1200    }
1201
1202#if defined(ASSERTION_USED)
1203    // rec_depth == 0 (called with start-node)
1204    // rec_depth == 1 (called twice with start-node (swap_assymetric AP_LEFT + AP_RIGHT))
1205    // rec_depth == 2 (called twice with each adjacent node -> 8 calls)
1206    // rec_depth == 3 (called twice with each adjacent node, but not with those were recursion came from -> 6 calls)
1207
1208    if (!is_root_edge()) {
1209        switch (rec_depth) {
1210            case 0:
1211                ap_assert(visited_subtrees == 2);
1212                ap_assert(forbidden_descends == 0);
1213                break;
1214            case 1:
1215                ap_assert(visited_subtrees <= 8);
1216                ap_assert(forbidden_descends == 0);
1217                break;
1218            default:
1219                ap_assert(visited_subtrees <= 6);
1220                ap_assert(forbidden_descends == 2);
1221                break;
1222        }
1223    }
1224    else { // at root
1225        switch (rec_depth) {
1226            case 0:
1227                ap_assert(visited_subtrees <= 2);
1228                break;
1229            case 1:
1230                ap_assert(visited_subtrees <= 8);
1231                ap_assert(forbidden_descends <= 2); // in case of subtree-optimization, 2 descends may be forbidden
1232                break;
1233            default:
1234                ap_assert(visited_subtrees <= 8);
1235                break;
1236        }
1237    }
1238#endif
1239
1240    int rec_width;
1241    if (better_subtrees) {
1242        rec_width = better_subtrees; // @@@ wrong if static/dynamic reduction would allow more
1243
1244        // @@@ IMO the whole concept of incrementing depth when a better topology was found has no positive effect
1245        // (the better topology is kept anyway and next recursive KL will do a full optimization starting from that edge as well)
1246
1247    }
1248    else {
1249        rec_width = visited_subtrees;
1250        if (KL.rec_type & AP_STATIC) {
1251            int rec_width_static = (rec_depth < CUSTOM_DEPTHS) ? KL.rec_width[rec_depth] : 1;
1252            rec_width            = std::min(rec_width, rec_width_static);
1253        }
1254        if (KL.rec_type & AP_DYNAMIK) {
1255            rec_width = std::min(rec_width, rec_width_dynamic);
1256        }
1257    }
1258    ap_assert(rec_width<=visited_subtrees);
1259
1260    bool found_better = false;
1261    for (int i=0; i<rec_width && !found_better; i++) {
1262        AP_tree_edge * const subedge = descend[order[i]];
1263
1264        ap_main->remember();
1265        subedge->kl_visited = true; // mark
1266        subedge->sonNode()->swap_assymetric(idx2side(order[i])); // swap
1267        rootNode()->parsimony_rec();
1268
1269        if (better_subtrees) {
1270            KL_params modified      = KL;
1271            modified.rec_type       = AP_STATIC;
1272            modified.max_rec_depth += KL.inc_rec_depth;
1273
1274            subedge->kl_rec(modified, rec_depth+1, pars_best);
1275            found_better = true;
1276        }
1277        else {
1278            found_better = subedge->kl_rec(KL, rec_depth+1, pars_best);
1279        }
1280
1281        subedge->kl_visited = false;      // unmark
1282        ap_main->accept_if(found_better); // revert
1283    }
1284
1285    ap_main->accept_if(found_better); // undo set_root otherwise
1286    return found_better;
1287}
1288
1289void AP_tree_nlen::exchange(AP_tree_nlen *other) {
1290    // exchange 'this' with other
1291    // 'this' has to be in tree; other has to be a "single node"
1292    //
1293    // Used by quick-add.
1294
1295    AP_tree_root *root = get_tree_root();
1296    ap_assert(root);
1297    ap_assert(!other->get_tree_root());
1298
1299    ASSERT_VALID_TREE(rootNode());
1300    ASSERT_VALID_TREE(other);
1301
1302    ap_main->push_node(this, STRUCTURE);
1303    ap_main->push_node(other, STRUCTURE);
1304    ap_main->push_node(get_father(), BOTH);
1305    push_all_upnode_sequences(get_father());
1306
1307    AP_tree_edge *myEdge    = nextEdge(NULp);
1308    AP_tree_nlen *connected = myEdge->otherNode(this);
1309    myEdge->unlink();
1310
1311    if (is_leftson()) {
1312        father->leftson = other;
1313    }
1314    else {
1315        father->rightson = other;
1316    }
1317    other->father = father;
1318    father        = NULp;
1319
1320    other->set_tree_root(root);
1321    set_tree_root(NULp);
1322
1323    myEdge->relink(other, connected);
1324
1325    ASSERT_VALID_TREE(rootNode());
1326    ASSERT_VALID_TREE(this);
1327}
1328
1329const char* AP_tree_nlen::sortByName() {
1330    if (name) return name;  // leafs
1331
1332    const char *n1 = get_leftson()->sortByName();
1333    const char *n2 = get_rightson()->sortByName();
1334
1335    if (strcmp(n1, n2)<0) return n1;
1336
1337    AP_tree::swap_sons();
1338
1339    return n2;
1340}
1341
1342const char *AP_tree_nlen::fullname() const {
1343    if (!name) {
1344        static char *buffer;
1345        char        *lName = ARB_strdup(get_leftson()->fullname());
1346        char        *rName = ARB_strdup(get_rightson()->fullname());
1347        int          len   = strlen(lName)+strlen(rName)+4;
1348
1349        if (buffer) free(buffer);
1350
1351        ARB_alloc(buffer, len);
1352
1353        strcpy(buffer, "[");
1354        strcat(buffer, lName);
1355        strcat(buffer, ",");
1356        strcat(buffer, rName);
1357        strcat(buffer, "]");
1358
1359        free(lName);
1360        free(rName);
1361
1362        return buffer;
1363    }
1364
1365    return name;
1366}
1367
1368
1369char* AP_tree_nlen::getSequenceCopy() {
1370    costs();
1371
1372    AP_sequence_parsimony *pseq = DOWNCAST(AP_sequence_parsimony*, get_seq());
1373    ap_assert(pseq->hasSequence());
1374
1375    size_t  len = pseq->get_sequence_length();
1376    char   *s   = new char[len];
1377    memcpy(s, pseq->get_sequence(), len);
1378
1379    return s;
1380}
1381
1382
1383GB_ERROR AP_pars_root::saveToDB() {
1384    has_been_saved = true;
1385    return AP_tree_root::saveToDB();
1386}
1387
Note: See TracBrowser for help on using the repository browser.