Schrift
[thread]13064[/thread]

Hash mit Arrays zu langsam - wie sortieren und suchen?

Leser: 1


<< |< 1 2 3 4 >| >> 39 Einträge, 4 Seiten
Gast Gast
 2009-01-28 14:02
#118410 #118410
Hi Leute!

Ich habe folgendes Problem:

Ich habe aus mehreren XML Files die Daten in zwei große Hash-Listen eingelesen (etwa 100.000-200.000 Werte). Die Schlüssel sind eindeutige IDs (Strings), die Werte bestehen aus jeweils einem Array, das wiederum 4 Zahlen enthält.
Etwa so:
Code (perl): (dl )
%myhash = ('ad3475' => [2.3, 4.5, 2.4, 8.9], 'ff3845' => [1.2, 2.4, 5.4, 2.0],...


Das Skript soll eine Mapping Tabelle erstellen. Dazu nehme ich momentan ein Eintrag aus dem einen Hash, gehe dann in einer Schleife durch alle Einträge aus dem zweiten hash und Suche nach dem besten Treffer. Der muss nicht gleich sein, sondern am nähsten dran. Das erreiche ich über den 4-dimensionalen euklidischen Abstand=sqrt((x1[0]-x2[0])^2 + (x1[1]-x2[1]) + ...)
x1 ist in diesem Fall das Array aus Hash 1 und x2 entsprechend das aus Hash 2. Ich muss aber inmmer die ganze Liste durch gehen, weil es ja immer noch einen besseren Treffer geben könnte. Das dauert ewig. Ich habe das mal Laufen lassen, und auf meinem Rechner würde das Mapping mit dem Algorithmus ca. 14TAGE(!!) dauern.

Ich muss mir also etwas besseres Ausdenken, und mir fällt nix ein. Es wäre schön, wenn man die eine LIste sortieren könnte und danach darin suchen könnte.
Aber mir fällt kein guter Sortieralgorithmus ein. Denn einfach nur nach dem ersten Array-Eintrag zu sortieren geht nicht, da es ja auf den eukl. Abstand Ankommt, und nicht auf die Gleichheit einzelner Werte. Hier ein Beispiel für das Problem:

Such Array: [5, 1, 1, 1]
Hash, in dem gesucht wird:
[1, 1, 1, 1] Abstand: 4
[2, 2, 2, 2] Abstand: 3,5
[3, 3, 3, 3] Abstand: 4
[4, 4, 4, 4] Abstand: 5,3
[5, 5, 5, 5] Abstand: 6,9
[6, 6, 6, 6] Abstand: 8,7

Daran sieht man, sortieren nach z.B. der ersten Zahl hätte als Ergebnis das Array [5,5,5,5] gebracht. Das Array mit dem geringsten Abstand ist allerdings [2,2,2,2].

Bitte um Hilfe!! Hat jemand eine Idee?

Gruß Jan
Struppi
 2009-01-28 15:06
#118418 #118418
User since
2006-02-17
628 Artikel
BenutzerIn
[Homepage]
user image
Das läßt sich vermutlich so allgemein nicht sagen. Kannst du ein kleines Beispiel zeigen?
Taulmarill
 2009-01-28 16:00
#118420 #118420
User since
2004-02-19
1750 Artikel
BenutzerIn

user image
Ganz einfach könnte man das ganze beschleunigen indem man Werte überspringt bei denen der lineare Abstand in einer Dimension schon größer ist als der bisher gefundene, kleinste euklidische Abstand.

... Ich weiß jetzt nicht genau, ob der obige Absatz mathematisch korrekt formuliert ist, aber ich meine auf jeden Fall schon mal das richtige :-)
$_=unpack"B*",~pack"H*",$_ and y&1|0& |#&&print"$_\n"for@.=qw BFA2F7C39139F45F78
0A28104594444504400 0A2F107D54447DE7800 0A2110453444450500 73CF1045138445F4800 0
F3EF2044E3D17DE 8A08A0451412411 F3CF207DF41C79E 820A20451412414 83E93C4513D17D2B
Hagen
 2009-01-28 16:13
#118424 #118424
User since
2007-09-06
233 Artikel
BenutzerIn
[default_avatar]
Ich bin zwar vom Verständnis noch nicht ganz durch, aber vielleicht könnte dies PDF weiter helfen.

Ist zwar 'nur' im 2D-Raum, aber das kann man bestimmt auch erweitern.
Gruß
Hagen
barney
 2009-01-28 17:05
#118431 #118431
User since
2008-08-31
131 Artikel
BenutzerIn
[Homepage] [default_avatar]
Hast du in der Abstandsfunktion mal die Quadratwurzel weggelassen?
Das sollte in der Sortierung nichts ändern, da die Wurzel stetig steigend ist.
murphy
 2009-01-28 19:06
#118444 #118444
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
Ich wuerde da einen R-Tree als Index empfehlen.
When C++ is your hammer, every problem looks like your thumb.
Gast Gast
 2009-01-28 20:43
#118447 #118447
@ Struppi:
Ähm, noch nicht Beispiel genug? :) Ich weiß nicht so recht, was du noch sehen möchtest?

@Taulmarill: Das geht eben nicht, was ich mit dem einen Beispiel zeigen wollte.

@Hagen: Wow, jep, das ist genau das Problem. Eigentlich sind meine 4 Werte auch genau 2 XY Punktepaare die ich der Einfachheit halber als 4-dim Wert behandelt habe. Ich muss mir das noch mal genau angucken, aber danke schon mal.

