Skip to contents

This traces the primary grip() engine, including the coarse-level global-repulsion term used by the quality-first default layout. For backwards-compatible traces of the historical local-force wrapper, use trace.legacy.grip().

Usage

trace.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,
  trace = c("round", "level"),
  trace.every = 1,
  diagnostics = c("none", "light", "full"),
  target_coords = NULL,
  diagnostic_sample_size_nonedge = 1000L,
  diagnostic_sample_size_stress = 500L,
  diagnostic_nonedge_seed = 1L,
  diagnostic_stress_seed = 1L
)

Arguments

edges

Two-column integer matrix of edges (1-based vertex ids).

n

Number of vertices.

adj_list

Adjacency list (1-based) for undirected graphs.

weight_list

Optional parallel list of edge weights (edge lengths). If NULL, all edges are treated as weight 1. All weights must be finite and strictly positive.

edge_weights

Optional vector of edge weights for edges. All weights must be finite and strictly positive.

dim

Layout dimension (2 or 3). Default is 3.

placement

Initial placement strategy. "circle" is only used for 2D.

preset

Optional tuning preset. NULL uses 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. 0 disables 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. `0` disables 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 below `1` damp 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_mish parameter.

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 the K_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 with insertion_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. 0 disables 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. When NULL, this falls back to lgkk_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). When NULL, this falls back to lgkk_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). When NULL, this falls back to lgkk_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.

trace

Snapshot granularity. "round" records the coarsest initialization, each level start, every trace.every completed rounds, and the final layout. "level" records the coarsest initialization, every trace.everyth level start, and the final layout.

trace.every

Positive integer thinning factor for recorded rounds or levels. Initial and final snapshots are always included.

diagnostics

Optional per-frame diagnostic mode. "none" skips extra scoring, "light" appends lightweight shape diagnostics, and "full" also computes sampled stress on each traced frame.

target_coords

Optional numeric target coordinate matrix used to append per-frame Procrustes RMSE diagnostics. It must have `n` rows and `dim` columns.

diagnostic_sample_size_nonedge

Positive integer sample size used for per-frame non-edge separation diagnostics when diagnostics != "none".

diagnostic_sample_size_stress

Positive integer sample size used for per-frame sampled stress when diagnostics = "full".

diagnostic_nonedge_seed

RNG seed base used for per-frame non-edge separation diagnostics.

diagnostic_stress_seed

RNG seed base used for per-frame sampled stress diagnostics.

Value

A list with final, frames, meta, trace, trace.every, canonical stage_trace and stage_data, and optionally diagnostics and lgkk.polish. final is the final coordinate matrix. frames is a list of coordinate matrices with NA rows for vertices that have not yet been introduced by GRIP. meta is a data frame describing each frame with columns frame, phase, level_index, misf_level, round_in_level, and active_vertices. stage_trace and stage_data lift the raw frames onto the shared MISF stage schema used by the geodesic multiscale methods, with canonical states such as seed, initial_placement, top_level, insertion, refinement, and final_polish. When diagnostics are requested, diagnostics is a data frame parallel to meta that appends per-frame quality metrics such as edge.length.cv, sampled.nonedge.sep.ratio, and optional procrustes.rmse.

Examples

edges <- cbind(1:5, 2:6)
tr <- trace.grip(edges, n = 6, dim = 2,
                        placement = "barycenter",
                        rounds = 3, final_rounds = 2,
                        num_init = 3, num_nbrs = 4,
                        trace = "level",
                        trace.every = 1,
                        diagnostics = "light",
                        seed = 1)
tr$diagnostics
#>   frame       phase level_index misf_level round_in_level active_vertices
#> 1     1        init           1          1              0               3
#> 2     2 level_start           2          0              0               6
#> 3     3       final           2          0              2               6
#>   active.edges edge.length.cv median.edge.length sampled.nonedge.sep.ratio
#> 1            0             NA                 NA                        NA
#> 2            5      0.6138489           40.35679                 0.9923493
#> 3            5      0.3423293           30.12023                 1.5678969
#>   sampled.stress procrustes.rmse
#> 1             NA              NA
#> 2             NA              NA
#> 3             NA              NA