Construct the initial Gabriel graph, adapt local scales and prune edges, returning graphs, affinities and diagnostics. By default, proposed bridge edges are protected so that pruning retains connectivity, and the audited retry-power numerical policy permits one checked retry after an eligible solver rejection. These are explicit variants of reference IAN.
Usage
create.ian.graph(
X,
distances = NULL,
specimen.ids = NULL,
participant.ids = NULL,
graph = NULL,
diagnostics = c("summary", "full"),
backend = NULL,
max.solves = 10000L,
numerical.policy = "IAN evaluated-LP retry-power 0.1",
preserve.connectivity = TRUE
)Arguments
- X
Finite numeric specimen-by-feature matrix, at least two rows and one column. There is no fixed experimental row cap. Input size must fit R/native index representations and available memory. Dense distances and affinities require quadratic storage: each n-by-n double matrix uses
8*n*nbytes before overhead. Several matrices/copies coexist; this is not a peak-memory estimate. Initial Gabriel construction has cubic worst-case cost. Full diagnostics retain additional dense data. See the backend guide for tested sizes.- distances
Optional unsquared distance matrix or
dist. When absent, Euclidean distances are computed withstats::dist(X). Supplied distances are used exactly; duplicate feature rows must have identical distance rows. Coordinates are always required to define duplicate profiles. Row/column order must match X; named distances must match specimen IDs.- specimen.ids
Unique nonempty IDs; defaults to row names or row numbers.
- participant.ids
Optional specimen-level nonempty IDs, possibly repeated.
- graph
Reserved supplied-graph argument; currently must be
NULL. The actual initial Gabriel graph is always constructed by IAN.- diagnostics
"summary"or"full"; full includes dense LP payloads.- backend
Optional path to the separately built
dgraphs_ian.somodule.- max.solves
Positive integer safety limit; reaching it returns refusal.
- numerical.policy
Exactly
"IAN evaluated-LP 1.0"(strict, without retries) or"IAN evaluated-LP retry-power 0.1"(default: one eligible checked retry).- preserve.connectivity
Logical scalar, default
TRUE. UseFALSEfor reference pruning, which may disconnect the graph. WithTRUE, cache encountered bridges and skip them before testing each proposed edge's pruning eligibility. Check noncached edges in the current graph after preceding deletions. Skips do not consume the deletion allowance. All vertices are retained. An initially disconnected graph returns refusal. This explicit variant does not change the numerical solver policy.
Value
A list with complete, structured error, initial Gabriel graph,
final_graph only on full completion, last_valid_graph (possibly partial),
profile mapping, local scales and an affinity matrix distinct from metric
edge lengths. Graph indices and mappings are one-based. Full traces retain
original zero-based core indices and declare this in diagnostics. Summary diagnostics
include per-solve status, acceptance, settings, residuals and iteration counts.
Refusal and interruption return incomplete structured results; invalid R
arguments error before native execution. Interrupts are checked at engine
events; they do not interrupt an active solver call. In connectivity mode,
diagnostics$connectivity contains protected.edges (one-based profile
rows and IDs, first/last encounter iteration, count and first statistic),
per-iteration history, and stop.reason. Iterations in this summary are
one-based. Protected edges are encountered proposals, not necessarily edges
that would pass the pruning criteria. Full traces also include every edge
proposal and whether eligibility was tested. A complete pass with no
deletion stops, including when statistical candidates remain protected.
Partial results retain available protection diagnostics; final_graph
remains NULL if later optimization or affinity construction fails.
Details
Build the optional module once with build.ian.backend() and pass its returned
path as backend. The supported build target is macOS arm64. The function
itself does not compile code, download dependencies or launch an external
solver. See system.file("ian", "README.md", package = "dgraphs") for the
numerical contract, setup requirements and bounded qualification.
Input rows are specimens; graph vertices are unique feature profiles in
first-occurrence order. Always check complete before using final_graph.
Invalid R arguments or an unavailable backend raise an R error. Numerical
refusal and interruption during engine execution return an incomplete result
with the available diagnostics. Memory exhaustion or process termination is
not a recoverable-result guarantee.
The default numerical policy is IAN evaluated-LP retry-power 0.1.
A rejected original return remains rejected. Its single eligible retry must
itself pass strict solver success and the unchanged original-unit checks.
numerical.policy="IAN evaluated-LP 1.0" together with
preserve.connectivity=FALSE selects the previous strict/reference behavior.
This public default adoption changes neither policy's implementation.
The returned top-level fields are complete, error, initial_graph,
final_graph, last_valid_graph, mapping, scales, affinity,
diagnostics and backend. Graphs are dgraph() objects with metric edge
lengths in input distance units; affinity values are separate similarities.
Mapping contains one-based representatives and member_to_profile, plus
specimen, profile and participant IDs. Repeated participant IDs do not merge
specimens. Error information contains kind, code and message.
diagnostics$solver_history retains both accepted and rejected attempts.
Backend information identifies the selected policies, source and settings.
Checkpoint/resume is not exposed through this R interface.
Examples
# Set this variable to the path returned by build.ian.backend().
backend <- Sys.getenv("DGRAPHS_IAN_BACKEND")
if (nzchar(backend) && file.exists(backend)) {
X <- rbind(c(0, 0), c(1, 0), c(2, 0), c(0, 0))
fit <- create.ian.graph(X, backend = backend,
specimen.ids = c("alpha", "beta", "gamma", "delta"))
stopifnot(fit$complete)
graph.edges(fit$initial_graph)
graph.edges(fit$final_graph)
fit$mapping$member_to_profile # Four specimens, three unique profiles.
fit$diagnostics$connectivity$protected.edges
}