Die binäre Suche hat mich enttäuscht, als ich versucht habe, sie auf die reale Welt anzuwenden. Das Szenario ist wie folgt.
Ich muss die Reichweite eines Geräts testen, das über Funk kommuniziert. Kommunikation muss schnell erfolgen, aber langsame Übertragung ist tolerierbar, bis zu einem Punkt (etwa 3 Minuten). Ich muss testen ob die Übertragung alle 200 Fuß bis zum Ausfall erfolgreich ist, bis zu 1600 Füße. Alle 200 Fuß wird ein Test durchgeführt, der 3 Minuten dauert ausführen.
Ich nahm naiv an, dass eine binäre Suche die effizienteste Methode wäre, um den Fehlerpunkt zu finden, aber betrachte eine Reisegeschwindigkeit von 200 ft / min und eine Testzeit von 3 Minuten. Wenn der Übertragungsfehler bei 500 Fuß auftritt, ist die binäre Suche nicht das effizienteste Mittel, um den Fehlerpunkt zu finden, wie unten gezeigt.
Einfach zu gehen und jeden einzelnen Punkt zu testen, hätte die Lösung früher gefunden und dauert nur 12 Minuten, während binäre Suche & amp; Testen würde 16 Minuten dauern.
Meine Frage: Wie berechnen Sie den effizientesten Weg zur Lösung, wenn die Reisezeit zählt? Wie heißt das (z. B. binäre Reisesuche, etc.)?
Die binäre Suche wird tatsächlich auf O(1)
Zugriffszeiten basiert; Es gibt wenig Sinn darin, eine verknüpfte Liste zu durchsuchen, aber [siehe Anmerkung 1], und das ist im Wesentlichen das, was Sie tun, da Sie davon ausgehen, dass nur einzelne Intervalle es wert sind, getestet zu werden. Wenn Sie nach einer genaueren Antwort suchen, würden Sie feststellen, dass die binäre Suche eine willkürliche Genauigkeit ermöglicht, auf Kosten von einem zusätzlichen Test pro Bit Genauigkeit.
Nehmen wir an, Sie wissen nicht einmal, was der Maximalwert sein könnte. Dann könntest du nicht erst in der Mitte testen, da du nicht wüsstest wo die Mitte ist. Stattdessen können Sie eine exponentielle Suche nach einem Limit durchführen (was eine Art binäre Suche nach innen ist); Sie beginnen mit dem Testen bei x
, dann 2x
, dann 4x
, bis Sie einen Punkt erreichen, der größer als das Maximum ist (das Signal erreicht nicht so weit). ( x
ist die kleinste Antwort, die Sie interessant finden; mit anderen Worten, wenn der erste Test bei x
anzeigt, dass das Signal nicht erreicht wird, hören Sie dann auf.) Am Ende dieser Phase sind Sie bei 2ix
, für eine ganze Zahl i
, und Sie werden wissen, dass die Antwort zwischen 2i-1x
und 2ix
liegt.
Jetzt können Sie tatsächlich die binäre Suche durchführen, indem Sie rückwärts um 2i-2x
gehen. Von dort aus können Sie entweder vorwärts oder rückwärts gehen, aber Sie werden definitiv 2i-3x
reisen, und die nächste Iteration werden Sie 2i-4x
fahren, und so weiter.
Also, in der ersten Phase (Suche nach einem Maximum) sind Sie zu 2ix
gelaufen und haben i
getestet. In der zweiten Phase, der binären Verfeinerung, gehst du insgesamt (2i-1-1)x
und tust i-1
-Tests. Sie werden irgendwann in d
enden, was zwischen 2i-1
und 2i
liegt. Im schlimmsten Fall haben Sie also 3d
des letzten Punkts gelaufen (und bestenfalls haben Sie 3d/2
durchschritten). ). Die Anzahl der Tests, die Sie gemacht haben, ist 2*ceil(log2(d/x)) - 1
, was innerhalb eines Tests von 2*log2(d/x)
liegt.
Unter welchen Umständen sollten Sie dann den binären Suchalgorithmus durchführen? Grundsätzlich hängt es vom Verhältnis der Laufzeit und der Testzeit und der gewünschten Genauigkeit der Antwort ab. Der einfache sequenzielle Algorithmus findet die Position d
nach d/x
Bewegungen der Größe x
und d/x
Tests; Der obige binäre Suchalgorithmus findet die Position d
, nachdem er am meisten 3d
gereist ist, aber nur um 2 log(d/x)
testet. Grob gesagt, wenn ein Test kostet mehr als das Doppelte der Kosten von Reisen d/x
, und die erwartete Entfernung ist ausreichend größer als die Genauigkeit, sollten Sie die binäre Suche bevorzugen.
In Ihrem Beispiel scheint das Ergebnis mit einer Genauigkeit von 200 Fuß angezeigt zu werden. Die Fahrzeit beträgt 1 Minute und die Testzeit beträgt 3 Minuten. Dies ist mehr als die doppelte Fahrzeit. Sie sollten also die binäre Suche bevorzugen, es sei denn, Sie erwarten, dass die Antwort in einer kleinen Anzahl von Vielfachen der Genauigkeit gefunden wird (wie es der Fall ist). Beachten Sie, dass, obwohl der binäre Algorithmus vier Tests und 1000 Fuß Weg verwendet (verglichen mit drei Tests und 600 Fuß für den sequentiellen Algorithmus), eine Verbesserung der Genauigkeit auf 50 Fuß nur vier weitere Tests und 150 Fuß Weg zum binären Algorithmus hinzufügt, während der sequentielle Algorithmus 20 Tests benötigt.
Hinweis 1: Tatsächlich könnte es sinnvoll sein, eine verknüpfte Liste unter Verwendung genau des obigen Algorithmus zu durchsuchen, wenn die Kosten des Tests hoch sind. Unter der Annahme, dass die Kosten des Tests nicht proportional zum Index in der Liste sind, ist die Komplexität der Suche O(N)
sowohl für eine lineare Suche als auch für die binäre Suche, aber die binäre Suche wird O(log N)
tests und O(N)
Schritte, während die sequentielle Suche O(N)
Tests und O(N)
Schritte ausführt. Für groß genug N ist dies egal, aber für real-Größe N könnte es eine Rolle spielen.
In Wirklichkeit kann die binäre Suche hier angewendet werden, aber mit mehreren Änderungen. Wir müssen nicht zentrieren, aber eine optimale Position zu besuchen.
%Vor%Weil wir die erste Position finden müssen, wo die Kommunikation fehlschlägt, manchmal müssen wir zurückgehen, danach kann man optimal andere Strategien verwenden
%Vor%Also, unsere Aufgabe - um einen solchen optimalen Faktor zu finden, Increase, factorDecrease, stepIncrease, stepDecrease, wird der Wert der Summe von f (failPos) minimal sein. Wie? Volles Bruteforce wird dir helfen, wenn n (Gesamtlänge / 200.0f) klein ist. Andernfalls können Sie versuchen, genetische Algorithmen oder einfach zu verwenden.
Schrittgenauigkeit = 1, Schrittgrenze = [0, n). Faktor eps - 1 / (4 * n), Faktorgrenze - [0,1).
Nun, einfacher Code (c #), um dies zu demonstrieren:
%Vor%Also einige Werte (f ++ - factorIncrease, s ++ - stepIncrease, f-- - factorDecrease):
%Vor%Abhängig davon, was Sie eigentlich optimieren möchten, gibt es möglicherweise eine Möglichkeit, ein optimales Suchmuster zu erarbeiten. Ich gehe davon aus, dass Sie die Worst-Case-Zeit nicht optimieren wollen, denn der langsamste Fall für viele Suchstrategien wird sein, wenn die Unterbrechung ganz am Ende ist, und die binäre Suche ist hier ziemlich gut - Sie gehen ohne Richtungswechsel ans Ende , und Sie machen nicht viele Haltestellen.
Sie können verschiedene Binärbäume in Betracht ziehen und vielleicht die durchschnittliche Zeit berechnen, die Sie für die Bearbeitung eines Blattes benötigen. Die binäre Suche ist eine Art von Baum, und so geht man entlang und testet, während man geht - ein sehr unausgewogener Baum, in dem jeder Knoten mindestens ein Blatt hat.
Wenn Sie einem solchen Baum folgen, beginnen Sie immer an dem einen oder anderen Ende der Linie, gehen Sie eine gewisse Distanz vor, bevor Sie eine Messung durchführen, und stoppen Sie je nach Ergebnis und Baum den Vorgang oder wiederholen Sie den Vorgang mit einer kürzeren Linie, wo du am einen oder anderen Ende bist.
Dies gibt Ihnen etwas, das Sie mit dynamischer Programmierung angreifen können. Angenommen, Sie haben das Problem für Längen von bis zu N Segmenten gelöst, so dass Sie die Kosten für die optimalen Lösungen dieser Längen kennen. Jetzt können Sie die optimale Lösung für N + 1 Segmente erarbeiten. Ziehen Sie in Betracht, die N + 1-Segmente auf N + 1-Wege in zwei Teile zu zerlegen. Berechnen Sie für jeden dieser Wege die Kosten, um zu seinem Entscheidungspunkt zu gelangen und eine Messung vorzunehmen, und addieren Sie dann die Kosten der bestmöglichen Lösungen für die zwei Abschnitte von Segmenten auf beiden Seiten des Entscheidungspunkts, möglicherweise gewichtet, um den Wahrscheinlichkeit, in diesen Abschnitten zu enden. Indem Sie diese N + 1 möglichen Wege betrachten, können Sie die beste Methode zur Aufspaltung von N + 1 Segmenten und deren Kosten ausarbeiten und weitermachen, bis Sie die beste Lösung für die Anzahl der Abschnitte gefunden haben, die Sie tatsächlich haben.
Tags und Links algorithm big-o traversal binary-search