49 #include <gtest/gtest.h> 57 #include "../../Algorithm/DBSCANT.hh" 60 const char *
const test1_map[] = {
69 " aaaa . . b b b bbb b ",
86 const char *
const test2_map[] = {
"aaaaAAaaaa", 0 };
90 Point(
double x,
double y,
char classifier,
double weight = 1.0) : x(x), y(y), weight(weight), classifier(classifier) {}
92 double length()
const {
93 return std::sqrt(x*x + y*y);
96 Point operator- (
const Point &rhs)
const {
97 return Point(x-rhs.x, y-rhs.y, classifier, weight);
100 double dist(
const Point &rhs)
const {
101 return operator-(rhs).length();
106 double operator() (
const Point &a,
const Point &b)
const {
113 double operator() (
const Point &a)
const {
122 template<
class OSTREAM>
123 OSTREAM &operator<< (OSTREAM &stream, Point* point) {
124 return stream <<
"(" << point->x <<
", " << point->y <<
", " << point->weight <<
", " <<
"'" << point->classifier <<
"'" <<
")";
127 template<
class OUTPUT_ITERATOR>
128 void parse_points(
const char *
const * input, OUTPUT_ITERATOR points_out,
double uc_weight = 1.0,
double lc_weight = 1.0) {
130 for (; *input != 0; ++input, ++y) {
132 for (
const char *it = *input; *it != 0; ++it, ++x) {
134 const double weight = islower(*it) ? lc_weight : uc_weight;
135 *points_out++ = Point(x, y, *it, weight);
141 testing::AssertionResult checkClusterConsistency(
const std::vector<Point> &points,
const std::vector<int> &cluster_map) {
142 std::map<int, char> cluster_2_classifier;
144 std::vector<int>::const_iterator cluster_it = cluster_map.begin();
145 for (std::vector<Point>::const_iterator point_it = points.begin(), point_it_end = points.end();
146 point_it != point_it_end; ++point_it, ++cluster_it) {
148 std::map<int, char>::const_iterator map_it = cluster_2_classifier.find(*cluster_it);
149 if (map_it == cluster_2_classifier.end()) {
150 cluster_2_classifier[*cluster_it] = point_it->classifier;
152 if (point_it->classifier ==
'.' && *cluster_it != 0) {
153 return testing::AssertionFailure() <<
"Noise point " << &(*point_it) <<
" was mapped to non-noise cluster " << *cluster_it <<
".";
156 if (*cluster_it == 0 && point_it->classifier !=
'.') {
157 return testing::AssertionFailure() <<
"Non-noise point " << &(*point_it) <<
" was mapped to noise cluster (0).";
160 if (map_it->second != point_it->classifier) {
161 return testing::AssertionFailure() <<
"Point " << &(*point_it) <<
" was mapped to cluster '" << map_it->second <<
"'.";
166 return testing::AssertionSuccess() <<
"All points were mapped to clusters as expected.";
169 template<
class II_1,
class II_2>
170 testing::AssertionResult checkCollectionEquivalence(II_1 first1, II_1 last1, II_2 first2, II_2 last2) {
171 for (
int index = 0; first1 != last1 && first2 != last2; ++first1, ++first2, ++index) {
172 if (*first1 != *first2)
173 return testing::AssertionFailure() <<
"Mismatch in element " << index <<
".";
177 return testing::AssertionFailure() <<
"Second collection longer than first one.";
180 return testing::AssertionFailure() <<
"First collection longer than second one.";
182 return testing::AssertionSuccess() <<
"Collections are equivalent.";
185 TEST(DBSCAN, manual_test_1) {
186 std::vector<Point> points;
187 parse_points(test1_map, std::back_inserter(points));
188 std::vector<int> clusters;
191 ACG::Algorithm::DBSCAN(points.begin(), points.end(), Point::DistanceFunc(),
192 std::back_inserter(clusters), 4.0001, 3.0));
193 EXPECT_TRUE(checkClusterConsistency(points, clusters));
197 ACG::Algorithm::DBSCAN(points.begin(), points.end(), Point::DistanceFunc(),
198 std::back_inserter(clusters), 4.0001, 3.0,
200 EXPECT_TRUE(checkClusterConsistency(points, clusters));
203 TEST(DBSCAN, manual_test_2_a) {
204 std::vector<Point> points;
205 parse_points(test2_map, std::back_inserter(points), 1.0, 1.0);
206 std::vector<int> clusters;
208 ACG::Algorithm::DBSCAN(points.begin(), points.end(), Point::DistanceFunc(),
209 std::back_inserter(clusters), 1.01, 1.2, Point::WeightFunc()));
211 const int expected[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
212 EXPECT_TRUE(checkCollectionEquivalence(clusters.begin(), clusters.end(), expected, expected + 10));
215 TEST(DBSCAN, manual_test_2_b) {
216 std::vector<Point> points;
217 parse_points(test2_map, std::back_inserter(points), 1.0, .5);
218 std::vector<int> clusters;
220 ACG::Algorithm::DBSCAN(points.begin(), points.end(), Point::DistanceFunc(),
221 std::back_inserter(clusters), 1.01, 1.2, Point::WeightFunc()));
223 const int expected[] = { 0, 0, 1, 1, 1, 1, 1, 1, 0, 0 };
224 EXPECT_TRUE(checkCollectionEquivalence(clusters.begin(), clusters.end(), expected, expected + 10));