BinarySpaceTree<BoundType, StatisticType, MatType, SplitType>::BinarySpaceTree( const BinarySpaceTree& other) : left(NULL), right(NULL), parent(other.parent), begin(other.begin), count(other.count), maxLeafSize(other.maxLeafSize), bound(other.bound), stat(other.stat), splitDimension(other.splitDimension), parentDistance(other.parentDistance), furthestDescendantDistance(other.furthestDescendantDistance), dataset(other.dataset) { // Create left and right children (if any). if (other.Left()) { left = new BinarySpaceTree(*other.Left()); left->Parent() = this; // Set parent to this, not other tree. } if (other.Right()) { right = new BinarySpaceTree(*other.Right()); right->Parent() = this; // Set parent to this, not other tree. } }
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>:: BinarySpaceTree( const BinarySpaceTree& other) : left(NULL), right(NULL), parent(other.parent), begin(other.begin), count(other.count), bound(other.bound), stat(other.stat), parentDistance(other.parentDistance), furthestDescendantDistance(other.furthestDescendantDistance), // Copy matrix, but only if we are the root. dataset((other.parent == NULL) ? new MatType(*other.dataset) : NULL) { // Create left and right children (if any). if (other.Left()) { left = new BinarySpaceTree(*other.Left()); left->Parent() = this; // Set parent to this, not other tree. } if (other.Right()) { right = new BinarySpaceTree(*other.Right()); right->Parent() = this; // Set parent to this, not other tree. } // Propagate matrix, but only if we are the root. if (parent == NULL) { std::queue<BinarySpaceTree*> queue; if (left) queue.push(left); if (right) queue.push(right); while (!queue.empty()) { BinarySpaceTree* node = queue.front(); queue.pop(); node->dataset = dataset; if (node->left) queue.push(node->left); if (node->right) queue.push(node->right); } } }
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>:: Serialize(Archive& ar, const unsigned int /* version */) { using data::CreateNVP; // If we're loading, and we have children, they need to be deleted. if (Archive::is_loading::value) { if (left) delete left; if (right) delete right; if (!parent) delete dataset; } ar & CreateNVP(parent, "parent"); ar & CreateNVP(begin, "begin"); ar & CreateNVP(count, "count"); ar & CreateNVP(bound, "bound"); ar & CreateNVP(stat, "statistic"); ar & CreateNVP(parentDistance, "parentDistance"); ar & CreateNVP(furthestDescendantDistance, "furthestDescendantDistance"); ar & CreateNVP(dataset, "dataset"); // Save children last; otherwise boost::serialization gets confused. ar & CreateNVP(left, "left"); ar & CreateNVP(right, "right"); // Due to quirks of boost::serialization, if a tree is saved as an object and // not a pointer, the first level of the tree will be duplicated on load. // Therefore, if we are the root of the tree, then we need to make sure our // children's parent links are correct, and delete the duplicated node if // necessary. if (Archive::is_loading::value) { // Get parents of left and right children, or, NULL, if they don't exist. BinarySpaceTree* leftParent = left ? left->Parent() : NULL; BinarySpaceTree* rightParent = right ? right->Parent() : NULL; // Reassign parent links if necessary. if (left && left->Parent() != this) left->Parent() = this; if (right && right->Parent() != this) right->Parent() = this; // Do we need to delete the left parent? if (leftParent != NULL && leftParent != this) { // Sever the duplicate parent's children. Ensure we don't delete the // dataset, by faking the duplicated parent's parent (that is, we need to // set the parent to something non-NULL; 'this' works). leftParent->Parent() = this; leftParent->Left() = NULL; leftParent->Right() = NULL; delete leftParent; } // Do we need to delete the right parent? if (rightParent != NULL && rightParent != this && rightParent != leftParent) { // Sever the duplicate parent's children, in the same way as above. rightParent->Parent() = this; rightParent->Left() = NULL; rightParent->Right() = NULL; delete rightParent; } } }
void BinarySpaceTree<BoundType, StatisticType, MatType>:: SingleTreeTraverser<RuleType>::Traverse( const size_t queryIndex, BinarySpaceTree<BoundType, StatisticType, MatType>& referenceNode) { // If we are a leaf, run the base case as necessary. if (referenceNode.IsLeaf()) { for (size_t i = referenceNode.Begin(); i < referenceNode.End(); ++i) rule.BaseCase(queryIndex, i); } else { // If either score is DBL_MAX, we do not recurse into that node. double leftScore = rule.Score(queryIndex, *referenceNode.Left()); double rightScore = rule.Score(queryIndex, *referenceNode.Right()); if (leftScore < rightScore) { // Recurse to the left. Traverse(queryIndex, *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(queryIndex, *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) Traverse(queryIndex, *referenceNode.Right()); // Recurse to the right. else ++numPrunes; } else if (rightScore < leftScore) { // Recurse to the right. Traverse(queryIndex, *referenceNode.Right()); // Is it still valid to recurse to the left? leftScore = rule.Rescore(queryIndex, *referenceNode.Left(), leftScore); if (leftScore != DBL_MAX) Traverse(queryIndex, *referenceNode.Left()); // Recurse to the left. else ++numPrunes; } else // leftScore is equal to rightScore. { if (leftScore == DBL_MAX) { numPrunes += 2; // Pruned both left and right. } else { // Choose the left first. Traverse(queryIndex, *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(queryIndex, *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) Traverse(queryIndex, *referenceNode.Right()); else ++numPrunes; } } } }
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>:: DualTreeTraverser<RuleType>::Traverse( BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>& queryNode, BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>& referenceNode) { // Increment the visit counter. ++numVisited; // Store the current traversal info. traversalInfo = rule.TraversalInfo(); // If both are leaves, we must evaluate the base case. if (queryNode.IsLeaf() && referenceNode.IsLeaf()) { // Loop through each of the points in each node. const size_t queryEnd = queryNode.Begin() + queryNode.Count(); const size_t refEnd = referenceNode.Begin() + referenceNode.Count(); for (size_t query = queryNode.Begin(); query < queryEnd; ++query) { // See if we need to investigate this point (this function should be // implemented for the single-tree recursion too). Restore the traversal // information first. rule.TraversalInfo() = traversalInfo; const double childScore = rule.Score(query, referenceNode); if (childScore == DBL_MAX) continue; // We can't improve this particular point. for (size_t ref = referenceNode.Begin(); ref < refEnd; ++ref) rule.BaseCase(query, ref); numBaseCases += referenceNode.Count(); } } else if (((!queryNode.IsLeaf()) && referenceNode.IsLeaf()) || (queryNode.NumDescendants() > 3 * referenceNode.NumDescendants() && !queryNode.IsLeaf() && !referenceNode.IsLeaf())) { // We have to recurse down the query node. In this case the recursion order // does not matter. const double leftScore = rule.Score(*queryNode.Left(), referenceNode); ++numScores; if (leftScore != DBL_MAX) Traverse(*queryNode.Left(), referenceNode); else ++numPrunes; // Before recursing, we have to set the traversal information correctly. rule.TraversalInfo() = traversalInfo; const double rightScore = rule.Score(*queryNode.Right(), referenceNode); ++numScores; if (rightScore != DBL_MAX) Traverse(*queryNode.Right(), referenceNode); else ++numPrunes; } else if (queryNode.IsLeaf() && (!referenceNode.IsLeaf())) { // We have to recurse down the reference node. In this case the recursion // order does matter. Before recursing, though, we have to set the // traversal information correctly. double leftScore = rule.Score(queryNode, *referenceNode.Left()); typename RuleType::TraversalInfoType leftInfo = rule.TraversalInfo(); rule.TraversalInfo() = traversalInfo; double rightScore = rule.Score(queryNode, *referenceNode.Right()); numScores += 2; if (leftScore < rightScore) { // Recurse to the left. Restore the left traversal info. Store the right // traversal info. traversalInfo = rule.TraversalInfo(); rule.TraversalInfo() = leftInfo; Traverse(queryNode, *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(queryNode, *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) { // Restore the right traversal info. rule.TraversalInfo() = traversalInfo; Traverse(queryNode, *referenceNode.Right()); } else ++numPrunes; } else if (rightScore < leftScore) { // Recurse to the right. Traverse(queryNode, *referenceNode.Right()); // Is it still valid to recurse to the left? leftScore = rule.Rescore(queryNode, *referenceNode.Left(), leftScore); if (leftScore != DBL_MAX) { // Restore the left traversal info. rule.TraversalInfo() = leftInfo; Traverse(queryNode, *referenceNode.Left()); } else ++numPrunes; } else // leftScore is equal to rightScore. { if (leftScore == DBL_MAX) { numPrunes += 2; } else { // Choose the left first. Restore the left traversal info. Store the // right traversal info. traversalInfo = rule.TraversalInfo(); rule.TraversalInfo() = leftInfo; Traverse(queryNode, *referenceNode.Left()); rightScore = rule.Rescore(queryNode, *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) { // Restore the right traversal info. rule.TraversalInfo() = traversalInfo; Traverse(queryNode, *referenceNode.Right()); } else ++numPrunes; } } } else { // We have to recurse down both query and reference nodes. Because the // query descent order does not matter, we will go to the left query child // first. Before recursing, we have to set the traversal information // correctly. double leftScore = rule.Score(*queryNode.Left(), *referenceNode.Left()); typename RuleType::TraversalInfoType leftInfo = rule.TraversalInfo(); rule.TraversalInfo() = traversalInfo; double rightScore = rule.Score(*queryNode.Left(), *referenceNode.Right()); typename RuleType::TraversalInfoType rightInfo; numScores += 2; if (leftScore < rightScore) { // Recurse to the left. Restore the left traversal info. Store the right // traversal info. rightInfo = rule.TraversalInfo(); rule.TraversalInfo() = leftInfo; Traverse(*queryNode.Left(), *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(*queryNode.Left(), *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) { // Restore the right traversal info. rule.TraversalInfo() = rightInfo; Traverse(*queryNode.Left(), *referenceNode.Right()); } else ++numPrunes; } else if (rightScore < leftScore) { // Recurse to the right. Traverse(*queryNode.Left(), *referenceNode.Right()); // Is it still valid to recurse to the left? leftScore = rule.Rescore(*queryNode.Left(), *referenceNode.Left(), leftScore); if (leftScore != DBL_MAX) { // Restore the left traversal info. rule.TraversalInfo() = leftInfo; Traverse(*queryNode.Left(), *referenceNode.Left()); } else ++numPrunes; } else { if (leftScore == DBL_MAX) { numPrunes += 2; } else { // Choose the left first. Restore the left traversal info and store the // right traversal info. rightInfo = rule.TraversalInfo(); rule.TraversalInfo() = leftInfo; Traverse(*queryNode.Left(), *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(*queryNode.Left(), *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) { // Restore the right traversal information. rule.TraversalInfo() = rightInfo; Traverse(*queryNode.Left(), *referenceNode.Right()); } else ++numPrunes; } } // Restore the main traversal information. rule.TraversalInfo() = traversalInfo; // Now recurse down the right query node. leftScore = rule.Score(*queryNode.Right(), *referenceNode.Left()); leftInfo = rule.TraversalInfo(); rule.TraversalInfo() = traversalInfo; rightScore = rule.Score(*queryNode.Right(), *referenceNode.Right()); numScores += 2; if (leftScore < rightScore) { // Recurse to the left. Restore the left traversal info. Store the right // traversal info. rightInfo = rule.TraversalInfo(); rule.TraversalInfo() = leftInfo; Traverse(*queryNode.Right(), *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(*queryNode.Right(), *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) { // Restore the right traversal info. rule.TraversalInfo() = rightInfo; Traverse(*queryNode.Right(), *referenceNode.Right()); } else ++numPrunes; } else if (rightScore < leftScore) { // Recurse to the right. Traverse(*queryNode.Right(), *referenceNode.Right()); // Is it still valid to recurse to the left? leftScore = rule.Rescore(*queryNode.Right(), *referenceNode.Left(), leftScore); if (leftScore != DBL_MAX) { // Restore the left traversal info. rule.TraversalInfo() = leftInfo; Traverse(*queryNode.Right(), *referenceNode.Left()); } else ++numPrunes; } else { if (leftScore == DBL_MAX) { numPrunes += 2; } else { // Choose the left first. Restore the left traversal info. Store the // right traversal info. rightInfo = rule.TraversalInfo(); rule.TraversalInfo() = leftInfo; Traverse(*queryNode.Right(), *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(*queryNode.Right(), *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) { // Restore the right traversal info. rule.TraversalInfo() = rightInfo; Traverse(*queryNode.Right(), *referenceNode.Right()); } else ++numPrunes; } } } }
void BinarySpaceTree<BoundType, StatisticType, MatType>:: DualTreeTraverser<RuleType>::Traverse( BinarySpaceTree<BoundType, StatisticType, MatType>& queryNode, BinarySpaceTree<BoundType, StatisticType, MatType>& referenceNode) { // If both are leaves, we must evaluate the base case. if (queryNode.IsLeaf() && referenceNode.IsLeaf()) { // Loop through each of the points in each node. for (size_t query = queryNode.Begin(); query < queryNode.End(); ++query) { // See if we need to investigate this point (this function should be // implemented for the single-tree recursion too). const double score = rule.Score(query, referenceNode); if (score == DBL_MAX) continue; // We can't improve this particular point. for (size_t ref = referenceNode.Begin(); ref < referenceNode.End(); ++ref) rule.BaseCase(query, ref); } } else if ((!queryNode.IsLeaf()) && referenceNode.IsLeaf()) { // We have to recurse down the query node. In this case the recursion order // does not matter. double leftScore = rule.Score(*queryNode.Left(), referenceNode); if (leftScore != DBL_MAX) Traverse(*queryNode.Left(), referenceNode); else ++numPrunes; double rightScore = rule.Score(*queryNode.Right(), referenceNode); if (rightScore != DBL_MAX) Traverse(*queryNode.Right(), referenceNode); else ++numPrunes; } else if (queryNode.IsLeaf() && (!referenceNode.IsLeaf())) { // We have to recurse down the reference node. In this case the recursion // order does matter. double leftScore = rule.Score(queryNode, *referenceNode.Left()); double rightScore = rule.Score(queryNode, *referenceNode.Right()); if (leftScore < rightScore) { // Recurse to the left. Traverse(queryNode, *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(queryNode, *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) Traverse(queryNode, *referenceNode.Right()); else ++numPrunes; } else if (rightScore < leftScore) { // Recurse to the right. Traverse(queryNode, *referenceNode.Right()); // Is it still valid to recurse to the left? leftScore = rule.Rescore(queryNode, *referenceNode.Left(), leftScore); if (leftScore != DBL_MAX) Traverse(queryNode, *referenceNode.Left()); else ++numPrunes; } else // leftScore is equal to rightScore. { if (leftScore == DBL_MAX) { numPrunes += 2; } else { // Choose the left first. Traverse(queryNode, *referenceNode.Left()); rightScore = rule.Rescore(queryNode, *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) Traverse(queryNode, *referenceNode.Right()); else ++numPrunes; } } } else { // We have to recurse down both query and reference nodes. Because the // query descent order does not matter, we will go to the left query child // first. double leftScore = rule.Score(*queryNode.Left(), *referenceNode.Left()); double rightScore = rule.Score(*queryNode.Left(), *referenceNode.Right()); if (leftScore < rightScore) { // Recurse to the left. Traverse(*queryNode.Left(), *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(*queryNode.Left(), *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) Traverse(*queryNode.Left(), *referenceNode.Right()); else ++numPrunes; } else if (rightScore < leftScore) { // Recurse to the right. Traverse(*queryNode.Left(), *referenceNode.Right()); // Is it still valid to recurse to the left? leftScore = rule.Rescore(*queryNode.Left(), *referenceNode.Left(), leftScore); if (leftScore != DBL_MAX) Traverse(*queryNode.Left(), *referenceNode.Left()); else ++numPrunes; } else { if (leftScore == DBL_MAX) { numPrunes += 2; } else { // Choose the left first. Traverse(*queryNode.Left(), *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(*queryNode.Left(), *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) Traverse(*queryNode.Left(), *referenceNode.Right()); else ++numPrunes; } } // Now recurse down the right query node. leftScore = rule.Score(*queryNode.Right(), *referenceNode.Left()); rightScore = rule.Score(*queryNode.Right(), *referenceNode.Right()); if (leftScore < rightScore) { // Recurse to the left. Traverse(*queryNode.Right(), *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(*queryNode.Right(), *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) Traverse(*queryNode.Right(), *referenceNode.Right()); else ++numPrunes; } else if (rightScore < leftScore) { // Recurse to the right. Traverse(*queryNode.Right(), *referenceNode.Right()); // Is it still valid to recurse to the left? leftScore = rule.Rescore(*queryNode.Right(), *referenceNode.Left(), leftScore); if (leftScore != DBL_MAX) Traverse(*queryNode.Right(), *referenceNode.Left()); else ++numPrunes; } else { if (leftScore == DBL_MAX) { numPrunes += 2; } else { // Choose the left first. Traverse(*queryNode.Right(), *referenceNode.Left()); // Is it still valid to recurse to the right? rightScore = rule.Rescore(*queryNode.Right(), *referenceNode.Right(), rightScore); if (rightScore != DBL_MAX) Traverse(*queryNode.Right(), *referenceNode.Right()); else ++numPrunes; } } } // Now update any necessary information after recursion. rule.UpdateAfterRecursion(queryNode, referenceNode); }
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>:: BreadthFirstDualTreeTraverser<RuleType>::Traverse( BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>& queryNode, std::priority_queue<QueueFrameType>& referenceQueue) { // Store queues for the children. We will recurse into the children once our // queue is empty. std::priority_queue<QueueFrameType> leftChildQueue; std::priority_queue<QueueFrameType> rightChildQueue; while (!referenceQueue.empty()) { QueueFrameType currentFrame = referenceQueue.top(); referenceQueue.pop(); BinarySpaceTree& queryNode = *currentFrame.queryNode; BinarySpaceTree& referenceNode = *currentFrame.referenceNode; typename RuleType::TraversalInfoType ti = currentFrame.traversalInfo; rule.TraversalInfo() = ti; const size_t queryDepth = currentFrame.queryDepth; double score = rule.Score(queryNode, referenceNode); ++numScores; if (score == DBL_MAX) { ++numPrunes; continue; } // If both are leaves, we must evaluate the base case. if (queryNode.IsLeaf() && referenceNode.IsLeaf()) { // Loop through each of the points in each node. const size_t queryEnd = queryNode.Begin() + queryNode.Count(); const size_t refEnd = referenceNode.Begin() + referenceNode.Count(); for (size_t query = queryNode.Begin(); query < queryEnd; ++query) { // See if we need to investigate this point (this function should be // implemented for the single-tree recursion too). Restore the // traversal information first. // const double childScore = rule.Score(query, referenceNode); // if (childScore == DBL_MAX) // continue; // We can't improve this particular point. for (size_t ref = referenceNode.Begin(); ref < refEnd; ++ref) rule.BaseCase(query, ref); numBaseCases += referenceNode.Count(); } } else if ((!queryNode.IsLeaf()) && referenceNode.IsLeaf()) { // We have to recurse down the query node. QueueFrameType fl = { queryNode.Left(), &referenceNode, queryDepth + 1, score, rule.TraversalInfo() }; leftChildQueue.push(fl); QueueFrameType fr = { queryNode.Right(), &referenceNode, queryDepth + 1, score, ti }; rightChildQueue.push(fr); } else if (queryNode.IsLeaf() && (!referenceNode.IsLeaf())) { // We have to recurse down the reference node. In this case the recursion // order does matter. Before recursing, though, we have to set the // traversal information correctly. QueueFrameType fl = { &queryNode, referenceNode.Left(), queryDepth, score, rule.TraversalInfo() }; referenceQueue.push(fl); QueueFrameType fr = { &queryNode, referenceNode.Right(), queryDepth, score, ti }; referenceQueue.push(fr); } else { // We have to recurse down both query and reference nodes. Because the // query descent order does not matter, we will go to the left query child // first. Before recursing, we have to set the traversal information // correctly. QueueFrameType fll = { queryNode.Left(), referenceNode.Left(), queryDepth + 1, score, rule.TraversalInfo() }; leftChildQueue.push(fll); QueueFrameType flr = { queryNode.Left(), referenceNode.Right(), queryDepth + 1, score, rule.TraversalInfo() }; leftChildQueue.push(flr); QueueFrameType frl = { queryNode.Right(), referenceNode.Left(), queryDepth + 1, score, rule.TraversalInfo() }; rightChildQueue.push(frl); QueueFrameType frr = { queryNode.Right(), referenceNode.Right(), queryDepth + 1, score, rule.TraversalInfo() }; rightChildQueue.push(frr); } } // Now, recurse into the left and right children queues. The order doesn't // matter. if (leftChildQueue.size() > 0) Traverse(*queryNode.Left(), leftChildQueue); if (rightChildQueue.size() > 0) Traverse(*queryNode.Right(), rightChildQueue); }