class DBSCAN {

    public Set<Set<T>> cluster(Iterable<? extends T> data) {
        Validate.notNull(data, "data must not be null");
        Set<Set<T>> clusters = new HashSet<>();
        Set<T> visited = new HashSet<>();
        Set<T> clustered = new HashSet<>();
        for (T d : data) {
            if (visited.contains(d)) {
                continue;
            }
            visited.add(d);
            Set<T> neighbors = regionQuery(d, data);
            if (neighbors.size() < minPts) {
                // modification to original algorithm; add noise points as singleton clusters
                clusters.add(Collections.singleton(d));
            } else {
                Set<T> currentCluster = expandCluster(d, neighbors, data, visited, clustered);
                clustered.addAll(currentCluster);
                clusters.add(currentCluster);
            }
        }
        return clusters;
    }

    public  DBSCAN(double eps, int minPts, Distance<? super T> distance);

}