Nothing
# The local-quadratic box-integral mass estimator for an outer tensor cell
# (gcol33/tulpa#326).
#
# A cell's shipped mass is the midpoint atom `Delta exp(ell_c)`, which cannot see
# the log-marginal's gradient across the cell. `.joint_local_ccd_box_mass()`
# integrates the cell's own local quadratic over the cell's own box instead, off
# the same three-point stencil the design scale already differences, so it costs
# no inner solve. What is checked here is the closed form against quadrature, the
# per-axis handling of a convex axis, and what the rule does to the reported read
# when it is run through the #322 harness at zero fitting minutes.
# The axis integral by composite Simpson on the max-shifted exponent. Independent
# of `stats::integrate()`, so the estimator's numeric route is not being compared
# against itself.
.bxm_simpson <- function(g, a, h_lo, h_hi, m_pts = 20001L) {
expo <- function(u) g * u - 0.5 * a * u^2
cand <- c(-h_lo, h_hi)
if (a > 0) cand <- c(cand, min(max(g / a, -h_lo), h_hi))
mx <- max(expo(cand))
u <- seq(-h_lo, h_hi, length.out = m_pts)
step <- (h_hi + h_lo) / (m_pts - 1L)
w <- c(1, rep(c(4, 2), length.out = m_pts - 2L), 1)
mx + log(step / 3 * sum(w * exp(expo(u) - mx))) - log(h_lo + h_hi)
}
# The same integral through `stats::integrate()`, on the max shift the closed
# form's own algebra supplies.
.bxm_integrate <- function(g, a, h_lo, h_hi) {
mu <- g / a
mx <- 0.5 * g^2 / a - 0.5 * a * (min(max(mu, -h_lo), h_hi) - mu)^2
v <- stats::integrate(function(u) exp(g * u - 0.5 * a * u^2 - mx),
-h_lo, h_hi, rel.tol = .Machine$double.eps^0.75)$value
mx + log(v) - log(h_lo + h_hi)
}
# --------------------------------------------------------------------------- #
# The measurement (gcol33/tulpa#322's harness, no fitting minutes) #
# --------------------------------------------------------------------------- #
# The candidate weight vector: the box multiplier entering as a per-cell design
# weight, exactly the way the harness takes one.
.bxm_weights <- function(d) {
bm <- tulpa:::.joint_local_ccd_box_mass(d$joint_grid, d$log_marginal,
d$axis_names, d$axis_tags)
base <- if (is.null(d$dnode)) rep(1, nrow(d$joint_grid)) else d$dnode
list(bm = bm, w = outer_grid_weights(d, dnode = base * exp(bm$log_box_ratio)))
}
# Every axis's own u-space level spacing. The multiplier form is only a rule at
# all because the common cell volume `Delta` cancels in the softmax, and that is
# a property of the grid rather than of the rule.
.bxm_spacings <- function(d) {
lapply(seq_len(ncol(d$joint_grid)), function(j)
diff(sort(unique(tulpa:::.joint_pareto_fwd(d$axis_tags[j],
d$joint_grid[, j])))))
}
skip_on_cran_budget()
test_that("the factor is the issue's pnorm form where that form can be evaluated", {
skip_on_cran_budget()
# exp(0.5 g^2/a) sqrt(2 pi/a) (Phi(h; mu, s) - Phi(-h; mu, s)) / (2h), written
# out directly. Its two factors diverge against each other as the local peak
# leaves the box -- exp(0.5 g^2/a) up, the pnorm difference down at the
# matching rate -- so the product stays O(1) while each side runs out of double
# range on its own: at g = 10, a = 0.02 the leading term is exp(2500) = Inf
# against a pnorm difference of 0, and the answer comes back NaN. Only the logs
# stay in range, which is why the implementation carries them.
direct <- function(g, a, h) {
exp(0.5 * g^2 / a) * sqrt(2 * pi / a) *
(stats::pnorm(h, g / a, 1 / sqrt(a)) -
stats::pnorm(-h, g / a, 1 / sqrt(a))) / (2 * h)
}
gr <- expand.grid(g = c(0, 0.5, 1, 2), a = c(0.5, 1, 3, 20), h = c(0.25, 1, 2))
rel <- numeric(nrow(gr))
for (i in seq_len(nrow(gr))) {
m <- exp(tulpa:::.joint_local_ccd_axis_box(gr$g[i], gr$a[i],
gr$h[i], gr$h[i])$log_factor)
rel[i] <- abs(m / direct(gr$g[i], gr$a[i], gr$h[i]) - 1)
}
expect_lt(max(rel), 1e-12)
expect_true(is.nan(direct(10, 0.02, 1)))
for (p in list(c(4.44, 0.05), c(10, 0.02))) {
f <- tulpa:::.joint_local_ccd_axis_box(p[1L], p[2L], 1, 1)
expect_identical(f$route, "closed")
expect_equal(f$log_factor, .bxm_integrate(p[1L], p[2L], 1, 1),
tolerance = 1e-10)
}
})
test_that("a cell convex on one axis keeps the exact factor on the others", {
skip_on_cran_budget()
# The separability is the whole argument for the diagonal rule: the decline is
# per axis, so three good axes are not thrown away for a fourth the local
# quadratic came back convex on.
st <- list(g = c(1.0, -0.5, 2.0, 0.3), d2 = c(-2, -1, -0.5, 0.8),
half_lo = rep(0.5, 4L), half_hi = rep(0.5, 4L))
bm <- tulpa:::.joint_local_ccd_cell_box_mass(st)
expect_identical(bm$n_axes_declined, 0L)
expect_identical(bm$n_axes_closed, 3L)
expect_identical(bm$n_axes_numeric, 1L)
exact <- sum(vapply(seq_len(4L), function(j)
.bxm_simpson(st$g[j], -st$d2[j], st$half_lo[j], st$half_hi[j]),
numeric(1)))
expect_equal(bm$log_box_ratio, exact, tolerance = 1e-12)
# A flat cell is its own atom on every axis, so the multiplier is exactly 1.
flat <- tulpa:::.joint_local_ccd_cell_box_mass(
list(g = rep(0, 3L), d2 = rep(0, 3L), half_lo = rep(1, 3L),
half_hi = rep(1, 3L)))
expect_equal(flat$log_box_ratio, 0, tolerance = 1e-14)
})
# --------------------------------------------------------------------------- #
# The stencil the gradient comes off #
# --------------------------------------------------------------------------- #
test_that("the gradient is the same three points the curvature is", {
skip_on_cran_budget()
# An exactly quadratic target in u, so the three-point stencil reproduces both
# derivatives exactly and the two readings can be checked against the truth
# rather than against each other.
mu <- c(0.3, -0.2, 0.7); s <- c(0.8, 1.3, 0.5)
lv <- list(a = c(-1, 0, 1.5), b = c(-1.2, 0.1, 1), c = c(-0.8, 0.2, 1.4))
gg <- as.matrix(expand.grid(lv, KEEP.OUT.ATTRS = FALSE))
colnames(gg) <- names(lv)
lm <- -0.5 * rowSums(sweep(sweep(gg, 2L, mu, "-")^2, 2L, s^2, "/"))
nb <- tulpa:::.joint_local_ccd_neighbors(gg, gg, seq_len(3L))
ctr <- which(gg[, 1L] == 0 & gg[, 2L] == 0.1 & gg[, 3L] == 0.2)
st <- tulpa:::.joint_local_ccd_cell_stencil(ctr, gg, lm, nb$up, nb$dn)
expect_equal(st$g, -(gg[ctr, ] - mu) / s^2, tolerance = 1e-12,
ignore_attr = TRUE)
expect_equal(st$d2, -1 / s^2, tolerance = 1e-12, ignore_attr = TRUE)
# The curvature reading is unchanged by the gradient having been extracted
# from the same stencil, and carries it.
cc <- tulpa:::.joint_local_ccd_cell_curv(ctr, gg, lm, nb$up, nb$dn)
expect_equal(cc$sd, s, tolerance = 1e-12, ignore_attr = TRUE)
expect_equal(cc$g, st$g, tolerance = 1e-14)
expect_equal(cc$d2, st$d2, tolerance = 1e-14)
# Unequal spacing: the divided differences are the interpolating quadratic's,
# so an unevenly spaced stencil is exact on a quadratic too.
q <- function(u) 1.4 + 2.1 * u - 0.65 * u^2
fd <- tulpa:::.joint_local_ccd_diff3(-0.3, 0, 1.7, q(-0.3), q(0), q(1.7))
expect_equal(fd$d1, 2.1, tolerance = 1e-12)
expect_equal(fd$d2, -1.3, tolerance = 1e-12)
expect_equal(fd$half_lo, 0.15, tolerance = 1e-14)
expect_equal(fd$half_hi, 0.85, tolerance = 1e-14)
expect_null(tulpa:::.joint_local_ccd_diff3(0, 0, 1, 1, 1, 1))
expect_null(tulpa:::.joint_local_ccd_diff3(-1, 0, 1, 1, NA_real_, 1))
})
test_that("a boundary cell has no centred stencil and keeps its midpoint atom", {
skip_on_cran_budget()
mu <- c(0.3, -0.2); s <- c(0.8, 1.3)
lv <- list(a = c(-1, 0, 1), b = c(-1, 0, 1))
gg <- as.matrix(expand.grid(lv, KEEP.OUT.ATTRS = FALSE))
colnames(gg) <- names(lv)
lm <- -0.5 * rowSums(sweep(sweep(gg, 2L, mu, "-")^2, 2L, s^2, "/"))
tags <- c("identity", "identity")
bm <- tulpa:::.joint_local_ccd_box_mass(gg, lm, colnames(gg), tags)
interior <- gg[, 1L] == 0 & gg[, 2L] == 0
expect_identical(bm$computed, unname(interior))
# Exactly one interior cell on a 3 x 3 grid, and every other cell is the atom
# it already was: multiplier 1, log 0.
expect_equal(sum(bm$computed), 1L)
expect_true(all(bm$log_box_ratio[!bm$computed] == 0))
expect_true(bm$log_box_ratio[interior] != 0)
expect_identical(bm$n_axes_declined, 0L)
# No axis that reached a per-axis gate fell at one, and the eight boundary
# cells account for their own axes: the stencil is a cell-level object, so a
# cell missing a neighbour on one axis has no local quadratic on either. The
# count and the tally are read together rather than one summing to the other
# (gcol33/tulpa#334).
expect_identical(bm$declined_reasons,
c(boundary = 16L, no_factor = 0L, cancellation = 0L))
expect_identical(bm$n_axes_declined,
sum(bm$declined_reasons[c("no_factor", "cancellation")]))
# The interior cell's multiplier is the product of its own axis factors.
nb <- tulpa:::.joint_local_ccd_neighbors(gg, gg, seq_len(2L))
st <- tulpa:::.joint_local_ccd_cell_stencil(which(interior), gg, lm,
nb$up, nb$dn)
expect_equal(bm$log_box_ratio[interior],
sum(vapply(1:2, function(j)
.bxm_simpson(st$g[j], -st$d2[j], st$half_lo[j], st$half_hi[j]),
numeric(1))), tolerance = 1e-10, ignore_attr = TRUE)
# An unguessable-support grid declines whole rather than guessing a transform.
# No cell was scored at all there, so no axis declined at a gate and the tally
# is empty: the whole-grid decline is what `computed` reports, not a per-axis
# refusal.
none <- tulpa:::.joint_local_ccd_box_mass(gg, lm, colnames(gg), NULL)
expect_false(any(none$computed))
expect_true(all(none$log_box_ratio == 0))
expect_true(all(none$declined_reasons == 0L))
expect_identical(names(none$declined_reasons), tulpa:::.LCCD_BOX_REASONS)
})
# --------------------------------------------------------------------------- #
# What a declined axis declined at (gcol33/tulpa#334) #
# --------------------------------------------------------------------------- #
test_that("a declined box axis names the gate it fell at", {
skip_on_cran_budget()
# `no_factor`: the quadratic never formed. A box of zero extent has no
# integral to divide by its own width, and a non-finite coefficient has no
# integrand at all.
for (p in list(c(1, 1, 0, 0), c(NA_real_, 1, 1, 1), c(1, NA_real_, 1, 1))) {
f <- tulpa:::.joint_local_ccd_axis_box(p[1L], p[2L], p[3L], p[4L])
expect_null(f$log_factor)
expect_identical(f$reason, "no_factor")
}
# `cancellation`: the local peak sits 5e11 nats above the box, past
# `.LCCD_BOX_CANCEL`, so the closed form is refused before it is formed and
# the quadrature that takes over is handed a needle 1e-6 wide in a box of
# width 2 and returns nothing either. The quadratic here is perfectly good and
# only its arithmetic is out of reach, which is the distinction the reason
# carries and the count cannot.
expect_gt(0.5 * 1e6^2 / 1, tulpa:::.LCCD_BOX_CANCEL)
f <- tulpa:::.joint_local_ccd_axis_box(1e6, 1, 1, 1)
expect_null(f$log_factor)
expect_identical(f$reason, "cancellation")
# One decade of gradient lower is inside the budget and is answered.
ok <- tulpa:::.joint_local_ccd_axis_box(1e5, 1, 1, 1)
expect_identical(ok$route, "numeric")
expect_true(is.na(ok$reason))
expect_true(is.finite(ok$log_factor))
})
test_that("a cell's decline tally is per axis, alongside the count", {
skip_on_cran_budget()
# Four axes: one concave and answered in closed form, one whose closed form is
# refused for conditioning and whose quadrature then returns nothing, one with
# no extent at all, and one convex axis that is integrated rather than
# declined. The count says two axes went unread; the tally says they went
# unread for structurally different reasons, and only the second of the two
# would be fixed by a finer grid.
st <- list(g = c(1.0, 1e6, 0.3, 2.0), d2 = c(-2, -1, 0, 0.8),
half_lo = c(0.5, 1, 0, 0.5), half_hi = c(0.5, 1, 0, 0.5))
bm <- tulpa:::.joint_local_ccd_cell_box_mass(st)
expect_identical(bm$n_axes_declined, 2L)
expect_identical(bm$declined_reasons,
c(boundary = 0L, no_factor = 1L, cancellation = 1L))
# `boundary` cannot fire on a cell that already holds a stencil, and the slot
# is carried anyway so the tally is the same object the grid-wide entry point
# returns.
expect_identical(names(bm$declined_reasons), tulpa:::.LCCD_BOX_REASONS)
# The two axes that were read still contribute their exact factors, which is
# the separability the diagonal form is chosen for.
expect_identical(bm$n_axes_closed, 1L)
expect_identical(bm$n_axes_numeric, 1L)
expect_equal(bm$log_box_ratio,
.bxm_simpson(1.0, 2, 0.5, 0.5) +
.bxm_simpson(2.0, -0.8, 0.5, 0.5),
tolerance = 1e-12)
})
test_that("a refined cell records the box mass beside the cloud's own", {
skip_on_cran_budget()
mu <- c(0.5, 0.5); s <- c(0.3, 0.3)
lv <- list(a = c(-1, 0.5, 2), b = c(-1, 0.5, 2))
gg <- as.matrix(expand.grid(lv, KEEP.OUT.ATTRS = FALSE))
colnames(gg) <- names(lv)
lmf <- function(th) -0.5 * rowSums(sweep(sweep(th, 2L, mu, "-")^2, 2L, s^2, "/"))
out <- tulpa:::.joint_local_ccd_refine(
gg, lmf(gg), NULL, NULL, colnames(gg), c(a = "identity", b = "identity"),
eval_nodes = function(theta_mat, warm)
list(log_marginal = lmf(theta_mat), modes = NULL),
max_cells = 4L)
nc <- out$info$n_cells_refined
expect_gt(nc, 0L)
expect_length(out$info$log_box_ratio, nc)
expect_true(all(is.finite(out$info$log_box_ratio)))
# It is the grid-wide rule's reading of the same cells, so the two entry
# points cannot drift apart.
bm <- tulpa:::.joint_local_ccd_box_mass(gg, lmf(gg), colnames(gg),
c("identity", "identity"))
expect_equal(out$info$log_box_ratio, bm$log_box_ratio[out$info$cells],
tolerance = 1e-12)
})
skip_on_cran()
# --------------------------------------------------------------------------- #
# The closed form #
# --------------------------------------------------------------------------- #
test_that("the concave axis factor is the box integral, to machine precision", {
skip_on_cran()
gr <- expand.grid(g = c(0, 0.25, 1, 2, 4.44, -3), a = c(0.05, 0.5, 1, 3, 20),
h = c(0.25, 1, 2))
err_int <- numeric(nrow(gr))
err_sim <- numeric(nrow(gr))
route <- character(nrow(gr))
for (i in seq_len(nrow(gr))) {
f <- tulpa:::.joint_local_ccd_axis_box(gr$g[i], gr$a[i], gr$h[i], gr$h[i])
route[i] <- f$route
err_int[i] <- abs(f$log_factor - .bxm_integrate(gr$g[i], gr$a[i],
gr$h[i], gr$h[i]))
err_sim[i] <- abs(f$log_factor - .bxm_simpson(gr$g[i], gr$a[i],
gr$h[i], gr$h[i]))
}
# Every one of these takes the closed form: the whole point is that a concave
# axis needs no quadrature.
expect_identical(unique(route), "closed")
# Measured over the 90 combinations, on the log scale: 6.13e-14 against
# integrate() and 6.08e-14 against Simpson, the two arbiters agreeing with
# each other to the same figure. The tolerances are floating slack.
expect_lt(max(err_int), 1e-12)
expect_lt(max(err_sim), 1e-12)
# An asymmetric box -- the cell's Voronoi half-widths need not match, and the
# factor divides by the axis's own extent so the product stays a multiplier on
# the cell's own volume.
expect_equal(tulpa:::.joint_local_ccd_axis_box(1.3, 0.7, 0.4, 1.1)$log_factor,
.bxm_integrate(1.3, 0.7, 0.4, 1.1), tolerance = 1e-12)
# A cell the log-marginal is flat across is its own midpoint atom exactly.
expect_equal(tulpa:::.joint_local_ccd_axis_box(0, 0, 1, 1)$log_factor, 0,
tolerance = 1e-14)
})
# --------------------------------------------------------------------------- #
# The convex axis #
# --------------------------------------------------------------------------- #
test_that("a convex axis is integrated rather than declined", {
skip_on_cran()
gr <- expand.grid(g = c(0, 0.5, 2, -2), a = c(0, -0.05, -0.5, -2),
h = c(0.5, 1, 2))
err <- numeric(nrow(gr))
route <- character(nrow(gr))
for (i in seq_len(nrow(gr))) {
f <- tulpa:::.joint_local_ccd_axis_box(gr$g[i], gr$a[i], gr$h[i], gr$h[i])
expect_false(is.null(f$log_factor))
expect_true(is.na(f$reason))
route[i] <- f$route
err[i] <- abs(f$log_factor - .bxm_simpson(gr$g[i], gr$a[i],
gr$h[i], gr$h[i]))
}
expect_identical(unique(route), "numeric")
# Measured: 1.3e-14 over the 48 combinations. A bounded interval and a smooth
# integrand is where quadrature is exact, which is what buys the convex axis a
# factor instead of a decline.
expect_lt(max(err), 1e-12)
# And a near-flat concave axis, where the closed form's own two pieces cancel:
# 0.5 g^2/a diverges while the pnorm difference vanishes at the matching rate.
# The reading is refused there and taken by quadrature, not returned wrong.
f <- tulpa:::.joint_local_ccd_axis_box(0, 1e-14, 1, 1)
expect_identical(f$route, "numeric")
expect_equal(f$log_factor, .bxm_simpson(0, 1e-14, 1, 1), tolerance = 1e-12)
expect_true(is.na(tulpa:::.joint_local_ccd_log_pnorm_diff(-5e-8, 5e-8)))
})
test_that("the base grid's cells have equal volume, so Delta cancels", {
skip_on_cran()
d <- outer_grid_dump(ogd_fixture_fit(ogd_fixture_sim(c(0.8, 0.5, 0.3)), 5L))
# A geometric sigma grid is uniform in u = log sigma, so every interior cell
# is congruent and the multiplier can enter without carrying Delta_c. Asserted
# rather than assumed: on a grid whose cells differ in volume the same
# multiplier would silently drop a per-cell factor.
for (sp in .bxm_spacings(d)) {
expect_gt(length(sp), 1L)
expect_lt(stats::sd(sp) / mean(sp), 1e-12)
}
# And the cell volume is the same on every axis-interior cell, which is the
# statement the softmax needs.
vol <- prod(vapply(.bxm_spacings(d), function(sp) sp[1L], numeric(1)))
expect_true(is.finite(vol) && vol > 0)
})
test_that("the box rule's read is reported against what this grid can resolve", {
skip_on_cran()
sim <- ogd_fixture_sim(c(0.8, 0.5, 0.3))
# A five-level tensor base: 125 cells, 27 of them interior on all three axes,
# and those 27 carry 0.99999 of the integration weight, so the rule is scored
# where the posterior actually is.
d5 <- outer_grid_dump(ogd_fixture_fit(sim, 5L))
expect_null(d5$dnode)
expect_identical(d5$support, "density")
b5 <- .bxm_weights(d5)
expect_identical(sum(b5$bm$computed), 27L)
expect_identical(b5$bm$n_axes_declined, 0L)
expect_gt(sum(d5$weights[b5$bm$computed]), 0.999)
r5 <- outer_grid_weight_report(d5, b5$w)
# Measured under the read the engine ships (`dev_notes/issue744/boxmass744.R`):
# at five levels the rule moves no part of the read by as much as one step of
# coarsening moves it -- endpoints 0.1043 against a floor of 0.1496, widths
# 0.2085 against 0.2297, median 0.0072 against 0.0219. On this grid the
# correction is not resolved.
#
# Whether a part is resolved at this resolution is a property of the
# within-cell read, not of the rule (gcol33/tulpa#599). Under `chord` the same
# fit resolves the median (0.0127 against a floor of 0.0043) and still neither
# half of the interval (0.0287 against 0.2414, 0.0573 against 0.4827). Both
# reads place the same mass in the same cells and differ in where inside a
# cell they place it, and on a five-level grid that is a half-cell -- the
# resolution these parts are read at. The floor moves with the read for the
# same reason (median 0.0043 -> 0.0219), so this is the resolution of the
# reported read changing rather than the rule's effect.
expect_false(any(r5$above_floor))
expect_lt(r5$diff$widths, r5$floor$widths)
# Coarser, which is where a cell carries a real gradient: at four levels the
# same rule moves the endpoints 0.2453 against a floor of 0.1308 and the
# median 0.2503 against 0.0797, above what the grid resolves, and the widths
# 0.2032 against 0.2196, not. The multiplier is not a small correction there
# -- the steepest cell's log multiplier is 15.5 nats -- because a four-level
# grid puts whole nats of log-marginal across a single cell. Under `chord` all
# three parts clear their floors at four levels.
d4 <- outer_grid_dump(ogd_fixture_fit(sim, 4L))
b4 <- .bxm_weights(d4)
expect_identical(sum(b4$bm$computed), 8L)
r4 <- outer_grid_weight_report(d4, b4$w)
expect_gt(r4$diff$endpoints, r4$floor$endpoints)
expect_true(r4$above_floor[["endpoints"]])
expect_true(r4$above_floor[["median"]])
expect_gt(max(b4$bm$log_box_ratio), 10)
})
test_that("where the read moves above the floor it moves toward the dense answer", {
skip_on_cran()
# The floor says whether a difference is resolved; it does not say which
# direction is right. The arbiter for that is the same model on a grid fine
# enough for the read to be a property of the posterior -- twelve levels per
# axis, 1728 cells -- against which both the midpoint atom and the box rule
# are scored on the coarse grid.
sim <- ogd_fixture_sim(c(0.8, 0.5, 0.3))
ref <- outer_grid_rebuild(outer_grid_dump(ogd_fixture_fit(sim, 12L)))
d4 <- outer_grid_dump(ogd_fixture_fit(sim, 4L))
e0 <- outer_grid_read_diff(ref, outer_grid_rebuild(d4))
e1 <- outer_grid_read_diff(ref, outer_grid_rebuild(d4, .bxm_weights(d4)$w))
# Measured on the four-level grid: endpoint error 0.2126 -> 0.1797 and width
# error 0.3326 -> 0.1679, so the interval the coarse grid reports moves toward
# the converged one, by a sixth on the endpoints and twofold on the widths.
# The median goes the other way, 0.1427 -> 0.1487: the rule redistributes mass
# toward the cell edges nearest the peak, which sharpens the spread and
# overshoots the location.
#
# The box-uniform read already recovers part of what the rule recovers -- the
# same three errors read under `chord` start at 0.4046 / 0.8092 / 0.1050 -- so
# the rule has a smaller remaining gain here than it does against that read,
# and the endpoint margin is the thin one of the three.
expect_lt(e1$endpoints, e0$endpoints)
expect_lt(e1$widths, e0$widths)
expect_gt(e1$median, e0$median)
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.