43 #include <gtest/gtest.h> 51 #include "../../Algorithm/DBSCANT.hh" 54 const char *
const test1_map[] = {
63 " aaaa . . b b b bbb b ",
80 const char *
const test2_map[] = {
"aaaaAAaaaa", 0 };
84 Point(
double x,
double y,
char classifier,
double weight = 1.0) : x(x), y(y), weight(weight), classifier(classifier) {}
86 double length()
const {
87 return std::sqrt(x*x + y*y);
90 Point operator- (
const Point &rhs)
const {
91 return Point(x-rhs.x, y-rhs.y, classifier, weight);
94 double dist(
const Point &rhs)
const {
95 return operator-(rhs).length();
100 double operator() (
const Point &a,
const Point &b)
const {
107 double operator() (
const Point &a)
const {
116 template<
class OSTREAM>
117 OSTREAM &operator<< (OSTREAM &stream, Point* point) {
118 return stream <<
"(" << point->x <<
", " << point->y <<
", " << point->weight <<
", " <<
"'" << point->classifier <<
"'" <<
")";
121 template<
class OUTPUT_ITERATOR>
122 void parse_points(
const char *
const * input, OUTPUT_ITERATOR points_out,
double uc_weight = 1.0,
double lc_weight = 1.0) {
124 for (; *input != 0; ++input, ++y) {
126 for (
const char *it = *input; *it != 0; ++it, ++x) {
128 const double weight = islower(*it) ? lc_weight : uc_weight;
129 *points_out++ = Point(x, y, *it, weight);
135 testing::AssertionResult checkClusterConsistency(
const std::vector<Point> &points,
const std::vector<int> &cluster_map) {
136 std::map<int, char> cluster_2_classifier;
138 std::vector<int>::const_iterator cluster_it = cluster_map.begin();
139 for (std::vector<Point>::const_iterator point_it = points.begin(), point_it_end = points.end();
140 point_it != point_it_end; ++point_it, ++cluster_it) {
142 std::map<int, char>::const_iterator map_it = cluster_2_classifier.find(*cluster_it);
143 if (map_it == cluster_2_classifier.end()) {
144 cluster_2_classifier[*cluster_it] = point_it->classifier;
146 if (point_it->classifier ==
'.' && *cluster_it != 0) {
147 return testing::AssertionFailure() <<
"Noise point " << &(*point_it) <<
" was mapped to non-noise cluster " << *cluster_it <<
".";
150 if (*cluster_it == 0 && point_it->classifier !=
'.') {
151 return testing::AssertionFailure() <<
"Non-noise point " << &(*point_it) <<
" was mapped to noise cluster (0).";
154 if (map_it->second != point_it->classifier) {
155 return testing::AssertionFailure() <<
"Point " << &(*point_it) <<
" was mapped to cluster '" << map_it->second <<
"'.";
160 return testing::AssertionSuccess() <<
"All points were mapped to clusters as expected.";
163 template<
class II_1,
class II_2>
164 testing::AssertionResult checkCollectionEquivalence(II_1 first1, II_1 last1, II_2 first2, II_2 last2) {
165 for (
int index = 0; first1 != last1 && first2 != last2; ++first1, ++first2, ++index) {
166 if (*first1 != *first2)
167 return testing::AssertionFailure() <<
"Mismatch in element " << index <<
".";
171 return testing::AssertionFailure() <<
"Second collection longer than first one.";
174 return testing::AssertionFailure() <<
"First collection longer than second one.";
176 return testing::AssertionSuccess() <<
"Collections are equivalent.";
179 TEST(DBSCAN, manual_test_1) {
180 std::vector<Point> points;
181 parse_points(test1_map, std::back_inserter(points));
182 std::vector<int> clusters;
185 ACG::Algorithm::DBSCAN(points.begin(), points.end(), Point::DistanceFunc(),
186 std::back_inserter(clusters), 4.0001, 3.0));
187 EXPECT_TRUE(checkClusterConsistency(points, clusters));
191 ACG::Algorithm::DBSCAN(points.begin(), points.end(), Point::DistanceFunc(),
192 std::back_inserter(clusters), 4.0001, 3.0,
194 EXPECT_TRUE(checkClusterConsistency(points, clusters));
197 TEST(DBSCAN, manual_test_2_a) {
198 std::vector<Point> points;
199 parse_points(test2_map, std::back_inserter(points), 1.0, 1.0);
200 std::vector<int> clusters;
202 ACG::Algorithm::DBSCAN(points.begin(), points.end(), Point::DistanceFunc(),
203 std::back_inserter(clusters), 1.01, 1.2, Point::WeightFunc()));
205 const int expected[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
206 EXPECT_TRUE(checkCollectionEquivalence(clusters.begin(), clusters.end(), expected, expected + 10));
209 TEST(DBSCAN, manual_test_2_b) {
210 std::vector<Point> points;
211 parse_points(test2_map, std::back_inserter(points), 1.0, .5);
212 std::vector<int> clusters;
214 ACG::Algorithm::DBSCAN(points.begin(), points.end(), Point::DistanceFunc(),
215 std::back_inserter(clusters), 1.01, 1.2, Point::WeightFunc()));
217 const int expected[] = { 0, 0, 1, 1, 1, 1, 1, 1, 0, 0 };
218 EXPECT_TRUE(checkCollectionEquivalence(clusters.begin(), clusters.end(), expected, expected + 10));