Skip to content

Commit

Permalink
Added test cases for DBSCAN
Browse files Browse the repository at this point in the history
  • Loading branch information
spirosmaggioros committed Apr 12, 2024
1 parent 533cb63 commit fc5b638
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 98 deletions.
16 changes: 8 additions & 8 deletions examples/graph/unnamed.dot
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
graph G{
2--0[weight=7]
0--1[weight=6]
0--2[weight=7]
4--3[weight=5]
3--1[weight=4]
3--4[weight=5]
1--3[weight=4]
1--0[weight=6]
2--0[label=7]
0--1[label=6]
0--2[label=7]
4--3[label=5]
3--1[label=4]
3--4[label=5]
1--3[label=4]
1--0[label=6]
}
90 changes: 0 additions & 90 deletions src/machine_learning/clustering/DBSCAN/dbscan.cc

This file was deleted.

98 changes: 98 additions & 0 deletions src/machine_learning/clustering/DBSCAN/dbscan.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <math.h>
#include <utility>
#include <cstdint>
#include <stdexcept>
#endif

/**
Expand Down Expand Up @@ -90,4 +91,101 @@ class DBSCAN{
std::vector<std::pair<double, double> > get_noise();
};

int64_t DBSCAN::nextId(int64_t cluster_id){
try{
if(cluster_id < -1){
throw std::logic_error("cluster_id can't be less than -1");
}
}
catch(std::logic_error &e){
std::cerr << e.what() << '\n';
return -2;
}
cluster_id++;
return cluster_id;
}

bool DBSCAN::ExpandCluster(std::vector<std::pair<double, double> > setOfPoints, std::pair<double, double> point, int64_t cluster_id, double Eps, int64_t MinPts){
std::vector<std::pair<double, double> > seeds = get_query(setOfPoints, point, Eps);
if(seeds.size() < MinPts){
// no core point
points[point] = -1;
return false;
}
else{
// we have a core point
// all the points in seeds are density-reachable from point
for(auto & x : seeds){
points[x] = cluster_id;
}
for(auto it = seeds.begin(); it != seeds.end(); it++){
if((*it).first == point.first && (*it).second == point.second){
seeds.erase(it);
break;
}
}

while(!seeds.empty()){
auto current = seeds[0];
std::vector<std::pair<double, double> > result = get_query(setOfPoints, current, Eps);

if(result.size() >= MinPts){
for(size_t i = 0; i<result.size(); i++){
std::pair<double, double> result_p = result[i];
if(points.find(result_p) == points.end() || points[result_p] == -1){
if(points.find(result_p) == points.end()){
seeds.push_back(result_p);
}
points[result_p] = cluster_id;
} // unclassified or noise
}
}
for(auto it = seeds.begin(); it != seeds.end(); it++){
if((*it).first == current.first && (*it).second == current.second){
seeds.erase(it);
break;
}
}
}
return true;
}
return false;
}

std::vector<std::pair<double, double> > DBSCAN::get_query(std::vector<std::pair<double, double> > setOfPoints, std::pair<double, double> point, double Eps){
std::vector<std::pair<double, double> > ans;
for(size_t i = 0; i<setOfPoints.size(); i++){
std::pair<double, double> curr = setOfPoints[i];
if(dist(point, curr) <= Eps){
ans.push_back(curr);
}
}
return ans;
}

double DBSCAN::dist(std::pair<double, double> a, std::pair<double, double> b){
return sqrt( pow(b.second - a.second, 2) + pow(b.first - a.first, 2) );
}

std::map< std::pair<double, double>, int64_t> DBSCAN::get_clusters(){
std::map< std::pair<double, double>, int64_t> ans;
for(size_t i = 0; i<setOfPoints.size(); i++){
if(points[setOfPoints[i]] != -1){
ans[setOfPoints[i]] = points[setOfPoints[i]];
}
}
return ans;
}

std::vector< std::pair<double, double>> DBSCAN::get_noise(){
std::vector< std::pair<double, double> > ans;
for(size_t i = 0; i<setOfPoints.size(); i++){
if(points[setOfPoints[i]] == -1){
ans.push_back(setOfPoints[i]);
}
}
return ans;
}


#endif
17 changes: 17 additions & 0 deletions src/machine_learning/image/_image.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once
#ifndef _IMAGE_H
#define _IMAGE_H


#ifdef __cplusplus
#include <iostream>
#include <vector>
#endif


class image_handler{
private:

};

#endif
36 changes: 36 additions & 0 deletions tests/machine_learning/clustering/DBSCAN/dbscan.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "../../../../src/machine_learning/clustering/DBSCAN/dbscan.h"
#include "../../../../third_party/catch.hpp"
#include <vector>

TEST_CASE("Testing clustering [1] DBSCAN"){
std::vector<std::pair<double, double> > v = {{1.0, 1.25}, {1.1, 1.3}, {0.9, 0.85}, {40.0, 41.0}, {41.2, 42}, {39.8, 39.2}, {100.4, 100.2}};
DBSCAN a(v, 3, 1);
std::map<std::pair<double, double>, int64_t> ans = a.get_clusters();
std::map<std::pair<double, double>, int64_t> check;
for(int i = 0; i<3; i++){
check[v[i]] = 0;
}
for(int i = 3; i <= 5; i++){
check[v[i]] = 1;
}
check[v[6]] = 2;

for(auto & x : ans){
REQUIRE(x.second == check[x.first]);
}
}

TEST_CASE("Testing noise in [1] DBSCAN"){
std::vector<std::pair<double, double> > v = {{1.0, 1.25}, {1.1, 1.3}, {0.9, 0.85}, {3, 3.5}};
DBSCAN a(v, 0.5, 2);
std::map<std::pair<double, double>, int64_t> ans = a.get_clusters();
std::map<std::pair<double, double>, int64_t> check;
for(int i = 0; i<3; i++){
check[v[i]] = 0;
}
check[v[3]] = -1;

for(auto & x : ans){
REQUIRE(x.second == check[x.first]);
}
}

0 comments on commit fc5b638

Please sign in to comment.