Просте запитання, складне рішення.
Найкращий метод, який я знаю, використовує імітований відпал (я використав це для виділення декількох десятків балів із десятків тисяч, і це надзвичайно добре відбирає 200 пунктів: масштабування підлінійне), але це вимагає ретельного кодування та значних експериментів, оскільки а також величезна кількість обчислень. Спершу слід переглянути більш прості, швидші методи, щоб побачити, чи вистачить їх.
Один із способів - спочатку кластеризувати місця зберігання . У кожному кластері виберіть магазин, найближчий до центру кластера.
Дійсно швидким методом кластеризації є K-засоби . Ось R
рішення, яке його використовує.
scatter <- function(points, nClusters) {
#
# Find clusters. (Different methods will yield different results.)
#
clusters <- kmeans(points, nClusters)
#
# Select the point nearest the center of each cluster.
#
groups <- clusters$cluster
centers <- clusters$centers
eps <- sqrt(min(clusters$withinss)) / 1000
distance <- function(x,y) sqrt(sum((x-y)^2))
f <- function(k) distance(centers[groups[k],], points[k,])
n <- dim(points)[1]
radii <- apply(matrix(1:n), 1, f) + runif(n, max=eps)
# (Distances are changed randomly to select a unique point in each cluster.)
minima <- tapply(radii, groups, min)
points[radii == minima[groups],]
}
Аргументами scatter
є список місць зберігання (як матриця n на 2) та кількість магазинів, які потрібно вибрати (наприклад, 200). Він повертає масив локацій.
Як приклад його застосування, давайте згенеруємо n = 1000 випадково розташованих магазинів і подивимося, як виглядає рішення:
# Create random points for testing.
#
set.seed(17)
n <- 1000
nClusters <- 200
points <- matrix(rnorm(2*n, sd=10), nrow=n, ncol=2)
#
# Do the work.
#
system.time(centers <- scatter(points, nClusters))
#
# Map the stores (open circles) and selected ones (closed circles).
#
plot(centers, cex=1.5, pch=19, col="Gray", xlab="Easting (Km)", ylab="Northing")
points(points, col=hsv((1:nClusters)/(nClusters+1), v=0.8, s=0.8))
Цей розрахунок зайняв 0,03 секунди:
Ви можете бачити, що це не дуже здорово (але це теж не дуже погано). Для того, щоб зробити це набагато краще, знадобляться або стохастичні методи, наприклад, імітований відпал, або алгоритми, які, ймовірно, масштабують в експоненціальному розмірі з проблемою. (Я реалізував такий алгоритм: на вибір 10 найпоширеніших точок з 20 потрібно 12 секунд. Застосування його до 200 кластерів не виникає.)
Хорошою альтернативою K-засобам є ієрархічний алгоритм кластеризації; спершу спробуйте метод "Уорда" і подумайте про експерименти з іншими посиланнями. Для цього знадобиться більше обчислень, але ми все ще говоримо лише про кілька секунд для 1000 магазинів та 200 кластерів.
Існують і інші методи. Наприклад, ви можете покрити регіон звичайною шестикутною сіткою і для комірок, що містять один або кілька магазинів, виберіть магазин, найближчий до його центру. Пограйте трохи з розміром осередку, поки не буде вибрано приблизно 200 магазинів. Це створить дуже регулярний інтервал між магазинами, який ви можете або не хочете. (Якщо це справді місця розташування магазинів, це, мабуть, буде поганим рішенням, оскільки це може мати тенденцію вибору магазинів у найменш населених районах. В інших додатках це може бути набагато кращим рішенням.)