void mfl_reroot_subtree(node *n, node *atip, node *subtr, node *base, node *up, node *dn, tree *swapingon, tree **savedtrees, int ntax, int nchar, int numnodes, mfl_searchrec *searchrec, int diff) { /* Traverses the subtree and re-roots it at each branch in preorder and then * calls regrafting traversal (same as used in SPR).*/ if (searchrec->success) { return; } mfl_join_nodes(base->next->next, n->edge); mfl_join_nodes(base->next, n); // Reoptimize the subtree base mfl_reopt_subtr_root(base, nchar); if (!base->next->edge->origbase && !base->next->next->edge->origbase) { up->visited = 0; dn->visited = 0; } mfl_regrafting_traversal(up, subtr, swapingon, savedtrees, ntax, nchar, numnodes, searchrec, diff); if (searchrec->success) { up->visited = 1; dn->visited = 1; base->skip = true; return; } mfl_regrafting_traversal(dn, subtr, swapingon, savedtrees, ntax, nchar, numnodes, searchrec, diff); up->visited = 1; dn->visited = 1; base->skip = true; if (searchrec->success) { return; } // Remove the base mfl_join_nodes(base->next->edge, base->next->next->edge); if (n->tip) { return; } mfl_reroot_subtree(n->next->edge, atip, subtr, base, up, dn, swapingon, savedtrees, ntax, nchar, numnodes, searchrec, diff); if (searchrec->success) { return; } mfl_reroot_subtree(n->next->next->edge, atip, subtr, base, up, dn, swapingon, savedtrees, ntax, nchar, numnodes, searchrec, diff); }
void mfl_insert_branch(node *br, node *target, int ntax) { // Inserts a branch with a ring base into another branch node *br1, *br2, *tdesc; tdesc = target->edge; if (br->tip) { br1 = br->edge->next; br2 = br1->next; } else { br1 = mfl_seek_ringnode(br, ntax); br2 = mfl_seek_ringnode(br1->next, ntax); } if (br1->edge || br2->edge) { dbg_printf("Error in branch insertion\n"); return; } mfl_join_nodes(br1, target); mfl_join_nodes(br2, tdesc); }
struct node * cpyfromNWK(char *nwktr, int nwklen, int ntax, int numnodes, int *pos, nodearray nds, bool isRooted) { int i, tipnum; char tipbuf[10]; node *n, *nlst, *p; n = mfl_seek_internal(ntax - 1, numnodes, nds); n->initialized = 1; nlst = n; do { *pos = *pos + 1; if (nwktr[*pos] == ')') { nlst->next = n; return n; } if (isdigit(nwktr[*pos])) { for (i = 0; nwktr[*pos] != ',' && nwktr[*pos] != ')'; ++i, ++*pos) { tipbuf[i] = nwktr[*pos]; } tipbuf[i] = '\0'; tipnum = atoi(tipbuf); nlst->next = mfl_allocnode(); nlst = nlst->next; mfl_join_nodes(nds[tipnum - 1], nlst); if (nwktr[*pos] == ')') { nlst->next = n; mfl_set_ring_to_n(n); return n; } } if (nwktr[*pos] == '(') { nlst->next = mfl_allocnode(); nlst = nlst->next; p = cpyfromNWK(nwktr, nwklen, ntax, numnodes, pos, nds, isRooted); mfl_join_nodes(p, nlst); } } while (nwktr[*pos]); nlst->next = n; return n; }
tree *mfl_addseq_randasis(int ntax, int nchar, int numnodes, charstate *tipdata, bool addRandom, tree **savedtrees) { int i, nbeslen = 0; int *bestlen = &nbeslen; int *taxarray; node *p, *bestpos; tree *newtree = mfl_alloc_noring(ntax, numnodes); taxarray = (int*)malloc(ntax * sizeof(int)); memset(taxarray, 0, ntax * sizeof(int)); // This is to see if I can fix the problem mfl_init_taxarray(taxarray, ntax); if (addRandom) { dbg_printf("Joining taxa by random addition sequence\n"); mfl_shuffle(taxarray, ntax); } else { dbg_printf("Joining taxa according to order in matrix\n"); } p = newtree->trnodes[ntax + 1]; mfl_newring(p, ntax); i = 0; do { mfl_join_nodes(newtree->trnodes[taxarray[i] - 1], p); p = p->next; ++i; } while (p != newtree->trnodes[ntax + 1]); mfl_temproot(newtree, taxarray[0] - 1, ntax); newtree->length = *bestlen; bestpos = newtree->trnodes[taxarray[0] - 1]; for (i = 3; i < ntax; ++i) { mfl_newring(newtree->trnodes[ntax + i - 1], ntax); mfl_join_nodes(newtree->trnodes[taxarray[i] - 1], newtree->trnodes[ntax + i - 1]->next); mfl_insert_branch(newtree->trnodes[taxarray[i] - 1], newtree->trnodes[taxarray[0] - 1], ntax); *bestlen = mfl_get_sttreelen(newtree, tipdata, ntax, nchar, bestlen); //dbg_printf("Preliminary length: %i\n", *bestlen); mfl_remove_branch(newtree->trnodes[taxarray[i] - 1]); bestpos = mfl_tryall(newtree->root, newtree->trnodes[taxarray[i] - 1], bestpos, ntax, nchar, numnodes, bestlen, newtree, savedtrees, tipdata); //Join the nodes// mfl_insert_branch(newtree->trnodes[taxarray[i] - 1], bestpos, ntax); *bestlen = 0; } mfl_undo_temproot(ntax, newtree); //newtree->bipartitions = mfl_tree_biparts(newtree, ntax, numnodes); free(taxarray); return newtree; }
struct tree *randunrooted(int ntax, int numnodes) { /* Returns a random unrooted tree*/ int i; int *taxarray; node *p, *q; tree *randtree; taxarray =(int*) malloc(ntax * sizeof(int)); mfl_init_taxarray(taxarray, ntax); mfl_shuffle(taxarray, ntax); randtree = mfl_alloctree(ntax, numnodes); randtree->trnodes[0]->start = true; randtree->trnodes[0]->edge = randtree->trnodes[taxarray[0]]; // Join all the internal nodes (except the root) together for (i = 1; i <= (ntax - 3); ++i) { p = randtree->trnodes[ntax + i]->next->next; q = randtree->trnodes[ntax + i + 1]; mfl_join_nodes(p, q); } // Add all the tips to the appropriate internal nodes mfl_join_nodes(randtree->trnodes[ntax + 1], randtree->trnodes[taxarray[0] - 1]); for (i = 1; i < ntax - 1; ++i) { randtree->trnodes[taxarray[i] - 1]->edge = randtree->trnodes[ntax + i]->next; randtree->trnodes[ntax + i]->next->edge = randtree->trnodes[taxarray[i] - 1]; } randtree->trnodes[2 * ntax - 2]->next->next->edge = randtree->trnodes[taxarray[i] - 1]; randtree->trnodes[taxarray[i] - 1]->edge = randtree->trnodes[2 * ntax - 2]->next->next; free(taxarray); /*printNewick(randtree->trnodes[0]);*/ dbg_printf(";\n"); return (randtree); }
void mfl_remove_branch(node *n) { node *p, *q, *nb; nb = n->edge; p = nb->next->edge; q = nb->next->next->edge; nb->next->edge = NULL; nb->next->next->edge = NULL; mfl_join_nodes(p, q); }
void mfl_bisection_traversal(node *n, tree *swapingon, tree **savedtrees, int ntax, int nchar, int numnodes, mfl_searchrec *searchrec) { /* Traverses a binary tree clipping out a subtree in postorder and passing * a pointer to the subtree to mfl_reroot_subtree. */ int i, diff, *srcchanging, *tgtchanging; node *p, *q, *src, *tgt, *s_dn, *s_up, *t_dn, *t_up, *t_dn_N, *t_up_N; node *s_dn_N, *s_up_N, *atip; nodearray nds = swapingon->trnodes; mfl_undone_tree(swapingon->trnodes, numnodes); for (i = ntax + 1; i < numnodes; ++i) { p = nds[i]; q = nds[i]; do { src = p->edge; tgt = p; src->done = true; if (!tgt->done) { if (!src->skip) { src->skip = true; if (src->tip) { memcpy(src->apomorphies, src->tempapos, nchar * sizeof(charstate)); } else { mfl_set_updown(src, &s_up, &s_dn); s_up_N = s_up->edge; s_dn_N = s_dn->edge; if (src->tocalcroot) { srcchanging = mfl_get_subtr_changing(src, NULL, NULL, nchar); mfl_reopt_subtr(src, swapingon, nchar, numnodes, srcchanging); free(srcchanging); } else { if (src->next->edge->tip && src->next->next->edge->tip) { mfl_set_rootstates(src, nchar, NULL); } else { srcchanging = mfl_get_tgt_changing(s_dn->edge, s_up, s_dn, nchar); mfl_join_nodes(s_dn, s_up); mfl_partial_downpass(s_dn, swapingon, numnodes, ntax, nchar, srcchanging); mfl_join_nodes(s_up_N, s_up); mfl_join_nodes(s_dn_N, s_dn); mfl_reopt_subtr_root(src, nchar); free(srcchanging); } } } mfl_set_updown(tgt, &t_up, &t_dn); t_up_N = t_up->edge; t_dn_N = t_dn->edge; if (!tgt->tocalcroot) { tgtchanging = mfl_get_tgt_changing(t_dn->edge, t_up, t_dn, nchar); // Pop out redundant node: mfl_join_nodes(t_up, t_dn); mfl_partial_downpass(t_dn, swapingon, numnodes, ntax, nchar, tgtchanging); free(tgtchanging); } else { tgtchanging = mfl_get_subtr_changing(tgt, NULL, NULL, nchar); tgt->isroot = true; mfl_reopt_subtr(tgt, swapingon, nchar, numnodes, tgtchanging); tgt->isroot = false; free(tgtchanging); // Pop out the redundant node: mfl_join_nodes(t_up, t_dn); } diff = mfl_subtr_reinsertion(src, t_up, t_dn, nchar); t_up->visited = true; t_dn->visited = true; if (mfl_subtr_isrerootable(src)) { atip = mfl_find_atip(src); mfl_join_nodes(s_up, s_dn); s_up->origbase = true; s_dn->origbase = true; mfl_reroot_subtree(atip->edge, atip, src->edge->next->next, src, t_up, t_dn, swapingon, savedtrees, ntax, nchar, numnodes, searchrec, diff); s_up->origbase = false; s_dn->origbase = false; if (searchrec->success) { t_up->visited = false; t_dn->visited = false; src->skip = false; return; } mfl_join_nodes(s_up_N, s_up); mfl_join_nodes(s_dn_N, s_dn); } else { mfl_regrafting_traversal(t_up, src->edge->next->next, swapingon, savedtrees, ntax, nchar, numnodes, searchrec, diff); mfl_regrafting_traversal(t_dn, src->edge->next->next, swapingon, savedtrees, ntax, nchar, numnodes, searchrec, diff); } t_up->visited = false; t_dn->visited = false; src->skip = false; if (searchrec->success) { return; } mfl_join_nodes(t_up, t_up_N); mfl_join_nodes(t_dn, t_dn_N); mfl_restore_origstates(swapingon, ntax, numnodes, nchar); src->skip = false; } else { src->skip = false; } } assert(q == nds[i]); p = p->next; } while (p != nds[i]); } }
void mfl_subtree_pruning(node *n, tree *swapingon, tree **savedtrees, int ntax, int nchar, int numnodes, mfl_searchrec *searchrec) { /* Indexes over the node array of a tree, pruning subtrees and calling * the regrafting function */ int i, diff = 0, *srcchanging, *tgtchanging; node *p, *q, *src, *tgt, *s_dn, *s_up, *t_dn, *t_up, *t_dn_N, *t_up_N; node *s_dn_N, *s_up_N; nodearray nds = swapingon->trnodes; mfl_undone_tree(swapingon->trnodes, numnodes); for (i = ntax + 1; i < numnodes; ++i) { p = nds[i]; q = nds[i]; do { if (!p->edge->skip) { p->edge->skip = true; src = p->edge; tgt = p; if (!tgt->tocalcroot) { mfl_set_updown(tgt, &t_up, &t_dn); tgtchanging = mfl_get_tgt_changing(t_dn->edge, t_up, t_dn, nchar); // Pop out redundant node: t_up_N = t_up->edge; t_dn_N = t_dn->edge; mfl_join_nodes(t_up, t_dn); mfl_partial_downpass(t_dn, swapingon, numnodes, ntax, nchar, tgtchanging); free(tgtchanging); } else { mfl_set_updown(tgt, &t_up, &t_dn); if (t_up->tip && t_dn->tip) { p = p->next; continue; } else { //mfl_set_updown(tgt, &t_up, &t_dn); tgtchanging = mfl_get_subtr_changing(tgt, NULL, NULL, nchar); tgt->isroot = true; mfl_reopt_subtr(tgt, swapingon, nchar, numnodes, tgtchanging); tgt->isroot = false; free(tgtchanging); } // Pop out the redundant node: t_up_N = t_up->edge; t_dn_N = t_dn->edge; mfl_join_nodes(t_up, t_dn); } if (src->tip) { memcpy(src->apomorphies, src->tempapos, nchar * sizeof(charstate)); } else if (src->tocalcroot) { mfl_set_rootstates(src, nchar, NULL); /*if (src->next->edge->tip && src->next->next->edge->tip) { printNewick(src); dbg_printf("\n"); }*/ } else { if (src->next->edge->tip && src->next->next->edge->tip) { mfl_set_rootstates(src, nchar, NULL); } else { mfl_set_updown(src, &s_up, &s_dn); srcchanging = mfl_get_tgt_changing(s_dn->edge, s_up, s_dn, nchar); s_up_N = s_up->edge; s_dn_N = s_dn->edge; mfl_join_nodes(s_dn, s_up); mfl_partial_downpass(s_dn, swapingon, numnodes, ntax, nchar, srcchanging); mfl_join_nodes(s_up_N, s_up); mfl_join_nodes(s_dn_N, s_dn); mfl_reopt_subtr_root(src, nchar); free(srcchanging); } } diff = mfl_subtr_reinsertion(src, t_up, t_dn, nchar); // Perform all reinsertions of SRC on TGT /* OPTIMIZATION: This program can be greatly speeded up by * taking advantage of the fact that the two subtrees are * already reoptimized at this stage. Once one set of * reinsertions has been completed and did not result in a * better tree, this function can reverse the order and begin * reinserting the old target tree on the source tree. In this * diff may need to be recalculated. */ t_up->visited = true; t_dn->visited = true; mfl_regrafting_traversal(t_up, src->edge->next->next, swapingon, savedtrees, ntax, nchar, numnodes, searchrec, diff); mfl_regrafting_traversal(t_dn, src->edge->next->next, swapingon, savedtrees, ntax, nchar, numnodes, searchrec, diff); t_up->visited = false; t_dn->visited = false; p->edge->skip = false; if (searchrec->success) { return; } mfl_join_nodes(t_up, t_up_N); mfl_join_nodes(t_dn, t_dn_N); mfl_restore_origstates(swapingon, ntax, numnodes, nchar); } assert(q == nds[i]); p->edge->skip = false; p = p->next; } while (p != nds[i]); } }
void mfl_regrafting_traversal(node *n, node *subtr, tree *swapingon, tree **savedtrees, int ntax, int nchar, int numnodes, mfl_searchrec *searchrec, int diff) { /* Called from within any subtree pruning algorithm used in either SPR or * TBR branch swapping. Traverses a binary tree in preorder, inserting the * subtree at each node and (hopefully) skipping a reinsertion at the original * site of pruning (flagged by the "visited" boolean values in those nodes) */ if (searchrec->success) { return; } int trlength = 0; int al = 0; node *up; node *down, *top; if (!(n->visited) && !(n->edge->visited)) { up = n->edge; al = mfl_locreopt_cost(subtr->next->edge, n, up, nchar, diff); trlength = searchrec->bestinrep - diff + al; assert(trlength >= 0); searchrec->niter_total = searchrec->niter_total + 1; #ifdef MFY_DEBUG /*** BEGIN COMMENT OUT BEFORE COMMIT *** int trulen = 0; if (subtr->tocalcroot) { down = subtr; top = subtr->next->next; } else { down = subtr->next->next; top = subtr; } mfl_join_nodes(top, up); mfl_join_nodes(down, n); mfl_temproot(swapingon, 0, ntax); mfl_count_postorder(swapingon->root, &trulen, nchar, NULL); trulen = 0; mfl_fitch_preorder(swapingon->root, nchar, &trulen); mfl_undo_temproot(ntax, swapingon); if (trulen != trlength) { if (subtr->next->edge->tocalcroot) { printNewick(subtr->next->edge); dbg_printf("\n"); printNewick(swapingon->trnodes[0]); dbg_printf("\n"); } dbg_printf("estimated: %i\n", trlength); dbg_printf("true: %i\n", trulen); dbg_printf("diff: %i\n", diff); dbg_printf("al: %i\n\n", al); //trlength = trulen; //dbg_printf("report mismatch\n"); } else { dbg_printf("MATCH:\n"); dbg_printf("estimated: %i\n", trlength); dbg_printf("true: %i\n", trulen); dbg_printf("diff: %i\n", diff); dbg_printf("al: %i\n\n", al); } trlength = trulen; mfl_join_nodes(n, up); *** END COMMENT OUT BEFORE COMMIT ***/ #endif if (trlength < searchrec->bestinrep) { dbg_printf("length: %i\n", trlength); mfl_join_nodes(subtr->next->next, up); mfl_join_nodes(subtr, n); searchrec->foundbettertr = true; searchrec->success = true; swapingon->length = trlength; searchrec->bestinrep = trlength; if (searchrec->bestinrep < searchrec->bestlength) { searchrec->bestlength = searchrec->bestinrep; mfl_reinit_treebuffer(savedtrees, swapingon, &searchrec->nextinbuffer, numnodes); } else { mfl_reinit_tbinrange(savedtrees, swapingon, searchrec->trbufstart, &searchrec->nextinbuffer, numnodes); } free(swapingon->compressedtr); swapingon->compressedtr = mfl_compress_tree(swapingon, ntax, numnodes); searchrec->nextinbuffer = searchrec->nextinbuffer + 1; return; } searchrec->foundbettertr = false; searchrec->success = false; if (trlength == searchrec->bestinrep) { if (subtr->tocalcroot) { down = subtr; top = subtr->next->next; } else { down = subtr->next->next; top = subtr; } mfl_join_nodes(top, up); mfl_join_nodes(down, n); if (!mfl_compare_alltrees(swapingon, savedtrees, ntax, numnodes, &searchrec->trbufstart, searchrec->nextinbuffer)) { if (searchrec->currentreplicate > 0) { if (trlength == searchrec->bestlength) { long int bstart = 0; if (mfl_compare_alltrees(swapingon, savedtrees, ntax, numnodes, &bstart, searchrec->trbufstart)) { mfl_reinit_tbinrange(savedtrees, swapingon, searchrec->trbufstart, &searchrec->nextinbuffer, numnodes); searchrec->success = true; return; } } } savedtrees[searchrec->nextinbuffer] = mfl_copytree(swapingon, ntax, numnodes); savedtrees[searchrec->nextinbuffer]->index = searchrec->nextinbuffer; savedtrees[searchrec->nextinbuffer]->length = trlength; savedtrees[searchrec->nextinbuffer]->swapped = false; searchrec->nextinbuffer = searchrec->nextinbuffer + 1; } trlength = 0; } mfl_join_nodes(n, up); } if (n->tip) { return; } mfl_regrafting_traversal(n->next->edge, subtr, swapingon, savedtrees, ntax, nchar, numnodes, searchrec, diff); if (searchrec->success) { return; } mfl_regrafting_traversal(n->next->next->edge, subtr, swapingon, savedtrees, ntax, nchar, numnodes, searchrec, diff); }