This gallery demonstrates multiscale GRIP on six graph families. For the recommended embedding workflow, see the SGD metric-MDS gallery.
This gallery complements the function guide and synthetic graph examples.
This article is a guide to the synthetic graph families shipped with
grip. The package no longer provides only a few toy
generators for smoke tests. It now includes a broad collection of
geometry-rich benchmark families covering:
For many of these families, the package stores both:
grip(metric = "edge_length").As a workflow guide, use grip() on the purely
topological versions of these families when you want an unweighted
baseline, and use grip(metric = "edge_length") on the
weighted bundles when the induced geometry is part of the problem.
Advanced GKK/LGKK scoring can be layered onto smaller weighted examples
later, but that is not the main purpose of this article.
The views rotate and zoom. Reference and fitted coordinates are displayed without rotation or scale fitting. The original 2D tree fit is preserved and shown in the z = 0 plane of a 3D viewer.
The table below lists a representative subset of the larger family collection.
| Family class | Representative helper | Why it matters |
|---|---|---|
| Lifted lattices | mesh.surface.graph() |
Plain topology, nontrivial metric geometry |
| Wrapped surfaces | torus.surface.graph() |
Closed periodic surface geometry |
| Recursive fractals | vicsek.surface.graph() |
Self-similar bottlenecks and holes |
| Irregular manifolds | irregular.annulus.surface.graph() |
Non-lattice surface geometry with boundary |
| Porous 3D families | cube.channel.network.surface.graph() |
Volumetric geodesic detours |
| Intrinsic trees | kary.tree.weighted.graph() |
Geometry from edge lengths rather than ambient space |
This article shows one representative example from each class. The
interactive family browser described in
Interactive Exploration with gripui exposes a much larger
catalog.
The simplest geometry-rich family keeps the graph topology of a
rectangular mesh but induces edge lengths from a curved embedding in
R^3.
mesh.graph <- mesh.surface.graph(
5, 5,
surface = "saddle",
amplitude = 0.8
)
mesh.coords <- grip(metric = "edge_length",
mesh.graph$edges,
n = mesh.graph$n,
edge.weights = mesh.graph$edge_weights,
dim = 3,
preset = "mesh",
seed = 1
)
mesh.summary <- data.frame(
family = mesh.graph$family,
surface = mesh.graph$surface,
n = mesh.graph$n,
m = nrow(mesh.graph$edges),
weight_scale = mesh.graph$weight_scale
)
knitr::kable(mesh.summary, digits = 3)| family | surface | n | m | weight_scale |
|---|---|---|---|---|
| mesh | saddle | 25 | 40 | 0.66 |
documentation.view(list(`Weighted GRIP`=mesh.coords, `Reference geometry`=mesh.graph$coords_surface, `Parameter grid`=cbind(mesh.graph$coords_param,z=0)), edges=mesh.graph$edges,
aligned=TRUE, description="Drag to rotate; scroll to zoom; select a geometry.")Drag to rotate; scroll to zoom; select a geometry.
The useful design pattern here is that the topology stays simple while the metric geometry becomes nontrivial.
Wrapped lattices extend the same idea to periodic topologies such as a torus.
torus.graph <- torus.surface.graph(
5, 6,
surface = "pinched",
minor.radius = 0.33,
amplitude = 0.18,
twist = 0.18
)
torus.coords <- grip(metric = "edge_length",
torus.graph$edges,
n = torus.graph$n,
edge.weights = torus.graph$edge_weights,
dim = 3,
preset = "torus",
seed = 2
)
knitr::kable(
data.frame(
family = torus.graph$family,
surface = torus.graph$surface,
n = torus.graph$n,
m = nrow(torus.graph$edges)
)
)| family | surface | n | m |
|---|---|---|---|
| torus | pinched | 30 | 60 |
documentation.view(list(`Weighted GRIP`=torus.coords, `Reference geometry`=torus.graph$coords_surface), edges=torus.graph$edges,
aligned=TRUE, description="Drag to rotate; scroll to zoom; select a geometry.")Drag to rotate; scroll to zoom; select a geometry.
These wrapped families are especially useful when ordinary planar intuition is misleading and a 3D layout is the natural target.
The package now includes recursive square-mask families such as the Vicsek fractal and Sierpinski carpet variants, all of which can be lifted into curved surface geometries.
vicsek.graph <- vicsek.surface.graph(
level = 2,
surface = "ripple",
amplitude = 0.55
)
vicsek.coords <- grip(metric = "edge_length",
vicsek.graph$edges,
n = vicsek.graph$n,
edge.weights = vicsek.graph$edge_weights,
dim = 3,
preset = "carpet",
seed = 3
)documentation.view(list(`Weighted GRIP`=vicsek.coords, `Reference geometry`=vicsek.graph$coords_surface), edges=vicsek.graph$edges,
aligned=TRUE, description="Drag to rotate; scroll to zoom; select a geometry.")Drag to rotate; scroll to zoom; select a geometry.
Recursive families are useful because they create holes, bottlenecks, and multi-scale detours that are hard to capture with simpler lattices.
Not all surface families in grip are based on regular
grids. The package also includes irregular triangulated manifolds with
boundary and closed irregular surfaces.
annulus.graph <- irregular.annulus.surface.graph(
rings = 5,
outer.count = 24,
inner.radius = 0.42,
surface = "folded",
amplitude = 0.2
)
annulus.coords <- grip(metric = "edge_length",
annulus.graph$edges,
n = annulus.graph$n,
edge.weights = annulus.graph$edge_weights,
dim = 3,
preset = "irregular",
seed = 4
)documentation.view(list(`Weighted GRIP`=annulus.coords, `Reference geometry`=annulus.graph$coords_surface), edges=annulus.graph$edges,
aligned=TRUE, description="Drag to rotate; scroll to zoom; select a geometry.")Drag to rotate; scroll to zoom; select a geometry.
These families are important because they reduce lattice bias and produce more variable local geometry than mesh-like constructions.
The cubical branch introduces graphs that are genuinely volumetric rather than surface-like. Channel networks and related porous families create 3D geodesic detours that are hard to flatten cleanly.
cube.graph <- cube.channel.network.surface.graph(
side = 5,
level = 1,
surface = "twisted",
twist = 0.2
)
cube.coords <- grip(metric = "edge_length",
cube.graph$edges,
n = cube.graph$n,
edge.weights = cube.graph$edge_weights,
dim = 3,
preset = "irregular",
seed = 5
)
knitr::kable(
data.frame(
family = cube.graph$family,
n = cube.graph$n,
m = nrow(cube.graph$edges)
)
)| family | n | m |
|---|---|---|
| cube.channel.network | 104 | 212 |
documentation.view(list(`Weighted GRIP`=cube.coords, `Reference geometry`=cube.graph$coords_surface), edges=cube.graph$edges,
aligned=TRUE, description="Drag to rotate; scroll to zoom; select a geometry.")Drag to rotate; scroll to zoom; select a geometry.
This family class is especially useful for testing whether a method can preserve large-scale volumetric structure without collapsing tunnels and channels.
Some family geometries are intrinsic rather than ambient. The weighted tree helpers preserve the exact tree topology while assigning edge lengths directly from branch-depth and branch-position rules.
tree.graph <- kary.tree.weighted.graph(
k = 2,
depth = 4,
depth.rule = "geometric",
depth.decay = 0.82,
branch.rule = "linear",
branch.spread = 0.25
)
tree.coords <- grip(metric = "edge_length",
tree.graph$edges,
n = tree.graph$n,
edge.weights = tree.graph$edge_weights,
dim = 2,
preset = "tree",
seed = 6
)
knitr::kable(
head(tree.graph$edge_table[, c(
"parent",
"child",
"child_depth",
"branch_index",
"edge_weight"
)]),
digits = 3
)| parent | child | child_depth | branch_index | edge_weight |
|---|---|---|---|---|
| 1 | 2 | 1 | 1 | 1.411 |
| 1 | 3 | 1 | 2 | 1.814 |
| 2 | 4 | 2 | 1 | 1.157 |
| 2 | 5 | 2 | 2 | 1.487 |
| 3 | 6 | 2 | 1 | 1.157 |
| 3 | 7 | 2 | 2 | 1.487 |
documentation.view(list(`Weighted GRIP (2D fit)`=cbind(tree.coords,z=0)), edges=tree.graph$edges,
aligned=TRUE, description="Drag to rotate; scroll to zoom; select a geometry.")Drag to rotate; scroll to zoom; select a geometry.
These tree families are useful because they separate intrinsic weighted geometry from any arbitrary 3D embedding choice.
The family collection now serves three roles:
Getting Started with grip introduces the main layout
APIs.Weighted Graph Layouts with grip explains how to use
these family bundles with the weighted sister API.Interactive Exploration with gripui shows how to browse
the larger family registry through
run.gripui.family().