Program Listing for File cover.hpp¶
↰ Return to documentation for file (/home/docs/checkouts/readthedocs.org/user_builds/bats/checkouts/stable/include/topology/cover.hpp
)
#pragma once
/*
utilities for creating covers
*/
#include <cstddef>
#include <vector>
#include <set>
#include <algorithm>
#include <cmath>
#include <tuple>
#include <util/set.hpp>
#include <multigraph/diagram.hpp>
#include "data.hpp"
#include "inclusion.hpp"
#include "landmark.hpp"
#include "neighborhood.hpp"
namespace bats {
using Cover = std::vector<std::set<size_t>>;
// helper function for assigning lower set
template <typename T>
int assign_set_lower(const T v, const T min_val, const double bin_width, const size_t nsets) {
double offset = (v - min_val) / bin_width;
size_t bin = (size_t) floor(offset) * 2;
if (!(bin < nsets)) {
return -1;
}
return bin;
}
// helper function for assigning upper set
template <typename T>
int assign_set_upper(const T v, const T min_val, const double bin_width, const size_t nsets) {
double offset = (v - min_val) / bin_width - 0.5;
size_t bin = 1 + (size_t) floor(offset) * 2;
if (!(bin > 0) || !(bin < nsets)) {
return -1;
}
return bin;
}
/*
Create a cover of a space from projection onto the real line
INPUTS:
x - vector of coordinates of points
nsets - number of open sets to produce
OUTPUT:
vector of sets, each set holds indices of x
each subsequent set shares half the width
*/
template <typename T>
bats::Cover uniform_interval_cover(
const std::vector<T> &x,
const size_t nsets
) {
auto [min, max] = std::minmax_element(x.cbegin(), x.cend());
T min_val = *min;
T max_val = *max;
T length = max_val - min_val;
double bin_width = (double) length * 2.0 / (nsets);
// start a cover with nsets
std::vector<std::set<size_t>> cover(nsets);
for (size_t i = 0; i < x.size(); i++) {
int bl = assign_set_lower(x[i], min_val, bin_width, nsets);
int bu = assign_set_upper(x[i], min_val, bin_width, nsets);
if (bl != -1) {
cover[bl].emplace(i);
}
if (bu != -1) {
cover[bu].emplace(i);
}
}
return cover;
}
// project data x in d dimensions onto coordinate i
template <typename T>
std::vector<T> coordinate_projection(const DataSet<T> &X, const size_t i) {
std::vector<T> p;
p.reserve(X.size());
for (size_t j = 0; j < X.size(); j++) {
// std::cout << j << ": " << X(j, i) << std::endl;
p.emplace_back(X(j, i));
}
return p;
}
// get subset of data
template <typename T>
DataSet<T> get_subset(
const DataSet<T> &X,
const std::set<size_t> &ind
) {
size_t d = X.dim();
Matrix<T> XS(ind.size(), d);
size_t i = 0;
for (auto it = ind.cbegin(); it != ind.cend(); it++) {
for (size_t j = 0; j < d; j++) {
XS(i, j) = X(*it, j);
}
i++;
}
return DataSet(XS);
}
/*
Assign points in data sets to k nearest landmarks
*/
// template over data type, distance
template <typename T, typename M>
bats::Cover landmark_cover(
const DataSet<T> &X,
const DataSet<T> &L,
const M &dist,
size_t k
) {
auto ns = neighborhoods(X, L, dist, k);
// ns[i] contains k closest points in L to X[i]
bats::Cover cover(L.size());
for (size_t i = 0; i < ns.size(); i++) {
for (auto j : ns[i]) {
cover[j].emplace(i);
}
}
return cover;
}
// get cover that assigns to closest landmark
// also any other landmark that is within eps distance of closest landmark
// template over data type, distance
template <typename T, typename M>
bats::Cover landmark_eps_cover(
const DataSet<T> &X,
const DataSet<T> &L,
const M &dist,
T eps
) {
// initialize cover
bats::Cover cover(L.size());
// loop over points in X
for (size_t i = 0; i < X.size(); i++) {
auto di = dist(X[i], L); // distance from X[i] to points in L
auto it = std::min_element(di.cbegin(), di.cend());
for (size_t j = 0; j < L.size(); j++) {
if (di[j] < *it + eps) {
// add i to any landmark set that is within eps of closest landmark
// this should include closest point
cover[j].emplace(i);
}
}
}
return cover;
}
/*
produce bivariate cover of cover1, cover2
i.e. restriction to diagonal in cover1 x cover2
also return maps to cover1 and cover2 (extends to SimplicialMap on Nerves)
*/
auto bivariate_cover(
const std::vector<std::set<size_t>> &cover1,
const std::vector<std::set<size_t>> &cover2
) {
std::vector<std::set<size_t>> cover12;
std::vector<size_t> f1;
std::vector<size_t> f2;
for (size_t i = 0; i < cover1.size(); i++) {
for (size_t j = 0; j < cover2.size(); j++) {
std::set<size_t> intersection;
bats::util::intersect_sorted(
cover1[i],
cover2[j],
intersection
);
if (intersection.size() > 0) {
// cover1[i] and cover2[j] have nonempy intersection
cover12.emplace_back(intersection);
f1.emplace_back(i);
f2.emplace_back(j);
}
}
}
return std::make_tuple(cover12, f1, f2);
}
} // namespace bats