Autor |
Beitrag |
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 13.05.09 12:26
Irgendwo häng ich grad ein wenig.
Ich habe ein Bitfeld, welches NICHT in ein Register passt (4*32*32*3 Einträge), wobei es eine Hierarchische Ordnung gibt, um gesetzte Bits schneller zu lokalisieren. d.h. jeder Bitfeld kann als Knoten in einem Baum aufgefasst werden, welches angibt, welche Kindknoten existieren. Im Speicher gibt es dazu aber nur 4 Arrays: Für jede Ebene eines.
Also wenn in Knoten 2-0-3 Eintrag 1 gesetzt ist, sieht das etwa so aus (weitere Einträge sind vorhanden):
Delphi-Quelltext 1: 2: 3: 4:
| Ebene 1: 1100 Ebene 2, Eintrag für 2: 00000111 00000000 00000000 00000001 Ebene 3, Eintrag für 2-0: 00000000 00000000 01011110 00101000 Ebene 4, Eintrag für 2-0-3: 010 |
Speichertechnisch liegt Ebene 4 als 3 Bitsets vor, aus denen Ebene 3 dynamisch generiert wird. Die Priorität funktioniert dort aber ähnlich.
Was ich nun suche ist eine elegente Möglichkeit, dass wenn mehrere Bits gesetzt sind, ich bestimmte (niederwertige Bits) ignorieren kann, um immer in einem Zyklus durchzugehen... D.h. dass wenn der letzte Eintrag, der gelesen wurde aus dem Bitfeld, Eintrag 2-1-0-1 war, mindestens 2-1-0-2 folgen muss, selbst wenn auch 0-0-0-0 gesetzt wäre (sei denn, dort gibt es keinen gesetzten Eintrag mehr, dann von vorne). Irgendwo häng ich da mit der Logik grad ...
Zum Lesen der Bitfelder hab ich Funktionen, die immer das LSB, liefern, bzw. mir Bitmasken generieren. For-Schleifen sind IMHO nicht nötig, daher zu vermeiden.
Soweit ich das überblicke, müsste das in Linearzeit möglich sein.
Bisher hab ich aber leider nur den Ansatz für den ersten Eintrag der Liste (im obigen Beispiel also laut Beispiel 2-0-3-1. Wäre 2-0-0-0 gesetzt, würde mir der folgende Algo diesen Liefern (wenn die Leseposition aber 2-0-3-0 anzeigt, darf frühstens dieser auftauchen).
Hier mal ein Beispiel für das Lesen (des frühsten) möglichen (unabhängig vom Lesezeiger):
Delphi-Quelltext 1: 2: 3: 4:
| e[0]:=log2(getlsb(data.e0)); e[1]:=log2(getlsb(data.e1[e[0]])); e[2]:=log2(getlsb(data.e2[e[0]][e[1]])); e[3]:=log2(getlsb(data.e3[e[0]][e[1]][e[2]])); |
Wo ich jetzt nicht weiterkomme ist, wie ich welche Bits vorübergehend ausblenden muss, damit ich die Positionsanzeige korrekt erhalte. data darf nicht verändert werden.
Bin über jegliche Tipps dankbar.
Bei Alternativvorschlägen: Müssen konstanten Speicherverbrauch haben UND echtzeitfähig sein.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Thorsten83
      
Beiträge: 191
Erhaltene Danke: 1
|
Verfasst: Mi 13.05.09 15:58
Bin mir gerade nicht ganz sicher ob ich das Problem richtig verstanden habe, ich fass es mal zusammen:
In der untersten Ebene stehen die Bits, die dich interessieren (12288 Stück)
Die Ebene darüber hat weniger Bits (4096), jedes davon bedeutet, dass von den 3 darunter liegenden Bits eines gesetzt ist, oder nicht (Also bits[n] = bits[3*n] | bits[3*n + 1] | bits[3*n + 2]).
Du willst jetzt durchgehen, und rausfinden, welche Bits der unteren Ebene gesetzt sind?
|
|
BenBE 
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 13.05.09 18:22
Könnte man grob so umschreiben, wobei ich nicht ein beliebiges Bit herausfinden will von der ersten Ebene, sondern das erste Bit links (oder gleich) dem Bitzeiger. (Wibei die Anzahl Bits und die Struktur konfigurierbar ist in gewissen Maßen, das Layout sieht nur etw so aus).
Nehmen wir einfach mal an, unser Bitfeld wäre etwas kleiner (Pro Ebene nur jeweils 2 Bit:
Quelltext 1: 2: 3: 4: 5:
| Position: FEDCBA9876543210- Ebene 1: 0 1- Ebene 2: 0 0 1 1- Ebene 3: 0 0 0 0 0 1 1 0- Ebene 4: 0000000000100100- |
d.h. Bit 2 und 5 sind derzeit gesetzt. Wie kann ich nun möglichst effizient das nächste Bit herausfinden, wenn der aktuelle Zeiger auf Bit 3 steht (Korrekte Antwort des Algo muss Bit 5 sein)?
(Allgemein: Das Bit mit der kleinsten Bitnummer >= Zeigerposition)
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Mi 13.05.09 22:29
Einfacher inorder Durchlauf.
Wenn du bei Bit 3 bist alle in der ebene links davon verarbeiten und schaun ob 1, wenn nciht ebene höher und dort durchgehen Bis 1. falls icht gefunden wieder höher usw. wenn gefunden wieder wurzel verarbeiten etc.
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
Thorsten83
      
Beiträge: 191
Erhaltene Danke: 1
|
Verfasst: Do 14.05.09 01:08
uall@ogc hat folgendes geschrieben : | Einfacher inorder Durchlauf.
Wenn du bei Bit 3 bist alle in der ebene links davon verarbeiten und schaun ob 1, wenn nciht ebene höher und dort durchgehen Bis 1. falls icht gefunden wieder höher usw. wenn gefunden wieder wurzel verarbeiten etc. |
Ist eine Lösung, funktioniert aber nur, wenn es ausreicht, eine Liste mit den abzuarbeitenden Bits zu erstellen.
Alternativ einfach eine Warteschlange?
Ich gehe mal davon aus, dass die Anzahl der 1-Bits relativ gering ist, sonst würdest du das wohl kaum so aufwendig machen, oder?
Vorteil: enqueue/dequeue in O(1), Speicherbedarf O(n).
Ansonsten ist halt auch die Frage: was passiert, wenn du das nächste 1-Bit suchst, aber keines findest? Durchläufst du den Baum immer wieder? Sowas kann eine SPS z.B. zum Abschmieren bringen, wenn die neuen Daten nicht per Interrupt reinkommen...
|
|
BenBE 
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 15.05.09 09:49
Regelfall ist durchaus, dass nur sehr wenige Bits gesetzt werden. Sind keine Bits gesetzt, lässt sich dies direkt in der obersten Ebene abfangen.
Ganz O(n) ist der Speicherbedarf durch die Baumstruktur nicht; würde das eher als "zwischen O(n) und O(n*log(n))" beschreiben.
Derzeit hab ich erstmal eine Lösung umgesetzt, die statt einem Overflow nur die Positionsänderung bewirkt, sonst aber kein Element unqueued. Das ist für meinen Fall durchaus auch akzeptabel.
Wo ich aber noch unsicher bin ist die Frage bzgl. dem "Ebene hoch und nächstes Element" inwiefern man da u.U. Code sparen kann, so dass man nicht alle 15 Cases vollständig ausprogrammieren muss (Case 16 ist "kein Bit gesetzt").
@Baum-Traversierung: Ja, derzeit schon. Daher such ich ja eine Effiziente Lösung, mit der ich das auf ein Minimum beschränken kann.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
|