Domanda semplice, soluzione difficile.
Il metodo migliore che conosco utilizza la ricottura simulata (l'ho usato per selezionare alcune decine di punti su decine di migliaia e si adatta perfettamente alla selezione di 200 punti: il ridimensionamento è sublineare), ma ciò richiede un'attenta codifica e una notevole sperimentazione, come oltre a un'enorme quantità di calcolo. Dovresti iniziare guardando prima i metodi più semplici e veloci per vedere se saranno sufficienti.
Un modo è innanzitutto raggruppare le posizioni dei negozi . All'interno di ciascun cluster selezionare il negozio più vicino al centro del cluster.
Un metodo di clustering molto veloce è K-medie . Ecco una R
soluzione che lo utilizza.
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],]
}
Gli argomenti da utilizzare scatter
sono un elenco di posizioni dei negozi (come matrice n per 2) e il numero di negozi da selezionare (ad es. 200). Restituisce una serie di posizioni.
Come esempio della sua applicazione, generiamo n = 1000 negozi posizionati casualmente e vediamo come appare la soluzione:
# 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))
Questo calcolo ha impiegato 0,03 secondi:
Puoi vedere che non è eccezionale (ma non è neanche tanto male). Fare molto meglio richiederà metodi stocastici, come ricottura simulata, o algoritmi che potrebbero ridimensionarsi esponenzialmente con la dimensione del problema. (Ho implementato un tale algoritmo: ci vogliono 12 secondi per selezionare i 10 punti più distanziati su 20. Applicarlo a 200 cluster è fuori discussione.)
Una buona alternativa a K-medie è un algoritmo di clustering gerarchico; prova prima il metodo "Ward" e considera di sperimentare altri collegamenti. Questo richiederà più calcoli, ma stiamo ancora parlando di pochi secondi per 1000 negozi e 200 cluster.
Esistono altri metodi. Ad esempio, potresti coprire la regione con una griglia esagonale regolare e, per le celle che contengono uno o più negozi, selezionare il negozio più vicino al suo centro. Gioca un po 'con le dimensioni della cella fino a quando sono stati selezionati circa 200 negozi. Ciò produrrà una spaziatura molto regolare di negozi, che potresti o non potresti desiderare. (Se questi sono veramente punti vendita, questa sarebbe probabilmente una cattiva soluzione, perché avrebbe la tendenza a scegliere negozi nelle aree meno popolate. In altre applicazioni questa potrebbe essere una soluzione molto migliore.)