本文整理汇总了C++中TreeType::Parent方法的典型用法代码示例。如果您正苦于以下问题:C++ TreeType::Parent方法的具体用法?C++ TreeType::Parent怎么用?C++ TreeType::Parent使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类TreeType
的用法示例。
在下文中一共展示了TreeType::Parent方法的13个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: BaseCase
double RangeSearchRules<MetricType, TreeType>::Score(const size_t queryIndex,
TreeType& referenceNode)
{
// We must get the minimum and maximum distances and store them in this
// object.
math::Range distances;
if (tree::TreeTraits<TreeType>::FirstPointIsCentroid)
{
// In this situation, we calculate the base case. So we should check to be
// sure we haven't already done that.
double baseCase;
if (tree::TreeTraits<TreeType>::HasSelfChildren &&
(referenceNode.Parent() != NULL) &&
(referenceNode.Point(0) == referenceNode.Parent()->Point(0)))
{
// If the tree has self-children and this is a self-child, the base case
// was already calculated.
baseCase = referenceNode.Parent()->Stat().LastDistance();
lastQueryIndex = queryIndex;
lastReferenceIndex = referenceNode.Point(0);
}
else
{
// We must calculate the base case by hand.
baseCase = BaseCase(queryIndex, referenceNode.Point(0));
}
// This may be possibly loose for non-ball bound trees.
distances.Lo() = baseCase - referenceNode.FurthestDescendantDistance();
distances.Hi() = baseCase + referenceNode.FurthestDescendantDistance();
// Update last distance calculation.
referenceNode.Stat().LastDistance() = baseCase;
}
else
{
distances = referenceNode.RangeDistance(querySet.unsafe_col(queryIndex));
}
// If the ranges do not overlap, prune this node.
if (!distances.Contains(range))
return DBL_MAX;
// In this case, all of the points in the reference node will be part of the
// results.
if ((distances.Lo() >= range.Lo()) && (distances.Hi() <= range.Hi()))
{
AddResult(queryIndex, referenceNode);
return DBL_MAX; // We don't need to go any deeper.
}
// Otherwise the score doesn't matter. Recursion order is irrelevant in
// range search.
return 0.0;
}
示例2: DualTreeKMeansStatistic
DualTreeKMeansStatistic(TreeType& node) :
neighbor::NeighborSearchStat<neighbor::NearestNeighborSort>(),
upperBound(DBL_MAX),
lowerBound(DBL_MAX),
owner(size_t(-1)),
pruned(size_t(-1)),
staticPruned(false),
staticUpperBoundMovement(0.0),
staticLowerBoundMovement(0.0),
trueParent(node.Parent())
{
// Empirically calculate the centroid.
centroid.zeros(node.Dataset().n_rows);
for (size_t i = 0; i < node.NumPoints(); ++i)
{
// Correct handling of cover tree: don't double-count the point which
// appears in the children.
if (tree::TreeTraits<TreeType>::HasSelfChildren && i == 0 &&
node.NumChildren() > 0)
continue;
centroid += node.Dataset().col(node.Point(i));
}
for (size_t i = 0; i < node.NumChildren(); ++i)
centroid += node.Child(i).NumDescendants() *
node.Child(i).Stat().Centroid();
centroid /= node.NumDescendants();
// Set the true children correctly.
trueChildren.resize(node.NumChildren());
for (size_t i = 0; i < node.NumChildren(); ++i)
trueChildren[i] = &node.Child(i);
}
示例3: CheckFills
void CheckFills(const TreeType& tree)
{
if (tree.IsLeaf())
{
BOOST_REQUIRE(tree.Count() >= tree.MinLeafSize() || tree.Parent() == NULL);
BOOST_REQUIRE(tree.Count() <= tree.MaxLeafSize());
}
else
{
for (size_t i = 0; i < tree.NumChildren(); i++)
{
BOOST_REQUIRE(tree.NumChildren() >= tree.MinNumChildren() ||
tree.Parent() == NULL);
BOOST_REQUIRE(tree.NumChildren() <= tree.MaxNumChildren());
CheckFills(*tree.Children()[i]);
}
}
}
示例4: Score
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Score(
const size_t queryIndex,
TreeType& referenceNode)
{
++scores; // Count number of Score() calls.
double distance;
if (tree::TreeTraits<TreeType>::FirstPointIsCentroid)
{
// The first point in the tree is the centroid. So we can then calculate
// the base case between that and the query point.
double baseCase = -1.0;
if (tree::TreeTraits<TreeType>::HasSelfChildren)
{
// If the parent node is the same, then we have already calculated the
// base case.
if ((referenceNode.Parent() != NULL) &&
(referenceNode.Point(0) == referenceNode.Parent()->Point(0)))
baseCase = referenceNode.Parent()->Stat().LastDistance();
else
baseCase = BaseCase(queryIndex, referenceNode.Point(0));
// Save this evaluation.
referenceNode.Stat().LastDistance() = baseCase;
}
distance = SortPolicy::CombineBest(baseCase,
referenceNode.FurthestDescendantDistance());
}
else
{
distance = SortPolicy::BestPointToNodeDistance(querySet.col(queryIndex),
&referenceNode);
}
// Compare against the best k'th distance for this query point so far.
const double bestDistance = distances(distances.n_rows - 1, queryIndex);
return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}
示例5: cornerPoint
double PellegMooreKMeansRules<MetricType, TreeType>::Score(
const size_t /* queryIndex */,
TreeType& referenceNode)
{
// Obtain the parent's blacklist. If this is the root node, we'll start with
// an empty blacklist. This means that after each iteration, we don't need to
// reset any statistics.
if (referenceNode.Parent() == NULL ||
referenceNode.Parent()->Stat().Blacklist().n_elem == 0)
referenceNode.Stat().Blacklist().zeros(centroids.n_cols);
else
referenceNode.Stat().Blacklist() =
referenceNode.Parent()->Stat().Blacklist();
// The query index is a fake index that we won't use, and the reference node
// holds all of the points in the dataset. Our goal is to determine whether
// or not this node is dominated by a single cluster.
const size_t whitelisted = centroids.n_cols -
arma::accu(referenceNode.Stat().Blacklist());
distanceCalculations += whitelisted;
// Which cluster has minimum distance to the node?
size_t closestCluster = centroids.n_cols;
double minMinDistance = DBL_MAX;
for (size_t i = 0; i < centroids.n_cols; ++i)
{
if (referenceNode.Stat().Blacklist()[i] == 0)
{
const double minDistance = referenceNode.MinDistance(centroids.col(i));
if (minDistance < minMinDistance)
{
minMinDistance = minDistance;
closestCluster = i;
}
}
}
// Now, for every other whitelisted cluster, determine if the closest cluster
// owns the point. This calculation is specific to hyperrectangle trees (but,
// this implementation is specific to kd-trees, so that's okay). For
// circular-bound trees, the condition should be simpler and can probably be
// expressed as a comparison between minimum and maximum distances.
size_t newBlacklisted = 0;
for (size_t c = 0; c < centroids.n_cols; ++c)
{
if (referenceNode.Stat().Blacklist()[c] == 1 || c == closestCluster)
continue;
// This algorithm comes from the proof of Lemma 4 in the extended version
// of the Pelleg-Moore paper (the CMU tech report, that is). It has been
// adapted for speed.
arma::vec cornerPoint(centroids.n_rows);
for (size_t d = 0; d < referenceNode.Bound().Dim(); ++d)
{
if (centroids(d, c) > centroids(d, closestCluster))
cornerPoint(d) = referenceNode.Bound()[d].Hi();
else
cornerPoint(d) = referenceNode.Bound()[d].Lo();
}
const double closestDist = metric.Evaluate(cornerPoint,
centroids.col(closestCluster));
const double otherDist = metric.Evaluate(cornerPoint, centroids.col(c));
distanceCalculations += 3; // One for cornerPoint, then two distances.
if (closestDist < otherDist)
{
// The closest cluster dominates the node with respect to the cluster c.
// So we can blacklist c.
referenceNode.Stat().Blacklist()[c] = 1;
++newBlacklisted;
}
}
if (whitelisted - newBlacklisted == 1)
{
// This node is dominated by the closest cluster.
counts[closestCluster] += referenceNode.NumDescendants();
newCentroids.col(closestCluster) += referenceNode.NumDescendants() *
referenceNode.Stat().Centroid();
return DBL_MAX;
}
// Perform the base case here.
for (size_t i = 0; i < referenceNode.NumPoints(); ++i)
{
size_t bestCluster = centroids.n_cols;
double bestDistance = DBL_MAX;
for (size_t c = 0; c < centroids.n_cols; ++c)
{
if (referenceNode.Stat().Blacklist()[c] == 1)
continue;
++distanceCalculations;
// The reference index is the index of the data point.
const double distance = metric.Evaluate(centroids.col(c),
//.........这里部分代码省略.........
示例6: localHilbertValues
DiscreteHilbertValue<TreeElemType>::
DiscreteHilbertValue(const DiscreteHilbertValue& other,
TreeType* tree,
bool deepCopy) :
localHilbertValues(NULL),
ownsLocalHilbertValues(other.ownsLocalHilbertValues),
numValues(other.NumValues()),
valueToInsert(NULL),
ownsValueToInsert(other.ownsValueToInsert)
{
if (deepCopy)
{
// Only leaf nodes own the localHilbertValues dataset.
// Intermediate nodes store the pointer to the corresponding dataset.
if (ownsLocalHilbertValues)
localHilbertValues = new arma::Mat<HilbertElemType>(
*other.LocalHilbertValues());
else
localHilbertValues = NULL;
// Only the root owns ownsValueToInsert. Other nodes the pointer.
if (ownsValueToInsert)
valueToInsert = new arma::Col<HilbertElemType>(
*other.ValueToInsert());
else
{
assert(tree->Parent() != NULL);
// Copy the pointer from the parent node.
valueToInsert = const_cast<arma::Col<HilbertElemType>*>
(tree->Parent()->AuxiliaryInfo().HilbertValue().ValueToInsert());
}
if (tree->NumChildren() == 0)
{
// We have to update pointers to the localHilbertValues dataset in
// intermediate nodes.
TreeType* node = tree;
while (node->Parent() != NULL)
{
if (node->Parent()->NumChildren() > 1)
{
const std::vector<TreeType*> parentChildren =
node->AuxiliaryInfo().Children(node->Parent());
// If node is not the last child of its parent, we shouldn't copy
// the localHilbertValues pointer.
if (parentChildren[node->Parent()->NumChildren() - 2] == NULL)
break;
}
node->Parent()->AuxiliaryInfo().HilbertValue().LocalHilbertValues() =
localHilbertValues;
node = node->Parent();
}
}
}
else
{
localHilbertValues = const_cast<arma::Mat<HilbertElemType>*>
(other.LocalHilbertValues());
valueToInsert = const_cast<arma::Col<HilbertElemType>*>
(other.ValueToInsert());
}
}
示例7: CheckTrees
void CheckTrees(TreeType& tree,
TreeType& xmlTree,
TreeType& textTree,
TreeType& binaryTree)
{
const typename TreeType::Mat* dataset = &tree.Dataset();
// Make sure that the data matrices are the same.
if (tree.Parent() == NULL)
{
CheckMatrices(*dataset,
xmlTree.Dataset(),
textTree.Dataset(),
binaryTree.Dataset());
// Also ensure that the other parents are null too.
BOOST_REQUIRE_EQUAL(xmlTree.Parent(), (TreeType*) NULL);
BOOST_REQUIRE_EQUAL(textTree.Parent(), (TreeType*) NULL);
BOOST_REQUIRE_EQUAL(binaryTree.Parent(), (TreeType*) NULL);
}
// Make sure the number of children is the same.
BOOST_REQUIRE_EQUAL(tree.NumChildren(), xmlTree.NumChildren());
BOOST_REQUIRE_EQUAL(tree.NumChildren(), textTree.NumChildren());
BOOST_REQUIRE_EQUAL(tree.NumChildren(), binaryTree.NumChildren());
// Make sure the number of descendants is the same.
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), xmlTree.NumDescendants());
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), textTree.NumDescendants());
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), binaryTree.NumDescendants());
// Make sure the number of points is the same.
BOOST_REQUIRE_EQUAL(tree.NumPoints(), xmlTree.NumPoints());
BOOST_REQUIRE_EQUAL(tree.NumPoints(), textTree.NumPoints());
BOOST_REQUIRE_EQUAL(tree.NumPoints(), binaryTree.NumPoints());
// Check that each point is the same.
for (size_t i = 0; i < tree.NumPoints(); ++i)
{
BOOST_REQUIRE_EQUAL(tree.Point(i), xmlTree.Point(i));
BOOST_REQUIRE_EQUAL(tree.Point(i), textTree.Point(i));
BOOST_REQUIRE_EQUAL(tree.Point(i), binaryTree.Point(i));
}
// Check that the parent distance is the same.
BOOST_REQUIRE_CLOSE(tree.ParentDistance(), xmlTree.ParentDistance(), 1e-8);
BOOST_REQUIRE_CLOSE(tree.ParentDistance(), textTree.ParentDistance(), 1e-8);
BOOST_REQUIRE_CLOSE(tree.ParentDistance(), binaryTree.ParentDistance(), 1e-8);
// Check that the furthest descendant distance is the same.
BOOST_REQUIRE_CLOSE(tree.FurthestDescendantDistance(),
xmlTree.FurthestDescendantDistance(), 1e-8);
BOOST_REQUIRE_CLOSE(tree.FurthestDescendantDistance(),
textTree.FurthestDescendantDistance(), 1e-8);
BOOST_REQUIRE_CLOSE(tree.FurthestDescendantDistance(),
binaryTree.FurthestDescendantDistance(), 1e-8);
// Check that the minimum bound distance is the same.
BOOST_REQUIRE_CLOSE(tree.MinimumBoundDistance(),
xmlTree.MinimumBoundDistance(), 1e-8);
BOOST_REQUIRE_CLOSE(tree.MinimumBoundDistance(),
textTree.MinimumBoundDistance(), 1e-8);
BOOST_REQUIRE_CLOSE(tree.MinimumBoundDistance(),
binaryTree.MinimumBoundDistance(), 1e-8);
// Recurse into the children.
for (size_t i = 0; i < tree.NumChildren(); ++i)
{
// Check that the child dataset is the same.
BOOST_REQUIRE_EQUAL(&xmlTree.Dataset(), &xmlTree.Child(i).Dataset());
BOOST_REQUIRE_EQUAL(&textTree.Dataset(), &textTree.Child(i).Dataset());
BOOST_REQUIRE_EQUAL(&binaryTree.Dataset(), &binaryTree.Child(i).Dataset());
// Make sure the parent link is right.
BOOST_REQUIRE_EQUAL(xmlTree.Child(i).Parent(), &xmlTree);
BOOST_REQUIRE_EQUAL(textTree.Child(i).Parent(), &textTree);
BOOST_REQUIRE_EQUAL(binaryTree.Child(i).Parent(), &binaryTree);
CheckTrees(tree.Child(i), xmlTree.Child(i), textTree.Child(i),
binaryTree.Child(i));
}
}
示例8: TreeType
bool HilbertRTreeSplit<splitOrder>::
SplitNonLeafNode(TreeType* tree, std::vector<bool>& relevels)
{
// If we are splitting the root node, we need will do things differently so
// that the constructor and other methods don't confuse the end user by giving
// an address of another node.
if (tree->Parent() == NULL)
{
// We actually want to copy this way. Pointers and everything.
TreeType* copy = new TreeType(*tree, false);
// Only the root node owns this variable.
copy->AuxiliaryInfo().HilbertValue().OwnsValueToInsert() = false;
copy->Parent() = tree;
tree->NumChildren() = 0;
tree->NullifyData();
tree->children[(tree->NumChildren())++] = copy;
SplitNonLeafNode(copy, relevels);
return true;
}
TreeType* parent = tree->Parent();
size_t iTree = 0;
for (iTree = 0; parent->children[iTree] != tree; iTree++);
// Try to find splitOrder cooperating siblings in order to redistribute
// children among them and avoid split.
size_t firstSibling, lastSibling;
if (FindCooperatingSiblings(parent, iTree, firstSibling, lastSibling))
{
RedistributeNodesEvenly(parent, firstSibling, lastSibling);
return false;
}
// We can not find splitOrder cooperating siblings since they are all full.
// We introduce new one instead.
size_t iNewSibling = (iTree + splitOrder < parent->NumChildren() ?
iTree + splitOrder : parent->NumChildren());
for (size_t i = parent->NumChildren(); i > iNewSibling ; i--)
parent->children[i] = parent->children[i - 1];
parent->NumChildren()++;
parent->children[iNewSibling] = new TreeType(parent);
lastSibling = (iTree + splitOrder < parent->NumChildren() ?
iTree + splitOrder : parent->NumChildren() - 1);
firstSibling = (lastSibling > splitOrder ?
lastSibling - splitOrder : 0);
assert(lastSibling - firstSibling <= splitOrder);
assert(firstSibling >= 0);
assert(lastSibling < parent->NumChildren());
// Redistribute children among (splitOrder + 1) cooperating siblings evenly.
RedistributeNodesEvenly(parent, firstSibling, lastSibling);
if (parent->NumChildren() == parent->MaxNumChildren() + 1)
SplitNonLeafNode(parent, relevels);
return false;
}
示例9: points
void HilbertRTreeSplit<splitOrder>::
RedistributePointsEvenly(TreeType* parent,
const size_t firstSibling,
const size_t lastSibling)
{
size_t numPoints = 0;
size_t numPointsPerNode, numRestPoints;
for (size_t i = firstSibling; i <= lastSibling; i++)
numPoints += parent->Child(i).NumPoints();
numPointsPerNode = numPoints / (lastSibling - firstSibling + 1);
numRestPoints = numPoints % (lastSibling - firstSibling + 1);
std::vector<size_t> points(numPoints);
// Copy children's points in order to redistribute them.
size_t iPoint = 0;
for (size_t i = firstSibling; i <= lastSibling; i++)
{
for (size_t j = 0; j < parent->Child(i).NumPoints(); j++)
points[iPoint++] = parent->Child(i).Point(j);
}
iPoint = 0;
for (size_t i = firstSibling; i <= lastSibling; i++)
{
// Since we redistribute points of a sibling we should recalculate the
// bound.
parent->Child(i).Bound().Clear();
size_t j;
for (j = 0; j < numPointsPerNode; j++)
{
parent->Child(i).Bound() |= parent->Dataset().col(points[iPoint]);
parent->Child(i).Point(j) = points[iPoint];
iPoint++;
}
if (numRestPoints > 0)
{
parent->Child(i).Bound() |= parent->Dataset().col(points[iPoint]);
parent->Child(i).Point(j) = points[iPoint];
parent->Child(i).Count() = numPointsPerNode + 1;
numRestPoints--;
iPoint++;
}
else
{
parent->Child(i).Count() = numPointsPerNode;
}
parent->Child(i).numDescendants = parent->Child(i).Count();
assert(parent->Child(i).NumPoints() <=
parent->Child(i).MaxLeafSize());
}
// Fix the largest Hilbert values of the siblings.
parent->AuxiliaryInfo().HilbertValue().RedistributeHilbertValues(parent,
firstSibling, lastSibling);
TreeType* root = parent;
while (root != NULL)
{
root->AuxiliaryInfo().HilbertValue().UpdateLargestValue(root);
root = root->Parent();
}
}
示例10: CalculateBound
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::
CalculateBound(TreeType& queryNode) const
{
// We have five possible bounds, and we must take the best of them all. We
// don't use min/max here, but instead "best/worst", because this is general
// to the nearest-neighbors/furthest-neighbors cases. For nearest neighbors,
// min = best, max = worst.
//
// (1) worst ( worst_{all points p in queryNode} D_p[k],
// worst_{all children c in queryNode} B(c) );
// (2) best_{all points p in queryNode} D_p[k] + worst child distance +
// worst descendant distance;
// (3) best_{all children c in queryNode} B(c) +
// 2 ( worst descendant distance of queryNode -
// worst descendant distance of c );
// (4) B_1(parent of queryNode)
// (5) B_2(parent of queryNode);
//
// D_p[k] is the current k'th candidate distance for point p.
// So we will loop over the points in queryNode and the children in queryNode
// to calculate all five of these quantities.
// Hm, can we populate our distances vector with estimates from the parent?
// This is written specifically for the cover tree and assumes only one point
// in a node.
// if (queryNode.Parent() != NULL && queryNode.NumPoints() > 0)
// {
// size_t parentIndexStart = 0;
// for (size_t i = 0; i < neighbors.n_rows; ++i)
// {
// const double pointDistance = distances(i, queryNode.Point(0));
// if (pointDistance == DBL_MAX)
// {
// // Cool, can we take an estimate from the parent?
// const double parentWorstBound = distances(distances.n_rows - 1,
// queryNode.Parent()->Point(0));
// if (parentWorstBound != DBL_MAX)
// {
// const double parentAdjustedDistance = parentWorstBound +
// queryNode.ParentDistance();
// distances(i, queryNode.Point(0)) = parentAdjustedDistance;
// }
// }
// }
// }
double worstPointDistance = SortPolicy::BestDistance();
double bestPointDistance = SortPolicy::WorstDistance();
// Loop over all points in this node to find the best and worst distance
// candidates (for (1) and (2)).
for (size_t i = 0; i < queryNode.NumPoints(); ++i)
{
const double distance = distances(distances.n_rows - 1,
queryNode.Point(i));
if (SortPolicy::IsBetter(distance, bestPointDistance))
bestPointDistance = distance;
if (SortPolicy::IsBetter(worstPointDistance, distance))
worstPointDistance = distance;
}
// Loop over all the children in this node to find the worst bound (for (1))
// and the best bound with the correcting factor for descendant distances (for
// (3)).
double worstChildBound = SortPolicy::BestDistance();
double bestAdjustedChildBound = SortPolicy::WorstDistance();
const double queryMaxDescendantDistance =
queryNode.FurthestDescendantDistance();
for (size_t i = 0; i < queryNode.NumChildren(); ++i)
{
const double firstBound = queryNode.Child(i).Stat().FirstBound();
const double secondBound = queryNode.Child(i).Stat().SecondBound();
const double childMaxDescendantDistance =
queryNode.Child(i).FurthestDescendantDistance();
if (SortPolicy::IsBetter(worstChildBound, firstBound))
worstChildBound = firstBound;
// Now calculate adjustment for maximum descendant distances.
const double adjustedBound = SortPolicy::CombineWorst(secondBound,
2 * (queryMaxDescendantDistance - childMaxDescendantDistance));
if (SortPolicy::IsBetter(adjustedBound, bestAdjustedChildBound))
bestAdjustedChildBound = adjustedBound;
}
// This is bound (1).
const double firstBound =
(SortPolicy::IsBetter(worstPointDistance, worstChildBound)) ?
worstChildBound : worstPointDistance;
// This is bound (2).
const double secondBound = SortPolicy::CombineWorst(
SortPolicy::CombineWorst(bestPointDistance, queryMaxDescendantDistance),
queryNode.FurthestPointDistance());
// Bound (3) is bestAdjustedChildBound.
// Bounds (4) and (5) are the parent bounds.
const double fourthBound = (queryNode.Parent() != NULL) ?
//.........这里部分代码省略.........
示例11: if
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Score(
TreeType& queryNode,
TreeType& referenceNode)
{
++scores; // Count number of Score() calls.
// Update our bound.
const double bestDistance = CalculateBound(queryNode);
// Use the traversal info to see if a parent-child or parent-parent prune is
// possible. This is a looser bound than we could make, but it might be
// sufficient.
const double queryParentDist = queryNode.ParentDistance();
const double queryDescDist = queryNode.FurthestDescendantDistance();
const double refParentDist = referenceNode.ParentDistance();
const double refDescDist = referenceNode.FurthestDescendantDistance();
const double score = traversalInfo.LastScore();
double adjustedScore;
// We want to set adjustedScore to be the distance between the centroid of the
// last query node and last reference node. We will do this by adjusting the
// last score. In some cases, we can just use the last base case.
if (tree::TreeTraits<TreeType>::FirstPointIsCentroid)
{
adjustedScore = traversalInfo.LastBaseCase();
}
else if (score == 0.0) // Nothing we can do here.
{
adjustedScore = 0.0;
}
else
{
// The last score is equal to the distance between the centroids minus the
// radii of the query and reference bounds along the axis of the line
// between the two centroids. In the best case, these radii are the
// furthest descendant distances, but that is not always true. It would
// take too long to calculate the exact radii, so we are forced to use
// MinimumBoundDistance() as a lower-bound approximation.
const double lastQueryDescDist =
traversalInfo.LastQueryNode()->MinimumBoundDistance();
const double lastRefDescDist =
traversalInfo.LastReferenceNode()->MinimumBoundDistance();
adjustedScore = SortPolicy::CombineWorst(score, lastQueryDescDist);
adjustedScore = SortPolicy::CombineWorst(score, lastRefDescDist);
}
// Assemble an adjusted score. For nearest neighbor search, this adjusted
// score is a lower bound on MinDistance(queryNode, referenceNode) that is
// assembled without actually calculating MinDistance(). For furthest
// neighbor search, it is an upper bound on
// MaxDistance(queryNode, referenceNode). If the traversalInfo isn't usable
// then the node should not be pruned by this.
if (traversalInfo.LastQueryNode() == queryNode.Parent())
{
const double queryAdjust = queryParentDist + queryDescDist;
adjustedScore = SortPolicy::CombineBest(adjustedScore, queryAdjust);
}
else if (traversalInfo.LastQueryNode() == &queryNode)
{
adjustedScore = SortPolicy::CombineBest(adjustedScore, queryDescDist);
}
else
{
// The last query node wasn't this query node or its parent. So we force
// the adjustedScore to be such that this combination can't be pruned here,
// because we don't really know anything about it.
// It would be possible to modify this section to try and make a prune based
// on the query descendant distance and the distance between the query node
// and last traversal query node, but this case doesn't actually happen for
// kd-trees or cover trees.
adjustedScore = SortPolicy::BestDistance();
}
if (traversalInfo.LastReferenceNode() == referenceNode.Parent())
{
const double refAdjust = refParentDist + refDescDist;
adjustedScore = SortPolicy::CombineBest(adjustedScore, refAdjust);
}
else if (traversalInfo.LastReferenceNode() == &referenceNode)
{
adjustedScore = SortPolicy::CombineBest(adjustedScore, refDescDist);
}
else
{
// The last reference node wasn't this reference node or its parent. So we
// force the adjustedScore to be such that this combination can't be pruned
// here, because we don't really know anything about it.
// It would be possible to modify this section to try and make a prune based
// on the reference descendant distance and the distance between the
// reference node and last traversal reference node, but this case doesn't
// actually happen for kd-trees or cover trees.
adjustedScore = SortPolicy::BestDistance();
}
// Can we prune?
if (SortPolicy::IsBetter(bestDistance, adjustedScore))
{
if (!(tree::TreeTraits<TreeType>::FirstPointIsCentroid && score == 0.0))
//.........这里部分代码省略.........
示例12: products
double FastMKSRules<KernelType, TreeType>::CalculateBound(TreeType& queryNode)
const
{
// We have four possible bounds -- just like NeighborSearchRules, but they are
// slightly different in this context.
//
// (1) min ( min_{all points p in queryNode} P_p[k],
// min_{all children c in queryNode} B(c) );
// (2) max_{all points p in queryNode} P_p[k] + (worst child distance + worst
// descendant distance) sqrt(K(I_p[k], I_p[k]));
// (3) max_{all children c in queryNode} B(c) + <-- not done yet. ignored.
// (4) B(parent of queryNode);
double worstPointKernel = DBL_MAX;
double bestAdjustedPointKernel = -DBL_MAX;
const double queryDescendantDistance = queryNode.FurthestDescendantDistance();
// Loop over all points in this node to find the best and worst.
for (size_t i = 0; i < queryNode.NumPoints(); ++i)
{
const size_t point = queryNode.Point(i);
if (products(products.n_rows - 1, point) < worstPointKernel)
worstPointKernel = products(products.n_rows - 1, point);
if (products(products.n_rows - 1, point) == -DBL_MAX)
continue; // Avoid underflow.
// This should be (queryDescendantDistance + centroidDistance) for any tree
// but it works for cover trees since centroidDistance = 0 for cover trees.
const double candidateKernel = products(products.n_rows - 1, point) -
queryDescendantDistance *
referenceKernels[indices(indices.n_rows - 1, point)];
if (candidateKernel > bestAdjustedPointKernel)
bestAdjustedPointKernel = candidateKernel;
}
// Loop over all the children in the node.
double worstChildKernel = DBL_MAX;
for (size_t i = 0; i < queryNode.NumChildren(); ++i)
{
if (queryNode.Child(i).Stat().Bound() < worstChildKernel)
worstChildKernel = queryNode.Child(i).Stat().Bound();
}
// Now assemble bound (1).
const double firstBound = (worstPointKernel < worstChildKernel) ?
worstPointKernel : worstChildKernel;
// Bound (2) is bestAdjustedPointKernel.
const double fourthBound = (queryNode.Parent() == NULL) ? -DBL_MAX :
queryNode.Parent()->Stat().Bound();
// Pick the best of these bounds.
const double interA = (firstBound > bestAdjustedPointKernel) ? firstBound :
bestAdjustedPointKernel;
// const double interA = 0.0;
const double interB = fourthBound;
return (interA > interB) ? interA : interB;
}
示例13: CalculateBound
double FastMKSRules<KernelType, TreeType>::Score(TreeType& queryNode,
TreeType& referenceNode)
{
// Update and get the query node's bound.
queryNode.Stat().Bound() = CalculateBound(queryNode);
const double bestKernel = queryNode.Stat().Bound();
// First, see if we can make a parent-child or parent-parent prune. These
// four bounds on the maximum kernel value are looser than the bound normally
// used, but they can prevent a base case from needing to be calculated.
// Convenience caching so lines are shorter.
const double queryParentDist = queryNode.ParentDistance();
const double queryDescDist = queryNode.FurthestDescendantDistance();
const double refParentDist = referenceNode.ParentDistance();
const double refDescDist = referenceNode.FurthestDescendantDistance();
double adjustedScore = traversalInfo.LastBaseCase();
const double queryDistBound = (queryParentDist + queryDescDist);
const double refDistBound = (refParentDist + refDescDist);
double dualQueryTerm;
double dualRefTerm;
// The parent-child and parent-parent prunes work by applying the same pruning
// condition as when the parent node was used, except they are tighter because
// queryDistBound < queryNode.Parent()->FurthestDescendantDistance()
// and
// refDistBound < referenceNode.Parent()->FurthestDescendantDistance()
// so we construct the same bounds that were used when Score() was called with
// the parents, except with the tighter distance bounds. Sometimes this
// allows us to prune nodes without evaluating the base cases between them.
if (traversalInfo.LastQueryNode() == queryNode.Parent())
{
// We can assume that queryNode.Parent() != NULL, because at the root node
// combination, the traversalInfo.LastQueryNode() pointer will _not_ be
// NULL. We also should be guaranteed that
// traversalInfo.LastReferenceNode() is either the reference node or the
// parent of the reference node.
adjustedScore += queryDistBound *
traversalInfo.LastReferenceNode()->Stat().SelfKernel();
dualQueryTerm = queryDistBound;
}
else
{
// The query parent could be NULL, which does weird things and we have to
// consider.
if (traversalInfo.LastReferenceNode() != NULL)
{
adjustedScore += queryDescDist *
traversalInfo.LastReferenceNode()->Stat().SelfKernel();
dualQueryTerm = queryDescDist;
}
else
{
// This makes it so a child-parent (or parent-parent) prune is not
// possible.
dualQueryTerm = 0.0;
adjustedScore = bestKernel;
}
}
if (traversalInfo.LastReferenceNode() == referenceNode.Parent())
{
// We can assume that referenceNode.Parent() != NULL, because at the root
// node combination, the traversalInfo.LastReferenceNode() pointer will
// _not_ be NULL.
adjustedScore += refDistBound *
traversalInfo.LastQueryNode()->Stat().SelfKernel();
dualRefTerm = refDistBound;
}
else
{
// The reference parent could be NULL, which does weird things and we have
// to consider.
if (traversalInfo.LastQueryNode() != NULL)
{
adjustedScore += refDescDist *
traversalInfo.LastQueryNode()->Stat().SelfKernel();
dualRefTerm = refDescDist;
}
else
{
// This makes it so a child-parent (or parent-parent) prune is not
// possible.
dualRefTerm = 0.0;
adjustedScore = bestKernel;
}
}
// Now add the dual term.
adjustedScore += (dualQueryTerm * dualRefTerm);
if (adjustedScore < bestKernel)
{
// It is not possible that this node combination can contain a point
// combination with kernel value better than the minimum kernel value to
// improve any of the results, so we can prune it.
return DBL_MAX;
}
//.........这里部分代码省略.........