[mlpack-svn] r10893 - in mlpack/tags: . mlpack-1.0.0 mlpack-1.0.0/src/mlpack mlpack-1.0.0/src/mlpack/core/tree mlpack-1.0.0/src/mlpack/core/util mlpack-1.0.0/src/mlpack/methods mlpack-1.0.0/src/mlpack/tests
fastlab-svn at coffeetalk-1.cc.gatech.edu
fastlab-svn at coffeetalk-1.cc.gatech.edu
Sat Dec 17 04:02:48 EST 2011
Author: rcurtin
Date: 2011-12-17 04:02:47 -0500 (Sat, 17 Dec 2011)
New Revision: 10893
Added:
mlpack/tags/mlpack-1.0.0/
mlpack/tags/mlpack-1.0.0/src/mlpack/core.hpp
mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/CMakeLists.txt
mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/bounds.hpp
mlpack/tags/mlpack-1.0.0/src/mlpack/core/util/save_restore_utility.cpp
mlpack/tags/mlpack-1.0.0/src/mlpack/methods/CMakeLists.txt
mlpack/tags/mlpack-1.0.0/src/mlpack/tests/tree_test.cpp
Removed:
mlpack/tags/mlpack-1.0.0/src/mlpack/core.hpp
mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/CMakeLists.txt
mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/bounds.hpp
mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/periodichrectbound.hpp
mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/periodichrectbound_impl.hpp
mlpack/tags/mlpack-1.0.0/src/mlpack/core/util/save_restore_utility.cpp
mlpack/tags/mlpack-1.0.0/src/mlpack/methods/CMakeLists.txt
mlpack/tags/mlpack-1.0.0/src/mlpack/methods/kernel_pca/
mlpack/tags/mlpack-1.0.0/src/mlpack/tests/tree_test.cpp
mlpack/tags/mlpack-1.0/
Modified:
mlpack/tags/mlpack-1.0.0/Doxyfile
mlpack/tags/mlpack-1.0.0/src/mlpack/CMakeLists.txt
Log:
Move to 1.0.0 (more specific version).
Modified: mlpack/tags/mlpack-1.0.0/Doxyfile
===================================================================
--- mlpack/tags/mlpack-1.0/Doxyfile 2011-12-17 08:36:15 UTC (rev 10887)
+++ mlpack/tags/mlpack-1.0.0/Doxyfile 2011-12-17 09:02:47 UTC (rev 10893)
@@ -4,7 +4,7 @@
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = MLPACK
-PROJECT_NUMBER = trunk
+PROJECT_NUMBER = 1.0.0
OUTPUT_DIRECTORY = ./doc
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
Modified: mlpack/tags/mlpack-1.0.0/src/mlpack/CMakeLists.txt
===================================================================
--- mlpack/tags/mlpack-1.0/src/mlpack/CMakeLists.txt 2011-12-17 08:36:15 UTC (rev 10887)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/CMakeLists.txt 2011-12-17 09:02:47 UTC (rev 10893)
@@ -26,8 +26,8 @@
)
set_target_properties(mlpack
PROPERTIES
- VERSION 0.99.0
- SOVERSION 0.99.0
+ VERSION 1.0.0
+ SOVERSION 1.0.0
)
# Collect all header files in the library.
Deleted: mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/CMakeLists.txt
===================================================================
--- mlpack/tags/mlpack-1.0/src/mlpack/core/tree/CMakeLists.txt 2011-12-17 08:36:15 UTC (rev 10887)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/CMakeLists.txt 2011-12-17 09:02:47 UTC (rev 10893)
@@ -1,25 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-# Define the files we need to compile.
-# Anything not in this list will not be compiled into MLPACK.
-set(SOURCES
- ballbound.hpp
- ballbound_impl.hpp
- binary_space_tree.hpp
- binary_space_tree_impl.hpp
- bounds.hpp
- hrectbound.hpp
- hrectbound_impl.hpp
- periodichrectbound.hpp
- periodichrectbound_impl.hpp
- statistic.hpp
-)
-
-# add directory name to sources
-set(DIR_SRCS)
-foreach(file ${SOURCES})
- set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file})
-endforeach()
-# Append sources (with directory name) to list of all MLPACK sources (used at
-# the parent scope).
-set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
Copied: mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/CMakeLists.txt (from rev 10889, mlpack/tags/mlpack-1.0/src/mlpack/core/tree/CMakeLists.txt)
===================================================================
--- mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/CMakeLists.txt (rev 0)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/CMakeLists.txt 2011-12-17 09:02:47 UTC (rev 10893)
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 2.8)
+
+# Define the files we need to compile.
+# Anything not in this list will not be compiled into MLPACK.
+set(SOURCES
+ ballbound.hpp
+ ballbound_impl.hpp
+ binary_space_tree.hpp
+ binary_space_tree_impl.hpp
+ bounds.hpp
+ hrectbound.hpp
+ hrectbound_impl.hpp
+ statistic.hpp
+)
+
+# add directory name to sources
+set(DIR_SRCS)
+foreach(file ${SOURCES})
+ set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file})
+endforeach()
+# Append sources (with directory name) to list of all MLPACK sources (used at
+# the parent scope).
+set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
Deleted: mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/bounds.hpp
===================================================================
--- mlpack/tags/mlpack-1.0/src/mlpack/core/tree/bounds.hpp 2011-12-17 08:36:15 UTC (rev 10887)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/bounds.hpp 2011-12-17 09:02:47 UTC (rev 10893)
@@ -1,17 +0,0 @@
-/**
- * @file bounds.hpp
- *
- * Bounds that are useful for binary space partitioning trees.
- */
-
-#ifndef __MLPACK_CORE_TREE_BOUNDS_HPP
-#define __MLPACK_CORE_TREE_BOUNDS_HPP
-
-#include <mlpack/core/math/range.hpp>
-#include <mlpack/core/metrics/lmetric.hpp>
-
-#include "hrectbound.hpp"
-#include "periodichrectbound.hpp"
-#include "ballbound.hpp"
-
-#endif // __MLPACK_CORE_TREE_BOUNDS_HPP
Copied: mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/bounds.hpp (from rev 10891, mlpack/tags/mlpack-1.0/src/mlpack/core/tree/bounds.hpp)
===================================================================
--- mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/bounds.hpp (rev 0)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/bounds.hpp 2011-12-17 09:02:47 UTC (rev 10893)
@@ -0,0 +1,16 @@
+/**
+ * @file bounds.hpp
+ *
+ * Bounds that are useful for binary space partitioning trees.
+ */
+
+#ifndef __MLPACK_CORE_TREE_BOUNDS_HPP
+#define __MLPACK_CORE_TREE_BOUNDS_HPP
+
+#include <mlpack/core/math/range.hpp>
+#include <mlpack/core/metrics/lmetric.hpp>
+
+#include "hrectbound.hpp"
+#include "ballbound.hpp"
+
+#endif // __MLPACK_CORE_TREE_BOUNDS_HPP
Deleted: mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/periodichrectbound.hpp
===================================================================
--- mlpack/tags/mlpack-1.0/src/mlpack/core/tree/periodichrectbound.hpp 2011-12-17 08:36:15 UTC (rev 10887)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/periodichrectbound.hpp 2011-12-17 09:02:47 UTC (rev 10893)
@@ -1,145 +0,0 @@
-/**
- * @file tree/periodichrectbound.h
- *
- * Bounds that are useful for binary space partitioning trees.
- *
- * This file describes the interface for the PeriodicHRectBound policy, which
- * implements a hyperrectangle bound in a periodic space.
- */
-#ifndef __MLPACK_CORE_TREE_PERCLIDICHRECTBOUND_HPP
-#define __MLPACK_CORE_TREE_PERCLIDICHRECTBOUND_HPP
-
-#include <mlpack/core.hpp>
-
-namespace mlpack {
-namespace bound {
-
-/**
- * Hyper-rectangle bound for an L-metric.
- *
- * Template parameter t_pow is the metric to use; use 2 for Euclidean (L2).
- */
-template<int t_pow = 2>
-class PeriodicHRectBound
-{
- public:
- /**
- * Empty constructor.
- */
- PeriodicHRectBound();
-
- /**
- * Specifies the box size. The dimensionality is set to the same of the box
- * size, and the bounds are initialized to be empty.
- */
- PeriodicHRectBound(arma::vec box);
-
- /***
- * Copy constructor and copy operator. These are necessary because we do our
- * own memory management.
- */
- PeriodicHRectBound(const PeriodicHRectBound& other);
- PeriodicHRectBound& operator=(const PeriodicHRectBound& other);
-
- /**
- * Destructor: clean up memory.
- */
- ~PeriodicHRectBound();
-
- /**
- * Modifies the box to the desired dimenstions.
- */
- void SetBoxSize(arma::vec box);
-
- /**
- * Returns the box vector.
- */
- const arma::vec& Box() const { return box; }
-
- /**
- * Resets all dimensions to the empty set.
- */
- void Clear();
-
- /** Gets the dimensionality */
- size_t Dim() const { return dim; }
-
- /**
- * Sets and gets the range for a particular dimension.
- */
- math::Range& operator[](size_t i);
- const math::Range operator[](size_t i) const;
-
- /***
- * Calculates the centroid of the range. This does not factor in periodic
- * coordinates, so the centroid may not necessarily be inside the given box.
- *
- * @param centroid Vector to write the centroid to.
- */
- void Centroid(arma::vec& centroid) const;
-
- /**
- * Calculates minimum bound-to-point squared distance in the periodic bound
- * case.
- */
- double MinDistance(const arma::vec& point) const;
-
- /**
- * Calculates minimum bound-to-bound squared distance in the periodic bound
- * case.
- *
- * Example: bound1.MinDistance(other) for minimum squared distance.
- */
- double MinDistance(const PeriodicHRectBound& other) const;
-
- /**
- * Calculates maximum bound-to-point squared distance in the periodic bound
- * case.
- */
- double MaxDistance(const arma::vec& point) const;
-
- /**
- * Computes maximum bound-to-bound squared distance in the periodic bound
- * case.
- */
- double MaxDistance(const PeriodicHRectBound& other) const;
-
- /**
- * Calculates minimum and maximum bound-to-point squared distance in the
- * periodic bound case.
- */
- math::Range RangeDistance(const arma::vec& point) const;
-
- /**
- * Calculates minimum and maximum bound-to-bound squared distance in the
- * periodic bound case.
- */
- math::Range RangeDistance(const PeriodicHRectBound& other) const;
-
- /**
- * Expands this region to include a new point.
- */
- PeriodicHRectBound& operator|=(const arma::vec& vector);
-
- /**
- * Expands this region to encompass another bound.
- */
- PeriodicHRectBound& operator|=(const PeriodicHRectBound& other);
-
- /**
- * Determines if a point is within this bound.
- */
- bool Contains(const arma::vec& point) const;
-
- private:
- math::Range *bounds;
- size_t dim;
- arma::vec box;
-};
-
-}; // namespace bound
-}; // namespace mlpack
-
-#include "periodichrectbound_impl.hpp"
-
-#endif // __MLPACK_CORE_TREE_PERCLIDICHRECTBOUND_HPP
Deleted: mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/periodichrectbound_impl.hpp
===================================================================
--- mlpack/tags/mlpack-1.0/src/mlpack/core/tree/periodichrectbound_impl.hpp 2011-12-17 08:36:15 UTC (rev 10887)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/core/tree/periodichrectbound_impl.hpp 2011-12-17 09:02:47 UTC (rev 10893)
@@ -1,571 +0,0 @@
-/**
- * @file tree/periodichrectbound_impl.h
- *
- * Implementation of periodic hyper-rectangle bound policy class.
- * Template parameter t_pow is the metric to use; use 2 for Euclidian (L2).
- */
-#ifndef __MLPACK_CORE_TREE_PERIODICHRECTBOUND_IMPL_HPP
-#define __MLPACK_CORE_TREE_PERIODICHRECTBOUND_IMPL_HPP
-
-// In case it has not already been included.
-#include "periodichrectbound.hpp"
-
-#include <math.h>
-
-namespace mlpack {
-namespace bound {
-
-/**
- * Empty constructor
- */
-template<int t_pow>
-PeriodicHRectBound<t_pow>::PeriodicHRectBound() :
- bounds(NULL),
- dim(0),
- box(/* empty */)
-{ /* nothing to do */ }
-
-/**
- * Specifies the box size, but not dimensionality.
- */
-template<int t_pow>
-PeriodicHRectBound<t_pow>::PeriodicHRectBound(arma::vec box) :
- bounds(new math::Range[box.n_rows]),
- dim(box.n_rows),
- box(box)
-{ /* nothing to do */ }
-
-/***
- * Copy constructor.
- */
-template<int t_pow>
-PeriodicHRectBound<t_pow>::PeriodicHRectBound(const PeriodicHRectBound& other) :
- dim(other.Dim()),
- box(other.box())
-{
- bounds = new math::Range[other.Dim()];
- for (size_t i = 0; i < dim; i++)
- bounds[i] |= other[i];
-}
-
-/***
- * Copy operator.
- */
-template<int t_pow>
-PeriodicHRectBound<t_pow>& PeriodicHRectBound<t_pow>::operator=(
- const PeriodicHRectBound& other)
-{
- // not done yet
-
- return *this;
-}
-
-/**
- * Destructor: clean up memory
- */
-template<int t_pow>
-PeriodicHRectBound<t_pow>::~PeriodicHRectBound()
-{
- if (bounds)
- delete[] bounds;
-}
-
-/**
- * Modifies the box to the desired dimenstions.
- */
-template<int t_pow>
-void PeriodicHRectBound<t_pow>::SetBoxSize(arma::vec box)
-{
- box = box;
-}
-
-/**
- * Resets all dimensions to the empty set.
- */
-template<int t_pow>
-void PeriodicHRectBound<t_pow>::Clear()
-{
- for (size_t i = 0; i < dim; i++)
- bounds[i] = math::Range();
-}
-
-/**
- * Gets the range for a particular dimension.
- */
-template<int t_pow>
-const math::Range PeriodicHRectBound<t_pow>::operator[](size_t i) const
-{
- return bounds[i];
-}
-
-/**
- * Sets the range for the given dimension.
- */
-template<int t_pow>
-math::Range& PeriodicHRectBound<t_pow>::operator[](size_t i)
-{
- return bounds[i];
-}
-
-/** Calculates the midpoint of the range */
-template<int t_pow>
-void PeriodicHRectBound<t_pow>::Centroid(arma::vec& centroid) const
-{
- // set size correctly if necessary
- if (!(centroid.n_elem == dim))
- centroid.set_size(dim);
-
- for (size_t i = 0; i < dim; i++)
- centroid(i) = bounds[i].Mid();
-}
-
-/**
- * Calculates minimum bound-to-point squared distance.
- *
- */
-
-template<int t_pow>
-double PeriodicHRectBound<t_pow>::MinDistance(const arma::vec& point) const
-{
- arma::vec point2 = point;
- double totalMin = 0;
- // Create the mirrored images. The minimum distance from the bound to a
- // mirrored point is the minimum periodic distance.
- arma::vec box = box;
- for (int i = 0; i < dim; i++)
- {
- point2 = point;
- double min = 100000000;
- // Mod the point within the box.
-
- if (box[i] < 0)
- {
- box[i] = abs(box[i]);
- }
- if (box[i] != 0)
- {
- if (abs(point[i]) > box[i])
- {
- point2[i] = fmod(point2[i],box[i]);
- }
- }
-
- for (int k = 0; k < 3; k++)
- {
- arma::vec point3 = point2;
-
- if (k == 1)
- point3[i] += box[i];
- else if (k == 2)
- point3[i] -= box[i];
-
- double tempMin;
- double sum = 0;
-
- double lower, higher;
- lower = bounds[i].Lo() - point3[i];
- higher = point3[i] - bounds[i].Hi();
-
- sum += pow((lower + fabs(lower)) +
- (higher + fabs(higher)), (double) t_pow);
- tempMin = pow(sum, 2.0 / (double) t_pow) / 4.0;
-
- if (tempMin < min)
- min = tempMin;
- }
-
- totalMin += min;
- }
- return totalMin;
-
-}
-
-/**
- * Calculates minimum bound-to-bound squared distance.
- *
- * Example: bound1.MinDistance(other) for minimum squared distance.
- */
-template<int t_pow>
-double PeriodicHRectBound<t_pow>::MinDistance(
- const PeriodicHRectBound& other) const
-{
- double totalMin = 0;
- // Create the mirrored images. The minimum distance from the bound to a
- // mirrored point is the minimum periodic distance.
- arma::vec box = box;
- PeriodicHRectBound<2> a(other);
-
- for (int i = 0; i < dim; i++)
- {
- double min = DBL_MAX;
- if (box[i] < 0)
- box[i] = abs(box[i]);
-
- if (box[i] != 0)
- {
- if (abs(other[i].Lo()) > box[i])
- a[i].Lo() = fmod(a[i].Lo(),box[i]);
-
- if (abs(other[i].Hi()) > box[i])
- a[i].Hi() = fmod(a[i].Hi(),box[i]);
- }
-
- for (int k = 0; k < 3; k++)
- {
- PeriodicHRectBound<2> b = a;
- if (k == 1)
- {
- b[i].Lo() += box[i];
- b[i].Hi() += box[i];
- }
- else if (k == 2)
- {
- b[i].Lo() -= box[i];
- b[i].Hi() -= box[i];
- }
-
- double sum = 0;
- double tempMin;
- double sumLower = 0;
- double sumHigher = 0;
-
- double lower, higher, lowerLower, lowerHigher, higherLower,
- higherHigher;
-
- // If the bound crosses over the box, split ito two seperate bounds and
- // find the minimum distance between them.
- if (b[i].Hi() < b[i].Lo())
- {
- PeriodicHRectBound<2> d(b);
- PeriodicHRectBound<2> c(b);
- d[i].Lo() = 0;
- c[i].Hi() = box[i];
-
- if (k == 1)
- {
- d[i].Lo() += box[i];
- c[i].Hi() += box[i];
- }
- else if (k == 2)
- {
- d[i].Lo() -= box[i];
- c[i].Hi() -= box[i];
- }
-
- d[i].Hi() = b[i].Hi();
- c[i].Lo() = b[i].Lo();
-
- lowerLower = d[i].Lo() - bounds[i].Hi();
- higherLower = bounds[i].Lo() - d[i].Hi();
-
- lowerHigher = c[i].Lo() - bounds[i].Hi();
- higherHigher = bounds[i].Lo() - c[i].Hi();
-
- sumLower += pow((lowerLower + fabs(lowerLower)) +
- (higherLower + fabs(higherLower)), (double) t_pow);
-
- sumHigher += pow((lowerHigher + fabs(lowerHigher)) +
- (higherHigher + fabs(higherHigher)), (double) t_pow);
-
- if (sumLower > sumHigher)
- tempMin = pow(sumHigher, 2.0 / (double) t_pow) / 4.0;
- else
- tempMin = pow(sumLower, 2.0 / (double) t_pow) / 4.0;
- }
- else
- {
- lower = b[i].Lo() - bounds[i].Hi();
- higher = bounds[i].Lo() - b[i].Hi();
- // We invoke the following:
- // x + fabs(x) = max(x * 2, 0)
- // (x * 2)^2 / 4 = x^2
- sum += pow((lower + fabs(lower)) +
- (higher + fabs(higher)), (double) t_pow);
- tempMin = pow(sum, 2.0 / (double) t_pow) / 4.0;
- }
-
- if (tempMin < min)
- min = tempMin;
- }
- totalMin += min;
- }
- return totalMin;
-}
-
-
-/**
- * Calculates maximum bound-to-point squared distance.
- */
-template<int t_pow>
-double PeriodicHRectBound<t_pow>::MaxDistance(const arma::vec& point) const
-{
- arma::vec point2 = point;
- double totalMax = 0;
- //Create the mirrored images. The minimum distance from the bound to a
- //mirrored point is the minimum periodic distance.
- arma::vec box = box;
- for (int i = 0; i < dim; i++)
- {
- point2 = point;
- double max = 0;
- // Mod the point within the box.
-
- if (box[i] < 0)
- box[i] = abs(box[i]);
-
- if (box[i] != 0)
- if (abs(point[i]) > box[i])
- point2[i] = fmod(point2[i],box[i]);
-
- for (int k = 0; k < 3; k++)
- {
- arma::vec point3 = point2;
-
- if (k == 1)
- point3[i] += box[i];
- else if (k == 2)
- point3[i] -= box[i];
-
- double tempMax;
- double sum = 0;
-
- double v = fabs(std::max(point3[i] - bounds[i].Lo(),
- bounds[i].Hi() - point3[i]));
- sum += pow(v, (double) t_pow);
-
- tempMax = pow(sum, 2.0 / (double) t_pow) / 4.0;
-
- if (tempMax > max)
- max = tempMax;
- }
-
- totalMax += max;
- }
- return totalMax;
-
-}
-
-/**
- * Computes maximum distance.
- */
-template<int t_pow>
-double PeriodicHRectBound<t_pow>::MaxDistance(
- const PeriodicHRectBound& other) const
-{
- double totalMax = 0;
- //Create the mirrored images. The minimum distance from the bound to a
- //mirrored point is the minimum periodic distance.
- arma::vec box = box;
- PeriodicHRectBound<2> a(other);
-
-
- for (int i = 0; i < dim; i++)
- {
- double max = 0;
- if (box[i] < 0)
- box[i] = abs(box[i]);
-
- if (box[i] != 0)
- {
- if (abs(other[i].Lo()) > box[i])
- a[i].Lo() = fmod(a[i].Lo(),box[i]);
-
- if (abs(other[i].Hi()) > box[i])
- a[i].Hi() = fmod(a[i].Hi(),box[i]);
- }
-
- for (int k = 0; k < 3; k++)
- {
- PeriodicHRectBound<2> b = a;
- if (k == 1)
- {
- b[i].Lo() += box[i];
- b[i].Hi() += box[i];
- }
- else if (k == 2)
- {
- b[i].Lo() -= box[i];
- b[i].Hi() -= box[i];
- }
-
- double sum = 0;
- double tempMax;
-
- double sumLower = 0, sumHigher = 0;
-
-
- // If the bound corsses over the box, split ito two seperate bounds and
- // find thhe minimum distance between them.
- if (b[i].Hi() < b[i].Lo())
- {
- PeriodicHRectBound<2> d(b);
- PeriodicHRectBound<2> c(b);
- a[i].Lo() = 0;
- c[i].Hi() = box[i];
-
- if (k == 1)
- {
- d[i].Lo() += box[i];
- c[i].Hi() += box[i];
- }
- else if (k == 2)
- {
- d[i].Lo() -= box[i];
- c[i].Hi() -= box[i];
- }
-
- d[i].Hi() = b[i].Hi();
- c[i].Lo() = b[i].Lo();
-
- double vLower = fabs(std::max(d.bounds[i].Hi() - bounds[i].Lo(),
- bounds[i].Hi() - d.bounds[i].Lo()));
-
- double vHigher = fabs(std::max(c.bounds[i].Hi() - bounds[i].Lo(),
- bounds[i].Hi() - c.bounds[i].Lo()));
-
- sumLower += pow(vLower, (double) t_pow);
- sumHigher += pow(vHigher, (double) t_pow);
-
- if (sumLower > sumHigher)
- tempMax = pow(sumHigher, 2.0 / (double) t_pow) / 4.0;
- else
- tempMax = pow(sumLower, 2.0 / (double) t_pow) / 4.0;
- }
- else
- {
- double v = fabs(std::max(b.bounds[i].Hi() - bounds[i].Lo(),
- bounds[i].Hi() - b.bounds[i].Lo()));
- sum += pow(v, (double) t_pow); // v is non-negative.
- tempMax = pow(sum, 2.0 / (double) t_pow);
- }
-
-
- if (tempMax > max)
- max = tempMax;
- }
- totalMax += max;
- }
- return totalMax;
-}
-
-/**
- * Calculates minimum and maximum bound-to-point squared distance.
- */
-template<int t_pow>
-math::Range PeriodicHRectBound<t_pow>::RangeDistance(
- const arma::vec& point) const
-{
- double sum_lo = 0;
- double sum_hi = 0;
-
- Log::Assert(point.n_elem == dim);
-
- double v1, v2, v_lo, v_hi;
- for (size_t d = 0; d < dim; d++)
- {
- v1 = bounds[d].Lo() - point[d];
- v2 = point[d] - bounds[d].Hi();
- // One of v1 or v2 is negative.
- if (v1 >= 0)
- {
- v_hi = -v2;
- v_lo = v1;
- }
- else
- {
- v_hi = -v1;
- v_lo = v2;
- }
-
- sum_lo += pow(v_lo, (double) t_pow);
- sum_hi += pow(v_hi, (double) t_pow);
- }
-
- return math::Range(pow(sum_lo, 2.0 / (double) t_pow),
- pow(sum_hi, 2.0 / (double) t_pow));
-}
-
-/**
- * Calculates minimum and maximum bound-to-bound squared distance.
- */
-template<int t_pow>
-math::Range PeriodicHRectBound<t_pow>::RangeDistance(
- const PeriodicHRectBound& other) const
-{
- double sum_lo = 0;
- double sum_hi = 0;
-
- Log::Assert(dim == other.dim);
-
- double v1, v2, v_lo, v_hi;
- for (size_t d = 0; d < dim; d++)
- {
- v1 = other.bounds[d].Lo() - bounds[d].Hi();
- v2 = bounds[d].Lo() - other.bounds[d].Hi();
- // One of v1 or v2 is negative.
- if (v1 >= v2)
- {
- v_hi = -v2; // Make it nonnegative.
- v_lo = (v1 > 0) ? v1 : 0; // Force to be 0 if negative.
- }
- else
- {
- v_hi = -v1; // Make it nonnegative.
- v_lo = (v2 > 0) ? v2 : 0; // Force to be 0 if negative.
- }
-
- sum_lo += pow(v_lo, (double) t_pow);
- sum_hi += pow(v_hi, (double) t_pow);
- }
-
- return math::Range(pow(sum_lo, 2.0 / (double) t_pow),
- pow(sum_hi, 2.0 / (double) t_pow));
-}
-
-/**
- * Expands this region to include a new point.
- */
-template<int t_pow>
-PeriodicHRectBound<t_pow>& PeriodicHRectBound<t_pow>::operator|=(
- const arma::vec& vector)
-{
- Log::Assert(vector.n_elem == dim);
-
- for (size_t i = 0; i < dim; i++)
- bounds[i] |= vector[i];
-
- return *this;
-}
-
-/**
- * Expands this region to encompass another bound.
- */
-template<int t_pow>
-PeriodicHRectBound<t_pow>& PeriodicHRectBound<t_pow>::operator|=(
- const PeriodicHRectBound& other)
-{
- Log::Assert(other.dim == dim);
-
- for (size_t i = 0; i < dim; i++)
- bounds[i] |= other.bounds[i];
-
- return *this;
-}
-
-/**
- * Determines if a point is within this bound.
- */
-template<int t_pow>
-bool PeriodicHRectBound<t_pow>::Contains(const arma::vec& point) const
-{
- for (size_t i = 0; i < point.n_elem; i++)
- if (!bounds[i].Contains(point(i)))
- return false;
-
- return true;
-}
-
-}; // namespace bound
-}; // namespace mlpack
-
-#endif // __MLPACK_CORE_TREE_PERIODICHRECTBOUND_IMPL_HPP
Deleted: mlpack/tags/mlpack-1.0.0/src/mlpack/core/util/save_restore_utility.cpp
===================================================================
--- mlpack/tags/mlpack-1.0/src/mlpack/core/util/save_restore_utility.cpp 2011-12-17 08:36:15 UTC (rev 10887)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/core/util/save_restore_utility.cpp 2011-12-17 09:02:47 UTC (rev 10893)
@@ -1,206 +0,0 @@
-/**
- * @file utilities/save_restore_utility.cpp
- * @author Neil Slagle
- *
- * The SaveRestoreUtility provides helper functions in saving and
- * restoring models. The current output file type is XML.
- */
-#include "save_restore_utility.hpp"
-
-using namespace mlpack;
-using namespace utilities;
-
-bool SaveRestoreUtility::ReadFile(const std::string filename)
-{
- xmlDocPtr xmlDocTree = NULL;
- if (NULL == (xmlDocTree = xmlReadFile(filename.c_str(), NULL, 0)))
- {
- Log::Fatal << "Could not load XML file '" << filename << "'!" << std::endl;
- }
-
- xmlNodePtr root = xmlDocGetRootElement(xmlDocTree);
- parameters.clear();
-
- RecurseOnNodes(root->children);
- xmlFreeDoc(xmlDocTree);
- return true;
-}
-
-void SaveRestoreUtility::RecurseOnNodes(xmlNode* n)
-{
- xmlNodePtr current = NULL;
- for (current = n; current; current = current->next)
- {
- if (current->type == XML_ELEMENT_NODE)
- {
- xmlChar* content = xmlNodeGetContent(current);
- parameters[(const char*) current->name] = (const char*) content;
- xmlFree(content);
- }
- RecurseOnNodes(current->children);
- }
-}
-
-bool SaveRestoreUtility::WriteFile(const std::string filename)
-{
- bool success = false;
- xmlDocPtr xmlDocTree = xmlNewDoc(BAD_CAST "1.0");
- xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "root");
- xmlNodePtr child = NULL;
-
- xmlDocSetRootElement(xmlDocTree, root);
-
- for (std::map<std::string, std::string>::iterator it = parameters.begin();
- it != parameters.end();
- ++it)
- {
- child = xmlNewChild(root, NULL,
- BAD_CAST(*it).first.c_str(),
- BAD_CAST(*it).second.c_str());
- /* TODO: perhaps we'll add more later?
- * xmlNewProp(child, BAD_CAST "attr", BAD_CAST "add more addibutes?"); */
- }
- /* save the file */
- xmlSaveFormatFileEnc(filename.c_str(), xmlDocTree, "UTF-8", 1);
- xmlFreeDoc(xmlDocTree);
- return success;
-}
-
-arma::mat& SaveRestoreUtility::LoadParameter(arma::mat& matrix,
- const std::string name)
-{
- std::map<std::string, std::string>::iterator it = parameters.find(name);
- if (it != parameters.end())
- {
- std::string value = (*it).second;
- boost::char_separator<char> sep ("\n");
- boost::tokenizer<boost::char_separator<char> > tok (value, sep);
- std::list<std::list<double> > rows;
- for (boost::tokenizer<boost::char_separator<char> >::iterator
- tokIt = tok.begin();
- tokIt != tok.end();
- ++tokIt)
- {
- std::string row = *tokIt;
- boost::char_separator<char> sepComma (",");
- boost::tokenizer<boost::char_separator<char> >
- tokInner (row, sepComma);
- std::list<double> rowList;
- for (boost::tokenizer<boost::char_separator<char> >::iterator
- tokInnerIt = tokInner.begin();
- tokInnerIt != tokInner.end();
- ++tokInnerIt)
- {
- double element;
- std::istringstream iss (*tokInnerIt);
- iss >> element;
- rowList.push_back(element);
- }
- rows.push_back(rowList);
- }
- matrix.zeros(rows.size(), (*(rows.begin())).size());
- size_t rowCounter = 0;
- size_t columnCounter = 0;
- for (std::list<std::list<double> >::iterator rowIt = rows.begin();
- rowIt != rows.end();
- ++rowIt)
- {
- std::list<double> row = *rowIt;
- columnCounter = 0;
- for (std::list<double>::iterator elementIt = row.begin();
- elementIt != row.end();
- ++elementIt)
- {
- matrix(rowCounter, columnCounter) = *elementIt;
- columnCounter++;
- }
- rowCounter++;
- }
- return matrix;
- }
- else
- {
- Log::Fatal << "LoadParameter(): node '" << name << "' not found.\n";
- }
- return matrix;
-}
-
-std::string SaveRestoreUtility::LoadParameter(std::string& str,
- const std::string name)
-{
- std::map<std::string, std::string>::iterator it = parameters.find(name);
- if (it != parameters.end())
- {
- return str = (*it).second;
- }
- else
- {
- Log::Fatal << "LoadParameter(): node '" << name << "' not found.\n";
- }
- return "";
-}
-
-char SaveRestoreUtility::LoadParameter(char c, const std::string name)
-{
- int temp;
- std::map<std::string, std::string>::iterator it = parameters.find(name);
- if (it != parameters.end())
- {
- std::string value = (*it).second;
- std::istringstream input (value);
- input >> temp;
- return c = (char) temp;
- }
- else
- {
- Log::Fatal << "LoadParameter(): node '" << name << "' not found.\n";
- }
- return 0;
-}
-
-void SaveRestoreUtility::SaveParameter(const char c, const std::string name)
-{
- int temp = (int) c;
- std::ostringstream output;
- output << temp;
- parameters[name] = output.str();
-}
-
-void SaveRestoreUtility::SaveParameter(const arma::mat& mat,
- const std::string name)
-{
- std::ostringstream output;
- size_t columns = mat.n_cols;
- size_t rows = mat.n_rows;
- for (size_t r = 0; r < rows; ++r)
- {
- for (size_t c = 0; c < columns - 1; ++c)
- {
- output << mat(r,c) << ",";
- }
- output << mat(r,columns - 1) << std::endl;
- }
- parameters[name] = output.str();
-}
-
-// Special template specializations for vectors.
-
-namespace mlpack {
-namespace utilities {
-
-template<>
-arma::vec& SaveRestoreUtility::LoadParameter(arma::vec& t,
- const std::string name)
-{
- return (arma::vec&) LoadParameter((arma::mat&) t, name);
-}
-
-template<>
-void SaveRestoreUtility::SaveParameter(const arma::vec& t,
- const std::string name)
-{
- SaveParameter((const arma::mat&) t, name);
-}
-
-}; // namespace utilities
-}; // namespace mlpack
Copied: mlpack/tags/mlpack-1.0.0/src/mlpack/core/util/save_restore_utility.cpp (from rev 10892, mlpack/tags/mlpack-1.0/src/mlpack/core/util/save_restore_utility.cpp)
===================================================================
--- mlpack/tags/mlpack-1.0.0/src/mlpack/core/util/save_restore_utility.cpp (rev 0)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/core/util/save_restore_utility.cpp 2011-12-17 09:02:47 UTC (rev 10893)
@@ -0,0 +1,208 @@
+/**
+ * @file utilities/save_restore_utility.cpp
+ * @author Neil Slagle
+ *
+ * The SaveRestoreUtility provides helper functions in saving and
+ * restoring models. The current output file type is XML.
+ */
+#include "save_restore_utility.hpp"
+
+using namespace mlpack;
+using namespace utilities;
+
+bool SaveRestoreUtility::ReadFile(const std::string filename)
+{
+ xmlDocPtr xmlDocTree = NULL;
+ if (NULL == (xmlDocTree = xmlReadFile(filename.c_str(), NULL, 0)))
+ {
+ Log::Fatal << "Could not load XML file '" << filename << "'!" << std::endl;
+ }
+
+ xmlNodePtr root = xmlDocGetRootElement(xmlDocTree);
+ parameters.clear();
+
+ RecurseOnNodes(root->children);
+ xmlFreeDoc(xmlDocTree);
+ return true;
+}
+
+void SaveRestoreUtility::RecurseOnNodes(xmlNode* n)
+{
+ xmlNodePtr current = NULL;
+ for (current = n; current; current = current->next)
+ {
+ if (current->type == XML_ELEMENT_NODE)
+ {
+ xmlChar* content = xmlNodeGetContent(current);
+ parameters[(const char*) current->name] = (const char*) content;
+ xmlFree(content);
+ }
+ RecurseOnNodes(current->children);
+ }
+}
+
+bool SaveRestoreUtility::WriteFile(const std::string filename)
+{
+ bool success = false;
+ xmlDocPtr xmlDocTree = xmlNewDoc(BAD_CAST "1.0");
+ xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "root");
+// xmlNodePtr child = NULL;
+
+ xmlDocSetRootElement(xmlDocTree, root);
+
+ for (std::map<std::string, std::string>::iterator it = parameters.begin();
+ it != parameters.end();
+ ++it)
+ {
+// child = xmlNewChild(root, NULL,
+// BAD_CAST(*it).first.c_str(),
+// BAD_CAST(*it).second.c_str());
+ xmlNewChild(root, NULL, BAD_CAST(*it).first.c_str(),
+ BAD_CAST(*it).second.c_str());
+ /* TODO: perhaps we'll add more later?
+ * xmlNewProp(child, BAD_CAST "attr", BAD_CAST "add more addibutes?"); */
+ }
+ /* save the file */
+ xmlSaveFormatFileEnc(filename.c_str(), xmlDocTree, "UTF-8", 1);
+ xmlFreeDoc(xmlDocTree);
+ return success;
+}
+
+arma::mat& SaveRestoreUtility::LoadParameter(arma::mat& matrix,
+ const std::string name)
+{
+ std::map<std::string, std::string>::iterator it = parameters.find(name);
+ if (it != parameters.end())
+ {
+ std::string value = (*it).second;
+ boost::char_separator<char> sep ("\n");
+ boost::tokenizer<boost::char_separator<char> > tok (value, sep);
+ std::list<std::list<double> > rows;
+ for (boost::tokenizer<boost::char_separator<char> >::iterator
+ tokIt = tok.begin();
+ tokIt != tok.end();
+ ++tokIt)
+ {
+ std::string row = *tokIt;
+ boost::char_separator<char> sepComma (",");
+ boost::tokenizer<boost::char_separator<char> >
+ tokInner (row, sepComma);
+ std::list<double> rowList;
+ for (boost::tokenizer<boost::char_separator<char> >::iterator
+ tokInnerIt = tokInner.begin();
+ tokInnerIt != tokInner.end();
+ ++tokInnerIt)
+ {
+ double element;
+ std::istringstream iss (*tokInnerIt);
+ iss >> element;
+ rowList.push_back(element);
+ }
+ rows.push_back(rowList);
+ }
+ matrix.zeros(rows.size(), (*(rows.begin())).size());
+ size_t rowCounter = 0;
+ size_t columnCounter = 0;
+ for (std::list<std::list<double> >::iterator rowIt = rows.begin();
+ rowIt != rows.end();
+ ++rowIt)
+ {
+ std::list<double> row = *rowIt;
+ columnCounter = 0;
+ for (std::list<double>::iterator elementIt = row.begin();
+ elementIt != row.end();
+ ++elementIt)
+ {
+ matrix(rowCounter, columnCounter) = *elementIt;
+ columnCounter++;
+ }
+ rowCounter++;
+ }
+ return matrix;
+ }
+ else
+ {
+ Log::Fatal << "LoadParameter(): node '" << name << "' not found.\n";
+ }
+ return matrix;
+}
+
+std::string SaveRestoreUtility::LoadParameter(std::string& str,
+ const std::string name)
+{
+ std::map<std::string, std::string>::iterator it = parameters.find(name);
+ if (it != parameters.end())
+ {
+ return str = (*it).second;
+ }
+ else
+ {
+ Log::Fatal << "LoadParameter(): node '" << name << "' not found.\n";
+ }
+ return "";
+}
+
+char SaveRestoreUtility::LoadParameter(char c, const std::string name)
+{
+ int temp;
+ std::map<std::string, std::string>::iterator it = parameters.find(name);
+ if (it != parameters.end())
+ {
+ std::string value = (*it).second;
+ std::istringstream input (value);
+ input >> temp;
+ return c = (char) temp;
+ }
+ else
+ {
+ Log::Fatal << "LoadParameter(): node '" << name << "' not found.\n";
+ }
+ return 0;
+}
+
+void SaveRestoreUtility::SaveParameter(const char c, const std::string name)
+{
+ int temp = (int) c;
+ std::ostringstream output;
+ output << temp;
+ parameters[name] = output.str();
+}
+
+void SaveRestoreUtility::SaveParameter(const arma::mat& mat,
+ const std::string name)
+{
+ std::ostringstream output;
+ size_t columns = mat.n_cols;
+ size_t rows = mat.n_rows;
+ for (size_t r = 0; r < rows; ++r)
+ {
+ for (size_t c = 0; c < columns - 1; ++c)
+ {
+ output << mat(r,c) << ",";
+ }
+ output << mat(r,columns - 1) << std::endl;
+ }
+ parameters[name] = output.str();
+}
+
+// Special template specializations for vectors.
+
+namespace mlpack {
+namespace utilities {
+
+template<>
+arma::vec& SaveRestoreUtility::LoadParameter(arma::vec& t,
+ const std::string name)
+{
+ return (arma::vec&) LoadParameter((arma::mat&) t, name);
+}
+
+template<>
+void SaveRestoreUtility::SaveParameter(const arma::vec& t,
+ const std::string name)
+{
+ SaveParameter((const arma::mat&) t, name);
+}
+
+}; // namespace utilities
+}; // namespace mlpack
Deleted: mlpack/tags/mlpack-1.0.0/src/mlpack/core.hpp
===================================================================
--- mlpack/tags/mlpack-1.0/src/mlpack/core.hpp 2011-12-17 08:36:15 UTC (rev 10887)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/core.hpp 2011-12-17 09:02:47 UTC (rev 10893)
@@ -1,143 +0,0 @@
-/***
- * @file core.hpp
- *
- * Include all of the base components required to write MLPACK methods, and the
- * main MLPACK Doxygen documentation.
- */
-#ifndef __MLPACK_CORE_HPP
-#define __MLPACK_CORE_HPP
-
-/**
- * @mainpage MLPACK Documentation
- *
- * @section intro_sec Introduction
- *
- * MLPACK is an intuitive, fast, scalable C++ machine learning library, meant to
- * be a machine learning analog to LAPACK. It aims to implement a wide array of
- * machine learning methods and function as a "swiss army knife" for machine
- * learning researchers. The MLPACK development website can be found at
- * http://mlpack.org.
- *
- * MLPACK uses the Armadillo C++ matrix library (http://arma.sourceforge.net)
- * for general matrix, vector, and linear algebra support. MLPACK also uses the
- * program_options, math_c99, and unit_test_framework components of the Boost
- * library; in addition, LibXml2 is used.
- *
- * @section howto How To Use This Documentation
- *
- * This documentation is API documentation similar to Javadoc. It isn't
- * necessarily a tutorial, but it does provide detailed documentation on every
- * namespace, method, and class.
- *
- * Each MLPACK namespace generally refers to one machine learning method, so
- * browsing the list of namespaces provides some insight as to the breadth of
- * the methods contained in the library.
- *
- * To generate this documentation in your own local copy of MLPACK, you can
- * simply use Doxygen, from the root directory (@c /mlpack/trunk/ ):
- *
- * @code
- * $ doxygen
- * @endcode
- *
- * @section executables Executables
- *
- * MLPACK provides several executables so that MLPACK methods can be used
- * without any need for knowledge of C++. These executables are all
- * self-documented, and that documentation can be accessed by running the
- * executables with the '-h' or '--help' flag.
- *
- * A full list of executables is given below:
- *
- * allkfn, allknn, emst, gmm, hmm_train, hmm_loglik, hmm_viterbi, hmm_generate,
- * kernel_pca, kmeans, lars, linear_regression, nbc, nca, pca, radical
- *
- * @section tutorial Tutorials
- *
- * A few short tutorials on how to use MLPACK are given below.
- *
- * - @ref build
- * - @ref matrices
- * - @ref iodoc
- * - @ref timer
- * - @ref sample
- *
- * @section methods Methods in MLPACK
- *
- * The following methods are included in MLPACK:
- *
- * - Euclidean Minimum Spanning Trees - mlpack::emst::DualTreeBoruvka
- * - Gaussian Mixture Models (GMMs) - mlpack::gmm::GMM
- * - Hidden Markov Models (HMMs) - mlpack::hmm::HMM
- * - Kernel PCA - mlpack::kpca::KernelPCA
- * - K-Means Clustering - mlpack::kmeans::KMeans
- * - Least-Angle Regression (LARS/LASSO) - mlpack::regression::LARS
- * - Naive Bayes Classifier - mlpack::naive_bayes::NaiveBayesClassifier
- * - Neighborhood Components Analysis (NCA) - mlpack::nca::NCA
- * - Principal Components Analysis (PCA) - mlpack::pca::PCA
- * - RADICAL (ICA) - mlpack::radical::Radical
- * - Simple Least-Squares Linear Regression -
- * mlpack::regression::LinearRegression
- * - Tree-based neighbor search (AllkNN, AllkFN) -
- * mlpack::neighbor::NeighborSearch
- * - Tree-based range search - mlpack::range::RangeSearch
- *
- * @section remarks Final Remarks
- *
- * This software was written in the FASTLab (http://www.fast-lab.org), which is
- * in the School of Computational Science and Engineering at the Georgia
- * Institute of Technology.
- *
- * MLPACK contributors include:
- *
- * - Ryan Curtin <gth671b at mail.gatech.edu>
- * - James Cline <james.cline at gatech.edu>
- * - Neil Slagle <nslagle3 at gatech.edu>
- * - Matthew Amidon <mamidon at gatech.edu>
- * - Vlad Grantcharov <vlad321 at gatech.edu>
- * - Ajinkya Kale <kaleajinkya at gmail.com>
- * - Bill March <march at gatech.edu>
- * - Dongryeol Lee <dongryel at cc.gatech.edu>
- * - Nishant Mehta <niche at cc.gatech.edu>
- * - Parikshit Ram <p.ram at gatech.edu>
- * - Chip Mappus <cmappus at gatech.edu>
- * - Hua Ouyang <houyang at gatech.edu>
- * - Long Quoc Tran <tqlong at gmail.com>
- * - Noah Kauffman <notoriousnoah at gmail.com>
- * - Guillermo Colon <gcolon7 at mail.gatech.edu>
- * - Wei Guan <wguan at cc.gatech.edu>
- */
-
-// First, standard includes.
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <limits.h>
-#include <float.h>
-#include <stdint.h>
-#include <iostream>
-
-// Defining __USE_MATH_DEFINES should set M_PI.
-#define _USE_MATH_DEFINES
-#include <math.h>
-
-// But if it's not defined, we'll do it.
-#ifndef M_PI
- #define M_PI 3.141592653589793238462643383279
-#endif
-
-// Now MLPACK-specific includes.
-#include <mlpack/core/arma_extend/arma_extend.hpp> // Includes Armadillo.
-#include <mlpack/core/util/log.hpp>
-#include <mlpack/core/util/cli.hpp>
-#include <mlpack/core/data/load.hpp>
-#include <mlpack/core/data/save.hpp>
-#include <mlpack/core/math/clamp.hpp>
-#include <mlpack/core/math/random.hpp>
-#include <mlpack/core/math/range.hpp>
-#include <mlpack/core/util/save_restore_utility.hpp>
-#include <mlpack/core/dists/discrete_distribution.hpp>
-#include <mlpack/core/dists/gaussian_distribution.hpp>
-
-#endif
Copied: mlpack/tags/mlpack-1.0.0/src/mlpack/core.hpp (from rev 10888, mlpack/tags/mlpack-1.0/src/mlpack/core.hpp)
===================================================================
--- mlpack/tags/mlpack-1.0.0/src/mlpack/core.hpp (rev 0)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/core.hpp 2011-12-17 09:02:47 UTC (rev 10893)
@@ -0,0 +1,143 @@
+/***
+ * @file core.hpp
+ *
+ * Include all of the base components required to write MLPACK methods, and the
+ * main MLPACK Doxygen documentation.
+ */
+#ifndef __MLPACK_CORE_HPP
+#define __MLPACK_CORE_HPP
+
+/**
+ * @mainpage MLPACK Documentation
+ *
+ * @section intro_sec Introduction
+ *
+ * MLPACK is an intuitive, fast, scalable C++ machine learning library, meant to
+ * be a machine learning analog to LAPACK. It aims to implement a wide array of
+ * machine learning methods and function as a "swiss army knife" for machine
+ * learning researchers. The MLPACK development website can be found at
+ * http://mlpack.org.
+ *
+ * MLPACK uses the Armadillo C++ matrix library (http://arma.sourceforge.net)
+ * for general matrix, vector, and linear algebra support. MLPACK also uses the
+ * program_options, math_c99, and unit_test_framework components of the Boost
+ * library; in addition, LibXml2 is used.
+ *
+ * @section howto How To Use This Documentation
+ *
+ * This documentation is API documentation similar to Javadoc. It isn't
+ * necessarily a tutorial, but it does provide detailed documentation on every
+ * namespace, method, and class.
+ *
+ * Each MLPACK namespace generally refers to one machine learning method, so
+ * browsing the list of namespaces provides some insight as to the breadth of
+ * the methods contained in the library.
+ *
+ * To generate this documentation in your own local copy of MLPACK, you can
+ * simply use Doxygen, from the root directory (@c /mlpack/trunk/ ):
+ *
+ * @code
+ * $ doxygen
+ * @endcode
+ *
+ * @section executables Executables
+ *
+ * MLPACK provides several executables so that MLPACK methods can be used
+ * without any need for knowledge of C++. These executables are all
+ * self-documented, and that documentation can be accessed by running the
+ * executables with the '-h' or '--help' flag.
+ *
+ * A full list of executables is given below:
+ *
+ * allkfn, allknn, emst, gmm, hmm_train, hmm_loglik, hmm_viterbi, hmm_generate,
+ * kmeans, lars, linear_regression, nbc, nca, pca, radical
+ *
+ * @section tutorial Tutorials
+ *
+ * A few short tutorials on how to use MLPACK are given below.
+ *
+ * - @ref build
+ * - @ref matrices
+ * - @ref iodoc
+ * - @ref timer
+ * - @ref sample
+ *
+ * @section methods Methods in MLPACK
+ *
+ * The following methods are included in MLPACK:
+ *
+ * - Euclidean Minimum Spanning Trees - mlpack::emst::DualTreeBoruvka
+ * - Gaussian Mixture Models (GMMs) - mlpack::gmm::GMM
+ * - Hidden Markov Models (HMMs) - mlpack::hmm::HMM
+ * - Kernel PCA - mlpack::kpca::KernelPCA
+ * - K-Means Clustering - mlpack::kmeans::KMeans
+ * - Least-Angle Regression (LARS/LASSO) - mlpack::regression::LARS
+ * - Naive Bayes Classifier - mlpack::naive_bayes::NaiveBayesClassifier
+ * - Neighborhood Components Analysis (NCA) - mlpack::nca::NCA
+ * - Principal Components Analysis (PCA) - mlpack::pca::PCA
+ * - RADICAL (ICA) - mlpack::radical::Radical
+ * - Simple Least-Squares Linear Regression -
+ * mlpack::regression::LinearRegression
+ * - Tree-based neighbor search (AllkNN, AllkFN) -
+ * mlpack::neighbor::NeighborSearch
+ * - Tree-based range search - mlpack::range::RangeSearch
+ *
+ * @section remarks Final Remarks
+ *
+ * This software was written in the FASTLab (http://www.fast-lab.org), which is
+ * in the School of Computational Science and Engineering at the Georgia
+ * Institute of Technology.
+ *
+ * MLPACK contributors include:
+ *
+ * - Ryan Curtin <gth671b at mail.gatech.edu>
+ * - James Cline <james.cline at gatech.edu>
+ * - Neil Slagle <nslagle3 at gatech.edu>
+ * - Matthew Amidon <mamidon at gatech.edu>
+ * - Vlad Grantcharov <vlad321 at gatech.edu>
+ * - Ajinkya Kale <kaleajinkya at gmail.com>
+ * - Bill March <march at gatech.edu>
+ * - Dongryeol Lee <dongryel at cc.gatech.edu>
+ * - Nishant Mehta <niche at cc.gatech.edu>
+ * - Parikshit Ram <p.ram at gatech.edu>
+ * - Chip Mappus <cmappus at gatech.edu>
+ * - Hua Ouyang <houyang at gatech.edu>
+ * - Long Quoc Tran <tqlong at gmail.com>
+ * - Noah Kauffman <notoriousnoah at gmail.com>
+ * - Guillermo Colon <gcolon7 at mail.gatech.edu>
+ * - Wei Guan <wguan at cc.gatech.edu>
+ */
+
+// First, standard includes.
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <float.h>
+#include <stdint.h>
+#include <iostream>
+
+// Defining __USE_MATH_DEFINES should set M_PI.
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+// But if it's not defined, we'll do it.
+#ifndef M_PI
+ #define M_PI 3.141592653589793238462643383279
+#endif
+
+// Now MLPACK-specific includes.
+#include <mlpack/core/arma_extend/arma_extend.hpp> // Includes Armadillo.
+#include <mlpack/core/util/log.hpp>
+#include <mlpack/core/util/cli.hpp>
+#include <mlpack/core/data/load.hpp>
+#include <mlpack/core/data/save.hpp>
+#include <mlpack/core/math/clamp.hpp>
+#include <mlpack/core/math/random.hpp>
+#include <mlpack/core/math/range.hpp>
+#include <mlpack/core/util/save_restore_utility.hpp>
+#include <mlpack/core/dists/discrete_distribution.hpp>
+#include <mlpack/core/dists/gaussian_distribution.hpp>
+
+#endif
Deleted: mlpack/tags/mlpack-1.0.0/src/mlpack/methods/CMakeLists.txt
===================================================================
--- mlpack/tags/mlpack-1.0/src/mlpack/methods/CMakeLists.txt 2011-12-17 08:36:15 UTC (rev 10887)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/methods/CMakeLists.txt 2011-12-17 09:02:47 UTC (rev 10893)
@@ -1,25 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-## recurse
-set(DIRS
- emst
- gmm
- hmm
- kernel_pca
- kmeans
- lars
- linear_regression
- mvu
- naive_bayes
- nca
- neighbor_search
- pca
- radical
- range_search
-)
-
-foreach(dir ${DIRS})
- add_subdirectory(${dir})
-endforeach()
-
-set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
Copied: mlpack/tags/mlpack-1.0.0/src/mlpack/methods/CMakeLists.txt (from rev 10888, mlpack/tags/mlpack-1.0/src/mlpack/methods/CMakeLists.txt)
===================================================================
--- mlpack/tags/mlpack-1.0.0/src/mlpack/methods/CMakeLists.txt (rev 0)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/methods/CMakeLists.txt 2011-12-17 09:02:47 UTC (rev 10893)
@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 2.8)
+
+## recurse
+set(DIRS
+ emst
+ gmm
+ hmm
+ kmeans
+ lars
+ linear_regression
+ mvu
+ naive_bayes
+ nca
+ neighbor_search
+ pca
+ radical
+ range_search
+)
+
+foreach(dir ${DIRS})
+ add_subdirectory(${dir})
+endforeach()
+
+set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
Deleted: mlpack/tags/mlpack-1.0.0/src/mlpack/tests/tree_test.cpp
===================================================================
--- mlpack/tags/mlpack-1.0/src/mlpack/tests/tree_test.cpp 2011-12-17 08:36:15 UTC (rev 10887)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/tests/tree_test.cpp 2011-12-17 09:02:47 UTC (rev 10893)
@@ -1,1439 +0,0 @@
-/**
- * @file tree_test.cpp
- *
- * Tests for tree-building methods.
- */
-#include <mlpack/core/tree/bounds.hpp>
-#include <mlpack/core/tree/binary_space_tree.hpp>
-#include <mlpack/core/metrics/lmetric.hpp>
-#include <vector>
-
-#include <boost/test/unit_test.hpp>
-
-using namespace mlpack;
-using namespace mlpack::math;
-using namespace mlpack::tree;
-using namespace mlpack::metric;
-using namespace mlpack::bound;
-
-BOOST_AUTO_TEST_SUITE(TreeTest);
-
-/**
- * Ensure that a bound, by default, is empty and has no dimensionality.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundEmptyConstructor)
-{
- HRectBound<2> b;
-
- BOOST_REQUIRE_EQUAL(b.Dim(), 0);
-}
-
-/**
- * Ensure that when we specify the dimensionality in the constructor, it is
- * correct, and the bounds are all the empty set.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundDimConstructor)
-{
- HRectBound<2> b(2); // We'll do this with 2 and 5 dimensions.
-
- BOOST_REQUIRE_EQUAL(b.Dim(), 2);
- BOOST_REQUIRE_SMALL(b[0].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(b[1].Width(), 1e-5);
-
- b = HRectBound<2>(5);
-
- BOOST_REQUIRE_EQUAL(b.Dim(), 5);
- BOOST_REQUIRE_SMALL(b[0].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(b[1].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(b[2].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(b[3].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(b[4].Width(), 1e-5);
-}
-
-/**
- * Test the copy constructor.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundCopyConstructor)
-{
- HRectBound<2> b(2);
- b[0] = Range(0.0, 2.0);
- b[1] = Range(2.0, 3.0);
-
- HRectBound<2> c(b);
-
- BOOST_REQUIRE_EQUAL(c.Dim(), 2);
- BOOST_REQUIRE_SMALL(c[0].Lo(), 1e-5);
- BOOST_REQUIRE_CLOSE(c[0].Hi(), 2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c[1].Lo(), 2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c[1].Hi(), 3.0, 1e-5);
-}
-
-/**
- * Test the assignment operator.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundAssignmentOperator)
-{
- HRectBound<2> b(2);
- b[0] = Range(0.0, 2.0);
- b[1] = Range(2.0, 3.0);
-
- HRectBound<2> c(4);
-
- c = b;
-
- BOOST_REQUIRE_EQUAL(c.Dim(), 2);
- BOOST_REQUIRE_SMALL(c[0].Lo(), 1e-5);
- BOOST_REQUIRE_CLOSE(c[0].Hi(), 2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c[1].Lo(), 2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c[1].Hi(), 3.0, 1e-5);
-}
-
-/**
- * Test that clearing the dimensions resets the bound to empty.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundClear)
-{
- HRectBound<2> b(2); // We'll do this with two dimensions only.
-
- b[0] = Range(0.0, 2.0);
- b[1] = Range(2.0, 4.0);
-
- // Now we just need to make sure that we clear the range.
- b.Clear();
-
- BOOST_REQUIRE_SMALL(b[0].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(b[1].Width(), 1e-5);
-}
-
-/**
- * Ensure that we get the correct centroid for our bound.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundCentroid)
-{
- // Create a simple 3-dimensional bound.
- HRectBound<2> b(3);
-
- b[0] = Range(0.0, 5.0);
- b[1] = Range(-2.0, -1.0);
- b[2] = Range(-10.0, 50.0);
-
- arma::vec centroid;
-
- b.Centroid(centroid);
-
- BOOST_REQUIRE_EQUAL(centroid.n_elem, 3);
- BOOST_REQUIRE_CLOSE(centroid[0], 2.5, 1e-5);
- BOOST_REQUIRE_CLOSE(centroid[1], -1.5, 1e-5);
- BOOST_REQUIRE_CLOSE(centroid[2], 20.0, 1e-5);
-}
-
-/**
- * Ensure that we calculate the correct minimum distance between a point and a
- * bound.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundMinDistancePoint)
-{
- // We'll do the calculation in five dimensions, and we'll use three cases for
- // the point: point is outside the bound; point is on the edge of the bound;
- // point is inside the bound. In the latter two cases, the distance should be
- // zero.
- HRectBound<2> b(5);
-
- b[0] = Range(0.0, 2.0);
- b[1] = Range(1.0, 5.0);
- b[2] = Range(-2.0, 2.0);
- b[3] = Range(-5.0, -2.0);
- b[4] = Range(1.0, 2.0);
-
- arma::vec point = "-2.0 0.0 10.0 3.0 3.0";
-
- // This will be the Euclidean squared distance.
- BOOST_REQUIRE_CLOSE(b.MinDistance(point), 95.0, 1e-5);
-
- point = "2.0 5.0 2.0 -5.0 1.0";
-
- BOOST_REQUIRE_SMALL(b.MinDistance(point), 1e-5);
-
- point = "1.0 2.0 0.0 -2.0 1.5";
-
- BOOST_REQUIRE_SMALL(b.MinDistance(point), 1e-5);
-}
-
-/**
- * Ensure that we calculate the correct minimum distance between a bound and
- * another bound.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundMinDistanceBound)
-{
- // We'll do the calculation in five dimensions, and we can use six cases.
- // The other bound is completely outside the bound; the other bound is on the
- // edge of the bound; the other bound partially overlaps the bound; the other
- // bound fully overlaps the bound; the other bound is entirely inside the
- // bound; the other bound entirely envelops the bound.
- HRectBound<2> b(5);
-
- b[0] = Range(0.0, 2.0);
- b[1] = Range(1.0, 5.0);
- b[2] = Range(-2.0, 2.0);
- b[3] = Range(-5.0, -2.0);
- b[4] = Range(1.0, 2.0);
-
- HRectBound<2> c(5);
-
- // The other bound is completely outside the bound.
- c[0] = Range(-5.0, -2.0);
- c[1] = Range(6.0, 7.0);
- c[2] = Range(-2.0, 2.0);
- c[3] = Range(2.0, 5.0);
- c[4] = Range(3.0, 4.0);
-
- BOOST_REQUIRE_CLOSE(b.MinDistance(c), 22.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c.MinDistance(b), 22.0, 1e-5);
-
- // The other bound is on the edge of the bound.
- c[0] = Range(-2.0, 0.0);
- c[1] = Range(0.0, 1.0);
- c[2] = Range(-3.0, -2.0);
- c[3] = Range(-10.0, -5.0);
- c[4] = Range(2.0, 3.0);
-
- BOOST_REQUIRE_SMALL(b.MinDistance(c), 1e-5);
- BOOST_REQUIRE_SMALL(c.MinDistance(b), 1e-5);
-
- // The other bound partially overlaps the bound.
- c[0] = Range(-2.0, 1.0);
- c[1] = Range(0.0, 2.0);
- c[2] = Range(-2.0, 2.0);
- c[3] = Range(-8.0, -4.0);
- c[4] = Range(0.0, 4.0);
-
- BOOST_REQUIRE_SMALL(b.MinDistance(c), 1e-5);
- BOOST_REQUIRE_SMALL(c.MinDistance(b), 1e-5);
-
- // The other bound fully overlaps the bound.
- BOOST_REQUIRE_SMALL(b.MinDistance(b), 1e-5);
- BOOST_REQUIRE_SMALL(c.MinDistance(c), 1e-5);
-
- // The other bound is entirely inside the bound / the other bound entirely
- // envelops the bound.
- c[0] = Range(-1.0, 3.0);
- c[1] = Range(0.0, 6.0);
- c[2] = Range(-3.0, 3.0);
- c[3] = Range(-7.0, 0.0);
- c[4] = Range(0.0, 5.0);
-
- BOOST_REQUIRE_SMALL(b.MinDistance(c), 1e-5);
- BOOST_REQUIRE_SMALL(c.MinDistance(b), 1e-5);
-
- // Now we must be sure that the minimum distance to itself is 0.
- BOOST_REQUIRE_SMALL(b.MinDistance(b), 1e-5);
- BOOST_REQUIRE_SMALL(c.MinDistance(c), 1e-5);
-}
-
-/**
- * Ensure that we calculate the correct maximum distance between a bound and a
- * point. This uses the same test cases as the MinDistance test.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundMaxDistancePoint)
-{
- // We'll do the calculation in five dimensions, and we'll use three cases for
- // the point: point is outside the bound; point is on the edge of the bound;
- // point is inside the bound. In the latter two cases, the distance should be
- // zero.
- HRectBound<2> b(5);
-
- b[0] = Range(0.0, 2.0);
- b[1] = Range(1.0, 5.0);
- b[2] = Range(-2.0, 2.0);
- b[3] = Range(-5.0, -2.0);
- b[4] = Range(1.0, 2.0);
-
- arma::vec point = "-2.0 0.0 10.0 3.0 3.0";
-
- // This will be the Euclidean squared distance.
- BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 253.0, 1e-5);
-
- point = "2.0 5.0 2.0 -5.0 1.0";
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 46.0, 1e-5);
-
- point = "1.0 2.0 0.0 -2.0 1.5";
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 23.25, 1e-5);
-}
-
-/**
- * Ensure that we calculate the correct maximum distance between a bound and
- * another bound. This uses the same test cases as the MinDistance test.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundMaxDistanceBound)
-{
- // We'll do the calculation in five dimensions, and we can use six cases.
- // The other bound is completely outside the bound; the other bound is on the
- // edge of the bound; the other bound partially overlaps the bound; the other
- // bound fully overlaps the bound; the other bound is entirely inside the
- // bound; the other bound entirely envelops the bound.
- HRectBound<2> b(5);
-
- b[0] = Range(0.0, 2.0);
- b[1] = Range(1.0, 5.0);
- b[2] = Range(-2.0, 2.0);
- b[3] = Range(-5.0, -2.0);
- b[4] = Range(1.0, 2.0);
-
- HRectBound<2> c(5);
-
- // The other bound is completely outside the bound.
- c[0] = Range(-5.0, -2.0);
- c[1] = Range(6.0, 7.0);
- c[2] = Range(-2.0, 2.0);
- c[3] = Range(2.0, 5.0);
- c[4] = Range(3.0, 4.0);
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 210.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 210.0, 1e-5);
-
- // The other bound is on the edge of the bound.
- c[0] = Range(-2.0, 0.0);
- c[1] = Range(0.0, 1.0);
- c[2] = Range(-3.0, -2.0);
- c[3] = Range(-10.0, -5.0);
- c[4] = Range(2.0, 3.0);
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 134.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 134.0, 1e-5);
-
- // The other bound partially overlaps the bound.
- c[0] = Range(-2.0, 1.0);
- c[1] = Range(0.0, 2.0);
- c[2] = Range(-2.0, 2.0);
- c[3] = Range(-8.0, -4.0);
- c[4] = Range(0.0, 4.0);
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 102.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 102.0, 1e-5);
-
- // The other bound fully overlaps the bound.
- BOOST_REQUIRE_CLOSE(b.MaxDistance(b), 46.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c.MaxDistance(c), 61.0, 1e-5);
-
- // The other bound is entirely inside the bound / the other bound entirely
- // envelops the bound.
- c[0] = Range(-1.0, 3.0);
- c[1] = Range(0.0, 6.0);
- c[2] = Range(-3.0, 3.0);
- c[3] = Range(-7.0, 0.0);
- c[4] = Range(0.0, 5.0);
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 100.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 100.0, 1e-5);
-
- // Identical bounds. This will be the sum of the squared widths in each
- // dimension.
- BOOST_REQUIRE_CLOSE(b.MaxDistance(b), 46.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c.MaxDistance(c), 162.0, 1e-5);
-
- // One last additional case. If the bound encloses only one point, the
- // maximum distance between it and itself is 0.
- HRectBound<2> d(2);
-
- d[0] = Range(2.0, 2.0);
- d[1] = Range(3.0, 3.0);
-
- BOOST_REQUIRE_SMALL(d.MaxDistance(d), 1e-5);
-}
-
-/**
- * Ensure that the ranges returned by RangeDistance() are equal to the minimum
- * and maximum distance. We will perform this test by creating random bounds
- * and comparing the behavior to MinDistance() and MaxDistance() -- so this test
- * is assuming that those passed and operate correctly.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundRangeDistanceBound)
-{
- for (int i = 0; i < 50; i++)
- {
- size_t dim = math::RandInt(20);
-
- HRectBound<2> a(dim);
- HRectBound<2> b(dim);
-
- // We will set the low randomly and the width randomly for each dimension of
- // each bound.
- arma::vec loA(dim);
- arma::vec widthA(dim);
-
- loA.randu();
- widthA.randu();
-
- arma::vec lo_b(dim);
- arma::vec width_b(dim);
-
- lo_b.randu();
- width_b.randu();
-
- for (size_t j = 0; j < dim; j++)
- {
- a[j] = Range(loA[j], loA[j] + widthA[j]);
- b[j] = Range(lo_b[j], lo_b[j] + width_b[j]);
- }
-
- // Now ensure that MinDistance and MaxDistance report the same.
- Range r = a.RangeDistance(b);
- Range s = b.RangeDistance(a);
-
- BOOST_REQUIRE_CLOSE(r.Lo(), s.Lo(), 1e-5);
- BOOST_REQUIRE_CLOSE(r.Hi(), s.Hi(), 1e-5);
-
- BOOST_REQUIRE_CLOSE(r.Lo(), a.MinDistance(b), 1e-5);
- BOOST_REQUIRE_CLOSE(r.Hi(), a.MaxDistance(b), 1e-5);
-
- BOOST_REQUIRE_CLOSE(s.Lo(), b.MinDistance(a), 1e-5);
- BOOST_REQUIRE_CLOSE(s.Hi(), b.MaxDistance(a), 1e-5);
- }
-}
-
-/**
- * Ensure that the ranges returned by RangeDistance() are equal to the minimum
- * and maximum distance. We will perform this test by creating random bounds
- * and comparing the bheavior to MinDistance() and MaxDistance() -- so this test
- * is assuming that those passed and operate correctly. This is for the
- * bound-to-point case.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundRangeDistancePoint)
-{
- for (int i = 0; i < 20; i++)
- {
- size_t dim = math::RandInt(20);
-
- HRectBound<2> a(dim);
-
- // We will set the low randomly and the width randomly for each dimension of
- // each bound.
- arma::vec loA(dim);
- arma::vec widthA(dim);
-
- loA.randu();
- widthA.randu();
-
- for (size_t j = 0; j < dim; j++)
- a[j] = Range(loA[j], loA[j] + widthA[j]);
-
- // Now run the test on a few points.
- for (int j = 0; j < 10; j++)
- {
- arma::vec point(dim);
-
- point.randu();
-
- Range r = a.RangeDistance(point);
-
- BOOST_REQUIRE_CLOSE(r.Lo(), a.MinDistance(point), 1e-5);
- BOOST_REQUIRE_CLOSE(r.Hi(), a.MaxDistance(point), 1e-5);
- }
- }
-}
-
-/**
- * Test that we can expand the bound to include a new point.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundOrOperatorPoint)
-{
- // Because this should be independent in each dimension, we can essentially
- // run five test cases at once.
- HRectBound<2> b(5);
-
- b[0] = Range(1.0, 3.0);
- b[1] = Range(2.0, 4.0);
- b[2] = Range(-2.0, -1.0);
- b[3] = Range(0.0, 0.0);
- b[4] = Range(); // Empty range.
-
- arma::vec point = "2.0 4.0 2.0 -1.0 6.0";
-
- b |= point;
-
- BOOST_REQUIRE_CLOSE(b[0].Lo(), 1.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[0].Hi(), 3.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[1].Lo(), 2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[1].Hi(), 4.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[2].Lo(), -2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[2].Hi(), 2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[3].Lo(), -1.0, 1e-5);
- BOOST_REQUIRE_SMALL(b[3].Hi(), 1e-5);
- BOOST_REQUIRE_CLOSE(b[4].Lo(), 6.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[4].Hi(), 6.0, 1e-5);
-}
-
-/**
- * Test that we can expand the bound to include another bound.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundOrOperatorBound)
-{
- // Because this should be independent in each dimension, we can run many tests
- // at once.
- HRectBound<2> b(8);
-
- b[0] = Range(1.0, 3.0);
- b[1] = Range(2.0, 4.0);
- b[2] = Range(-2.0, -1.0);
- b[3] = Range(4.0, 5.0);
- b[4] = Range(2.0, 4.0);
- b[5] = Range(0.0, 0.0);
- b[6] = Range();
- b[7] = Range(1.0, 3.0);
-
- HRectBound<2> c(8);
-
- c[0] = Range(-3.0, -1.0); // Entirely less than the other bound.
- c[1] = Range(0.0, 2.0); // Touching edges.
- c[2] = Range(-3.0, -1.5); // Partially overlapping.
- c[3] = Range(4.0, 5.0); // Identical.
- c[4] = Range(1.0, 5.0); // Entirely enclosing.
- c[5] = Range(2.0, 2.0); // A single point.
- c[6] = Range(1.0, 3.0);
- c[7] = Range(); // Empty set.
-
- HRectBound<2> d = c;
-
- b |= c;
- d |= b;
-
- BOOST_REQUIRE_CLOSE(b[0].Lo(), -3.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[0].Hi(), 3.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[0].Lo(), -3.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[0].Hi(), 3.0, 1e-5);
-
- BOOST_REQUIRE_CLOSE(b[1].Lo(), 0.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[1].Hi(), 4.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[1].Lo(), 0.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[1].Hi(), 4.0, 1e-5);
-
- BOOST_REQUIRE_CLOSE(b[2].Lo(), -3.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[2].Hi(), -1.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[2].Lo(), -3.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[2].Hi(), -1.0, 1e-5);
-
- BOOST_REQUIRE_CLOSE(b[3].Lo(), 4.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[3].Hi(), 5.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[3].Lo(), 4.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[3].Hi(), 5.0, 1e-5);
-
- BOOST_REQUIRE_CLOSE(b[4].Lo(), 1.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[4].Hi(), 5.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[4].Lo(), 1.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[4].Hi(), 5.0, 1e-5);
-
- BOOST_REQUIRE_SMALL(b[5].Lo(), 1e-5);
- BOOST_REQUIRE_CLOSE(b[5].Hi(), 2.0, 1e-5);
- BOOST_REQUIRE_SMALL(d[5].Lo(), 1e-5);
- BOOST_REQUIRE_CLOSE(d[5].Hi(), 2.0, 1e-5);
-
- BOOST_REQUIRE_CLOSE(b[6].Lo(), 1.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[6].Hi(), 3.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[6].Lo(), 1.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[6].Hi(), 3.0, 1e-5);
-
- BOOST_REQUIRE_CLOSE(b[7].Lo(), 1.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b[7].Hi(), 3.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[7].Lo(), 1.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d[7].Hi(), 3.0, 1e-5);
-}
-
-/**
- * Test that the Contains() function correctly figures out whether or not a
- * point is in a bound.
- */
-BOOST_AUTO_TEST_CASE(HRectBoundContains)
-{
- // We can test a couple different points: completely outside the bound,
- // adjacent in one dimension to the bound, adjacent in all dimensions to the
- // bound, and inside the bound.
- HRectBound<2> b(3);
-
- b[0] = Range(0.0, 2.0);
- b[1] = Range(0.0, 2.0);
- b[2] = Range(0.0, 2.0);
-
- // Completely outside the range.
- arma::vec point = "-1.0 4.0 4.0";
- BOOST_REQUIRE(!b.Contains(point));
-
- // Completely outside, but one dimension is in the range.
- point = "-1.0 4.0 1.0";
- BOOST_REQUIRE(!b.Contains(point));
-
- // Outside, but one dimension is on the edge.
- point = "-1.0 0.0 3.0";
- BOOST_REQUIRE(!b.Contains(point));
-
- // Two dimensions are on the edge, but one is outside.
- point = "0.0 0.0 3.0";
- BOOST_REQUIRE(!b.Contains(point));
-
- // Completely on the edge (should be contained).
- point = "0.0 0.0 0.0";
- BOOST_REQUIRE(b.Contains(point));
-
- // Inside the range.
- point = "0.3 1.0 0.4";
- BOOST_REQUIRE(b.Contains(point));
-}
-
-BOOST_AUTO_TEST_CASE(TestBallBound)
-{
- BallBound<> b1;
- BallBound<> b2;
-
- // Create two balls with a center distance of 1 from each other.
- // Give the first one a radius of 0.3 and the second a radius of 0.4.
- b1.Center().set_size(3);
- b1.Center()[0] = 1;
- b1.Center()[1] = 2;
- b1.Center()[2] = 3;
- b1.Radius() = 0.3;
-
- b2.Center().set_size(3);
- b2.Center()[0] = 1;
- b2.Center()[1] = 2;
- b2.Center()[2] = 4;
- b2.Radius() = 0.4;
-
- BOOST_REQUIRE_CLOSE(b1.MinDistance(b2), 1-0.3-0.4, 1e-5);
- BOOST_REQUIRE_CLOSE(b1.RangeDistance(b2).Hi(), 1+0.3+0.4, 1e-5);
- BOOST_REQUIRE_CLOSE(b1.RangeDistance(b2).Lo(), 1-0.3-0.4, 1e-5);
- BOOST_REQUIRE_CLOSE(b1.RangeDistance(b2).Hi(), 1+0.3+0.4, 1e-5);
- BOOST_REQUIRE_CLOSE(b1.RangeDistance(b2).Lo(), 1-0.3-0.4, 1e-5);
-
- BOOST_REQUIRE_CLOSE(b2.MinDistance(b1), 1-0.3-0.4, 1e-5);
- BOOST_REQUIRE_CLOSE(b2.MaxDistance(b1), 1+0.3+0.4, 1e-5);
- BOOST_REQUIRE_CLOSE(b2.RangeDistance(b1).Hi(), 1+0.3+0.4, 1e-5);
- BOOST_REQUIRE_CLOSE(b2.RangeDistance(b1).Lo(), 1-0.3-0.4, 1e-5);
-
- BOOST_REQUIRE(b1.Contains(b1.Center()));
- BOOST_REQUIRE(!b1.Contains(b2.Center()));
-
- BOOST_REQUIRE(!b2.Contains(b1.Center()));
- BOOST_REQUIRE(b2.Contains(b2.Center()));
- arma::vec b2point(3); // A point that's within the radius but not the center.
- b2point[0] = 1.1;
- b2point[1] = 2.1;
- b2point[2] = 4.1;
-
- BOOST_REQUIRE(b2.Contains(b2point));
-
- BOOST_REQUIRE_SMALL(b1.MinDistance(b1.Center()), 1e-5);
- BOOST_REQUIRE_CLOSE(b1.MinDistance(b2.Center()), 1 - 0.3, 1e-5);
- BOOST_REQUIRE_CLOSE(b2.MinDistance(b1.Center()), 1 - 0.4, 1e-5);
- BOOST_REQUIRE_CLOSE(b2.MaxDistance(b1.Center()), 1 + 0.4, 1e-5);
- BOOST_REQUIRE_CLOSE(b1.MaxDistance(b2.Center()), 1 + 0.3, 1e-5);
-}
-
-/**
- * Ensure that a bound, by default, is empty and has no dimensionality, and the
- * box size vector is empty.
- */
-BOOST_AUTO_TEST_CASE(PeriodicHRectBoundEmptyConstructor)
-{
- PeriodicHRectBound<2> b;
-
- BOOST_REQUIRE_EQUAL(b.Dim(), 0);
- BOOST_REQUIRE_EQUAL(b.box().n_elem, 0);
-}
-
-/**
- * Ensure that when we specify the dimensionality in the constructor, it is
- * correct, and the bounds are all the empty set.
- */
-BOOST_AUTO_TEST_CASE(PeriodicHRectBoundBoxConstructor)
-{
- PeriodicHRectBound<2> b(arma::vec("5 6"));
-
- BOOST_REQUIRE_EQUAL(b.Dim(), 2);
- BOOST_REQUIRE_SMALL(b[0].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(b[1].Width(), 1e-5);
- BOOST_REQUIRE_EQUAL(b.box().n_elem, 2);
- BOOST_REQUIRE_CLOSE(b.box()[0], 5.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b.box()[1], 6.0, 1e-5);
-
- PeriodicHRectBound<2> d(arma::vec("2 3 4 5 6"));
-
- BOOST_REQUIRE_EQUAL(d.Dim(), 5);
- BOOST_REQUIRE_SMALL(d[0].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(d[1].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(d[2].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(d[3].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(d[4].Width(), 1e-5);
- BOOST_REQUIRE_EQUAL(d.box().n_elem, 5);
- BOOST_REQUIRE_CLOSE(d.box()[0], 2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d.box()[1], 3.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d.box()[2], 4.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d.box()[3], 5.0, 1e-5);
- BOOST_REQUIRE_CLOSE(d.box()[4], 6.0, 1e-5);
-}
-
-/**
- * Test the copy constructor.
- */
-BOOST_AUTO_TEST_CASE(PeriodicHRectBoundCopyConstructor)
-{
- PeriodicHRectBound<2> b(arma::vec("3 4"));
- b[0] = Range(0.0, 2.0);
- b[1] = Range(2.0, 3.0);
-
- PeriodicHRectBound<2> c(b);
-
- BOOST_REQUIRE_EQUAL(c.Dim(), 2);
- BOOST_REQUIRE_SMALL(c[0].Lo(), 1e-5);
- BOOST_REQUIRE_CLOSE(c[0].Hi(), 2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c[1].Lo(), 2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c[1].Hi(), 3.0, 1e-5);
- BOOST_REQUIRE_EQUAL(c.box().n_elem, 2);
- BOOST_REQUIRE_CLOSE(c.box()[0], 3.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c.box()[1], 4.0, 1e-5);
-}
-
-/**
- * Test the assignment operator.
- *
-BOOST_AUTO_TEST_CASE(PeriodicHRectBoundAssignmentOperator)
-{
- PeriodicHRectBound<2> b(arma::vec("3 4"));
- b[0] = Range(0.0, 2.0);
- b[1] = Range(2.0, 3.0);
-
- PeriodicHRectBound<2> c(arma::vec("3 4 5 6"));
-
- c = b;
-
- BOOST_REQUIRE_EQUAL(c.Dim(), 2);
- BOOST_REQUIRE_SMALL(c[0].Lo(), 1e-5);
- BOOST_REQUIRE_CLOSE(c[0].Hi(), 2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c[1].Lo(), 2.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c[1].Hi(), 3.0, 1e-5);
- BOOST_REQUIRE_EQUAL(c.box().n_elem, 2);
- BOOST_REQUIRE_CLOSE(c.box()[0], 3.0, 1e-5);
- BOOST_REQUIRE_CLOSE(c.box()[1], 4.0, 1e-5);
-}*/
-
-/**
- * Ensure that we can set the box size correctly.
- *
-BOOST_AUTO_TEST_CASE(PeriodicHRectBoundSetBoxSize)
-{
- PeriodicHRectBound<2> b(arma::vec("1 2"));
-
- b.SetBoxSize(arma::vec("10 12"));
-
- BOOST_REQUIRE_EQUAL(b.box().n_elem, 2);
- BOOST_REQUIRE_CLOSE(b.box()[0], 10.0, 1e-5);
- BOOST_REQUIRE_CLOSE(b.box()[1], 12.0, 1e-5);
-}*/
-
-/**
- * Ensure that we can clear the dimensions correctly. This does not involve the
- * box size at all, so the test can be identical to the HRectBound test.
- *
-BOOST_AUTO_TEST_CASE(PeriodicHRectBoundClear)
-{
- // We'll do this with two dimensions only.
- PeriodicHRectBound<2> b(arma::vec("5 5"));
-
- b[0] = Range(0.0, 2.0);
- b[1] = Range(2.0, 4.0);
-
- // Now we just need to make sure that we clear the range.
- b.Clear();
-
- BOOST_REQUIRE_SMALL(b[0].Width(), 1e-5);
- BOOST_REQUIRE_SMALL(b[1].Width(), 1e-5);
-}*/
-
-/**
- * Ensure that we get the correct centroid for our bound.
- *
-BOOST_AUTO_TEST_CASE(PeriodicHRectBoundCentroid) {
- // Create a simple 3-dimensional bound. The centroid is not affected by the
- // periodic coordinates.
- PeriodicHRectBound<2> b(arma::vec("100 100 100"));
-
- b[0] = Range(0.0, 5.0);
- b[1] = Range(-2.0, -1.0);
- b[2] = Range(-10.0, 50.0);
-
- arma::vec centroid;
-
- b.Centroid(centroid);
-
- BOOST_REQUIRE_EQUAL(centroid.n_elem, 3);
- BOOST_REQUIRE_CLOSE(centroid[0], 2.5, 1e-5);
- BOOST_REQUIRE_CLOSE(centroid[1], -1.5, 1e-5);
- BOOST_REQUIRE_CLOSE(centroid[2], 20.0, 1e-5);
-}*/
-
-/**
- * Correctly calculate the minimum distance between the bound and a point in
- * periodic coordinates. We have to account for the shifts necessary in
- * periodic coordinates too, so that makes testing this a little more difficult.
- */
-BOOST_AUTO_TEST_CASE(PeriodicHRectBoundMinDistancePoint)
-{
- // First, we'll start with a simple 2-dimensional case where the point is
- // inside the bound, then on the edge of the bound, then barely outside the
- // bound. The box size will be large enough that this is basically the
- // HRectBound case.
- PeriodicHRectBound<2> b(arma::vec("100 100"));
-
- b[0] = Range(0.0, 5.0);
- b[1] = Range(2.0, 4.0);
-
- // Inside the bound.
- arma::vec point = "2.5 3.0";
-
- BOOST_REQUIRE_SMALL(b.MinDistance(point), 1e-5);
-
- // On the edge.
- point = "5.0 4.0";
-
- BOOST_REQUIRE_SMALL(b.MinDistance(point), 1e-5);
-
- // And just a little outside the bound.
- point = "6.0 5.0";
-
- BOOST_REQUIRE_CLOSE(b.MinDistance(point), 2.0, 1e-5);
-
- // Now we start to invoke the periodicity. This point will "alias" to (-1,
- // -1).
- point = "99.0 99.0";
-
- BOOST_REQUIRE_CLOSE(b.MinDistance(point), 10.0, 1e-5);
-
- // We will perform several tests on a one-dimensional bound.
- PeriodicHRectBound<2> a(arma::vec("5.0"));
- point.set_size(1);
-
- a[0] = Range(2.0, 4.0); // Entirely inside box.
- point[0] = 7.5; // Inside first right image of the box.
-
- BOOST_REQUIRE_SMALL(a.MinDistance(point), 1e-5);
-
- a[0] = Range(0.0, 5.0); // Fills box fully.
- point[1] = 19.3; // Inside the box, which covers everything.
-
- BOOST_REQUIRE_SMALL(a.MinDistance(point), 1e-5);
-
- a[0] = Range(-10.0, 10.0); // Larger than the box.
- point[0] = -500.0; // Inside the box, which covers everything.
-
- BOOST_REQUIRE_SMALL(a.MinDistance(point), 1e-5);
-
- a[0] = Range(-2.0, 1.0); // Crosses over an edge.
- point[0] = 2.9; // The first right image of the bound starts at 3.0.
-
- BOOST_REQUIRE_CLOSE(a.MinDistance(point), 0.01, 1e-5);
-
- a[0] = Range(2.0, 4.0); // Inside box.
- point[0] = 0.0; // Closest to the first left image of the bound.
-
- BOOST_REQUIRE_CLOSE(a.MinDistance(point), 1.0, 1e-5);
-
- a[0] = Range(0.0, 2.0); // On edge of box.
- point[0] = 7.1; // 0.1 away from the first right image of the bound.
-
- BOOST_REQUIRE_CLOSE(a.MinDistance(point), 0.01, 1e-5);
-
- PeriodicHRectBound<2> d(arma::vec("0.0"));
- d[0] = Range(-10.0, 10.0); // Box is of infinite size.
- point[0] = 810.0; // 800 away from the only image of the box.
-
- BOOST_REQUIRE_CLOSE(d.MinDistance(point), 640000, 1e-5);
-
- PeriodicHRectBound<2> e(arma::vec("-5.0"));
- e[0] = Range(2.0, 4.0); // Box size of -5 should function the same as 5.
- point[0] = -10.8; // Should alias to 4.2.
-
- BOOST_REQUIRE_CLOSE(e.MinDistance(point), 0.04, 1e-5);
-
- // Switch our bound to a higher dimensionality. This should ensure that the
- // dimensions are independent like they should be.
- PeriodicHRectBound<2> c(arma::vec("5.0 5.0 5.0 5.0 5.0 5.0 0.0 -5.0"));
-
- c[0] = Range(2.0, 4.0); // Entirely inside box.
- c[1] = Range(0.0, 5.0); // Fills box fully.
- c[2] = Range(-10.0, 10.0); // Larger than the box.
- c[3] = Range(-2.0, 1.0); // Crosses over an edge.
- c[4] = Range(2.0, 4.0); // Inside box.
- c[5] = Range(0.0, 2.0); // On edge of box.
- c[6] = Range(-10.0, 10.0); // Box is of infinite size.
- c[7] = Range(2.0, 4.0); // Box size of -5 should function the same as 5.
-
- point.set_size(8);
- point[0] = 7.5; // Inside first right image of the box.
- point[1] = 19.3; // Inside the box, which covers everything.
- point[2] = -500.0; // Inside the box, which covers everything.
- point[3] = 2.9; // The first right image of the bound starts at 3.0.
- point[4] = 0.0; // Closest to the first left image of the bound.
- point[5] = 7.1; // 0.1 away from the first right image of the bound.
- point[6] = 810.0; // 800 away from the only image of the box.
- point[7] = -10.8; // Should alias to 4.2.
-
- BOOST_REQUIRE_CLOSE(c.MinDistance(point), 640001.06, 1e-10);
-}
-
-/**
- * Correctly calculate the minimum distance between the bound and another bound in
- * periodic coordinates. We have to account for the shifts necessary in
- * periodic coordinates too, so that makes testing this a little more difficult.
- */
-BOOST_AUTO_TEST_CASE(PeriodicHRectBoundMinDistanceBound)
-{
- // First, we'll start with a simple 2-dimensional case where the bounds are nonoverlapping,
- // then one bound is on the edge of the other bound,
- // then overlapping, then one range entirely covering the other. The box size will be large enough that this is basically the
- // HRectBound case.
- PeriodicHRectBound<2> b(arma::vec("100 100"));
- PeriodicHRectBound<2> c(arma::vec("100 100"));
-
- b[0] = Range(0.0, 5.0);
- b[1] = Range(2.0, 4.0);
-
- // Inside the bound.
- c[0] = Range(7.0, 9.0);
- c[1] = Range(10.0,12.0);
-
-
- BOOST_REQUIRE_CLOSE(b.MinDistance(c), 40.0, 1e-5);
-
- // On the edge.
- c[0] = Range(5.0, 8.0);
- c[1] = Range(4.0, 6.0);
-
- BOOST_REQUIRE_SMALL(b.MinDistance(c), 1e-5);
-
- // Overlapping the bound.
- c[0] = Range(3.0, 6.0);
- c[1] = Range(1.0, 3.0);
-
- BOOST_REQUIRE_SMALL(b.MinDistance(c), 1e-5);
-
- // One range entirely covering the other
-
- c[0] = Range(0.0, 6.0);
- c[1] = Range(1.0, 7.0);
-
- BOOST_REQUIRE_SMALL(b.MinDistance(c), 1e-5);
-
- // Now we start to invoke the periodicity. These bounds "alias" to (-3.0,
- // -1.0) and (5,0,6.0).
-
- c[0] = Range(97.0, 99.0);
- c[1] = Range(105.0, 106.0);
-
- BOOST_REQUIRE_CLOSE(b.MinDistance(c), 2.0, 1e-5);
-
- // We will perform several tests on a one-dimensional bound and smaller box size and mostly overlapping.
- PeriodicHRectBound<2> a(arma::vec("5.0"));
- PeriodicHRectBound<2> d(a);
-
- a[0] = Range(2.0, 4.0); // Entirely inside box.
- d[0] = Range(7.5, 10.0); // In the right image of the box, overlapping ranges.
-
- BOOST_REQUIRE_SMALL(a.MinDistance(d), 1e-5);
-
- a[0] = Range(0.0, 5.0); // Fills box fully.
- d[0] = Range(19.3, 21.0); // Two intervals inside the box, same as range of b[0].
-
- BOOST_REQUIRE_SMALL(a.MinDistance(d), 1e-5);
-
- a[0] = Range(-10.0, 10.0); // Larger than the box.
- d[0] = Range(-500.0, -498.0); // Inside the box, which covers everything.
-
- BOOST_REQUIRE_SMALL(a.MinDistance(d), 1e-5);
-
- a[0] = Range(-2.0, 1.0); // Crosses over an edge.
- d[0] = Range(2.9, 5.1); // The first right image of the bound starts at 3.0. Overlapping
-
- BOOST_REQUIRE_SMALL(a.MinDistance(d), 1e-5);
-
- a[0] = Range(-1.0, 1.0); // Crosses over an edge.
- d[0] = Range(11.9, 12.5); // The first right image of the bound starts at 4.0.
- BOOST_REQUIRE_CLOSE(a.MinDistance(d), 0.81, 1e-5);
-
- a[0] = Range(2.0, 3.0);
- d[0] = Range(9.5, 11);
- BOOST_REQUIRE_CLOSE(a.MinDistance(d), 1, 1e-5);
-
-}
-
-/**
- * Correctly calculate the maximum distance between the bound and a point in
- * periodic coordinates. We have to account for the shifts necessary in
- * periodic coordinates too, so that makes testing this a little more difficult.
- */
-BOOST_AUTO_TEST_CASE(PeriodicHRectBoundMaxDistancePoint)
-{
- // First, we'll start with a simple 2-dimensional case where the point is
- // inside the bound, then on the edge of the bound, then barely outside the
- // bound. The box size will be large enough that this is basically the
- // HRectBound case.
- PeriodicHRectBound<2> b(arma::vec("100 100"));
-
- b[0] = Range(0.0, 5.0);
- b[1] = Range(2.0, 4.0);
-
- // Inside the bound.
- arma::vec point = "2.5 3.0";
-
- //BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 7.25, 1e-5);
-
- // On the edge.
- point = "5.0 4.0";
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 29.0, 1e-5);
-
- // And just a little outside the bound.
- point = "6.0 5.0";
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 45.0, 1e-5);
-
- // Now we start to invoke the periodicity. This point will "alias" to (-1,
- // -1).
- point = "99.0 99.0";
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 61.0, 1e-5);
-
- // We will perform several tests on a one-dimensional bound and smaller box size.
- PeriodicHRectBound<2> a(arma::vec("5.0"));
- point.set_size(1);
-
- a[0] = Range(2.0, 4.0); // Entirely inside box.
- point[0] = 7.5; // Inside first right image of the box.
-
- BOOST_REQUIRE_CLOSE(a.MaxDistance(point), 2.25, 1e-5);
-
- a[0] = Range(0.0, 5.0); // Fills box fully.
- point[1] = 19.3; // Inside the box, which covers everything.
-
- BOOST_REQUIRE_CLOSE(a.MaxDistance(point), 18.49, 1e-5);
-
- a[0] = Range(-10.0, 10.0); // Larger than the box.
- point[0] = -500.0; // Inside the box, which covers everything.
-
- BOOST_REQUIRE_CLOSE(a.MaxDistance(point), 25.0, 1e-5);
-
- a[0] = Range(-2.0, 1.0); // Crosses over an edge.
- point[0] = 2.9; // The first right image of the bound starts at 3.0.
-
- BOOST_REQUIRE_CLOSE(a.MaxDistance(point), 8.41, 1e-5);
-
- a[0] = Range(2.0, 4.0); // Inside box.
- point[0] = 0.0; // Farthest from the first right image of the bound.
-
- BOOST_REQUIRE_CLOSE(a.MaxDistance(point), 25.0, 1e-5);
-
- a[0] = Range(0.0, 2.0); // On edge of box.
- point[0] = 7.1; // 2.1 away from the first left image of the bound.
-
- BOOST_REQUIRE_CLOSE(a.MaxDistance(point), 4.41, 1e-5);
-
- PeriodicHRectBound<2> d(arma::vec("0.0"));
- d[0] = Range(-10.0, 10.0); // Box is of infinite size.
- point[0] = 810.0; // 820 away from the only left image of the box.
-
- BOOST_REQUIRE_CLOSE(d.MinDistance(point), 672400.0, 1e-5);
-
- PeriodicHRectBound<2> e(arma::vec("-5.0"));
- e[0] = Range(2.0, 4.0); // Box size of -5 should function the same as 5.
- point[0] = -10.8; // Should alias to 4.2.
-
- BOOST_REQUIRE_CLOSE(e.MaxDistance(point), 4.84, 1e-5);
-
- // Switch our bound to a higher dimensionality. This should ensure that the
- // dimensions are independent like they should be.
- PeriodicHRectBound<2> c(arma::vec("5.0 5.0 5.0 5.0 5.0 5.0 0.0 -5.0"));
-
- c[0] = Range(2.0, 4.0); // Entirely inside box.
- c[1] = Range(0.0, 5.0); // Fills box fully.
- c[2] = Range(-10.0, 10.0); // Larger than the box.
- c[3] = Range(-2.0, 1.0); // Crosses over an edge.
- c[4] = Range(2.0, 4.0); // Inside box.
- c[5] = Range(0.0, 2.0); // On edge of box.
- c[6] = Range(-10.0, 10.0); // Box is of infinite size.
- c[7] = Range(2.0, 4.0); // Box size of -5 should function the same as 5.
-
- point.set_size(8);
- point[0] = 7.5; // Inside first right image of the box.
- point[1] = 19.3; // Inside the box, which covers everything.
- point[2] = -500.0; // Inside the box, which covers everything.
- point[3] = 2.9; // The first right image of the bound starts at 3.0.
- point[4] = 0.0; // Closest to the first left image of the bound.
- point[5] = 7.1; // 0.1 away from the first right image of the bound.
- point[6] = 810.0; // 800 away from the only image of the box.
- point[7] = -10.8; // Should alias to 4.2.
-
- BOOST_REQUIRE_CLOSE(c.MaxDistance(point), 672630.65, 1e-10);
-}
-
-/**
- * Correctly calculate the maximum distance between the bound and another bound in
- * periodic coordinates. We have to account for the shifts necessary in
- * periodic coordinates too, so that makes testing this a little more difficult.
- */
-BOOST_AUTO_TEST_CASE(PeriodicHRectBoundMaxDistanceBound)
-{
- // First, we'll start with a simple 2-dimensional case where the bounds are nonoverlapping,
- // then one bound is on the edge of the other bound,
- // then overlapping, then one range entirely covering the other. The box size will be large enough that this is basically the
- // HRectBound case.
- PeriodicHRectBound<2> b(arma::vec("100 100"));
- PeriodicHRectBound<2> c(b);
-
- b[0] = Range(0.0, 5.0);
- b[1] = Range(2.0, 4.0);
-
- // Inside the bound.
-
- c[0] = Range(7.0, 9.0);
- c[1] = Range(10.0,12.0);
-
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 181.0, 1e-5);
-
- // On the edge.
-
- c[0] = Range(5.0, 8.0);
- c[1] = Range(4.0, 6.0);
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 80.0, 1e-5);
-
- // Overlapping the bound.
-
- c[0] = Range(3.0, 6.0);
- c[1] = Range(1.0, 3.0);
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 45.0, 1e-5);
-
- // One range entirely covering the other
-
- c[0] = Range(0.0, 6.0);
- c[1] = Range(1.0, 7.0);
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 61.0, 1e-5);
-
- // Now we start to invoke the periodicity. Thess bounds "alias" to (-3.0,
- // -1.0) and (5,0,6.0).
-
- c[0] = Range(97.0, 99.0);
- c[1] = Range(105.0, 106.0);
-
- BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 80.0, 1e-5);
-
- // We will perform several tests on a one-dimensional bound and smaller box size.
- PeriodicHRectBound<2> a(arma::vec("5.0"));
- PeriodicHRectBound<2> d(a);
-
- a[0] = Range(2.0, 4.0); // Entirely inside box.
- d[0] = Range(7.5, 10); // In the right image of the box, overlapping ranges.
-
- BOOST_REQUIRE_CLOSE(a.MaxDistance(d), 9.0, 1e-5);
-
- a[0] = Range(0.0, 5.0); // Fills box fully.
- d[0] = Range(19.3, 21.0); // Two intervals inside the box, same as range of b[0].
-
- BOOST_REQUIRE_CLOSE(a.MaxDistance(d), 18.49, 1e-5);
-
- a[0] = Range(-10.0, 10.0); // Larger than the box.
- d[0] = Range(-500.0, -498.0); // Inside the box, which covers everything.
-
- BOOST_REQUIRE_CLOSE(a.MaxDistance(d), 9.0, 1e-5);
-
- a[0] = Range(-2.0, 1.0); // Crosses over an edge.
- d[0] = Range(2.9, 5.1); // The first right image of the bound starts at 3.0.
-
- BOOST_REQUIRE_CLOSE(a.MaxDistance(d), 24.01, 1e-5);
-}
-
-
-/**
- * It seems as though Bill has stumbled across a bug where
- * BinarySpaceTree<>::count() returns something different than
- * BinarySpaceTree<>::count_. So, let's build a simple tree and make sure they
- * are the same.
- */
-BOOST_AUTO_TEST_CASE(TreeCountMismatch)
-{
- arma::mat dataset = "2.0 5.0 9.0 4.0 8.0 7.0;"
- "3.0 4.0 6.0 7.0 1.0 2.0 ";
-
- // Leaf size of 1.
- BinarySpaceTree<HRectBound<2> > rootNode(dataset, 1);
-
- BOOST_REQUIRE(rootNode.Count() == 6);
- BOOST_REQUIRE(rootNode.Left()->Count() == 3);
- BOOST_REQUIRE(rootNode.Left()->Left()->Count() == 2);
- BOOST_REQUIRE(rootNode.Left()->Left()->Left()->Count() == 1);
- BOOST_REQUIRE(rootNode.Left()->Left()->Right()->Count() == 1);
- BOOST_REQUIRE(rootNode.Left()->Right()->Count() == 1);
- BOOST_REQUIRE(rootNode.Right()->Count() == 3);
- BOOST_REQUIRE(rootNode.Right()->Left()->Count() == 2);
- BOOST_REQUIRE(rootNode.Right()->Left()->Left()->Count() == 1);
- BOOST_REQUIRE(rootNode.Right()->Left()->Right()->Count() == 1);
- BOOST_REQUIRE(rootNode.Right()->Right()->Count() == 1);
-}
-
-// Forward declaration of methods we need for the next test.
-template<typename TreeType>
-bool CheckPointBounds(TreeType* node, const arma::mat& data);
-
-template<typename TreeType>
-void GenerateVectorOfTree(TreeType* node,
- size_t depth,
- std::vector<TreeType*>& v);
-
-template<int t_pow>
-bool DoBoundsIntersect(HRectBound<t_pow>& a,
- HRectBound<t_pow>& b,
- size_t ia,
- size_t ib);
-
-/**
- * Exhaustive kd-tree test based on #125.
- *
- * - Generate a random dataset of a random size.
- * - Build a tree on that dataset.
- * - Ensure all the permutation indices map back to the correct points.
- * - Verify that each point is contained inside all of the bounds of its parent
- * nodes.
- * - Verify that each bound at a particular level of the tree does not overlap
- * with any other bounds at that level.
- *
- * Then, we do that whole process a handful of times.
- */
-BOOST_AUTO_TEST_CASE(KdTreeTest)
-{
- typedef BinarySpaceTree<HRectBound<2> > TreeType;
-
- size_t maxRuns = 10; // Ten total tests.
- size_t pointIncrements = 1000; // Range is from 2000 points to 11000.
-
- // We use the default leaf size of 20.
- for(size_t run = 0; run < maxRuns; run++)
- {
- size_t dimensions = run + 2;
- size_t maxPoints = (run + 1) * pointIncrements;
-
- size_t size = maxPoints;
- arma::mat dataset = arma::mat(dimensions, size);
- arma::mat datacopy; // Used to test mappings.
-
- // Mappings for post-sort verification of data.
- std::vector<size_t> newToOld;
- std::vector<size_t> oldToNew;
-
- // Generate data.
- dataset.randu();
- datacopy = dataset; // Save a copy.
-
- // Build the tree itself.
- TreeType root(dataset, newToOld, oldToNew);
-
- // Ensure the size of the tree is correct.
- BOOST_REQUIRE_EQUAL(root.Count(), size);
-
- // Check the forward and backward mappings for correctness.
- for(size_t i = 0; i < size; i++)
- {
- for(size_t j = 0; j < dimensions; j++)
- {
- BOOST_REQUIRE_EQUAL(dataset(j, i), datacopy(j, newToOld[i]));
- BOOST_REQUIRE_EQUAL(dataset(j, oldToNew[i]), datacopy(j, i));
- }
- }
-
- // Now check that each point is contained inside of all bounds above it.
- CheckPointBounds(&root, dataset);
-
- // Now check that no peers overlap.
- std::vector<TreeType*> v;
- GenerateVectorOfTree(&root, 1, v);
-
- // Start with the first pair.
- size_t depth = 2;
- // Compare each peer against every other peer.
- while (depth < v.size())
- {
- for (size_t i = depth; i < 2 * depth && i < v.size(); i++)
- for (size_t j = i + 1; j < 2 * depth && j < v.size(); j++)
- if (v[i] != NULL && v[j] != NULL)
- BOOST_REQUIRE(!DoBoundsIntersect(v[i]->Bound(), v[j]->Bound(),
- i, j));
-
- depth *= 2;
- }
- }
-
- arma::mat dataset = arma::mat(25, 1000);
- for (size_t col = 0; col < dataset.n_cols; ++col)
- for (size_t row = 0; row < dataset.n_rows; ++row)
- dataset(row, col) = row + col;
-
- TreeType root(dataset);
- // Check the tree size.
- BOOST_REQUIRE_EQUAL(root.TreeSize(), 127);
- // Check the tree depth.
- BOOST_REQUIRE_EQUAL(root.TreeDepth(), 7);
-}
-
-// Recursively checks that each node contains all points that it claims to have.
-template<typename TreeType>
-bool CheckPointBounds(TreeType* node, const arma::mat& data)
-{
- if (node == NULL) // We have passed a leaf node.
- return true;
-
- TreeType* left = node->Left();
- TreeType* right = node->Right();
-
- size_t begin = node->Begin();
- size_t count = node->Count();
-
- // Check that each point which this tree claims is actually inside the tree.
- for (size_t index = begin; index < begin + count; index++)
- if (!node->Bound().Contains(data.col(index)))
- return false;
-
- return CheckPointBounds(left, data) && CheckPointBounds(right, data);
-}
-
-template<int t_pow>
-bool DoBoundsIntersect(HRectBound<t_pow>& a,
- HRectBound<t_pow>& b,
- size_t ia,
- size_t ib)
-{
- size_t dimensionality = a.Dim();
-
- Range r_a;
- Range r_b;
-
- for (size_t i = 0; i < dimensionality; i++)
- {
- r_a = a[i];
- r_b = b[i];
- if (r_a < r_b || r_a > r_b) // If a does not overlap b at all.
- return false;
- }
-
- return true;
-}
-
-template<typename TreeType>
-void GenerateVectorOfTree(TreeType* node,
- size_t depth,
- std::vector<TreeType*>& v)
-{
- if (node == NULL)
- return;
-
- if (depth >= v.size())
- v.resize(2 * depth + 1, NULL); // Resize to right size; fill with NULL.
-
- v[depth] = node;
-
- // Recurse to the left and right children.
- GenerateVectorOfTree(node->Left(), depth * 2, v);
- GenerateVectorOfTree(node->Right(), depth * 2 + 1, v);
-
- return;
-}
-
-/**
- * Exhaustive sparse kd-tree test based on #125.
- *
- * - Generate a random dataset of a random size.
- * - Build a tree on that dataset.
- * - Ensure all the permutation indices map back to the correct points.
- * - Verify that each point is contained inside all of the bounds of its parent
- * nodes.
- * - Verify that each bound at a particular level of the tree does not overlap
- * with any other bounds at that level.
- *
- * Then, we do that whole process a handful of times.
- */
-BOOST_AUTO_TEST_CASE(ExhaustiveSparseKDTreeTest)
-{
- typedef BinarySpaceTree<HRectBound<2>, EmptyStatistic, arma::SpMat<double> >
- TreeType;
-
- size_t maxRuns = 2; // Two total tests.
- size_t pointIncrements = 200; // Range is from 200 points to 400.
-
- // We use the default leaf size of 20.
- for(size_t run = 0; run < maxRuns; run++)
- {
- size_t dimensions = run + 2;
- size_t maxPoints = (run + 1) * pointIncrements;
-
- size_t size = maxPoints;
- arma::SpMat<double> dataset = arma::SpMat<double>(dimensions, size);
- arma::SpMat<double> datacopy; // Used to test mappings.
-
- // Mappings for post-sort verification of data.
- std::vector<size_t> newToOld;
- std::vector<size_t> oldToNew;
-
- // Generate data.
- dataset.randu();
- datacopy = dataset; // Save a copy.
-
- // Build the tree itself.
- TreeType root(dataset, newToOld, oldToNew);
-
- // Ensure the size of the tree is correct.
- BOOST_REQUIRE_EQUAL(root.Count(), size);
-
- // Check the forward and backward mappings for correctness.
- for(size_t i = 0; i < size; i++)
- {
- for(size_t j = 0; j < dimensions; j++)
- {
- BOOST_REQUIRE_EQUAL(dataset(j, i), datacopy(j, newToOld[i]));
- BOOST_REQUIRE_EQUAL(dataset(j, oldToNew[i]), datacopy(j, i));
- }
- }
-
- // Now check that each point is contained inside of all bounds above it.
- CheckPointBounds(&root, dataset);
-
- // Now check that no peers overlap.
- std::vector<TreeType*> v;
- GenerateVectorOfTree(&root, 1, v);
-
- // Start with the first pair.
- size_t depth = 2;
- // Compare each peer against every other peer.
- while (depth < v.size())
- {
- for (size_t i = depth; i < 2 * depth && i < v.size(); i++)
- for (size_t j = i + 1; j < 2 * depth && j < v.size(); j++)
- if (v[i] != NULL && v[j] != NULL)
- BOOST_REQUIRE(!DoBoundsIntersect(v[i]->Bound(), v[j]->Bound(),
- i, j));
-
- depth *= 2;
- }
- }
-
- arma::SpMat<double> dataset(25, 1000);
- for (size_t col = 0; col < dataset.n_cols; ++col)
- for (size_t row = 0; row < dataset.n_rows; ++row)
- dataset(row, col) = row + col;
-
- TreeType root(dataset);
- // Check the tree size.
- BOOST_REQUIRE_EQUAL(root.TreeSize(), 127);
- // Check the tree depth.
- BOOST_REQUIRE_EQUAL(root.TreeDepth(), 7);
-}
-
-BOOST_AUTO_TEST_SUITE_END();
Copied: mlpack/tags/mlpack-1.0.0/src/mlpack/tests/tree_test.cpp (from rev 10890, mlpack/tags/mlpack-1.0/src/mlpack/tests/tree_test.cpp)
===================================================================
--- mlpack/tags/mlpack-1.0.0/src/mlpack/tests/tree_test.cpp (rev 0)
+++ mlpack/tags/mlpack-1.0.0/src/mlpack/tests/tree_test.cpp 2011-12-17 09:02:47 UTC (rev 10893)
@@ -0,0 +1,914 @@
+/**
+ * @file tree_test.cpp
+ *
+ * Tests for tree-building methods.
+ */
+#include <mlpack/core/tree/bounds.hpp>
+#include <mlpack/core/tree/binary_space_tree.hpp>
+#include <mlpack/core/metrics/lmetric.hpp>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+using namespace mlpack;
+using namespace mlpack::math;
+using namespace mlpack::tree;
+using namespace mlpack::metric;
+using namespace mlpack::bound;
+
+BOOST_AUTO_TEST_SUITE(TreeTest);
+
+/**
+ * Ensure that a bound, by default, is empty and has no dimensionality.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundEmptyConstructor)
+{
+ HRectBound<2> b;
+
+ BOOST_REQUIRE_EQUAL(b.Dim(), 0);
+}
+
+/**
+ * Ensure that when we specify the dimensionality in the constructor, it is
+ * correct, and the bounds are all the empty set.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundDimConstructor)
+{
+ HRectBound<2> b(2); // We'll do this with 2 and 5 dimensions.
+
+ BOOST_REQUIRE_EQUAL(b.Dim(), 2);
+ BOOST_REQUIRE_SMALL(b[0].Width(), 1e-5);
+ BOOST_REQUIRE_SMALL(b[1].Width(), 1e-5);
+
+ b = HRectBound<2>(5);
+
+ BOOST_REQUIRE_EQUAL(b.Dim(), 5);
+ BOOST_REQUIRE_SMALL(b[0].Width(), 1e-5);
+ BOOST_REQUIRE_SMALL(b[1].Width(), 1e-5);
+ BOOST_REQUIRE_SMALL(b[2].Width(), 1e-5);
+ BOOST_REQUIRE_SMALL(b[3].Width(), 1e-5);
+ BOOST_REQUIRE_SMALL(b[4].Width(), 1e-5);
+}
+
+/**
+ * Test the copy constructor.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundCopyConstructor)
+{
+ HRectBound<2> b(2);
+ b[0] = Range(0.0, 2.0);
+ b[1] = Range(2.0, 3.0);
+
+ HRectBound<2> c(b);
+
+ BOOST_REQUIRE_EQUAL(c.Dim(), 2);
+ BOOST_REQUIRE_SMALL(c[0].Lo(), 1e-5);
+ BOOST_REQUIRE_CLOSE(c[0].Hi(), 2.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(c[1].Lo(), 2.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(c[1].Hi(), 3.0, 1e-5);
+}
+
+/**
+ * Test the assignment operator.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundAssignmentOperator)
+{
+ HRectBound<2> b(2);
+ b[0] = Range(0.0, 2.0);
+ b[1] = Range(2.0, 3.0);
+
+ HRectBound<2> c(4);
+
+ c = b;
+
+ BOOST_REQUIRE_EQUAL(c.Dim(), 2);
+ BOOST_REQUIRE_SMALL(c[0].Lo(), 1e-5);
+ BOOST_REQUIRE_CLOSE(c[0].Hi(), 2.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(c[1].Lo(), 2.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(c[1].Hi(), 3.0, 1e-5);
+}
+
+/**
+ * Test that clearing the dimensions resets the bound to empty.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundClear)
+{
+ HRectBound<2> b(2); // We'll do this with two dimensions only.
+
+ b[0] = Range(0.0, 2.0);
+ b[1] = Range(2.0, 4.0);
+
+ // Now we just need to make sure that we clear the range.
+ b.Clear();
+
+ BOOST_REQUIRE_SMALL(b[0].Width(), 1e-5);
+ BOOST_REQUIRE_SMALL(b[1].Width(), 1e-5);
+}
+
+/**
+ * Ensure that we get the correct centroid for our bound.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundCentroid)
+{
+ // Create a simple 3-dimensional bound.
+ HRectBound<2> b(3);
+
+ b[0] = Range(0.0, 5.0);
+ b[1] = Range(-2.0, -1.0);
+ b[2] = Range(-10.0, 50.0);
+
+ arma::vec centroid;
+
+ b.Centroid(centroid);
+
+ BOOST_REQUIRE_EQUAL(centroid.n_elem, 3);
+ BOOST_REQUIRE_CLOSE(centroid[0], 2.5, 1e-5);
+ BOOST_REQUIRE_CLOSE(centroid[1], -1.5, 1e-5);
+ BOOST_REQUIRE_CLOSE(centroid[2], 20.0, 1e-5);
+}
+
+/**
+ * Ensure that we calculate the correct minimum distance between a point and a
+ * bound.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundMinDistancePoint)
+{
+ // We'll do the calculation in five dimensions, and we'll use three cases for
+ // the point: point is outside the bound; point is on the edge of the bound;
+ // point is inside the bound. In the latter two cases, the distance should be
+ // zero.
+ HRectBound<2> b(5);
+
+ b[0] = Range(0.0, 2.0);
+ b[1] = Range(1.0, 5.0);
+ b[2] = Range(-2.0, 2.0);
+ b[3] = Range(-5.0, -2.0);
+ b[4] = Range(1.0, 2.0);
+
+ arma::vec point = "-2.0 0.0 10.0 3.0 3.0";
+
+ // This will be the Euclidean squared distance.
+ BOOST_REQUIRE_CLOSE(b.MinDistance(point), 95.0, 1e-5);
+
+ point = "2.0 5.0 2.0 -5.0 1.0";
+
+ BOOST_REQUIRE_SMALL(b.MinDistance(point), 1e-5);
+
+ point = "1.0 2.0 0.0 -2.0 1.5";
+
+ BOOST_REQUIRE_SMALL(b.MinDistance(point), 1e-5);
+}
+
+/**
+ * Ensure that we calculate the correct minimum distance between a bound and
+ * another bound.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundMinDistanceBound)
+{
+ // We'll do the calculation in five dimensions, and we can use six cases.
+ // The other bound is completely outside the bound; the other bound is on the
+ // edge of the bound; the other bound partially overlaps the bound; the other
+ // bound fully overlaps the bound; the other bound is entirely inside the
+ // bound; the other bound entirely envelops the bound.
+ HRectBound<2> b(5);
+
+ b[0] = Range(0.0, 2.0);
+ b[1] = Range(1.0, 5.0);
+ b[2] = Range(-2.0, 2.0);
+ b[3] = Range(-5.0, -2.0);
+ b[4] = Range(1.0, 2.0);
+
+ HRectBound<2> c(5);
+
+ // The other bound is completely outside the bound.
+ c[0] = Range(-5.0, -2.0);
+ c[1] = Range(6.0, 7.0);
+ c[2] = Range(-2.0, 2.0);
+ c[3] = Range(2.0, 5.0);
+ c[4] = Range(3.0, 4.0);
+
+ BOOST_REQUIRE_CLOSE(b.MinDistance(c), 22.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(c.MinDistance(b), 22.0, 1e-5);
+
+ // The other bound is on the edge of the bound.
+ c[0] = Range(-2.0, 0.0);
+ c[1] = Range(0.0, 1.0);
+ c[2] = Range(-3.0, -2.0);
+ c[3] = Range(-10.0, -5.0);
+ c[4] = Range(2.0, 3.0);
+
+ BOOST_REQUIRE_SMALL(b.MinDistance(c), 1e-5);
+ BOOST_REQUIRE_SMALL(c.MinDistance(b), 1e-5);
+
+ // The other bound partially overlaps the bound.
+ c[0] = Range(-2.0, 1.0);
+ c[1] = Range(0.0, 2.0);
+ c[2] = Range(-2.0, 2.0);
+ c[3] = Range(-8.0, -4.0);
+ c[4] = Range(0.0, 4.0);
+
+ BOOST_REQUIRE_SMALL(b.MinDistance(c), 1e-5);
+ BOOST_REQUIRE_SMALL(c.MinDistance(b), 1e-5);
+
+ // The other bound fully overlaps the bound.
+ BOOST_REQUIRE_SMALL(b.MinDistance(b), 1e-5);
+ BOOST_REQUIRE_SMALL(c.MinDistance(c), 1e-5);
+
+ // The other bound is entirely inside the bound / the other bound entirely
+ // envelops the bound.
+ c[0] = Range(-1.0, 3.0);
+ c[1] = Range(0.0, 6.0);
+ c[2] = Range(-3.0, 3.0);
+ c[3] = Range(-7.0, 0.0);
+ c[4] = Range(0.0, 5.0);
+
+ BOOST_REQUIRE_SMALL(b.MinDistance(c), 1e-5);
+ BOOST_REQUIRE_SMALL(c.MinDistance(b), 1e-5);
+
+ // Now we must be sure that the minimum distance to itself is 0.
+ BOOST_REQUIRE_SMALL(b.MinDistance(b), 1e-5);
+ BOOST_REQUIRE_SMALL(c.MinDistance(c), 1e-5);
+}
+
+/**
+ * Ensure that we calculate the correct maximum distance between a bound and a
+ * point. This uses the same test cases as the MinDistance test.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundMaxDistancePoint)
+{
+ // We'll do the calculation in five dimensions, and we'll use three cases for
+ // the point: point is outside the bound; point is on the edge of the bound;
+ // point is inside the bound. In the latter two cases, the distance should be
+ // zero.
+ HRectBound<2> b(5);
+
+ b[0] = Range(0.0, 2.0);
+ b[1] = Range(1.0, 5.0);
+ b[2] = Range(-2.0, 2.0);
+ b[3] = Range(-5.0, -2.0);
+ b[4] = Range(1.0, 2.0);
+
+ arma::vec point = "-2.0 0.0 10.0 3.0 3.0";
+
+ // This will be the Euclidean squared distance.
+ BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 253.0, 1e-5);
+
+ point = "2.0 5.0 2.0 -5.0 1.0";
+
+ BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 46.0, 1e-5);
+
+ point = "1.0 2.0 0.0 -2.0 1.5";
+
+ BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 23.25, 1e-5);
+}
+
+/**
+ * Ensure that we calculate the correct maximum distance between a bound and
+ * another bound. This uses the same test cases as the MinDistance test.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundMaxDistanceBound)
+{
+ // We'll do the calculation in five dimensions, and we can use six cases.
+ // The other bound is completely outside the bound; the other bound is on the
+ // edge of the bound; the other bound partially overlaps the bound; the other
+ // bound fully overlaps the bound; the other bound is entirely inside the
+ // bound; the other bound entirely envelops the bound.
+ HRectBound<2> b(5);
+
+ b[0] = Range(0.0, 2.0);
+ b[1] = Range(1.0, 5.0);
+ b[2] = Range(-2.0, 2.0);
+ b[3] = Range(-5.0, -2.0);
+ b[4] = Range(1.0, 2.0);
+
+ HRectBound<2> c(5);
+
+ // The other bound is completely outside the bound.
+ c[0] = Range(-5.0, -2.0);
+ c[1] = Range(6.0, 7.0);
+ c[2] = Range(-2.0, 2.0);
+ c[3] = Range(2.0, 5.0);
+ c[4] = Range(3.0, 4.0);
+
+ BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 210.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 210.0, 1e-5);
+
+ // The other bound is on the edge of the bound.
+ c[0] = Range(-2.0, 0.0);
+ c[1] = Range(0.0, 1.0);
+ c[2] = Range(-3.0, -2.0);
+ c[3] = Range(-10.0, -5.0);
+ c[4] = Range(2.0, 3.0);
+
+ BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 134.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 134.0, 1e-5);
+
+ // The other bound partially overlaps the bound.
+ c[0] = Range(-2.0, 1.0);
+ c[1] = Range(0.0, 2.0);
+ c[2] = Range(-2.0, 2.0);
+ c[3] = Range(-8.0, -4.0);
+ c[4] = Range(0.0, 4.0);
+
+ BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 102.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 102.0, 1e-5);
+
+ // The other bound fully overlaps the bound.
+ BOOST_REQUIRE_CLOSE(b.MaxDistance(b), 46.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(c.MaxDistance(c), 61.0, 1e-5);
+
+ // The other bound is entirely inside the bound / the other bound entirely
+ // envelops the bound.
+ c[0] = Range(-1.0, 3.0);
+ c[1] = Range(0.0, 6.0);
+ c[2] = Range(-3.0, 3.0);
+ c[3] = Range(-7.0, 0.0);
+ c[4] = Range(0.0, 5.0);
+
+ BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 100.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 100.0, 1e-5);
+
+ // Identical bounds. This will be the sum of the squared widths in each
+ // dimension.
+ BOOST_REQUIRE_CLOSE(b.MaxDistance(b), 46.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(c.MaxDistance(c), 162.0, 1e-5);
+
+ // One last additional case. If the bound encloses only one point, the
+ // maximum distance between it and itself is 0.
+ HRectBound<2> d(2);
+
+ d[0] = Range(2.0, 2.0);
+ d[1] = Range(3.0, 3.0);
+
+ BOOST_REQUIRE_SMALL(d.MaxDistance(d), 1e-5);
+}
+
+/**
+ * Ensure that the ranges returned by RangeDistance() are equal to the minimum
+ * and maximum distance. We will perform this test by creating random bounds
+ * and comparing the behavior to MinDistance() and MaxDistance() -- so this test
+ * is assuming that those passed and operate correctly.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundRangeDistanceBound)
+{
+ for (int i = 0; i < 50; i++)
+ {
+ size_t dim = math::RandInt(20);
+
+ HRectBound<2> a(dim);
+ HRectBound<2> b(dim);
+
+ // We will set the low randomly and the width randomly for each dimension of
+ // each bound.
+ arma::vec loA(dim);
+ arma::vec widthA(dim);
+
+ loA.randu();
+ widthA.randu();
+
+ arma::vec lo_b(dim);
+ arma::vec width_b(dim);
+
+ lo_b.randu();
+ width_b.randu();
+
+ for (size_t j = 0; j < dim; j++)
+ {
+ a[j] = Range(loA[j], loA[j] + widthA[j]);
+ b[j] = Range(lo_b[j], lo_b[j] + width_b[j]);
+ }
+
+ // Now ensure that MinDistance and MaxDistance report the same.
+ Range r = a.RangeDistance(b);
+ Range s = b.RangeDistance(a);
+
+ BOOST_REQUIRE_CLOSE(r.Lo(), s.Lo(), 1e-5);
+ BOOST_REQUIRE_CLOSE(r.Hi(), s.Hi(), 1e-5);
+
+ BOOST_REQUIRE_CLOSE(r.Lo(), a.MinDistance(b), 1e-5);
+ BOOST_REQUIRE_CLOSE(r.Hi(), a.MaxDistance(b), 1e-5);
+
+ BOOST_REQUIRE_CLOSE(s.Lo(), b.MinDistance(a), 1e-5);
+ BOOST_REQUIRE_CLOSE(s.Hi(), b.MaxDistance(a), 1e-5);
+ }
+}
+
+/**
+ * Ensure that the ranges returned by RangeDistance() are equal to the minimum
+ * and maximum distance. We will perform this test by creating random bounds
+ * and comparing the bheavior to MinDistance() and MaxDistance() -- so this test
+ * is assuming that those passed and operate correctly. This is for the
+ * bound-to-point case.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundRangeDistancePoint)
+{
+ for (int i = 0; i < 20; i++)
+ {
+ size_t dim = math::RandInt(20);
+
+ HRectBound<2> a(dim);
+
+ // We will set the low randomly and the width randomly for each dimension of
+ // each bound.
+ arma::vec loA(dim);
+ arma::vec widthA(dim);
+
+ loA.randu();
+ widthA.randu();
+
+ for (size_t j = 0; j < dim; j++)
+ a[j] = Range(loA[j], loA[j] + widthA[j]);
+
+ // Now run the test on a few points.
+ for (int j = 0; j < 10; j++)
+ {
+ arma::vec point(dim);
+
+ point.randu();
+
+ Range r = a.RangeDistance(point);
+
+ BOOST_REQUIRE_CLOSE(r.Lo(), a.MinDistance(point), 1e-5);
+ BOOST_REQUIRE_CLOSE(r.Hi(), a.MaxDistance(point), 1e-5);
+ }
+ }
+}
+
+/**
+ * Test that we can expand the bound to include a new point.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundOrOperatorPoint)
+{
+ // Because this should be independent in each dimension, we can essentially
+ // run five test cases at once.
+ HRectBound<2> b(5);
+
+ b[0] = Range(1.0, 3.0);
+ b[1] = Range(2.0, 4.0);
+ b[2] = Range(-2.0, -1.0);
+ b[3] = Range(0.0, 0.0);
+ b[4] = Range(); // Empty range.
+
+ arma::vec point = "2.0 4.0 2.0 -1.0 6.0";
+
+ b |= point;
+
+ BOOST_REQUIRE_CLOSE(b[0].Lo(), 1.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[0].Hi(), 3.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[1].Lo(), 2.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[1].Hi(), 4.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[2].Lo(), -2.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[2].Hi(), 2.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[3].Lo(), -1.0, 1e-5);
+ BOOST_REQUIRE_SMALL(b[3].Hi(), 1e-5);
+ BOOST_REQUIRE_CLOSE(b[4].Lo(), 6.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[4].Hi(), 6.0, 1e-5);
+}
+
+/**
+ * Test that we can expand the bound to include another bound.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundOrOperatorBound)
+{
+ // Because this should be independent in each dimension, we can run many tests
+ // at once.
+ HRectBound<2> b(8);
+
+ b[0] = Range(1.0, 3.0);
+ b[1] = Range(2.0, 4.0);
+ b[2] = Range(-2.0, -1.0);
+ b[3] = Range(4.0, 5.0);
+ b[4] = Range(2.0, 4.0);
+ b[5] = Range(0.0, 0.0);
+ b[6] = Range();
+ b[7] = Range(1.0, 3.0);
+
+ HRectBound<2> c(8);
+
+ c[0] = Range(-3.0, -1.0); // Entirely less than the other bound.
+ c[1] = Range(0.0, 2.0); // Touching edges.
+ c[2] = Range(-3.0, -1.5); // Partially overlapping.
+ c[3] = Range(4.0, 5.0); // Identical.
+ c[4] = Range(1.0, 5.0); // Entirely enclosing.
+ c[5] = Range(2.0, 2.0); // A single point.
+ c[6] = Range(1.0, 3.0);
+ c[7] = Range(); // Empty set.
+
+ HRectBound<2> d = c;
+
+ b |= c;
+ d |= b;
+
+ BOOST_REQUIRE_CLOSE(b[0].Lo(), -3.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[0].Hi(), 3.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[0].Lo(), -3.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[0].Hi(), 3.0, 1e-5);
+
+ BOOST_REQUIRE_CLOSE(b[1].Lo(), 0.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[1].Hi(), 4.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[1].Lo(), 0.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[1].Hi(), 4.0, 1e-5);
+
+ BOOST_REQUIRE_CLOSE(b[2].Lo(), -3.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[2].Hi(), -1.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[2].Lo(), -3.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[2].Hi(), -1.0, 1e-5);
+
+ BOOST_REQUIRE_CLOSE(b[3].Lo(), 4.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[3].Hi(), 5.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[3].Lo(), 4.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[3].Hi(), 5.0, 1e-5);
+
+ BOOST_REQUIRE_CLOSE(b[4].Lo(), 1.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[4].Hi(), 5.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[4].Lo(), 1.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[4].Hi(), 5.0, 1e-5);
+
+ BOOST_REQUIRE_SMALL(b[5].Lo(), 1e-5);
+ BOOST_REQUIRE_CLOSE(b[5].Hi(), 2.0, 1e-5);
+ BOOST_REQUIRE_SMALL(d[5].Lo(), 1e-5);
+ BOOST_REQUIRE_CLOSE(d[5].Hi(), 2.0, 1e-5);
+
+ BOOST_REQUIRE_CLOSE(b[6].Lo(), 1.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[6].Hi(), 3.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[6].Lo(), 1.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[6].Hi(), 3.0, 1e-5);
+
+ BOOST_REQUIRE_CLOSE(b[7].Lo(), 1.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(b[7].Hi(), 3.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[7].Lo(), 1.0, 1e-5);
+ BOOST_REQUIRE_CLOSE(d[7].Hi(), 3.0, 1e-5);
+}
+
+/**
+ * Test that the Contains() function correctly figures out whether or not a
+ * point is in a bound.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundContains)
+{
+ // We can test a couple different points: completely outside the bound,
+ // adjacent in one dimension to the bound, adjacent in all dimensions to the
+ // bound, and inside the bound.
+ HRectBound<2> b(3);
+
+ b[0] = Range(0.0, 2.0);
+ b[1] = Range(0.0, 2.0);
+ b[2] = Range(0.0, 2.0);
+
+ // Completely outside the range.
+ arma::vec point = "-1.0 4.0 4.0";
+ BOOST_REQUIRE(!b.Contains(point));
+
+ // Completely outside, but one dimension is in the range.
+ point = "-1.0 4.0 1.0";
+ BOOST_REQUIRE(!b.Contains(point));
+
+ // Outside, but one dimension is on the edge.
+ point = "-1.0 0.0 3.0";
+ BOOST_REQUIRE(!b.Contains(point));
+
+ // Two dimensions are on the edge, but one is outside.
+ point = "0.0 0.0 3.0";
+ BOOST_REQUIRE(!b.Contains(point));
+
+ // Completely on the edge (should be contained).
+ point = "0.0 0.0 0.0";
+ BOOST_REQUIRE(b.Contains(point));
+
+ // Inside the range.
+ point = "0.3 1.0 0.4";
+ BOOST_REQUIRE(b.Contains(point));
+}
+
+BOOST_AUTO_TEST_CASE(TestBallBound)
+{
+ BallBound<> b1;
+ BallBound<> b2;
+
+ // Create two balls with a center distance of 1 from each other.
+ // Give the first one a radius of 0.3 and the second a radius of 0.4.
+ b1.Center().set_size(3);
+ b1.Center()[0] = 1;
+ b1.Center()[1] = 2;
+ b1.Center()[2] = 3;
+ b1.Radius() = 0.3;
+
+ b2.Center().set_size(3);
+ b2.Center()[0] = 1;
+ b2.Center()[1] = 2;
+ b2.Center()[2] = 4;
+ b2.Radius() = 0.4;
+
+ BOOST_REQUIRE_CLOSE(b1.MinDistance(b2), 1-0.3-0.4, 1e-5);
+ BOOST_REQUIRE_CLOSE(b1.RangeDistance(b2).Hi(), 1+0.3+0.4, 1e-5);
+ BOOST_REQUIRE_CLOSE(b1.RangeDistance(b2).Lo(), 1-0.3-0.4, 1e-5);
+ BOOST_REQUIRE_CLOSE(b1.RangeDistance(b2).Hi(), 1+0.3+0.4, 1e-5);
+ BOOST_REQUIRE_CLOSE(b1.RangeDistance(b2).Lo(), 1-0.3-0.4, 1e-5);
+
+ BOOST_REQUIRE_CLOSE(b2.MinDistance(b1), 1-0.3-0.4, 1e-5);
+ BOOST_REQUIRE_CLOSE(b2.MaxDistance(b1), 1+0.3+0.4, 1e-5);
+ BOOST_REQUIRE_CLOSE(b2.RangeDistance(b1).Hi(), 1+0.3+0.4, 1e-5);
+ BOOST_REQUIRE_CLOSE(b2.RangeDistance(b1).Lo(), 1-0.3-0.4, 1e-5);
+
+ BOOST_REQUIRE(b1.Contains(b1.Center()));
+ BOOST_REQUIRE(!b1.Contains(b2.Center()));
+
+ BOOST_REQUIRE(!b2.Contains(b1.Center()));
+ BOOST_REQUIRE(b2.Contains(b2.Center()));
+ arma::vec b2point(3); // A point that's within the radius but not the center.
+ b2point[0] = 1.1;
+ b2point[1] = 2.1;
+ b2point[2] = 4.1;
+
+ BOOST_REQUIRE(b2.Contains(b2point));
+
+ BOOST_REQUIRE_SMALL(b1.MinDistance(b1.Center()), 1e-5);
+ BOOST_REQUIRE_CLOSE(b1.MinDistance(b2.Center()), 1 - 0.3, 1e-5);
+ BOOST_REQUIRE_CLOSE(b2.MinDistance(b1.Center()), 1 - 0.4, 1e-5);
+ BOOST_REQUIRE_CLOSE(b2.MaxDistance(b1.Center()), 1 + 0.4, 1e-5);
+ BOOST_REQUIRE_CLOSE(b1.MaxDistance(b2.Center()), 1 + 0.3, 1e-5);
+}
+
+/**
+ * It seems as though Bill has stumbled across a bug where
+ * BinarySpaceTree<>::count() returns something different than
+ * BinarySpaceTree<>::count_. So, let's build a simple tree and make sure they
+ * are the same.
+ */
+BOOST_AUTO_TEST_CASE(TreeCountMismatch)
+{
+ arma::mat dataset = "2.0 5.0 9.0 4.0 8.0 7.0;"
+ "3.0 4.0 6.0 7.0 1.0 2.0 ";
+
+ // Leaf size of 1.
+ BinarySpaceTree<HRectBound<2> > rootNode(dataset, 1);
+
+ BOOST_REQUIRE(rootNode.Count() == 6);
+ BOOST_REQUIRE(rootNode.Left()->Count() == 3);
+ BOOST_REQUIRE(rootNode.Left()->Left()->Count() == 2);
+ BOOST_REQUIRE(rootNode.Left()->Left()->Left()->Count() == 1);
+ BOOST_REQUIRE(rootNode.Left()->Left()->Right()->Count() == 1);
+ BOOST_REQUIRE(rootNode.Left()->Right()->Count() == 1);
+ BOOST_REQUIRE(rootNode.Right()->Count() == 3);
+ BOOST_REQUIRE(rootNode.Right()->Left()->Count() == 2);
+ BOOST_REQUIRE(rootNode.Right()->Left()->Left()->Count() == 1);
+ BOOST_REQUIRE(rootNode.Right()->Left()->Right()->Count() == 1);
+ BOOST_REQUIRE(rootNode.Right()->Right()->Count() == 1);
+}
+
+// Forward declaration of methods we need for the next test.
+template<typename TreeType>
+bool CheckPointBounds(TreeType* node, const arma::mat& data);
+
+template<typename TreeType>
+void GenerateVectorOfTree(TreeType* node,
+ size_t depth,
+ std::vector<TreeType*>& v);
+
+template<int t_pow>
+bool DoBoundsIntersect(HRectBound<t_pow>& a,
+ HRectBound<t_pow>& b,
+ size_t ia,
+ size_t ib);
+
+/**
+ * Exhaustive kd-tree test based on #125.
+ *
+ * - Generate a random dataset of a random size.
+ * - Build a tree on that dataset.
+ * - Ensure all the permutation indices map back to the correct points.
+ * - Verify that each point is contained inside all of the bounds of its parent
+ * nodes.
+ * - Verify that each bound at a particular level of the tree does not overlap
+ * with any other bounds at that level.
+ *
+ * Then, we do that whole process a handful of times.
+ */
+BOOST_AUTO_TEST_CASE(KdTreeTest)
+{
+ typedef BinarySpaceTree<HRectBound<2> > TreeType;
+
+ size_t maxRuns = 10; // Ten total tests.
+ size_t pointIncrements = 1000; // Range is from 2000 points to 11000.
+
+ // We use the default leaf size of 20.
+ for(size_t run = 0; run < maxRuns; run++)
+ {
+ size_t dimensions = run + 2;
+ size_t maxPoints = (run + 1) * pointIncrements;
+
+ size_t size = maxPoints;
+ arma::mat dataset = arma::mat(dimensions, size);
+ arma::mat datacopy; // Used to test mappings.
+
+ // Mappings for post-sort verification of data.
+ std::vector<size_t> newToOld;
+ std::vector<size_t> oldToNew;
+
+ // Generate data.
+ dataset.randu();
+ datacopy = dataset; // Save a copy.
+
+ // Build the tree itself.
+ TreeType root(dataset, newToOld, oldToNew);
+
+ // Ensure the size of the tree is correct.
+ BOOST_REQUIRE_EQUAL(root.Count(), size);
+
+ // Check the forward and backward mappings for correctness.
+ for(size_t i = 0; i < size; i++)
+ {
+ for(size_t j = 0; j < dimensions; j++)
+ {
+ BOOST_REQUIRE_EQUAL(dataset(j, i), datacopy(j, newToOld[i]));
+ BOOST_REQUIRE_EQUAL(dataset(j, oldToNew[i]), datacopy(j, i));
+ }
+ }
+
+ // Now check that each point is contained inside of all bounds above it.
+ CheckPointBounds(&root, dataset);
+
+ // Now check that no peers overlap.
+ std::vector<TreeType*> v;
+ GenerateVectorOfTree(&root, 1, v);
+
+ // Start with the first pair.
+ size_t depth = 2;
+ // Compare each peer against every other peer.
+ while (depth < v.size())
+ {
+ for (size_t i = depth; i < 2 * depth && i < v.size(); i++)
+ for (size_t j = i + 1; j < 2 * depth && j < v.size(); j++)
+ if (v[i] != NULL && v[j] != NULL)
+ BOOST_REQUIRE(!DoBoundsIntersect(v[i]->Bound(), v[j]->Bound(),
+ i, j));
+
+ depth *= 2;
+ }
+ }
+
+ arma::mat dataset = arma::mat(25, 1000);
+ for (size_t col = 0; col < dataset.n_cols; ++col)
+ for (size_t row = 0; row < dataset.n_rows; ++row)
+ dataset(row, col) = row + col;
+
+ TreeType root(dataset);
+ // Check the tree size.
+ BOOST_REQUIRE_EQUAL(root.TreeSize(), 127);
+ // Check the tree depth.
+ BOOST_REQUIRE_EQUAL(root.TreeDepth(), 7);
+}
+
+// Recursively checks that each node contains all points that it claims to have.
+template<typename TreeType>
+bool CheckPointBounds(TreeType* node, const arma::mat& data)
+{
+ if (node == NULL) // We have passed a leaf node.
+ return true;
+
+ TreeType* left = node->Left();
+ TreeType* right = node->Right();
+
+ size_t begin = node->Begin();
+ size_t count = node->Count();
+
+ // Check that each point which this tree claims is actually inside the tree.
+ for (size_t index = begin; index < begin + count; index++)
+ if (!node->Bound().Contains(data.col(index)))
+ return false;
+
+ return CheckPointBounds(left, data) && CheckPointBounds(right, data);
+}
+
+template<int t_pow>
+bool DoBoundsIntersect(HRectBound<t_pow>& a,
+ HRectBound<t_pow>& b,
+ size_t ia,
+ size_t ib)
+{
+ size_t dimensionality = a.Dim();
+
+ Range r_a;
+ Range r_b;
+
+ for (size_t i = 0; i < dimensionality; i++)
+ {
+ r_a = a[i];
+ r_b = b[i];
+ if (r_a < r_b || r_a > r_b) // If a does not overlap b at all.
+ return false;
+ }
+
+ return true;
+}
+
+template<typename TreeType>
+void GenerateVectorOfTree(TreeType* node,
+ size_t depth,
+ std::vector<TreeType*>& v)
+{
+ if (node == NULL)
+ return;
+
+ if (depth >= v.size())
+ v.resize(2 * depth + 1, NULL); // Resize to right size; fill with NULL.
+
+ v[depth] = node;
+
+ // Recurse to the left and right children.
+ GenerateVectorOfTree(node->Left(), depth * 2, v);
+ GenerateVectorOfTree(node->Right(), depth * 2 + 1, v);
+
+ return;
+}
+
+/**
+ * Exhaustive sparse kd-tree test based on #125.
+ *
+ * - Generate a random dataset of a random size.
+ * - Build a tree on that dataset.
+ * - Ensure all the permutation indices map back to the correct points.
+ * - Verify that each point is contained inside all of the bounds of its parent
+ * nodes.
+ * - Verify that each bound at a particular level of the tree does not overlap
+ * with any other bounds at that level.
+ *
+ * Then, we do that whole process a handful of times.
+ */
+BOOST_AUTO_TEST_CASE(ExhaustiveSparseKDTreeTest)
+{
+ typedef BinarySpaceTree<HRectBound<2>, EmptyStatistic, arma::SpMat<double> >
+ TreeType;
+
+ size_t maxRuns = 2; // Two total tests.
+ size_t pointIncrements = 200; // Range is from 200 points to 400.
+
+ // We use the default leaf size of 20.
+ for(size_t run = 0; run < maxRuns; run++)
+ {
+ size_t dimensions = run + 2;
+ size_t maxPoints = (run + 1) * pointIncrements;
+
+ size_t size = maxPoints;
+ arma::SpMat<double> dataset = arma::SpMat<double>(dimensions, size);
+ arma::SpMat<double> datacopy; // Used to test mappings.
+
+ // Mappings for post-sort verification of data.
+ std::vector<size_t> newToOld;
+ std::vector<size_t> oldToNew;
+
+ // Generate data.
+ dataset.randu();
+ datacopy = dataset; // Save a copy.
+
+ // Build the tree itself.
+ TreeType root(dataset, newToOld, oldToNew);
+
+ // Ensure the size of the tree is correct.
+ BOOST_REQUIRE_EQUAL(root.Count(), size);
+
+ // Check the forward and backward mappings for correctness.
+ for(size_t i = 0; i < size; i++)
+ {
+ for(size_t j = 0; j < dimensions; j++)
+ {
+ BOOST_REQUIRE_EQUAL(dataset(j, i), datacopy(j, newToOld[i]));
+ BOOST_REQUIRE_EQUAL(dataset(j, oldToNew[i]), datacopy(j, i));
+ }
+ }
+
+ // Now check that each point is contained inside of all bounds above it.
+ CheckPointBounds(&root, dataset);
+
+ // Now check that no peers overlap.
+ std::vector<TreeType*> v;
+ GenerateVectorOfTree(&root, 1, v);
+
+ // Start with the first pair.
+ size_t depth = 2;
+ // Compare each peer against every other peer.
+ while (depth < v.size())
+ {
+ for (size_t i = depth; i < 2 * depth && i < v.size(); i++)
+ for (size_t j = i + 1; j < 2 * depth && j < v.size(); j++)
+ if (v[i] != NULL && v[j] != NULL)
+ BOOST_REQUIRE(!DoBoundsIntersect(v[i]->Bound(), v[j]->Bound(),
+ i, j));
+
+ depth *= 2;
+ }
+ }
+
+ arma::SpMat<double> dataset(25, 1000);
+ for (size_t col = 0; col < dataset.n_cols; ++col)
+ for (size_t row = 0; row < dataset.n_rows; ++row)
+ dataset(row, col) = row + col;
+
+ TreeType root(dataset);
+ // Check the tree size.
+ BOOST_REQUIRE_EQUAL(root.TreeSize(), 127);
+ // Check the tree depth.
+ BOOST_REQUIRE_EQUAL(root.TreeDepth(), 7);
+}
+
+BOOST_AUTO_TEST_SUITE_END();
More information about the mlpack-svn
mailing list