From 57d0567dddff01feea73b348f38cc040dc3cf8e3 Mon Sep 17 00:00:00 2001 From: ryan Date: Wed, 22 Apr 2015 16:30:08 -0400 Subject: [PATCH] Refactor executables for new NeighborSearch API. --- .../methods/neighbor_search/allkfn_main.cpp | 222 ++++++---------- .../methods/neighbor_search/allknn_main.cpp | 251 +++++++----------- 2 files changed, 182 insertions(+), 291 deletions(-) diff --git a/src/mlpack/methods/neighbor_search/allkfn_main.cpp b/src/mlpack/methods/neighbor_search/allkfn_main.cpp index dcc29cd5df..28d79bc9fd 100644 --- a/src/mlpack/methods/neighbor_search/allkfn_main.cpp +++ b/src/mlpack/methods/neighbor_search/allkfn_main.cpp @@ -89,6 +89,12 @@ int main(int argc, char *argv[]) Log::Fatal << referenceData.n_cols << ")." << endl; } + if (CLI::GetParam("query_file") != "") + { + string queryFile = CLI::GetParam("query_file"); + data::Load(queryFile, queryData, true); + } + // Sanity check on leaf size. if (lsInt < 0) { @@ -103,192 +109,134 @@ int main(int argc, char *argv[]) Log::Warn << "--single_mode ignored because --naive is present." << endl; } - if (naive) - leafSize = referenceData.n_cols; - arma::Mat neighbors; arma::mat distances; - if(!CLI::HasParam("r_tree")) + if (naive) { - AllkFN* allkfn = NULL; + AllkFN allkfn(referenceData, false, naive); + if (CLI::HasParam("query_file")) + allkfn.Search(queryData, k, neighbors, distances); + else + allkfn.Search(k, neighbors, distances); + } + if (!CLI::HasParam("r_tree")) + { + // Use default kd-tree. std::vector oldFromNewRefs; + typedef BinarySpaceTree, + NeighborSearchStat> TreeType; + // Build trees by hand, so we can save memory: if we pass a tree to // NeighborSearch, it does not copy the matrix. Log::Info << "Building reference tree..." << endl; Timer::Start("reference_tree_building"); - - BinarySpaceTree, - NeighborSearchStat > - refTree(referenceData, oldFromNewRefs, leafSize); - BinarySpaceTree, - NeighborSearchStat >* - queryTree = NULL; // Empty for now. - + TreeType refTree(referenceData, oldFromNewRefs, leafSize); Timer::Stop("reference_tree_building"); std::vector oldFromNewQueries; - if (CLI::GetParam("query_file") != "") + AllkFN allkfn(&refTree, singleMode); + + arma::mat distancesOut(distances.n_rows, distances.n_cols); + arma::Mat neighborsOut(neighbors.n_rows, neighbors.n_cols); + + if (CLI::HasParam("query_file")) { - string queryFile = CLI::GetParam("query_file"); + if (!singleMode) + { + // Build trees by hand, so we can save memory: if we pass a tree to + // NeighborSearch, it does not copy the matrix. + Log::Info << "Building query tree..." << endl; + Timer::Start("tree_building"); + TreeType queryTree(queryData, oldFromNewQueries, leafSize); + Timer::Stop("tree_building"); + Log::Info << "Tree built." << endl; - data::Load(queryFile, queryData, true); - - Log::Info << "Loaded query data from '" << queryFile << "' (" - << queryData.n_rows << " x " << queryData.n_cols << ")." << endl; - - Log::Info << "Building query tree..." << endl; - - if (naive && leafSize < queryData.n_cols) - leafSize = queryData.n_cols; - - // Build trees by hand, so we can save memory: if we pass a tree to - // NeighborSearch, it does not copy the matrix. - Timer::Start("query_tree_building"); - - queryTree = new BinarySpaceTree, - NeighborSearchStat >(queryData, oldFromNewQueries, - leafSize); - - Timer::Stop("query_tree_building"); - - allkfn = new AllkFN(&refTree, queryTree, referenceData, queryData, - singleMode); - - Log::Info << "Tree built." << endl; + Log::Info << "Computing " << k << " furthest neighbors..." << endl; + allkfn.Search(&queryTree, k, neighborsOut, distancesOut); + } + else + { + Log::Info << "Computing " << k << " furthest neighbors..." << endl; + allkfn.Search(queryData, k, neighborsOut, distancesOut); + } } else { - allkfn = new AllkFN(&refTree, referenceData, singleMode); - - Log::Info << "Trees built." << endl; + Log::Info << "Computing " << k << " furthest neighbors..." << endl; + allkfn.Search(k, neighborsOut, distancesOut); } - Log::Info << "Computing " << k << " furthest neighbors..." << endl; - allkfn->Search(k, neighbors, distances); - Log::Info << "Neighbors computed." << endl; // We have to map back to the original indices from before the tree // construction. Log::Info << "Re-mapping indices..." << endl; - arma::mat distancesOut(distances.n_rows, distances.n_cols); - arma::Mat neighborsOut(neighbors.n_rows, neighbors.n_cols); - // Map the points back to their original locations. if ((CLI::GetParam("query_file") != "") && !singleMode) - Unmap(neighbors, distances, oldFromNewRefs, oldFromNewQueries, neighborsOut, - distancesOut); + Unmap(neighborsOut, distancesOut, oldFromNewRefs, oldFromNewQueries, neighbors, + distances); else if ((CLI::GetParam("query_file") != "") && singleMode) - Unmap(neighbors, distances, oldFromNewRefs, neighborsOut, distancesOut); + Unmap(neighborsOut, distancesOut, oldFromNewRefs, neighbors, distances); else - Unmap(neighbors, distances, oldFromNewRefs, oldFromNewRefs, neighborsOut, - distancesOut); - - // Clean up. - if (queryTree) - delete queryTree; - - delete allkfn; - - // Save output. - data::Save(distancesFile, distancesOut); - data::Save(neighborsFile, neighborsOut); - - } else { // Use the R tree. + Unmap(neighborsOut, distancesOut, oldFromNewRefs, oldFromNewRefs, neighbors, + distances); + } + else + { + // Use the R tree. Log::Info << "Using R tree for furthest-neighbor calculation." << endl; - // Because we may construct it differently, we need a pointer. - NeighborSearch, - RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat> >* allkfn = NULL; - + // Convenience typedef. + typedef RectangleTree< + tree::RStarTreeSplit, arma::mat>, + tree::RStarTreeDescentHeuristic, + NeighborSearchStat, + arma::mat> TreeType; // Build trees by hand, so we can save memory: if we pass a tree to // NeighborSearch, it does not copy the matrix. Log::Info << "Building reference tree..." << endl; Timer::Start("tree_building"); - - RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat> - refTree(referenceData, leafSize, leafSize * 0.4, 5, 2, 0); - - RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat>* - queryTree = NULL; // Empty for now. - + TreeType refTree(referenceData, leafSize, leafSize * 0.4, 5, 2, 0); Timer::Stop("tree_building"); + Log::Info << "Tree built." << endl; + + typedef NeighborSearch, + TreeType> AllkFNType; + AllkFNType allkfn(&refTree, singleMode); + if (CLI::GetParam("query_file") != "") { - string queryFile = CLI::GetParam("query_file"); - - data::Load(queryFile, queryData, true); - - Log::Info << "Loaded query data from '" << queryFile << "' (" - << queryData.n_rows << " x " << queryData.n_cols << ")." << endl; - - // Build trees by hand, so we can save memory: if we pass a tree to - // NeighborSearch, it does not copy the matrix. if (!singleMode) { Timer::Start("tree_building"); - - queryTree = new RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat>(queryData, leafSize, leafSize * 0.4, 5, 2, 0); - + TreeType queryTree(queryData, leafSize, leafSize * 0.4, 5, 2, 0); Timer::Stop("tree_building"); + + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allkfn.Search(&queryTree, k, neighbors, distances); + } + else + { + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allkfn.Search(queryData, k, neighbors, distances); } - - - allkfn = new NeighborSearch, - RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat> >(&refTree, queryTree, - referenceData, queryData, singleMode); - } else - { - allkfn = new NeighborSearch, - RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat> >(&refTree, - referenceData, singleMode); } - Log::Info << "Tree built." << endl; - - //arma::mat distancesOut; - //arma::Mat neighborsOut; - - Log::Info << "Computing " << k << " nearest neighbors..." << endl; - allkfn->Search(k, neighbors, distances); - + else + { + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allkfn.Search(k, neighbors, distances); + } Log::Info << "Neighbors computed." << endl; - - - if(queryTree) - delete queryTree; - - delete allkfn; - - // Save output. - data::Save(distancesFile, distances); - data::Save(neighborsFile, neighbors); - } - - + // Save output. + data::Save(distancesFile, distances); + data::Save(neighborsFile, neighbors); } diff --git a/src/mlpack/methods/neighbor_search/allknn_main.cpp b/src/mlpack/methods/neighbor_search/allknn_main.cpp index 3aaf45e531..5a83b4d719 100644 --- a/src/mlpack/methods/neighbor_search/allknn_main.cpp +++ b/src/mlpack/methods/neighbor_search/allknn_main.cpp @@ -68,13 +68,6 @@ int main(int argc, char *argv[]) // Give CLI the command line parameters the user passed in. CLI::ParseCommandLine(argc, argv); - Log::Info << "sizeof(BinarySpaceTree<>): " << sizeof(BinarySpaceTree>) << ".\n"; - Log::Info << "sizeof(HRectBound<2>): " << sizeof(bound::HRectBound<2>) << ".\n"; - Log::Info << "sizeof(NeighborSearchStat): " << sizeof(NeighborSearchStat) << ".\n"; - Log::Info << "sizeof(TreeType): " << -sizeof(BinarySpaceTree, -NeighborSearchStat>) << ".\n"; - if (CLI::GetParam("seed") != 0) math::RandomSeed((size_t) CLI::GetParam("seed")); else @@ -138,9 +131,6 @@ NeighborSearchStat>) << ".\n"; Log::Warn << "--cover_tree overrides --r_tree." << endl; } - if (naive) - leafSize = referenceData.n_cols; - // See if we want to project onto a random basis. if (randomBasis) { @@ -181,72 +171,67 @@ NeighborSearchStat>) << ".\n"; arma::Mat neighbors; arma::mat distances; - if (!CLI::HasParam("cover_tree")) + if (naive) { - if(!CLI::HasParam("r_tree")) - { - // Because we may construct it differently, we need a pointer. - AllkNN* allknn = NULL; + AllkNN allknn(referenceData, false, naive); + if (CLI::GetParam("query_file") != "") + allknn.Search(queryData, k, neighbors, distances); + else + allknn.Search(k, neighbors, distances); + } + else if (!CLI::HasParam("cover_tree")) + { + if (!CLI::HasParam("r_tree")) + { + // We're using the kd-tree. // Mappings for when we build the tree. std::vector oldFromNewRefs; + // Convenience typedef. + typedef BinarySpaceTree, + NeighborSearchStat> TreeType; + // Build trees by hand, so we can save memory: if we pass a tree to // NeighborSearch, it does not copy the matrix. Log::Info << "Building reference tree..." << endl; Timer::Start("tree_building"); - - BinarySpaceTree, - NeighborSearchStat > - refTree(referenceData, oldFromNewRefs, leafSize); - BinarySpaceTree, - NeighborSearchStat >* - queryTree = NULL; // Empty for now. - + TreeType refTree(referenceData, oldFromNewRefs, leafSize); Timer::Stop("tree_building"); + AllkNN allknn(&refTree, singleMode); + std::vector oldFromNewQueries; - if (CLI::GetParam("query_file") != "") - { - if (naive && leafSize < queryData.n_cols) - leafSize = queryData.n_cols; - - Log::Info << "Loaded query data from '" << queryFile << "' (" - << queryData.n_rows << " x " << queryData.n_cols << ")." << endl; - - Log::Info << "Building query tree..." << endl; - - // Build trees by hand, so we can save memory: if we pass a tree to - // NeighborSearch, it does not copy the matrix. - if (!singleMode) - { - Timer::Start("tree_building"); - - queryTree = new BinarySpaceTree, - NeighborSearchStat >(queryData, - oldFromNewQueries, leafSize); - - Timer::Stop("tree_building"); - } - - allknn = new AllkNN(&refTree, queryTree, referenceData, queryData, - singleMode); - - Log::Info << "Tree built." << endl; - } - else - { - allknn = new AllkNN(&refTree, referenceData, singleMode); - - Log::Info << "Trees built." << endl; - } - arma::mat distancesOut; arma::Mat neighborsOut; - Log::Info << "Computing " << k << " nearest neighbors..." << endl; - allknn->Search(k, neighborsOut, distancesOut); + if (CLI::GetParam("query_file") != "") + { + // Build trees by hand, so we can save memory: if we pass a tree to + // NeighborSearch, it does not copy the matrix. + if (!singleMode) + { + Log::Info << "Building query tree..." << endl; + Timer::Start("tree_building"); + TreeType queryTree(queryData, oldFromNewQueries, leafSize); + Timer::Stop("tree_building"); + Log::Info << "Tree built." << endl; + + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allknn.Search(&queryTree, k, neighborsOut, distancesOut); + } + else + { + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allknn.Search(queryData, k, neighborsOut, distancesOut); + } + } + else + { + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allknn.Search(k, neighborsOut, distancesOut); + } Log::Info << "Neighbors computed." << endl; @@ -263,90 +248,57 @@ NeighborSearchStat>) << ".\n"; else Unmap(neighborsOut, distancesOut, oldFromNewRefs, oldFromNewRefs, neighbors, distances); - - // Clean up. - if (queryTree) - delete queryTree; - - delete allknn; - } else { // R tree. + } + else + { // Make sure to notify the user that they are using an r tree. Log::Info << "Using R tree for nearest-neighbor calculation." << endl; - // Because we may construct it differently, we need a pointer. - NeighborSearch, - RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat> >* allknn = NULL; + // Convenience typedef. + typedef RectangleTree< + tree::RStarTreeSplit, arma::mat>, + tree::RStarTreeDescentHeuristic, + NeighborSearchStat, + arma::mat> TreeType; - // Build trees by hand, so we can save memory: if we pass a tree to - // NeighborSearch, it does not copy the matrix. + // Build tree by hand in order to apply user options. Log::Info << "Building reference tree..." << endl; Timer::Start("tree_building"); - - RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat> - refTree(referenceData, leafSize, leafSize * 0.4, 5, 2, 0); - - RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat>* - queryTree = NULL; // Empty for now. - + TreeType refTree(referenceData, leafSize, leafSize * 0.4, 5, 2, 0); Timer::Stop("tree_building"); + Log::Info << "Tree built." << endl; + + typedef NeighborSearch, + TreeType> AllkNNType; + AllkNNType allknn(&refTree, singleMode); if (CLI::GetParam("query_file") != "") { - Log::Info << "Loaded query data from '" << queryFile << "' (" - << queryData.n_rows << " x " << queryData.n_cols << ")." << endl; - // Build trees by hand, so we can save memory: if we pass a tree to // NeighborSearch, it does not copy the matrix. if (!singleMode) { + Log::Info << "Building query tree..." << endl; Timer::Start("tree_building"); - - queryTree = new RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat>(queryData, leafSize, leafSize * 0.4, 5, 2, 0); - + TreeType queryTree(queryData, leafSize, leafSize * 0.4, 5, 2, 0); Timer::Stop("tree_building"); + Log::Info << "Tree built." << endl; + + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allknn.Search(&queryTree, k, neighbors, distances); + } + else + { + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allknn.Search(queryData, k, neighbors, distances); } - - - allknn = new NeighborSearch, - RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat> >(&refTree, queryTree, - referenceData, queryData, singleMode); - } else - { - allknn = new NeighborSearch, - RectangleTree, arma::mat>, - tree::RStarTreeDescentHeuristic, - NeighborSearchStat, - arma::mat> >(&refTree, - referenceData, singleMode); } - Log::Info << "Tree built." << endl; - - //arma::mat distancesOut; - //arma::Mat neighborsOut; - - Log::Info << "Computing " << k << " nearest neighbors..." << endl; - allknn->Search(k, neighbors, distances); - - Log::Info << "Neighbors computed." << endl; - - if(queryTree) - delete queryTree; - delete allknn; + else + { + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allknn.Search(k, neighbors, distances); + } } } else // Cover trees. @@ -354,19 +306,19 @@ NeighborSearchStat>) << ".\n"; // Make sure to notify the user that they are using cover trees. Log::Info << "Using cover trees for nearest-neighbor calculation." << endl; + // Convenience typedef. + typedef CoverTree, tree::FirstPointIsRoot, + NeighborSearchStat> TreeType; + // Build our reference tree. Log::Info << "Building reference tree..." << endl; Timer::Start("tree_building"); - CoverTree, tree::FirstPointIsRoot, - NeighborSearchStat > referenceTree(referenceData, - 1.3); - CoverTree, tree::FirstPointIsRoot, - NeighborSearchStat >* queryTree = NULL; + TreeType refTree(referenceData, 1.3); Timer::Stop("tree_building"); - NeighborSearch, - CoverTree, tree::FirstPointIsRoot, - NeighborSearchStat > >* allknn = NULL; + typedef NeighborSearch, + TreeType> AllkNNType; + AllkNNType allknn(&refTree, singleMode); // See if we have query data. if (CLI::HasParam("query_file")) @@ -376,34 +328,25 @@ NeighborSearchStat>) << ".\n"; { Log::Info << "Building query tree..." << endl; Timer::Start("tree_building"); - queryTree = new CoverTree, - tree::FirstPointIsRoot, NeighborSearchStat >( - queryData, 1.3); + TreeType queryTree(queryData, 1.3); Timer::Stop("tree_building"); - } - allknn = new NeighborSearch, - CoverTree, tree::FirstPointIsRoot, - NeighborSearchStat > >(&referenceTree, queryTree, - referenceData, queryData, singleMode); + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allknn.Search(&queryTree, k, neighbors, distances); + } + else + { + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allknn.Search(queryData, k, neighbors, distances); + } } else { - allknn = new NeighborSearch, - CoverTree, tree::FirstPointIsRoot, - NeighborSearchStat > >(&referenceTree, - referenceData, singleMode); + Log::Info << "Computing " << k << " nearest neighbors..." << endl; + allknn.Search(k, neighbors, distances); } - Log::Info << "Computing " << k << " nearest neighbors..." << endl; - allknn->Search(k, neighbors, distances); - Log::Info << "Neighbors computed." << endl; - - delete allknn; - - if (queryTree) - delete queryTree; } // Save put.