@ barney: Das stimmt schon. Aber die Wurzel ist IMHO nicht das Problem obwohl sie natürlich stnädig aufgerufen wird, sondern dass immer die Gesamte LIste durchgegangen wird. Das heißt also Die Abstandsberechnung wird 100.000*100.000=10.000.000.000 aufgerufen!!! Das Ziel ist es durch vorherige Sortierung und/oder einen Besseren Algorithmus das Problem zu vereinfachen.

@ murphy: Jep auch deine Lösung scheint mir dem Problem sehr nahe zu kommen. Am Besten wäre es in der Tat einen Index zu haben der sich schnell berechnen ließe, quasi ein Hash-Wert der einen 4-Dim Punkt abbildet und nicht nur exakt sondern auch Näherungswerte zulässt.

Vielen Dank euch allen! Ich wollte schon fast zu einem Mathematiker gehen, das es in der Tat einen mathematisches Problem ist. Um so dankbarer bin ich, dass ihr mir so schnell helfen konntet!

Ich werde eure Ideen umsetzen und dann berichten, was und wie ich es gemacht habe und falls es nicht geht noch mal um Rat fragen!

Gruß Jan
Struppi
 2009-01-29 01:49
#118458 #118458
User since
2006-02-17
628 Artikel
BenutzerIn
[Homepage]
user image
Sorry für meinen Kommentar. Mir war Euklid bis heute unbekannt und versuche CPAN:Tree::R gerade zu analysieren. Wenn ich das richtig verstanden habe steckt dieser Euklid in der Funktion ChooseSubTree(). Aber die Funktionsweise von QuadraticSplit() heb' ich mir für morgen auf.

Danke für den anregenden Thread.
LanX-
 2009-01-29 02:15
#118459 #118459
User since
2008-07-15
1000 Artikel
BenutzerIn

user image
Ich weiß nicht was du unter einer "Mapping-Tabelle" verstehst...

wenn dein Problem lautet: Wie kann ich die 4D-Koordinaten so sortieren, dass ich zu einem beliebigen Punkt den euklidisch nächsten Punkt möglischt schnell finden kann, hätte ich nen naiven Vorschlag:

Lege zu jeder Dimension danach sortierte Arrays A1,A2,A3 und A4 an und untersuche nur die jeweils in der Dimension nächsten Punkte. Der jeweils geringste gefundeen Abstand gibt dir dann ein Abbruchkriterium, gewisserweise einen schrumpfenden Suchradius.

In deinem Beispiel würdest du zuerst [5,5,5,5] in A1 und [1,1,1,1] in A2,A3,A4 untersuchen.
der minimal gefundene Abstand wäre dann 4. D.h. man braucht nur noch Punkte mit x1 in 1 bis 9 und x2,x3,x4 in -3 bis 5 zu untersuchen.
Dann untersuchst du die nächsten Punkt in A1-A4, also [4,4,4,4] und [2,2,2,2], dabei letzteres mit minimalem Abstand, d.h Suchradius schrumpft auf 3.5,

Der Radius pro Achse ist sogar noch kleiner, weil du weist ja jetzt dass ein minimales Ergebnis in den Achsen 2, 3 und 4 mindestens einen Abstand von 1 hat, weil [2,2,2,2] einen kleineren Abstand als alle vorherigen Punkte in diesen Achsen hatte.

D.H der Suchradius in Achse 1 schrumpft auf sqrt(12-1²-1²-1²)=3

Gerade das letzte Argument mit dem Mindestabstand sollte helfen den Suchradius schnell schrumpfen zu lassen, sodass die Suche auch schnell beendet wird.

Das ist bestimmt nicht so effizient wie R-Trees wird aber leichter zu proggen sein und keine 14 Tage brauchen.

Also ich merk gerade das man das mathematisch sauberer hinschreiben könnte, aber ich hoffe die Idee wird klar ohen dass ich den kompletten Code hinschreiben muss.

Natürlich müsstest du die Arrays A1-A4 auch bzgl der anderen Achsen sortieren, lexikografisch gewissermaßen.
LanX-
 2009-01-29 02:37
#118460 #118460
User since
2008-07-15
1000 Artikel
BenutzerIn

user image
Struppi+2009-01-29 00:49:50--
Mir war Euklid bis heute unbekannt und versuche CPAN:Tree::R gerade zu analysieren.


Euklidischer Abstand ist nichts anderes als der triviale Abstand im (euklidischen) Anschauungsraum (also so wie man's "kennt") und das mit nem verallgemeinerten Pythagoras ausgerechnet.
Im R² trivialerweise der normale Pythagoras also Abstand²=delta_x²+delta_y².

Mathematiker kennen halt diverse Räume und Abstandsbegriffe, deswegen ziehen sie den Schöpfer der antiken Geometrie zur Bezeichnung des "trivialen Falles" heran.

R-Trees teilen den Raum schrittweise in immer kleinere Teilräume auf, z.B. den R² in 4 Quadranten um den Mittelpukt im ersten Schritt dann diese wiederum in Quadranten usw. Im R³ wärens dann entsprechend 8 Quader usw. Die Idee ist dabei im Suchbaum nur noch wenige Quadranten weiter unterteilen zu müssen, weil der Suchradius schnell schrumpft und entfernte Quadranten fix ausschließt.

Ich denke R-Trees sind wahrscheinlich cleverer als einfach nur mittig zu teilen, aber ich hoffe die Idee wird klar.
EDIT: Schau an der von mir beschriebene Sonderfall ist als Quadtree bei WP bekannt!
<< |< 1 2 3 4 >| >> 39 Einträge, 4 Seiten



View all threads created 2009-01-28 14:02.