## ----------------------------------------------------------------------------- #| label: setup #| include: false knitr::opts_chunk$set(collapse = TRUE, comment = "#>") library("Coreset") ## ----------------------------------------------------------------------------- #| label: install #| eval: false # install.packages("Coreset") ## ----------------------------------------------------------------------------- #| label: quickstart # Load the `eurodist` dist object data("eurodist") # Set a seed for a reproducible selection set.seed(1) # Select 4 maximally dispersed cities ffPick <- FarFirst(4L, eurodist) # View distances between selected cities as.matrix(eurodist)[ffPick, ffPick] # Quickly extract the minimum distance for a given selection MinDist(eurodist, ffPick) ## ----------------------------------------------------------------------------- #| label: gonzalez-random set.seed(1) FarFirst(6L, eurodist) # default: best of three random starts ## ----------------------------------------------------------------------------- #| label: gonzalez-ensemble set.seed(1) # Fewer starts provides a faster run, but the solution found may be inferior FarFirst(6L, eurodist, nSeeds = 2L) ## ----------------------------------------------------------------------------- #| label: gonzalez-seeds ffPick <- FarFirst(6L, eurodist, strategy = c("diameter", "anti_medoid")) MinDist(eurodist, ffPick) attr(ffPick, "winning_strategy") ## ----------------------------------------------------------------------------- #| label: gonzalez-oracle data("USArrests") arrestTypes <- USArrests[, c("Murder", "Assault", "Rape")] StateDist <- function(i) { diffs <- sweep(arrestTypes, 2, unlist(arrestTypes[i, ]), "-") sqrt(rowSums(diffs ^ 2)) } idx <- FarFirst(4L, StateDist, N = nrow(arrestTypes), strategy = 1L) arrestTypes[idx, ] ## ----------------------------------------------------------------------------- #| label: dropadd daPick <- DropAdd(6L, eurodist, plateau = 500L) daPick labels(eurodist)[daPick] ## ----------------------------------------------------------------------------- #| label: grasp set.seed(0) grPick <- Grasp(6L, eurodist, plateau = 50L) grPick labels(eurodist)[grPick] attr(grPick, "pr_calls") # path-relinking calls performed ## ----------------------------------------------------------------------------- #| label: sim-data set.seed(1) # Seed selected such that FarFirst < DropAdd < Grasp pts <- matrix(rnorm(100), ncol = 2) # 50 points, 2 dimensions d50 <- dist(pts) k <- 8L ## ----------------------------------------------------------------------------- #| label: compare-run set.seed(1) # Seed selected such that FarFirst < DropAdd < Grasp ffPick <- FarFirst(k, d50) da50Pick <- DropAdd(k, d50, plateau = 500L) gr50Pick <- Grasp(k, d50, plateau = 50L) ## ----------------------------------------------------------------------------- #| label: compare-scores scores <- c( FarFirst = attr(ffPick, "score"), DropAdd = attr(da50Pick, "score"), Grasp = attr(gr50Pick, "score") ) round(scores, 3) ## ----------------------------------------------------------------------------- #| label: compare-plot #| fig-width: 6.5 #| fig-height: 6 #| fig-cap: "Selections returned by each method on 50 random 2-D points #| (k = 8). Coloured symbols mark selected points; grey circles are the #| full candidate set." methods <- list( FarFirst = ffPick, DropAdd = da50Pick, Grasp = gr50Pick ) cols <- c(FarFirst = "#E41A1C", DropAdd = "#377EB8", Grasp = "#4DAF4A") pchs <- c(FarFirst = 1L, DropAdd = 3L, Grasp = 4L) plot(pts, pch = 1L, col = "grey75", asp = 1L, xlab = "x", ylab = "y", frame.plot = FALSE, main = "Coreset method comparison") for (nm in names(methods)) { sel <- methods[[nm]] points(pts[sel, 1L], pts[sel, 2L], pch = pchs[nm], col = cols[nm], cex = 1.6) } legend_labels <- lapply(seq_along(methods), function(i) { bquote(.(names(methods)[i]) ~ (T[k] == .(sprintf("%.3f", scores[i])))) }) legend("topleft", legend = as.expression(legend_labels), pch = pchs, col = cols, pt.bg = cols, pt.cex = 1.4, bty = "n") ## ----------------------------------------------------------------------------- #| label: install-highs #| eval: false # install.packages("highs") ## ----------------------------------------------------------------------------- #| label: exact-data set.seed(1L) pts30 <- matrix(rnorm(60L), ncol = 2L) d30 <- dist(pts30) ## ----------------------------------------------------------------------------- #| label: exact #| eval: !expr requireNamespace("highs", quietly = TRUE) # exPick <- ExactMaxMin(6L, d30, maxSeconds = 30L) # # attr(exPick, "proven") # TRUE ⟹ objective is the global optimum # attr(exPick, "score") # # # Compare to the greedy heuristic on the same instance # ff30Pick <- FarFirst(6L, d30) # c(exact = attr(exPick, "score"), # farFirst = MinDist(d30, ff30Pick)) ## ----------------------------------------------------------------------------- #| label: MinDist MinDist(d50, ffPick) # from dist MinDist(as.matrix(d50), ffPick) # from square matrix MinDist(points = pts, idx = ffPick) # from coordinates ## ----------------------------------------------------------------------------- #| label: exact-maxsum #| eval: !expr requireNamespace("highs", quietly = TRUE) # smPick <- ExactMaxSum(6L, d30, maxSeconds = 30L) # # attr(smPick, "proven") # TRUE ⟹ objective is the global optimum # attr(smPick, "score") # total pairwise distance within the selection ## ----------------------------------------------------------------------------- #| label: maxmean-data set.seed(1) affinity <- matrix(runif(30L * 30L, min = -10, max = 10), nrow = 30L) affinity <- (affinity + t(affinity)) / 2 # symmetric diag(affinity) <- 0 ## ----------------------------------------------------------------------------- #| label: maxmean set.seed(1) mmPick <- MaxMean(affinity, maxSeconds = 2) mmPick attr(mmPick, "size") # the algorithm chose this subset size attr(mmPick, "score") # achieved mean-dispersion objective ## ----------------------------------------------------------------------------- #| label: meandist MeanDist(affinity, mmPick) # matches attr(mmPick, "score") MeanDist(affinity, 1:30) # the full set scores lower ## ----------------------------------------------------------------------------- #| label: kcentre centres <- KCentre(4L, eurodist) labels(eurodist)[centres] centres ## ----------------------------------------------------------------------------- #| label: kcentre-radius ff <- FarFirst(4L, eurodist, strategy = "peripheral") c(KCentre = KCentreRadius(eurodist, centres), FarFirst = KCentreRadius(eurodist, ff)) ## ----------------------------------------------------------------------------- #| label: exact-kcentre #| eval: !expr requireNamespace("highs", quietly = TRUE) # kc <- ExactKCentre(4L, eurodist) # kc # attr(kc, "proven") # TRUE ⟹ radius is the global covering optimum ## ----------------------------------------------------------------------------- #| label: dispersion-vs-covering #| eval: !expr requireNamespace("highs", quietly = TRUE) # disp <- ExactMaxMin(4L, eurodist) # labels(eurodist)[disp] # dispersion: pushed to the extremes # labels(eurodist)[kc] # covering: pulled toward the interior ## ----------------------------------------------------------------------------- #| label: maxentropy mePick <- MaxEntropy(4L, eurodist) labels(eurodist)[mePick] attr(mePick, "score") # the achieved log-determinant attr(mePick, "exact") # TRUE if certified by exact enumeration ## ----------------------------------------------------------------------------- #| label: maxentropy-negmass attr(mePick, "negMass")