9 double distance_squared(
const Eigen::VectorXd&
a,
const Eigen::VectorXd&
b)
11 return (
b -
a).squaredNorm();
14 double distance(
const Eigen::VectorXd&
a,
const Eigen::VectorXd&
b)
16 return (
b -
a).norm();
22 bool operator>(
const Edge& other)
const {
return weight > other.weight; }
28 Eigen::Index n = points.cols();
36 for (Eigen::Index i = 0; i < n - 1; ++i) {
37 edges.emplace_back(
static_cast<size_t>(i),
static_cast<size_t>(i + 1));
41 "sequential_chain: {} points, generated {} edges", n, edges.size());
47 const Eigen::MatrixXd& points,
50 Eigen::Index n = points.cols();
55 k = std::min(k,
static_cast<size_t>(n - 1));
60 for (Eigen::Index i = 0; i < n; ++i) {
61 std::vector<std::pair<double, size_t>> distances;
62 distances.reserve(n - 1);
64 for (Eigen::Index j = 0; j < n; ++j) {
67 double dist_sq = distance_squared(points.col(i), points.col(j));
68 distances.emplace_back(dist_sq,
static_cast<size_t>(j));
73 distances.begin() + k,
76 for (
size_t neighbor_idx = 0; neighbor_idx < k; ++neighbor_idx) {
77 edges.emplace_back(
static_cast<size_t>(i), distances[neighbor_idx].second);
82 "k_nearest_neighbors: {} points, k={}, generated {} edges",
89 const Eigen::MatrixXd& points,
92 Eigen::Index n = points.cols();
97 double radius_sq = radius * radius;
100 for (Eigen::Index i = 0; i < n; ++i) {
101 for (Eigen::Index j = i + 1; j < n; ++j) {
102 double dist_sq = distance_squared(points.col(i), points.col(j));
103 if (dist_sq <= radius_sq) {
104 edges.emplace_back(
static_cast<size_t>(i),
static_cast<size_t>(j));
110 "radius_threshold_graph: {} points, radius={:.3f}, generated {} edges",
111 n, radius, edges.size());
118 Eigen::Index n = points.cols();
124 mst_edges.reserve(n - 1);
126 std::vector<bool> in_mst(n,
false);
127 std::priority_queue<Edge, std::vector<Edge>, std::greater<>> pq;
131 for (Eigen::Index j = 1; j < n; ++j) {
132 double dist = distance(points.col(0), points.col(j));
133 pq.push({ 0,
static_cast<size_t>(j), dist });
136 while (!pq.empty() && mst_edges.size() <
static_cast<size_t>(n - 1)) {
143 mst_edges.emplace_back(e.a, e.b);
146 for (Eigen::Index j = 0; j < n; ++j) {
148 double dist = distance(points.col(e.b), points.col(j));
149 pq.push({ e.b,
static_cast<size_t>(j), dist });
155 "minimum_spanning_tree: {} points, generated {} edges",
156 n, mst_edges.size());
163 Eigen::Index n = points.cols();
170 for (Eigen::Index i = 0; i < n; ++i) {
171 for (Eigen::Index j = i + 1; j < n; ++j) {
172 Eigen::VectorXd p = points.col(i);
173 Eigen::VectorXd
q = points.col(j);
175 double pq_dist_sq = distance_squared(p,
q);
176 bool is_gabriel_edge =
true;
178 for (Eigen::Index k = 0; k < n; ++k) {
179 if (k == i || k == j)
182 Eigen::VectorXd r = points.col(k);
184 double pr_dist_sq = distance_squared(p, r);
185 double qr_dist_sq = distance_squared(
q, r);
187 if (pr_dist_sq + qr_dist_sq < pq_dist_sq) {
188 is_gabriel_edge =
false;
193 if (is_gabriel_edge) {
194 edges.emplace_back(
static_cast<size_t>(i),
static_cast<size_t>(j));
200 "gabriel_graph: {} points, generated {} edges",
208 Eigen::Index n = points.cols();
216 for (Eigen::Index i = 0; i < n; ++i) {
217 double min_dist_sq = std::numeric_limits<double>::max();
220 for (Eigen::Index j = 0; j < n; ++j) {
224 double dist_sq = distance_squared(points.col(i), points.col(j));
225 if (dist_sq < min_dist_sq) {
226 min_dist_sq = dist_sq;
227 nearest =
static_cast<size_t>(j);
231 if (nearest !=
static_cast<size_t>(i)) {
232 edges.emplace_back(
static_cast<size_t>(i), nearest);
237 "nearest_neighbor_graph: {} points, generated {} edges", n, edges.size());
244 Eigen::Index n = points.cols();
251 for (Eigen::Index i = 0; i < n; ++i) {
252 for (Eigen::Index j = i + 1; j < n; ++j) {
253 Eigen::VectorXd p = points.col(i);
254 Eigen::VectorXd
q = points.col(j);
256 double pq_dist = distance(p,
q);
257 bool is_rng_edge =
true;
259 for (Eigen::Index k = 0; k < n; ++k) {
260 if (k == i || k == j)
263 Eigen::VectorXd r = points.col(k);
265 double pr_dist = distance(p, r);
266 double qr_dist = distance(
q, r);
268 double max_dist = std::max(pr_dist, qr_dist);
270 if (max_dist < pq_dist) {
277 edges.emplace_back(
static_cast<size_t>(i),
static_cast<size_t>(j));
283 "relative_neighborhood_graph: {} points, generated {} edges",
290 const Eigen::MatrixXd& points,
291 const std::function<
EdgeList(
const Eigen::MatrixXd&)>& connection_function)
293 if (!connection_function) {
295 "custom_proximity_graph: connection_function is null");
299 EdgeList edges = connection_function(points);
302 "custom_proximity_graph: {} points, generated {} edges",
303 points.cols(), edges.size());
309 const Eigen::MatrixXd& points,
312 switch (config.
mode) {
#define MF_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
@ Runtime
General runtime operations (default fallback)
@ Kinesis
General mathematical and physics algorithns.
EdgeList minimum_spanning_tree(const Eigen::MatrixXd &points)
Compute minimum spanning tree (Prim's algorithm)
EdgeList nearest_neighbor_graph(const Eigen::MatrixXd &points)
Compute nearest neighbor graph.
EdgeList custom_proximity_graph(const Eigen::MatrixXd &points, const std::function< EdgeList(const Eigen::MatrixXd &)> &connection_function)
Custom proximity graph via user function.
@ RELATIVE_NEIGHBORHOOD_GRAPH
EdgeList k_nearest_neighbors(const Eigen::MatrixXd &points, size_t k)
Compute K-nearest neighbors graph.
std::vector< std::pair< size_t, size_t > > EdgeList
EdgeList sequential_chain(const Eigen::MatrixXd &points)
Compute sequential chain graph.
EdgeList relative_neighborhood_graph(const Eigen::MatrixXd &points)
Compute relative neighborhood graph.
EdgeList generate_proximity_graph(const Eigen::MatrixXd &points, const ProximityConfig &config)
Generate proximity graph using specified mode.
EdgeList radius_threshold_graph(const Eigen::MatrixXd &points, double radius)
Compute radius threshold graph.
EdgeList gabriel_graph(const Eigen::MatrixXd &points)
Compute Gabriel graph.
std::function< EdgeList(const Eigen::MatrixXd &)> custom_function