## ----setup, include=FALSE----------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 6.5, fig.height = 5, warning = FALSE, message = FALSE ) ## ----data--------------------------------------------------------------------- library(dgraphs) set.seed(20260820) n <- 60L theta <- sort(c( runif(40L, 0, pi), runif(20L, pi, 2 * pi) )) X <- cbind(x = cos(theta), y = sin(theta)) + matrix(rnorm(2L * n, sd = 0.015), ncol = 2) ## ----constructors------------------------------------------------------------- graphs <- list( mutual = create.mknn.graph( X, k = 5, connect.components = TRUE ), symmetric = create.sknn.graph( X, k = 5, neighbor.method = "ann", connect.components = TRUE ), continuous = create.cknn.graph( X, k.scale = 5, delta = 1.2, connect.components = TRUE ), adaptive.max = create.rknn.graph( X, type = "adaptive.radius", k.scale = 5, radius.rule = "max", connect.components = TRUE ) ) ## ----candidate-summary-------------------------------------------------------- graph.summary <- do.call(rbind, lapply(names(graphs), function(name) { graph <- graphs[[name]] data.frame( graph = name, edges = sum(lengths(graph$adj_list)) / 2, raw.components = length(unique( graph.connected.components(graph$raw_adj_list) )), final.components = length(unique( graph.connected.components(graph$adj_list) )), bridges = graph$n_mst_edges_added ) })) graph.summary ## ----parameter-sequence------------------------------------------------------- radius.sequence <- create.rknn.graphs( X, k.values = 3:6, radius.search = "ann", connect.components = TRUE ) radius.sequence$k_statistics[, c( "k", "n_edges_before_pruning", "n_components_before", "n_mst_edges_added", "n_components_after" )] ## ----conversion--------------------------------------------------------------- selected <- graphs$continuous selected.igraph <- as_igraph(selected) c( vertices = igraph::vcount(selected.igraph), edges = igraph::ecount(selected.igraph) ) degree.pmf <- compute.graph.summary.pmf( selected, summary = "degree_distribution" ) degree.pmf$pmf ## ----graph-figure, fig.cap="Continuous-kNN graph on the variable-density circular point cloud. Lines are graph edges and points are observations.", fig.alt="A circular point cloud with denser sampling on the upper semicircle. Gray graph edges connect nearby points around the circle."---- edge.matrix <- convert.adjacency.to.edge.matrix( selected$adj_list )$edge.matrix plot( X, asp = 1, pch = 19, col = "#1F5A94", xlab = "Coordinate 1", ylab = "Coordinate 2" ) segments( X[edge.matrix[, 1], 1], X[edge.matrix[, 1], 2], X[edge.matrix[, 2], 1], X[edge.matrix[, 2], 2], col = grDevices::adjustcolor("grey35", alpha.f = 0.45) ) points(X, pch = 19, col = "#1F5A94") ## ----geodesic-diagnostics----------------------------------------------------- graph.distance <- graph.geodesic.distances(selected) angle.difference <- abs(outer(theta, theta, "-")) reference.distance <- pmin( angle.difference, 2 * pi - angle.difference ) round(isometry.geodesic.diagnostics( graph.distance, reference.distance ), 3)