[mlpack-svn] r12691 - mlpack/trunk/src/mlpack/core/tree

fastlab-svn at coffeetalk-1.cc.gatech.edu fastlab-svn at coffeetalk-1.cc.gatech.edu
Wed May 16 14:44:39 EDT 2012


Author: rcurtin
Date: 2012-05-16 14:44:38 -0400 (Wed, 16 May 2012)
New Revision: 12691

Modified:
   mlpack/trunk/src/mlpack/core/tree/cover_tree_impl.hpp
Log:
Correctly handle cases where implicit nodes are created.


Modified: mlpack/trunk/src/mlpack/core/tree/cover_tree_impl.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/tree/cover_tree_impl.hpp	2012-05-16 16:34:51 UTC (rev 12690)
+++ mlpack/trunk/src/mlpack/core/tree/cover_tree_impl.hpp	2012-05-16 18:44:38 UTC (rev 12691)
@@ -50,8 +50,28 @@
   children.push_back(new CoverTree(dataset, expansionConstant, point, scale - 1,
       indices, distances, childNearSetSize, childFarSetSize, childUsedSetSize));
 
+  // If we created an implicit node, take its self-child instead (this could
+  // happen multiple times).
+  while (children[children.size() - 1]->NumChildren() == 1)
+  {
+    CoverTree* old = children[children.size() - 1];
+    children.erase(children.begin() + children.size() - 1);
+
+    // Now take its child.
+    children.push_back(&(old->Child(0)));
+
+    // Remove its child (so it doesn't delete it).
+    old->Children().erase(old->Children().begin() + old->Children().size() - 1);
+
+    // Now delete it.
+    delete old;
+  }
+
   size_t nearSetSize = (dataset.n_cols - 1) - childUsedSetSize;
 
+  if (nearSetSize == 0) // We are done.
+    return;
+
   // We have no far set, so the array is organized thusly:
   // [ near | used ].  No resorting is necessary.
   // Therefore, go ahead and build the children.
@@ -105,6 +125,24 @@
         scale - 1, indices, distances, childNearSetSize, childFarSetSize,
         childUsedSetSize));
 
+    // If we created an implicit node, take its self-child instead (this could
+    // happen multiple times).
+    while (children[children.size() - 1]->NumChildren() == 1)
+    {
+      CoverTree* old = children[children.size() - 1];
+      children.erase(children.begin() + children.size() - 1);
+
+      // Now take its child.
+      children.push_back(&(old->Child(0)));
+
+      // Remove its child (so it doesn't delete it).
+      old->Children().erase(old->Children().begin() + old->Children().size()
+          - 1);
+
+      // Now delete it.
+      delete old;
+    }
+
     // Now the arrays, in memory, look like this:
     // [ childFar | childUsed | used ]
     // So we don't really need to do anything to them to get ready for the next
@@ -138,7 +176,6 @@
     scale(scale),
     expansionConstant(expansionConstant)
 {
-
   // If the size of the near set is 0, this is a leaf.
   if (nearSetSize == 0)
     return;
@@ -195,6 +232,23 @@
       nextScale, indices, distances, childNearSetSize, childFarSetSize,
       childUsedSetSize));
 
+  // If we created an implicit node, take its self-child instead (this could
+  // happen multiple times).
+  while (children[children.size() - 1]->NumChildren() == 1)
+  {
+    CoverTree* old = children[children.size() - 1];
+    children.erase(children.begin() + children.size() - 1);
+
+    // Now take its child.
+    children.push_back(&(old->Child(0)));
+
+    // Remove its child (so it doesn't delete it).
+    old->Children().erase(old->Children().begin() + old->Children().size() - 1);
+
+    // Now delete it.
+    delete old;
+  }
+
   // Now the arrays, in memory, look like this:
   // [ childFar | childUsed | far | used ]
   // but we need to move the used points past our far set:
@@ -205,14 +259,14 @@
   SortPointSet(indices, distances, childFarSetSize, childUsedSetSize,
       farSetSize);
 
-  // The self-child should not have used all the points in the near set.  If it
-  // did, this is an implicit node.
-  Log::Assert(childUsedSetSize < nearSetSize);
-
   // Update size of near set and used set.
   nearSetSize -= childUsedSetSize;
   usedSetSize += childUsedSetSize;
 
+  // If we used all the points in the near set, we don't need to continue.
+  if (nearSetSize == 0)
+    return;
+
   // Now for each point in the near set, we need to make children.  To save
   // computation later, we'll create an array holding the points in the near
   // set, and then after each run we'll check which of those (if any) were used
@@ -271,6 +325,24 @@
         nextScale, indices, distances, childNearSetSize, childFarSetSize,
         childUsedSetSize));
 
+    // If we created an implicit node, take its self-child instead (this could
+    // happen multiple times).
+    while (children[children.size() - 1]->NumChildren() == 1)
+    {
+      CoverTree* old = children[children.size() - 1];
+      children.erase(children.begin() + children.size() - 1);
+
+      // Now take its child.
+      children.push_back(&(old->Child(0)));
+
+      // Remove its child (so it doesn't delete it).
+      old->Children().erase(old->Children().begin() + old->Children().size()
+          - 1);
+
+      // Now delete it.
+      delete old;
+    }
+
     // Now the arrays, in memory, look like this:
     // [ childFar | childUsed | used ]
     // So we don't really need to do anything to them to get ready for the next
@@ -306,9 +378,7 @@
   // because all the points in the near set should be used up.
   farSetSize = childFarSetSize;
 
-  // No need to rebuild the distances if we never modified them.
-  if (nearSet.n_elem != 0)
-    ComputeDistances(pointIndex, indices, distances, farSetSize);
+  ComputeDistances(pointIndex, indices, distances, farSetSize);
 }
 
 template<typename MetricType, typename RootPointPolicy, typename StatisticType>




More information about the mlpack-svn mailing list