This is the primary layout API. It uses the quality-first multiscale GRIP
engine with extra coarse-level global repulsion to reduce foldovers while
preserving the usual GRIP refinement structure. With preset = NULL,
the default profile is tuned for higher-quality layouts and automatically
tapers final.rounds on larger graphs.
Usage
grip(
edges = NULL,
n = NULL,
adj.list = NULL,
weight.list = NULL,
edge.weights = NULL,
dim = 3,
placement = c("barycenter", "circle"),
preset = NULL,
rounds = 160,
final.rounds = 384,
num.init = 24,
num.nbrs = 20,
r = 0.03,
s = 7.5,
repulsion.factor = 2.5,
coarse.repulsion.factor = 1.5,
coarse.repulsion.sample = 16,
coarse.repulsion.exact.below = 64,
final.anchor.factor = 0,
final.move.scale.after.first = 1,
final.mode = c("fr", "kk_repulse"),
insertion.anchor.count = 3,
insertion.anchor.scope = c("any_higher", "prev_misf"),
insertion.anchor.strategy = c("first", "distance_band", "balanced_band", "spread_prev"),
level0.insertion.mode = c("inherit", "barycenter", "least_squares"),
level0.anchor.count = insertion.anchor.count,
level0.local.kk.steps = 3,
lgkk.polish.rounds = 0L,
lgkk.multiscale.rounds = 0L,
lgkk.rounds.coarse = NULL,
lgkk.rounds.pre.final = NULL,
lgkk.rounds.final = NULL,
lgkk.local.nbrs = 20L,
lgkk.landmark.count = 8L,
lgkk.multiscale.scope = c("all", "coarse"),
lgkk.active.limit = 4096L,
tinit.factor = 6,
seed = 6,
disconnected = c("components", "error"),
metric = c("hop", "edge_length"),
metric.neighbor.cap = NULL,
length.normalization = c("median", "mean", "none")
)Arguments
- edges
Two-column integer matrix of edges (1-based vertex ids). Supply either
edges/edge.weightsoradj.list/weight.list, not both. Fractional, nonfinite, and out-of-range vertex ids are rejected before integer conversion.- n
Number of vertices, a finite positive integer.
- adj.list
Adjacency list (1-based) for undirected graphs.
- weight.list
Parallel list of edge lengths for
adj.list. The edge-length-metric engine requires it; in the hop-metric engine,NULLtreats all edges as length 1. All supplied lengths must be finite and strictly positive.- edge.weights
Vector of edge lengths for
edges, in the same order as its rows. The edge-length-metric engine requires it; in the hop-metric engine,NULLtreats all edges as length 1. All supplied lengths must be finite and strictly positive. The selected engine determines whether lengths also define graph distances.- dim
Layout dimension (2 or 3). Default is 3.
- placement
Initial placement strategy. "circle" is only used for 2D.
- preset
Optional tuning preset.
NULLuses the quality-first defaults."carpet"applies a preset tuned for Sierpinski-carpet-like graphs and validated on carpet levels 3 and 4."mesh"applies a preset tuned for rectangular lattice graphs and validated on 8x8 and 12x12 mesh layouts."torus"applies a preset tuned for 3D torus layouts and validated on torus sizes from 8x8 through 20x20."tree"applies a preset tuned for symmetric force-directed layouts of tree-like graphs and validated on binary trees of depths 5 and 6. Presets only fill in tuning arguments that you did not supply explicitly.- rounds
Initial rounds for refinement.
- final.rounds
Final rounds for refinement.
- num.init
Number of initial vertices in the coarsest level.
- num.nbrs
Maximum number of graph-distance neighbors retained for local refinement at each filtration level.
- r
Main local temperature adaptation rate in
[0, 1].- s
Non-negative boost factor applied when successive displacements have a consistent direction.
- repulsion.factor
Non-negative multiplier applied to GRIP's finest-level repulsive force scale.
- coarse.repulsion.factor
Non-negative multiplier applied to the extra coarse-level active-set repulsion term.
0disables that extra term.- coarse.repulsion.sample
Positive integer sample size used to approximate active-set-wide repulsion on larger coarse levels.
- coarse.repulsion.exact.below
Positive integer threshold. When the active set size is at most this value, the coarse repulsion is computed exactly against all currently active vertices instead of being sampled.
- final.anchor.factor
Non-negative multiplier for an anchor term that pulls the final FR stage back toward the pre-final full-graph layout.
0disables the anchor and preserves the current behavior.- final.move.scale.after.first
Scalar in
[0, 1]applied to the final FR displacement after the first finest-level round. Values below1damp later full-graph movement while keeping the first FR round unchanged.- final.mode
Final full-graph refinement mode.
"fr"keeps the current Fruchterman-Reingold-style final stage."kk_repulse"uses a KK-style local distance-matching update with explicit active-set repulsion instead of the final FR phase.- insertion.anchor.count
Positive integer number of anchor vertices used during multiscale insertion on non-initial MISF refinement levels. This is the closest current implementation to a global
K_mishparameter.- insertion.anchor.scope
Anchor-eligibility rule used during multiscale insertion.
"any_higher"matches the historical GRIP behavior and allows anchors from any already placed higher MISF level."prev_misf"restricts anchors to the immediately previous MISF level only.- insertion.anchor.strategy
Anchor-selection rule used during multiscale insertion.
"first"keeps the historical first-anchors-found BFS behavior."distance_band"keeps exploring until theK_mish-th anchor distance band is exhausted, then places the new vertex from that less order-sensitive anchor pool."balanced_band"uses the same band expansion, then explicitly selects a subset whose centroid stays centered in the candidate cloud while remaining geometrically spread out."spread_prev"is a symmetry-oriented band strategy intended to be paired withinsertion.anchor.scope = "prev_misf"; it selects anchors with broad angular and geometric coverage before placement.- level0.insertion.mode
Level-0 insertion placement override used only when the finest filtration level is first populated.
"inherit"keeps the current GRIP behavior."barycenter"disables the 2D circle heuristic at level 0 and uses barycentric anchor placement."least_squares"uses a multi-anchor least-squares distance fit at level 0 before any local micro-polish.- level0.anchor.count
Positive integer number of already placed anchors to collect for level-0 insertion experiments. By default this inherits
insertion.anchor.count. The legacy behavior uses 3.- level0.local.kk.steps
Non-negative integer number of tiny local KK micro-polish steps applied immediately after each level-0 insertion. The legacy behavior uses 3.
- lgkk.polish.rounds
Non-negative integer number of experimental landmark-geodesic KK polish iterations applied after the main GRIP solve.
0disables the polish.- lgkk.multiscale.rounds
Non-negative integer number of compiled landmark-geodesic KK refinement rounds applied inside the multiscale solver after each eligible MISF level completes its standard GRIP rounds. This legacy shared budget is used as a fallback when any of the more specific per-stage budgets below are left
NULL.- lgkk.rounds.coarse
Optional non-negative integer number of compiled LGKK rounds applied on coarse MISF levels with
misf_level > 1. WhenNULL, this falls back tolgkk.multiscale.rounds.- lgkk.rounds.pre.final
Optional non-negative integer number of compiled LGKK rounds applied on the last coarse level just before the full graph is opened (
misf_level == 1). WhenNULL, this falls back tolgkk.multiscale.rounds.- lgkk.rounds.final
Optional non-negative integer number of compiled LGKK rounds applied after the full graph level completes its standard GRIP rounds (
misf_level == 0). WhenNULL, this falls back tolgkk.multiscale.rounds.- lgkk.local.nbrs
Number of nearest graph-metric neighbors retained per vertex in the LGKK sparse local set when either LGKK stage is enabled.
- lgkk.landmark.count
Number of farthest-point landmarks retained per vertex in the LGKK sparse long-range set when either LGKK stage is enabled.
- lgkk.multiscale.scope
Scope for the compiled multiscale LGKK stage.
"all"applies it after every eligible MISF level, including the final full-graph level."coarse"applies it only on coarse levels.- lgkk.active.limit
Positive integer upper bound on the active-set size for compiled multiscale LGKK cache construction. Levels larger than this skip the multiscale LGKK stage.
- tinit.factor
Initial temperature factor.
- seed
Optional RNG seed for reproducibility. If NULL, uses current time.
- disconnected
How to handle disconnected graphs:
"components"(default) lays out each connected component separately and packs them into one coordinate matrix;"error"stops with an error.- metric
Graph metric used by the multiscale GRIP engine.
"hop"(default) uses unweighted shortest-path hop counts to build the MISF hierarchy and graph neighborhoods."edge_length"uses shortest-path distances obtained by summing the supplied positive edge lengths. See Edge-length semantics for the exact role of edge lengths in each mode.- metric.neighbor.cap
Weighted-metric search limit used only when
metric = "edge_length".NULLperforms the exact weighted neighborhood search and stops once the required neighbors and anchors are filled. A positive integer enables an approximate search by limiting the number of settled vertices per search. It is an error to supply this argument withmetric = "hop".- length.normalization
Global normalization applied only when
metric = "edge_length":"median"(default) divides every edge length by their median,"mean"divides by their mean, and"none"preserves the supplied numerical scale. It is an error to supply this argument withmetric = "hop".
Details
Edge-length semantics
The arguments edge.weights and weight.list are historically
named but represent positive edge lengths or traversal costs, not
connection strengths, capacities, or similarities. A larger value requests
a longer geometric edge. If the available values are strengths for which a
larger value means a closer connection, convert them to positive lengths
before calling grip(), for example with a scientifically appropriate
reciprocal or other monotone decreasing transformation.
With metric = "hop", the standard GRIP hierarchy, insertion anchors,
and retained local neighborhoods use combinatorial shortest-path distance:
every traversed edge contributes one hop. When edge lengths are supplied,
they are nevertheless used as the desired lengths of adjacent vertex pairs
in the attractive force calculation. Thus this mode is useful when topology
should determine the multiscale organization but adjacent edges should have
unequal target lengths. No global length normalization is performed in this
mode. If no lengths are supplied, every edge has desired length one. Optional
LGKK stages use the supplied edge lengths for their geodesic distances even
though the standard GRIP stages remain hop based.
With metric = "edge_length", positive edge lengths are required. The
same lengths determine desired adjacent-edge lengths and the shortest-path
metric used for the MISF hierarchy, insertion anchors, retained graph
neighborhoods, and LGKK stages. Dijkstra-style weighted shortest paths are
used instead of hop-count breadth-first searches. By default, all lengths
are divided by their median before layout; this preserves relative geometry
while placing the numerical scale near the solver's unit scale. Use
length.normalization = "mean" for mean scaling or "none" when
the absolute supplied scale is intentional. Multiplying all input lengths
by the same positive constant therefore leaves the default normalized solve
unchanged.
For edges input, provide one value per row through
edge.weights. For adj.list input, provide a parallel
weight.list: weight.list[[i]][j] is the length of the edge from
vertex i to adj.list[[i]][j]. For an undirected graph, the
adjacency and length entries should be symmetric.
Workflow guides
Start with vignette("function-guide", package = "grip")
to choose a layout, diagnostic, or reference comparison. List installed
guides with vignette(package = "grip").
References
Gajer, P. and Kobourov, S.G. (2002). GRIP: Graph dRawing with Intelligent Placement. Journal of Graph Algorithms and Applications, 6(3), 203–224. doi:10.7155/jgaa.00052.
Gajer, P., Goodrich, M.T. and Kobourov, S.G. (2004). A multi-dimensional approach to force-directed layouts of large graphs. Computational Geometry, 29(1), 3–18. doi:10.1016/j.comgeo.2004.03.014.
Examples
edges <- edges.mesh(4, 4)
coords <- grip(edges, n = max(edges), dim = 2,
coarse.repulsion.factor = 0.2,
coarse.repulsion.sample = 8,
coarse.repulsion.exact.below = 32,
seed = 1)
round(coords, 3)
#> [,1] [,2]
#> [1,] -10.713 78.890
#> [2,] 13.068 65.728
#> [3,] 38.326 50.285
#> [4,] 60.879 35.116
#> [5,] -25.881 56.336
#> [6,] -1.844 42.112
#> [7,] 24.101 26.248
#> [8,] 47.718 11.335
#> [9,] -41.324 31.079
#> [10,] -17.708 16.166
#> [11,] 8.238 0.302
#> [12,] 32.275 -13.922
#> [13,] -54.486 7.298
#> [14,] -31.932 -7.871
#> [15,] -6.675 -23.315
#> [16,] 17.106 -36.476
# Use edge lengths throughout the multiscale graph metric.
path <- cbind(1:5, 2:6)
lengths <- c(1, 1, 2, 1, 1)
weighted.coords <- grip(
path, n = 6, edge.weights = lengths,
metric = "edge_length", dim = 2,
rounds = 4, final.rounds = 4, num.init = 3, seed = 1
)