Getting Started with grip

What this vignette covers

grip has four main user workflows:

This vignette is the shortest path through the default workflow. It shows how to:

For weighted layouts, real-data search, tracing, and interactive exploration, the later guides go deeper. Advanced GKK/LGKK tools are public, but they are treated as later-stage experimental helpers rather than the default starting point.

library(grip)

A first unweighted layout

For an ordinary unweighted graph, grip() is the default starting point. Here is a small mesh in 2D.

mesh.edges <- edges.mesh(5, 5)
mesh.coords <- grip(
  mesh.edges,
  n = 25,
  dim = 2,
  preset = "mesh",
  seed = 1
)

mesh.score <- score.layout(mesh.coords, edges = mesh.edges, n = 25)
knitr::kable(mesh.score[, c(
  "sampled.stress",
  "edge.length.cv",
  "sampled.nonedge.sep.ratio"
)], digits = 3)
sampled.stress edge.length.cv sampled.nonedge.sep.ratio
9.193 0.055 1.286
plot.layout(
  mesh.coords,
  mesh.edges,
  main = "grip() on a 5x5 mesh",
  pch = 16,
  cex = 0.65,
  edge.col = "gray82"
)

For small and medium unweighted graphs, that is often all you need:

Compare a few plausible candidates

If the first picture matters, it is usually better to compare a short candidate list than to tune blindly. compare.layouts() runs several seeds and summarizes the results in a score table.

mesh.cmp <- compare.layouts(
  edges = mesh.edges,
  n = 25,
  dim = 2,
  candidates = c("default", "mesh", "tree"),
  seeds = 1:2,
  sample.size.stress = 500L,
  sample.size.nonedge = 1000L,
  edge.crossings = "never"
)

knitr::kable(mesh.cmp$summary[, c(
  "candidate",
  "sampled.stress.mean",
  "edge.length.cv.mean",
  "sampled.nonedge.sep.ratio.mean",
  "score.composite"
)], digits = 3)
candidate sampled.stress.mean edge.length.cv.mean sampled.nonedge.sep.ratio.mean score.composite
mesh 9.189 0.055 1.289 0.194
tree 1.790 0.321 0.233 0.528
default 18.721 0.166 0.247 0.778

That same pattern scales to real graphs:

What if the graph is weighted?

If a graph has edge weights but those weights are mostly metadata, a topology-first grip() run can still be a useful baseline. When the edge lengths represent geometry that the layout should preserve, the default path changes:

When should you switch workflows?

Start with grip() when the graph is fundamentally unweighted and you mainly care about its combinatorial structure.

Switch to the other guides when the task changes:

Where to go next