/*---------------------------------------------------------------------------------------------------------------------- | Randomly chooses a node to serve as node Z (the bottom of the three nodes involved in a Larget-Simon move). The | supplied node `middle' is the node serving as Y. In the figure below, the nodes labeled Z are all possible | candidates for the return value of this function. The node selected as Z should be the owner of the lowermost edge | involved in the move (X owns the uppermost edge and Y owns the middle edge). |> | X X X | \ | / | \|/ | Z Z Y | \ | / | \|/ | Z | | |> */ TreeNode * LargetSimonMove::chooseZ( TreeNode * middle) /**< is the middle node (Y) */ { TreeNode * nd = NULL; TreeNode * U = middle->GetParent(); PHYCAS_ASSERT(U != NULL); unsigned uchildren = U->CountChildren(); unsigned which_child = rng->SampleUInt(uchildren); if (which_child == 0) { // Selected "child" is actually U's parent nd = U; } else { // Selected child is one of U's actual children (but cannot be equal to middle) unsigned k = 1; for (nd = U->GetLeftChild(); nd != NULL; nd = nd->GetRightSib()) { if (nd == middle) continue; else { if (k == which_child) break; ++k; } } PHYCAS_ASSERT(nd != NULL); } return nd; }
/*---------------------------------------------------------------------------------------------------------------------- | */ inline void effective_postorder_edge_iterator::BuildStackFromNodeAndSiblings(TreeNode * curr, const TreeNode * nodeToSkip) { // Handle case in which curr equals nodeToSkip if (nodeToSkip != NULL && curr == nodeToSkip) curr = curr->GetRightSib(); if (curr == NULL) return; // Create a temporary stack of nodes to remember std::stack<TreeNode *> ndStack; // Visit all nodes in the subtree extending up from curr's parent (with the exception // of the subtree whose root is nodeToSkip) for (;;) { TreeNode * par = curr->GetParent(); if ((!isValidChecker.empty()) && isValidChecker(curr, par)) { // edge was valid: // - let curr be curr's next sibling curr = curr->GetRightSib(); if (nodeToSkip != NULL && curr == nodeToSkip) curr = curr->GetRightSib(); } else { // edge was not valid: // - push edge onto edge stack // - if curr has a sibling, push that sibling onto ndStack (i.e. remember it so we can deal with it later) // - let curr be curr's left child edgeStack.push(EdgeEndpoints(curr, par)); TreeNode * r = curr->GetRightSib(); if (r != NULL && r == nodeToSkip) r = r->GetRightSib(); if (r != NULL) ndStack.push(r); curr = curr->GetLeftChild(); } if (curr == NULL) { // we've come to the end of the road for this subtree // let curr be node on top of ndStack if (ndStack.empty()) break; curr = ndStack.top(); ndStack.pop(); } } }
/*---------------------------------------------------------------------------------------------------------------------- | Selects a child of the supplied `nd' at random from a discrete uniform distribution. */ TreeNode * LargetSimonMove::randomChild( TreeNode * nd) /**< is the parent node whose children are candidates */ { unsigned ychildren = nd->CountChildren(); unsigned which_child = rng->SampleUInt(ychildren); unsigned k = 0; TreeNode * child = nd->GetLeftChild(); for (; child != NULL; child = child->GetRightSib()) { if (k == which_child) break; ++k; } PHYCAS_ASSERT(child != NULL); return child; }