Full metric MDS fits all vertex pairs. Sparse SGD keeps graph edges and approximates longer-range influences using representative vertices called pivots. It uses the sparse model of Ortmann, Klimenta and Brandes (2017) and the SGD updates of Zheng, Pawar and Goodman (2018).
With n vertices, m edges, and
h pivots, storage and work per pass are roughly
proportional to m + n*h, avoiding an all-pairs distance
matrix. More pivots cost more; improvement in every individual run is
not guaranteed.
g <- suitesparse.graph('dwt_307')
fit <- metric.mds(edges=g$edges,n=g$n,edge.weights=g$edge_weights,
dim=3,approximation='sparse',backend='sgd',seed=1,
sparse.control=list(n.pivots=32),max.iter=100)
ivue::plot3D.plain(fit$coords, layers=list(ivue::layer3D.edges(g$edges)), controls = FALSE)Full MDS remains the default. Sparse mode currently supports SGD only, with inverse-squared stress weights. Its defaults are random initialization, up to 200 pivots, and 30 epochs: provisional calibration choices. The 32 pivots and 100 epochs above are explicit illustrative choices. Supply connected graphs with positive lengths; disconnected graphs are rejected without adding edges.
Sparse mode accepts supplied starting coordinates but does not accept
classical initialization, uniform weights, multiple starts, dense
prepared objects, or dense diagnostics. Observation-based sparse
preparations are supported as described below. These restrictions avoid
an unexpected all-pairs calculation. Its
sparse_proxy_stress describes the fitted sparse
constraints, not full stress. When a supplied edge is longer than an
alternative route, sparse and full MDS can use different targets for
that edge. That distinction does not arise for the unit and Euclidean
chord lengths used in this experiment.
prepare.sparse.mds() constructs the pivots and weights
internally, without an all-pairs distance matrix. The default
method="euclidean" uses original-space Euclidean pivot
distances, published distance-proportional randomized pivot selection,
regional endpoint weights and symmetric nearest-neighbor local pairs.
Neighbor search uses the smallest ordinary PCA projection reaching 90%
variance; all edge lengths and fitting targets still use the original
observations.
prep <- prepare.sparse.mds(X, method="euclidean", n.pivots=200,
q=10, neighbor.variance.target=0.90, seed=1)
fit <- metric.mds(prepared=prep, approximation="sparse", backend="sgd",
dim=3, max.iter=100, seed=1,
sgd.control=list(scheduler="zheng", schedule.epsilon=0.1))Use pivot.selection="farthest" for the Euclidean or
L-infinity farthest-first alternative. method="uniform"
uses uniform landmarks without regional multipliers or local edges, but
retains inverse-squared distance weights. method="geodesic"
instead uses shortest-path targets on a connected neighbor graph. Its
exact component-MST repair evaluates distances as needed and never
stores their full matrix; worst-case repair time can nevertheless be
quadratic.
For maximum absolute coordinate differences, use
method="linf". It computes exact neighbors in the original
coordinates; equal distances are ordered by row index. Its default
neighbor.variance.target is NULL, and explicit
PCA targets are rejected because rotation changes this metric. No
normalization is implicit. For nonnegative abundance rows with positive
maxima, max normalization is:
stopifnot(all(is.finite(X)), all(X >= 0), all(apply(X, 1, max) > 0))
Xmax <- X / apply(X, 1, max)
# Consolidate any duplicate normalized rows and retain their sample mapping.
prep <- prepare.sparse.mds(Xmax, method="linf", n.pivots=200, q=10, seed=1)Exact L-infinity search has quadratic worst-case work but does not
store an all-pairs matrix. Its returned graph$edges table
holds the symmetric union of nearest-neighbor pairs and their L-infinity
lengths; graph$metadata records the search rule. It needs
no dgraphs dependency.
The Euclidean and geodesic methods require the accompanying
dgraphs support for search.data and streaming
component repair. Input rows must be distinct. Requested pivot counts
are capped at nrow(X)-1; keep the count small relative to
the data size for useful storage savings. The preparation can be reused
across dimensions and fit seeds. Its default schedule is
"zheng", using the published weight-based endpoints; the
legacy graph interface keeps its existing default schedule. Completing
the epoch budget does not certify convergence. See
?prepare.sparse.mds for returned audit information and
controls.
The October 2026 source-tree methods note under
vignettes/articles/sparse-mds-methods/ documents formulas
and a separate 288-fit quadratic-form validation. The existing
experiment below concerns the legacy graph interface and its recorded
settings.
The saved experiment compares full SGD, sparse SGD at several pivot counts, and weighted GRIP. Each setting uses seeds 1–3. SGD uses 100 epochs with the same random initial coordinates for paired runs; GRIP uses its own initialization. Full MDS retains its best checkpoint and fits scale; sparse SGD returns its terminal iterate without fitting scale. These are comparisons of the supplied methods, not equal work per epoch.
The structural graph below connects this comparison to the graph gallery. The larger saddle illustrates approximation at 4,096 vertices. Full SGD was not attempted above 512 vertices in this bounded experiment; that cutoff is not a measured capacity limit.
Errors are independently evaluated against graph shortest paths: all pairs for dwt_307, and all distances from 32 independently sampled source vertices for the larger saddle. Original error uses returned coordinates. Scale-adjusted error additionally fits one positive scalar, a diagnostic added after inspecting the original run; no layouts were refitted.
Total seconds includes graph preparation and fitting. Peak MiB includes the entire isolated R process, including package loading. Tables report medians over returned runs and show both the returned and attempted counts.
| Method | Returned | Attempted | Original error | Scale-adjusted error | Total seconds | Peak MiB |
|---|---|---|---|---|---|---|
| Full SGD | 3 | 3 | 0.132 | 0.132 | 0.775 | 127.531 |
| Sparse SGD: 8 pivots | 3 | 3 | 0.164 | 0.163 | 0.036 | 91.078 |
| Sparse SGD: 32 pivots | 3 | 3 | 0.140 | 0.140 | 0.101 | 91.203 |
| Weighted GRIP | 3 | 3 | 20.636 | 0.187 | 0.045 | 91.250 |
Seed-1 display scale multipliers: Full SGD 1; Sparse SGD: 8 pivots 0.976; Sparse SGD: 32 pivots 0.995; Weighted GRIP 0.0454.
| Method | Returned | Attempted | Original error | Scale-adjusted error | Total seconds | Peak MiB |
|---|---|---|---|---|---|---|
| Sparse SGD: 32 pivots | 3 | 3 | 0.060 | 0.059 | 1.449 | 121.094 |
| Sparse SGD: 128 pivots | 3 | 3 | 0.047 | 0.047 | 6.182 | 172.891 |
| Sparse SGD: 200 pivots | 3 | 3 | 0.044 | 0.043 | 11.193 | 211.922 |
| Weighted GRIP | 3 | 3 | 45.473 | 0.348 | 0.761 | 109.906 |
Seed-1 display scale multipliers: Sparse SGD: 32 pivots 0.996; Sparse SGD: 128 pivots 0.996; Sparse SGD: 200 pivots 0.999; Weighted GRIP 0.0195.
The figures show seed 1 with each method’s independently fitted scale multiplier. The saddle uses surface-shape alignment after scaling; the structural graph uses matched-vertex alignment to full SGD, which is a comparison reference, not a known true shape. The selector preserves the camera and scale.
The experiment appendix preserves every example, including the smaller saddle, paraboloid, and helix, all outcomes, numerical protocol, resource limits, and reproduction commands. A returned fit does not establish convergence. Compare independently evaluated error rather than sparse proxy values from different pivot counts.
Sparse SGD also accepts distances already computed by another method.
Supply n and a constraints list instead of
graph edges. Targets are used as given; no shortest-path calculation or
automatic pivot selection is performed. This is useful for exact
complete-graph Fermat distances computed at selected pairs without
storing a complete graph.
constraints <- list(pairs = rbind(c(1, 2), c(2, 3), c(1, 3)),
targets = c(1, 1, 2))
fit <- metric.mds(n = 3, approximation = "sparse", constraints = constraints,
seed = 1, max.iter = 30)
fit$metadata$constraint_source
#> [1] "explicit_distances"Unordered pairs must be unique and form a connected network. Targets
must be positive and finite; inverse-squared weighting cannot represent
zero distances. Optional count_i and count_j
give nonnegative endpoint multiplicities; both default to one. They are
divided by squared target distance for updates. The defaults give
symmetric sparse stress. Supplying asymmetric multiplicities supports
the pivot-region weighting used by the graph-based sparse method, but
the caller must compute those multiplicities consistently with its
metric. The returned metadata preserves the targets and
multiplicities.
For Fermat geometry, local constraints also need shortest-path targets: powered direct-edge lengths can exceed them. The dgraphs Fermat vignette includes an implicit-distance example and a helper constructing exact local and pivot constraints. The graph-based interface remains unchanged and continues to use supplied edge lengths for its local targets. Sparse fitting does not certify unmeasured distances or recover full stress; evaluate on independent pairs.