Beispiel #1
0
void Tree::copySubtree(Tree& subtree, std::shared_ptr<Node>& subtree_node, Node& original_node, int breaking_branch_anc, int breaking_branch_desc) {
    /* If this node == breaking_branch_anc */
    /* Then join the other descendent of this node with this node's ancestor */
    /* And skip to the other descendent */
    if (original_node.get_id() == breaking_branch_anc) {
        // Find node that is the sibling of the breaking branck
        Node& grand_descendent = *(original_node.desc1);
        if (original_node.desc1->get_id() == breaking_branch_desc) { // TODO: assert that desc2 == breaking_branch_anc instead
            grand_descendent = *(original_node.desc2);
        }
        auto breaking_branch_sibling = std::make_shared<Node>(grand_descendent.get_id());
        if (subtree_node->anc == nullptr) { // If the breaking branch ancestor is the root of the original tree,
            // then delete the node and set its other descendent as the root
            subtree.root_node = breaking_branch_sibling;
        }
        else { // If not the root, then "delete" the node by joining its ancestor with its other descendent
            breaking_branch_sibling->anc = subtree_node->anc;
            if (subtree_node->anc->desc1 == subtree_node) {
                subtree_node->anc->desc1 = breaking_branch_sibling;
            } else {
                subtree_node->anc->desc2 = breaking_branch_sibling;
            }
        }
        copySubtree(subtree, breaking_branch_sibling, grand_descendent, breaking_branch_anc, breaking_branch_desc);
    }
    /* Otherwise, add each descendent and recursively parse them. */
    /* TODO: Need to increment/decrement subtree values */
    else {
        if (subtree_node->get_id() > subtree.max_id) {
            subtree.max_id = subtree_node->get_id();
        }
        if (original_node.hasDescendents()) {
            auto desc1_copy = std::make_shared<Node>(original_node.desc1->get_id());
            subtree_node->desc1 = desc1_copy;
            desc1_copy->anc = subtree_node;
            copySubtree(subtree, desc1_copy, *(original_node.desc1), breaking_branch_anc, breaking_branch_desc);
            auto desc2_copy = std::make_shared<Node>(original_node.desc2->get_id());
            subtree_node->desc2 = desc2_copy;
            desc2_copy->anc = subtree_node;
            copySubtree(subtree, desc2_copy, *(original_node.desc2), breaking_branch_anc, breaking_branch_desc);
            subtree.nnodes += 2;
            subtree.nbranches += 2;
        }
        else {
            subtree.ntips++;
        }
    }
}
Beispiel #2
0
TreeNode<Token> *ExpTree::copySubtree(TreeNode<Token> *current) {

    if (current == nullptr) //base case to end recursion when at tree end
        return nullptr;

    //create the node and set the new key to original
    TreeNode<Token> *copy = new TreeNode<Token>;
    size++; //used for dot
    copy->setInfo(current->getInfo());
    copy->setKey(size);

    //just call recursively to copy the subtrees:
    copy->setLeft(copySubtree(current->getLeft()));
    copy->setRight(copySubtree(current->getRight()));

    return copy;

}//copySubtree
Beispiel #3
0
void Tree::splitTree(int anc_id, int desc_id, std::array<std::unique_ptr<Tree>, 2>& subtrees) {
    /* Check that anc and desc form a branch in the tree */
    std::shared_ptr<Node> anc_node = getNode(anc_id, root_node);
    if (anc_node->desc1->get_id() != desc_id && anc_node->desc2->get_id() != desc_id) {
        throw std::logic_error("Non-existent branch");
    }

    /* Parse the first subtree  */
    subtrees[0] = std::make_unique<Tree>();
    subtrees[0]->addTipFrom(root_node->get_id(), 0); // TODO: easier just to add constructor that takes a root_node id as param?
    subtrees[0]->nnodes++;
    subtrees[0]->max_id = root_node->get_id();
    copySubtree(*subtrees[0], subtrees[0]->root_node, *root_node, anc_id, desc_id);
    /* Parse the second subtree  */
    subtrees[1] = std::make_unique<Tree>();
    subtrees[1]->addTipFrom(desc_id, 0); // TODO: easier just to add constructor that takes a root_node id as param?
    subtrees[1]->nnodes++;
    subtrees[1]->max_id = desc_id;
    Node& break_desc_node = anc_node->desc1->get_id() == desc_id ? *(anc_node->desc1) : *(anc_node->desc2);
    copySubtree(*subtrees[1], subtrees[1]->root_node, break_desc_node, anc_id, desc_id);
}
Beispiel #4
0
void ExpTree::diffNode(TreeNode<Token> *current) { //recursive function to differentiate

    if (current == nullptr)//recursion guard
        return;

    Token temp;//var to set info

    if (current->getInfo().type == Token::NUMBER || current->getInfo().type == Token::PI) {//constants have derivative 0

        temp.number = 0;
        temp.type = Token::NUMBER;
        current->setInfo(temp);

    }//number derivative

    if (current->getInfo().type == Token::VARIABLE) {//differentiating w.r.t. x so that has derivative 1 others have 0

        temp.type = Token::NUMBER;

        if (current->getInfo().variable == 'x')
            temp.number = 1;
        else
            temp.number = 0;

        current->setInfo(temp);
    }//variable derivative

    if (current->getInfo().type == Token::PLUS ||
        current->getInfo().type == Token::MINUS) {//derivative of sum is sum of derivatives

        diffNode(current->getRight());
        diffNode(current->getLeft());

    }//sum rule

    if (current->getInfo().type == Token::PRODUCT) {//product rule d(fg) = d(f)g + fd(g)

        current->setRight(copySubtree(current)); //copy subtrees to differentiate
        current->setLeft(copySubtree(current->getRight()));

        temp.type = Token::PLUS;//set plus in current
        current->setInfo(temp);

        diffNode(current->getRight()->getRight());//differentiate the correct subtrees
        diffNode(current->getLeft()->getLeft());

    }//product rule

    if (current->getInfo().type == Token::SIN) {//derivative of sin

        current->setRight(copySubtree(current));
        temp.type = Token::PRODUCT;
        current->setInfo(temp);

        current->setLeft(copySubtree(current->getRight()->getRight()));//chain rule
        diffNode(current->getLeft());

        temp.type = Token::COS;
        current->getRight()->setInfo(temp);

    }//sin

    if (current->getInfo().type == Token::COS) {//derivative of cos

        current->setRight(copySubtree(current)); //copy subtree
        TreeNode<Token> *left = new TreeNode<Token>; //extra node is needed for the extra * -1
        current->setLeft(left);
        size++; //set tree size for dot
        current->getLeft()->setKey(size);
        temp.type = Token::NUMBER;
        temp.number = -1;
        current->getLeft()->setInfo(temp);

        temp.type = Token::PRODUCT;
        current->setInfo(temp);

        current->getRight()->setRight(copySubtree(current->getRight()));//copy subtree to the correct place
        current->getRight()->setLeft(copySubtree(current->getRight()->getRight()->getRight()));
        diffNode(current->getRight()->getLeft()); //chain rule
        current->getRight()->setInfo(temp);

        temp.type = Token::SIN;
        current->getRight()->getRight()->setInfo(temp);

    }//cos

    if (current->getInfo().type == Token::POW) { //power
        current->setLeft(copySubtree(current));//copy relevant subtrees
        current->setLeft(copySubtree(current));
        temp.type = Token::NUMBER;
        temp.number = current->getRight()->getInfo().number - 1; //d(x^C)=x^{C-1}*C
        current->getLeft()->getLeft()->getRight()->setInfo(temp);

        temp.type = Token::PRODUCT;
        current->setInfo(temp);
        current->getLeft()->setInfo(temp);
        current->setRight(copySubtree(current->getLeft()->getLeft()->getLeft()));

        diffNode(current->getRight());

    }//POW

    if (current->getInfo().type == Token::DIVIDE) {//d(f/g)=(d(f)*g-f*d(g))/(g^2)

        current->setLeft(copySubtree(current));

        current->getLeft()->setLeft(copySubtree(current->getLeft()));//copy relevant subtrees
        current->getLeft()->setRight(copySubtree(current->getLeft()->getLeft()));

        current->getRight()->setLeft(copySubtree(current->getRight()));
        temp.type = Token::NUMBER;
        temp.number = 2;
        TreeNode<Token> *right = new TreeNode<Token>; //new nodes are needed so create them and set them appropriately
        current->getRight()->setRight(right);
        size++;
        current->getRight()->getRight()->setKey(size);
        current->getRight()->getRight()->setInfo(temp);

        temp.type = Token::POW;
        current->getRight()->setInfo(temp);

        temp.type = Token::MINUS;
        current->getLeft()->setInfo(temp);

        temp.type = Token::PRODUCT;
        current->getLeft()->getLeft()->setInfo(temp);
        current->getLeft()->getRight()->setInfo(temp);

        diffNode(current->getLeft()->getLeft()->getLeft()); //differentiate the subtrees
        diffNode(current->getLeft()->getRight()->getRight());

    }//DIVIDE

}//diffNode