--- title: "Animating metric MDS: paraboloid and saddle" output: rmarkdown::html_vignette: toc: true math_method: mathml vignette: > %\VignetteIndexEntry{Animating metric MDS: paraboloid and saddle} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} library(grip) options(rgl.useNULL = TRUE) knitr::opts_chunk$set(collapse = TRUE, comment = "#>") source(system.file("scripts", "metric-mds-animation.R", package = "grip"), local = TRUE) ``` How does a random cloud become a curved surface when only its pairwise distances are known? The SGD backend of `metric.mds()` adjusts a pair of points at a time. Its optional **update trace** lets us inspect those actual states and animate the reconstruction. This example reconstructs a paraboloid and a saddle from the ambient distances between 250 points. Both have two intrinsic dimensions, but preserving their straight-line distances generally requires three embedding dimensions. Distances along the surface would define a different reconstruction problem. The vignette uses the tracing interface in the development version of grip (after 0.2.0). It rebuilds the fits from public R calls, without a separate instrumented solver or saved fitting results. The optional **ivue** and **rgl** packages provide the interactive view; numerical examples still run without them. See [Metric MDS](metric-mds-backends.html) for other weighting choices. ## Sample the same points on two surfaces On the unit disk, take \(z=x^2+y^2\) for the paraboloid and \(z=x^2-y^2\) for the saddle. Both have area element \(\sqrt{1+4r^2}\,r\,dr\,d\theta\). To sample uniformly over surface area, draw \(U\) uniformly on \([0,1]\), an independent uniform angle, and use \[ r=\sqrt{\frac{\{1+U(5^{3/2}-1)\}^{2/3}-1}{4}}. \] Thus the same sampled \(x,y\) positions give a surface-area sample on either surface. Only heights and target distances change. ```{r sample} set.seed(20261020) n <- 250L u <- runif(n) theta <- runif(n, 0, 2*pi) r <- sqrt(((1 + u*(5^(3/2) - 1))^(2/3) - 1)/4) paraboloid <- cbind(x = r*cos(theta), y = r*sin(theta), z = r^2) saddle <- paraboloid saddle[, "z"] <- saddle[, "x"]^2 - saddle[, "y"]^2 stopifnot(identical(paraboloid[, 1:2], saddle[, 1:2])) ``` We fit all \(250\times249/2=31{,}125\) unordered pairs. The view draws only 1,000 sampled chords to keep the surface visible; this display subset does not change the fit. ## Choose the target error and the initial cloud Let \(d_{ij}>0\) be a target distance and \(\widehat d_{ij}\) the distance in the current embedding. We display the mean squared relative error \[ S=\frac{1}{m}\sum_{i