Wie wähle ich eine Teilmenge von Punkten mit einer regelmäßigen Dichte? Formaler,
Gegeben
dist
(z. B. Euklidische Entfernung), Wie kann ich eine kleinste Teilmenge B auswählen, die unten erfüllt?
dist(x,y) <= d
Mein derzeitiger bester Schuss ist
und wiederholen Sie den gesamten Vorgang für das beste Glück. Aber gibt es bessere Wege?
Ich versuche das mit 280.000 18-D-Punkten zu machen, aber meine Frage ist in der allgemeinen Strategie. Ich möchte also wissen, wie man das mit 2-D-Punkten macht. Und ich brauche nicht wirklich eine Garantie für eine kleinste Teilmenge. Jede nützliche Methode ist willkommen. Danke.
y
, für die min(d(x,y) for x in selected)
am größten ist Ich nenne es Bottom-Up und den, den ich ursprünglich von oben nach unten gepostet habe. Dies ist am Anfang viel schneller, also sollte für spärliche Stichproben das besser sein?
Wenn keine Garantie der Optimalität erforderlich ist, können diese beiden Indikatoren meiner Meinung nach nützlich sein:
max {y in unselected} min(d(x,y) for x in selected)
min {y in selected != x} min(d(x,y) for x in selected)
RC ist minimal erlaubt d und es gibt keine absolute Ungleichheit zwischen diesen beiden. Aber RC <= RE
ist wünschenswerter.
Für eine kleine Demonstration dieses "Leistungsmaßes" habe ich 256 2-D-Punkte erzeugt, die gleichmäßig oder normal verteilt sind. Dann habe ich meine Top-Down- und Bottom-Up-Methoden mit ihnen versucht. Und das habe ich bekommen:
RC ist rot, RE ist blau. X-Achse ist die Anzahl der ausgewählten Punkte. Hast du gedacht, Bottom-Up könnte genauso gut sein? Ich dachte mir, ich schaue mir die Animation an, aber es scheint, dass Top-Down deutlich besser ist (schau dir die spärliche Region an). Nichtsdestotrotz nicht zu schrecklich, da es viel schneller ist.
Hier habe ich alles gepackt.
Ein genetischer Algorithmus kann hier wahrscheinlich gute Ergebnisse liefern.
update :
Ich habe ein wenig mit diesem Problem gespielt und das sind meine Ergebnisse:
Eine einfache Methode (nennen wir es Zufallsauswahl), um eine Menge von Punkten zu erhalten, die die angegebene Bedingung erfüllen, ist wie folgt:
Ein kd-Baum kann benutzt werden, um die Suche in Schritt 3 relativ schnell durchzuführen.
Die Experimente, die ich in 2D durchgeführt habe, zeigen, dass die generierten Teilmengen etwa halb so groß sind wie die, die von Ihrem Top-Down-Ansatz generiert werden.
Dann habe ich diesen Random-Selection-Algorithmus verwendet, um einen genetischen Algorithmus zu erzeugen, der zu einer weiteren 25% igen Reduktion der Größe der Teilmengen führte.
Für die Mutation, indem ich ein Chromosom gebe, das eine Teilmenge B darstellt, wähle ich zufällig einen Hyperball innerhalb der minimalen Achse-ausgerichteten Hyperbox, die alle Punkte in A abdeckt. Dann entferne ich alle Punkte, die sich auch im Hyperball befinden Verwenden Sie die Zufallsauswahl, um es erneut zu vervollständigen.
Beim Crossover verwende ich einen ähnlichen Ansatz und verwende einen zufälligen Hyperball, um die Mutter- und Vaterchromosomen zu teilen.
Ich habe alles in Perl mit meinem Wrapper für GAUL Bibliothek (GAUL kann von hier bezogen werden.
Das Skript ist hier: Ссылка
Es akzeptiert eine Liste von n-dimensionalen Punkten von stdin und erzeugt eine Sammlung von Bildern, die die beste Lösung für jede Iteration des genetischen Algorithmus zeigt. Das Begleitskript Ссылка kann verwendet werden, um die zufälligen Punkte mit a zu erzeugen gleichmäßige Verteilung.
Sie können Ihr Problem mit Graphen modellieren, Punkte als Knoten annehmen und zwei Knoten mit Kante verbinden, wenn ihre Entfernung kleiner als d ist. Jetzt sollten Sie die Mindestanzahl von Scheitelpunkten finden, so wie sie sind mit ihren verbundenen Knoten decken alle Knoten des Graphen, dies ist minimale Vertex Abdeckung Problem (die NP-Hard im Allgemeinen ist), aber Sie können schnelle 2-Approximation verwenden: wiederholt beide Endpunkte einer Kante in die Eckenabdeckung und entfernt sie dann aus dem Graph.
P.S: sicher, dass Sie Knoten auswählen sollten, die vollständig vom Graphen getrennt sind. Nachdem Sie diese Knoten entfernt haben (dh sie ausgewählt haben), ist Ihr Problem die Vertex-Abdeckung.
Hier ist ein Vorschlag, der eine Annahme der Manhattan-Distanz-Metrik macht:
Tatsächlich muss die Implementierung keine wirkliche Arbeit leisten, um Schritt eins zu machen, und Schritt zwei kann in einem Durchgang durch die Punkte ausgeführt werden, wobei ein Hash der Partitionskennung (der (floor (x1 / d) , ..., floor (xn / d))), um zu überprüfen, ob wir bereits einen Vertreter für einen bestimmten Rasterraum ausgewählt haben, dies kann sehr, sehr schnell erfolgen.
Einige andere Entfernungsmetriken können möglicherweise einen angepassten Ansatz verwenden. Zum Beispiel könnte die euklidische Metrik d / sqrt (n) -Größe verwenden. In diesem Fall möchten Sie möglicherweise einen Nachbearbeitungsschritt hinzufügen, der versucht, die Deckung ein wenig zu reduzieren (da die oben beschriebenen Gitter nicht mehr genau die Kugeln mit Radius-d sind - die Kugeln überlappen benachbarte Gitter etwas), aber ich ' Ich bin mir nicht sicher, wie dieser Teil aussehen würde.
Um faul zu sein, kann dies auf ein Set-Cover-Problem geworfen werden, das von gemischt-ganzzahligen Problemlösern / Optimierern gehandhabt werden kann. Hier ist ein GNU MathProg-Modell für den GLPK LP / MIP Solver. Hier bezeichnet C
, welcher Punkt jeden Punkt "erfüllen" kann.
Bei normal verteilten 1000 Punkten hat es nicht die optimale Teilmenge in 4 Minuten gefunden, aber es sagte, dass es das wahre Minimum kannte und es wählte nur einen weiteren Punkt aus.