From cdf58b4785c3c11573dfe5015a645190e939e2ee Mon Sep 17 00:00:00 2001 From: Jonathan Franklin Date: Thu, 8 May 2008 20:05:46 +0000 Subject: [PATCH] Added some concept checking, and renamed a few template parameters. [SVN r45227] --- .../boost/algorithm/cluster/cluster_data.hpp | 9 ++- include/boost/algorithm/cluster/concept.hpp | 38 +++++++++++ include/boost/algorithm/cluster/dbscan.hpp | 65 +++++++++++-------- 3 files changed, 83 insertions(+), 29 deletions(-) create mode 100644 include/boost/algorithm/cluster/concept.hpp diff --git a/include/boost/algorithm/cluster/cluster_data.hpp b/include/boost/algorithm/cluster/cluster_data.hpp index 7ba773b..c5186db 100644 --- a/include/boost/algorithm/cluster/cluster_data.hpp +++ b/include/boost/algorithm/cluster/cluster_data.hpp @@ -1,3 +1,8 @@ +// (C) Copyright Jonathan Franklin 2008. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + #if ! defined BOOST_ALGORITHM_CLUSTER_CLUSTER_DATA_HPP #define BOOST_ALGORITHM_CLUSTER_CLUSTER_DATA_HPP @@ -13,10 +18,10 @@ namespace cluster /*! TODO: Document this type. */ -template +template struct cluster_data { - typedef Cluster value_type; + typedef ClusterT value_type; typedef std::vector clusters; cluster_data() : m_pClusters(new clusters) {} ~cluster_data() {} diff --git a/include/boost/algorithm/cluster/concept.hpp b/include/boost/algorithm/cluster/concept.hpp new file mode 100644 index 0000000..9832756 --- /dev/null +++ b/include/boost/algorithm/cluster/concept.hpp @@ -0,0 +1,38 @@ +// (C) Copyright Jonathan Franklin 2008. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if ! defined BOOST_ALGORITHM_CLUSTER_CONCEPT_HPP +#define BOOST_ALGORITHM_CLUSTER_CONCEPT_HPP + +#include + +namespace boost +{ +namespace algorithm +{ +namespace cluster +{ + + // TODO: Document the purpose of this concept. + template + struct DistanceComparableConcept + { + void constraints() + { + // Operation + d(t, t); + } + private: + T t; + DistanceFunT d; + }; + + // TODO: Add concepts here, then delete this comment. + +} // End of namespace cluster; +} // End of namespace algorithm; +} // End of namespace boost; + +#endif // BOOST_ALGORITHM_CLUSTER_CONCEPT_HPP diff --git a/include/boost/algorithm/cluster/dbscan.hpp b/include/boost/algorithm/cluster/dbscan.hpp index 58befd6..6de93c7 100644 --- a/include/boost/algorithm/cluster/dbscan.hpp +++ b/include/boost/algorithm/cluster/dbscan.hpp @@ -1,7 +1,13 @@ +// (C) Copyright Jonathan Franklin 2008. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + #if ! defined BOOST_ALGORITHM_CLUSTER_DBSCAN_HPP #define BOOST_ALGORITHM_CLUSTER_DBSCAN_HPP #include +#include #include namespace boost @@ -13,19 +19,22 @@ namespace cluster namespace detail { +// TODO: Where should we put these? +int const UNCLASSIFIED = -1; +int const NOISE = 0; // TODO: Replace this naive query function w/ R*-tree or fractional cascading. // This query mechanism makes the runtime quadratic. -template +template static void query( - NTupleIter const & query_pt, - NTupleIter const & begin, - NTupleIter const & end, - typename NTupleIter::difference_type eps, - DistFun const & d, - std::vector & v) + NTupleIterT const & query_pt, + NTupleIterT const & begin, + NTupleIterT const & end, + typename NTupleIterT::difference_type eps, + DistFunT const & d, + std::vector & v) { - for(NTupleIter cur_pt = begin; cur_pt != end; ++cur_pt) + for(NTupleIterT cur_pt = begin; cur_pt != end; ++cur_pt) { if (query_pt == cur_pt) continue; @@ -38,12 +47,12 @@ static void query( } // TODO: Replace this so we don't have to store the cluster info for each tuple? -template +template struct node { - node(NTupleIter const & t) : tuple(t), cluster(UNCLASSIFIED) {} + node(NTupleIterT const & t) : tuple(t), cluster(UNCLASSIFIED) {} - NTupleIter tuple; + NTupleIterT tuple; int cluster; }; @@ -58,31 +67,33 @@ struct node * \param[in] d * \return The cluster data (partitioning of the tuples). */ -template -cluster_data -dbscan(NTupleIter const & begin, - NTupleIter const & end, - typename NTupleIter::difference_type const & eps, +template +cluster_data +dbscan(NTupleIterT const & begin, + NTupleIterT const & end, + typename NTupleIterT::difference_type const & eps, size_t min_points, - DistFun const & d) + DistFunT const & d) { - int const UNCLASSIFIED = -1; - int const NOISE = 0; + // Concept check. + function_requires< + DistanceComparableConcept >(); + //DistanceComparableConcept >(); // TODO: Rework the algorithm to NOT make this extra collection? - typedef detail::node node; + typedef detail::node node; typedef std::vector ntuple_nodes; ntuple_nodes tuples; // Initialize algorithm. //size_t num_elems = 0; - for(NTupleIter it = begin; it != end; ++it) + for(NTupleIterT it = begin; it != end; ++it) { //++num_elems; tuples.push_back(node(it)); } - typedef cluster_data > cluster_data; + typedef cluster_data > cluster_data; cluster_data p; // TODO: We should try to make cluster_num go away. @@ -90,7 +101,7 @@ dbscan(NTupleIter const & begin, for(ntuple_nodes::iterator it = tuples.begin(); it != tuples.end(); ++it) { // Skip this tuple if its already been classified as a cluster or noise. - if (it->cluster != UNCLASSIFIED) + if (it->cluster != detail::UNCLASSIFIED) continue; // Expand cluster. @@ -100,14 +111,14 @@ dbscan(NTupleIter const & begin, // If the neighborhood of this tuple is too small, then mark it as noise. if (seeds.size() < min_points) { - it->cluster = NOISE; + it->cluster = detail::NOISE; continue; } // Start the next cluster. ++cluster_num; - p.push_back(Cluster()); // TODO: This is goofy. - Cluster & cur_cluster = p.back(); + p.push_back(ClusterT()); // TODO: This is goofy. + ClusterT & cur_cluster = p.back(); // Mark entire neighborhood as part of the current cluster. it->cluster = cluster_num; @@ -134,7 +145,7 @@ dbscan(NTupleIter const & begin, { if (results[n]->cluster < 1) // Not assigned to cluster yet. { - if (UNCLASSIFIED == results[n]->cluster) + if (detail::UNCLASSIFIED == results[n]->cluster) seeds.push_back(results[n]); results[n]->cluster = cluster_num; cur_cluster.push_back(results[n]->tuple);