Пример #1
0
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree(const SpillTree& other) :
    left(NULL),
    right(NULL),
    parent(other.parent),
    count(other.count),
    pointsIndex(NULL),
    overlappingNode(other.overlappingNode),
    hyperplane(other.hyperplane),
    bound(other.bound),
    stat(other.stat),
    parentDistance(other.parentDistance),
    furthestDescendantDistance(other.furthestDescendantDistance),
    // Copy matrix, but only if we are the root and the other tree has its own
    // copy of the dataset.
    dataset((other.parent == NULL && other.localDataset) ?
        new MatType(*other.dataset) : other.dataset),
    localDataset(other.parent == NULL && other.localDataset)
{
  // Create left and right children (if any).
  if (other.Left())
  {
    left = new SpillTree(*other.Left());
    left->Parent() = this; // Set parent to this, not other tree.
  }

  if (other.Right())
  {
    right = new SpillTree(*other.Right());
    right->Parent() = this; // Set parent to this, not other tree.
  }

  // If vector of indexes, copy it.
  if (other.pointsIndex)
    pointsIndex = new arma::Col<size_t>(*other.pointsIndex);

  // Propagate matrix, but only if we are the root.
  if (parent == NULL && localDataset)
  {
    std::queue<SpillTree*> queue;
    if (left)
      queue.push(left);
    if (right)
      queue.push(right);
    while (!queue.empty())
    {
      SpillTree* node = queue.front();
      queue.pop();

      node->dataset = dataset;
      if (node->left)
        queue.push(node->left);
      if (node->right)
        queue.push(node->right);
    }
  }
}
Пример #2
0
size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
    SplitType>::GetFurthestChild(const SpillTree& queryNode)
{
  if (IsLeaf() || !left || !right)
    return 0;

  if (hyperplane.Left(queryNode.Bound()))
    return 1;
  if (hyperplane.Right(queryNode.Bound()))
    return 0;
  // Can't decide.
  return 2;
}
Пример #3
0
void SpillTree<MetricType, StatisticType, MatType, HyperplaneType, 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 && localDataset)
      delete dataset;
  }

  ar & CreateNVP(parent, "parent");
  ar & CreateNVP(count, "count");
  ar & CreateNVP(pointsIndex, "pointsIndex");
  ar & CreateNVP(overlappingNode, "overlappingNode");
  ar & CreateNVP(hyperplane, "hyperplane");
  ar & CreateNVP(bound, "bound");
  ar & CreateNVP(stat, "statistic");
  ar & CreateNVP(parentDistance, "parentDistance");
  ar & CreateNVP(furthestDescendantDistance, "furthestDescendantDistance");
  ar & CreateNVP(dataset, "dataset");

  if (Archive::is_loading::value && parent == NULL)
    localDataset = true;

  // 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.
    SpillTree* leftParent = left ? left->Parent() : NULL;
    SpillTree* 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 SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillSingleTreeTraverser<RuleType, Defeatist>::Traverse(
    const size_t queryIndex,
    SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>&
        referenceNode)
{
  // If we are a leaf, run the base case as necessary.
  if (referenceNode.IsLeaf())
  {
    for (size_t i = 0; i < referenceNode.NumPoints(); ++i)
      rule.BaseCase(queryIndex, referenceNode.Point(i));
  }
  else
  {
    if (Defeatist && referenceNode.Overlap())
    {
      // If referenceNode is a overlapping node we do defeatist search.
      size_t bestChild = rule.GetBestChild(queryIndex, referenceNode);
      Traverse(queryIndex, referenceNode.Child(bestChild));
      ++numPrunes;
    }
    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;
        }
      }
    }
  }
}