Einfache Frage, schwierige Lösung.
Die beste Methode, die ich kenne, verwendet simuliertes Tempern (ich habe dies verwendet, um ein paar Dutzend Punkte aus Zehntausenden auszuwählen, und es lässt sich sehr gut auf die Auswahl von 200 Punkten skalieren: Die Skalierung ist sublinear), dies erfordert jedoch sorgfältige Codierung und beträchtliche Experimente sowie eine enorme Menge an Berechnungen. Sie sollten sich zunächst einfachere und schnellere Methoden ansehen, um festzustellen, ob sie ausreichen.
Eine Möglichkeit besteht darin, zuerst die Filialstandorte zu gruppieren . Wählen Sie in jedem Cluster das Geschäft aus, das dem Cluster-Center am nächsten liegt.
Eine wirklich schnelle Clustering-Methode ist K-means . Hier ist eine R
Lösung, die es verwendet.
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],]
}
Die Argumente scatter
sind eine Liste der Filialstandorte (als n x 2-Matrix) und die Anzahl der auszuwählenden Filialen (z. B. 200). Es gibt eine Reihe von Speicherorten zurück.
Als Beispiel für seine Anwendung generieren wir n = 1000 zufällig angeordnete Speicher und sehen, wie die Lösung aussieht:
# 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))
Diese Berechnung dauerte 0,03 Sekunden:
Sie können sehen, dass es nicht großartig ist (aber es ist auch nicht schlecht). Um viel besser zu werden, sind entweder stochastische Methoden wie simuliertes Tempern oder Algorithmen erforderlich, die sich wahrscheinlich exponentiell mit der Größe des Problems skalieren lassen. (Ich habe einen solchen Algorithmus implementiert: Es dauert 12 Sekunden, um die 10 Punkte mit dem größten Abstand von 20 auszuwählen. Eine Anwendung auf 200 Cluster kommt nicht in Frage.)
Eine gute Alternative zu K-means ist ein hierarchischer Clustering-Algorithmus. Probieren Sie zuerst die Methode von "Ward" aus und experimentieren Sie mit anderen Verknüpfungen. Dies erfordert mehr Rechenaufwand, aber wir sprechen immer noch von wenigen Sekunden für 1000 Geschäfte und 200 Cluster.
Es gibt andere Methoden. Sie können beispielsweise die Region mit einem regelmäßigen sechseckigen Raster abdecken und für Zellen mit einem oder mehreren Geschäften das Geschäft auswählen, das der Mitte am nächsten liegt. Spielen Sie ein wenig mit der Zellengröße, bis ungefähr 200 Geschäfte ausgewählt wurden. Dies führt zu einem sehr regelmäßigen Abstand der Geschäfte, den Sie möglicherweise möchten oder nicht. (Wenn dies wirklich Filialen sind, wäre dies wahrscheinlich eine schlechte Lösung, da die Tendenz besteht, Filialen in den am dünnsten besiedelten Gebieten auszuwählen. In anderen Anwendungen ist dies möglicherweise eine viel bessere Lösung.)