Von der Domäne unabhängige Datenstrukturen im Dibs-Projekt
1. Grundlegende Begriffe
Ein einführendes Beispiel soll die grundlegende
Begriffe beim hierarchischen Design eines Systems erklären. Gleichzeitig
sind diese Begriffe die Namen der verwendeten Klassen:
Hierbei beschreibt ein Netz das Design einer einzelnen hierarchischen
Ebene eines Systems. Die Bestandteile eines Netzes sind Komponenten,
die über Bruecken miteinander verbunden sind. Komponenten können
die Basiseinheiten sein, aus denen das System aufgebaut wird (sogenannte
BasisKomponenten), oder komplexere Einheiten, deren Aufbau wiederum
durch ein Netz charakterisiert wird (NetzKomponenten). Grundlage
eines hierarchischen Designs ist es, daß Netze auch wieder in Netze
(als NetzKomponente) eingebaut werden können. Jede NetzKomponente
stellt also eine Instanz eines Netzes dar, für das eine Beschreibung
(in Form eines Files) hinterlegt wurde. Nehmen wir das Design eines Volladdierers
als Beispiel, so wird dieser durch ein Netz beschrieben, das zwei Halbaddierer
als NetzKomponenten enthält sowie Oder-Gatter und einige Leitungen
als BasisKomponenten. Die Halbaddierer sind also Instanzen eines Netzes
Halbaddierer, während das Gatter und die Leitungen BasisKomponenten
beim Design von Schaltkreisen darstellen.
Verbindungen zwischen den Komponenten einer Hierarchieebene werden durch
Bruecken repräsentiert. Um Verbindungen von Komponenten eines
Netzes mit einer übergeordneten Hierarchieebene zu ermöglichen,
werden die Komponenten über Bruecken mit sogenannten EinAusgang-
Komponenten verbunden. EinAusgang-Komponenten sind neben den schon
vorgestellten Netzkomponenten und Basiskomponenten eine weitere Alternative
für den Typ einer Komponente. (Sie sind vergleichbar mit Pads im Schaltkreisentwurf.)
In der übergeordneten Hierarchieebene stehen äquivalent zum Pin
einer BasisKomponente für jede EinAusgang- Komponente ein Punkt zur
Verfügung, an dem die NetzKomponente mit einer anderen Komponente
über eine Bruecke verbunden werden kann und muß. Das Verbinden
von zwei EinAusgang-Komponenten miteinander, konzeptuell möglich,
da es sich um zwei Komponenten handelt, wird vom Editor unterbunden, da
dies zu Durchläufern führt, die beim Durchsuchen der hierarchischen
Struktur Schwierigkeiten bereiten. Eine Einschränkung für den
Systementwurf ergibt sich daraus nicht.
Die hierarchische Sicht auf ein System ist nicht immer gewünscht.
In solchen Fällen kann man durch eine Expansion der hierarchischen
Datenstruktur ein expandiertes oder manchmal auch flach genanntes System
erzeugen, beschrieben durch ein ExpansionsNetz. Dessen Komponenten
sind einzig BasisKomponenten, nicht aber NetzKomponenten oder EinAusgang-Komponenten.
Ursprünglich im System vorhandene NetzKomponenten werden bei der Expansion
durch das Netz ihrer Komponenten ersetzt. Bruecken zu solchen NetzKomponenten
werden mit der jeweiligen Bruecke von der entsprechenden EinAusgang-Komponente
zu einer anderen Komponente in dem Beschreibungsnetz zusammengefaßt.
Durch diesen Schritt werden EinAusgang-Komponenten eliminiert. Damit die
Information über die hierarchische Struktur des Systems bei der Expansion
nicht verloren geht, wird dabei ein StrukturBaum aufgebaut. Eine
Instanz eines Strukturbaumes entspricht einer Komponente im Netz. Handelt
es sich um eine BasisKomponente wird ein StrukturBaumBlatt erzeugt,
ist die Komponente dagegen vom Typ NetzKomponente wird ein StrukturBaumKnoten
konstruiert. Beide Klassen sind von StrukturBaum abgeleitet. Die Anzahl
der Söhne eines StrukturBaumKnotens entspricht der Anzahl der realen
Komponenten (Netz- und BasisKomponenten), die die entsprechende NetzKomponente
entält.
Für die Eingabe der Systeme wird der für CADIC entwickelte
Editor benutzt. Intern werden die dabei entstehenden CADIC-Datenstrukturen
in die oben genannten umgesetzt. Die konkrete Implementierung des hier
Beschriebenen findet man in den Files.
2. Beispiel
Zur Veranschaulichung wählen wir ein Beispiel aus der Domäne
der Tankbalastsysteme: ein System, das aus drei Tanks besteht, die mit
jeweils einen Druckmesser ausgerüstet sind.
Wir wollen von der Geometrie abstrahieren, da eine Krümmung eines
Rohres in einer schematischen Zeichnung nicht mit dem wirklichen Verlauf
übereinstimmen muß. Da sich in jedem Tank ein Druckmeßgerät
befindet, fassen wir einen Tank, sein Drucksensor und das zuführende
Rohr zu einem Netz zusammen, von dem wir dann drei Instanzen bilden.
Komponenten: {k1,k2,k3,k4}
NetzKomponenten: {k1,k2,k3}
BasisKomponenten: {k4}
Brücken: {b1,b2,b3}
Komponenten: {k1,k2,k3,k4}
NetzKomponenten: {}
BasisKomponenten: {k1,k2,k3}
EinAusgang: {k4}
Brücken: {b1,b2,b3}
In einem expandierten Netz hätte das vorgestellte System die
Form:
Komponenten: {k1.1,k1.2,k1.3,
k2.1,k2.2,k2.3k3.1,k3.2,k3.3,k4}
NetzKomponenten: {}
BasisKomponenten: {k1.1,k1.2,k1.3,
k2.1,k2.2,k2.3, k3.1,k3.2,k3.3}
Brücken: {b1,b2,b3, b1.1,b1.2,
b2.1,b2.2,b3.1,b3.2}
Dabei wurden bei der Expansion die Komponenten EinAusgang k1.4,
k2.4, k3.4 entfernt und die Brückenpaare b1.3
und b1, b2.3 und b2, b3.3 und
b3 zu den Brücken b1, b2 bzw. b3
zusammengefaßt. Außerdem wurde folgender StrukturBaum aufgebaut:
Überblick Grundlegende Begriffe
3.
Die Files
4. Die Klasse
Netz
4.1 Basisklasse(n)
4.2 Wichtige Member
-
treenode *CadicTreenode;
ist der Zeiger auf die Wurzel des
Graphen in der CADIC-Datenstruktur
-
Komponente **KomponentenZeigerFeld;
enthält Zeiger auf alle Komponenten
eines Netzes. Dabei haben die Zeiger auf die realen Komponenten (Basis-
und NetzKomponenten) geringere Indizes, als die Zeiger auf die EinAusgang-Komponenten.
-
BrueckenZeiger BrueckenZeigerFeld[MAXBRUECKENANZAHL];
enthält Zeiger auf alle Brücken
des Netzes. Der Speicherplatz hierfür wurde nicht dynamisch allokiert,
weil der Algorithmus, mit dem die Brücken jetzt konstruiert werden,
sonst zweimal durchlaufen werden müßte, zum Zählen und
zum Konstruieren.
4.3 Wichtige Memberfunktionen
-
treenode* getCadicTreenode();
Liefert die Wurzel des Netzbeschreibungsbaumes in der CADIC-Datenstruktur
zurück.
-
long getAnzahlRealKomponenten();
Liefert die Summe der Anzahlen der im Netz enthaltenen Basis- und NetzKomponenten
zurück.
-
Komponente* getKomponentenZeiger(int Nr);
Liefert den Zeiger auf die Komponente mit dem Index Nr im KomponentenZeigerFeld
des Netzes zurück.
-
EinAusgang* getEinAusgangMitNummer(int);
Um die EinAusgang-Komponenten mit den Pins der NetzKomponente (die
beim Instanziieren des Netzes entsteht) identifizieren zu können,
werden sie in CADIC-Zählweise
-
Norden von links nach rechts
-
Osten von oben nach unten
-
Westen von oben nach unten
-
Süden von links nach rechts
durchnummeriert. Die Funktion liefert diese Nummer zuück. Sie steht
in keiner Relation mit dem Index der EinAusgang-Komponente im KomponentenZeigerFeld.
-
void deleteBrueckenZeiger(Bruecke*);
Überschreibt den angegebenen BrueckenZeiger im BrueckenZeigerFeld
des Netzes mit dem letzten gültigen.
-
Komponente* CreateComponents(Netz* pNetz, instance* it, long it_key,
char *it_name);
Diese vom DDL-Compiler erzeugte Funktion erzeugt in Abhüngigkeit
vom übergebenen Namen eine Komponente des Netzes. Entspricht der Name
dem einer (dem Compiler bekannten) BasisKomponenten-Klasse, so wird deren
Konstruktor aufgerufen. Ist dies nicht der Fall, wird eine NetzKomponente
konstruiert.
-
Netz(treenode*);
Der Konstruktor bekommt als Argument
die Wurzel des Beschreibungsgraphen der CADIC-Datenstruktur (Rückgabewert
der CADIC-Funktion read_dag(char
*Name,ROOTONLY), wobei
das zweite Argument (ist ein Makro) angibt, daß nur die Wurzel geladen
werden soll).
-
Komponenteninitialisierung
Der Graph (repräsentiert durch die Wurzel des Graphen) wird nach
Komponenten durchsucht. Einen Zeiger auf die Liste von Instanzen liefert
die CADIC-Funktion get_tn_instances(treenode
*Wurzel), die
als Argument die Wurzel des Graphen bekommt. Mit der Funktion get_it_succ(instance
*aktuelle_Instanz); kann
man die Liste der Instanzen durchlaufen. Zu beachten ist, daß dabei
nur Instanzen in CADIC-Sichtweise aufgezählt werden, d.h. nur Basis-
oder NetzKomponenten. EinAusgang-Komponenten (in CADIC Pads) werden gesondert
ermittelt (siehe Initialisierung
EinAusgang-Komponenten). Für jede der so ermittelten Komponenten
wird durch die Funktion Komponente* Netz::CreateComponents(Netz*,instance*,long,char*);
eine (Basis- oder Netz-)Komponente
konstruiert.
-
Initialisierung
EinAusgang-Komponenten
Analog erhält man mit der Funktion
get_tn_first_pad(treenode
*Wurzel); den Knotenindex
des ersten Pads. Mit der Funktion get_gn_next_pad(get_tn_graph(treenode
*Wurzel),int previous_pad);
kann man die Liste aller Pads durchlaufen (das erste Argument ist ein Zeiger
auf den Cgraph
des Graphen, der durch treenode
*Wurzel repräsentiert
ist). Alle genannten Funktionen stellt CADIC zur Verfügung. Für
jedes Pad wird eine EinAusgang-Komponente konstruiert.
-
Brückeninitialisierung
Ziel der Brückeninitialisierung
ist es, bestehende Verbindungen zwischen Komponenten zu finden und unzulässige
Verbindungsteile zu markieren. Unzulässig sind Verbindungsverzweigungen,
einseitig oder beidseitig offene Verbindungen und Verbindungen zwischen
zwei EinAusgang-Komponenten (Durchläuferproblematik). Eine Verbindung
oder auch Bruecke
verbindet also genau zwei Komponenten, von denen mindestens eine kein EinAusgang
ist (siehe auch Die Klasse Bruecke).
Zu Beginn der Brückeninitialisierung
werden alle Knoten als noch nicht besucht markiert ('u' in der userdata
jedes Knotens). Alle noch nicht besuchten Knoten werden daraufhin
untersucht, ob sie zu einer Komponente gehören. Wenn nicht, werden
sie übersprungen. Falls doch wird der Knoten als besucht markiert
('b' in der userdata
jedes Knotens). Über Kanten, die keine Kanten von Komponenten
sind (erfüllen das Prädikat is_a_wire(Cgraph*,int
Kantenindex)) wird von
diesem Knoten aus eine Verbindung zu einem unbesuchten Knoten gesucht,
der zu einer Komponente gehört. Bei dieser Suche werden alle durchlaufenen
Knoten im Graphen markiert, an denen man Verbindungsverzweigungen vorfindet.
Endet die Suche bei einem schon besuchten Knoten, wird ebenfalls ein Fehler
angezeigt, da eine Brückenverzweigung an einer Komponentenkante vorliegt.
Wird die Suche bei einem Knoten beendet, der zu keiner Komponente gehört,
hat man ein offenes Ende einer Brücke gefunden. Der Endknoten wird
als fehlerhaft markiert. Für jede korrekte Verbindung wird eine Instanz
der Klasse Bruecke
konstruiert. Zum Schluß müssen noch die eingezeichneten Verbindungen
als Fehler markiert werden, die keine Komponenten verbinden. Diese haben
die Eigenschaft, daß ihre Endpunkte noch unbesuchte Knoten sind,
die sie verbindenden Kanten aber nicht zu einer Komponente gehören
(erfüllen das Prädikat is_a_wire(Cgraph*,int
Kantenindex)).
-
~Netz();
Destruktor der Klasse Netz.
4.4 Davon abgeleitete Klasse(n)
Überblick Grundlegende Begriffe
5. Die Klasse
Bruecke
5.1 Basisklasse(n)
5.2 Wichtige Member
-
Komponente* EndenKomponente[2];
enthält Zeiger auf die beiden
Komponenten, die die Brücke verbindet
-
long IndexBrZgFeld[2];
Index der Bruecke im Brueckenzeigerfeld in der jeweiligen Komponente
-
long PinNummer[2];
enthält die Nummern der Pins (nach CADIC-Zählweise)
der jeweiligen Komponente, mit dem die Brücke verbunden ist. Handelt
es sich bei der Komponente um eine NetzKomponente, ist beim Expandieren
die Nummer der EinAusgang-Komponente (Pad) gleich der Nummer des Pins an
dem die Brücke mit der NetzKomponente verbunden ist.
5.3 Wichtige Memberfunktionen
-
virtual void Verbinde( UnknownQuantity&,
UnknownQuantity&, int);
-
virtual void Setze_LGS_Zeilen(CMatrix&,
CVector&);
-
virtual int GetAnzahlLGSZeilen();
-
virtual void Init (int);
-
Komponente* getEndenKomponente(int index);
Die Instanz einer Brücke verbindet
zwei Komponenten eines Netzes, von denen mindestens eine keine EinAusgang-Komponente
ist. Diese Funktion liefert den Zeiger auf die Komponente zurück,
die den Index index
in {0,1} hat .
-
void putEndenKomponente(int,Komponente*);
Setzt den entsprechenden Komponentenzeiger
um.
-
Komponente* getAndereKomponente(Komponente*);
Um zu ermitteln, mit welcher Komponente
eine bestimmte Komponente über eine bestimmte Brücke verbunden
ist, kann die Brücke einen Zeigervergleich durchführen. Diese
Funktion liefert den Zeiger auf die verbundene Komponente zurück,
wenn ihr die aufrufende Komponente einen this*
übergibt.
-
long getPinNummer(int);
liefert die Pin-Nummer der jeweiligen
Komponente zurück. Das ist die Nummer des Pins (nach CADIC-Zählweise)
an dem die Brücke mit der Komponente verbunden ist.
-
void putPinNummer(int,long);
Beim Konstruieren der Brücke
muß die Pin-Nummer auch gesetzt werden können.
-
long getMyPinNummer(Komponente*);
Damit eine Komponente in konstanter
Zeit (man könnte natürlich auch alle Pins durchlaufen, was lineare
Zeit beanspruchen würde) erfahren kann, über welchen Pin eine
bestimmte Brücke sie mit einer anderen Komponente verbindet, braucht
man diese Funktion.
-
Bruecke(Komponente*,long,long,Komponente*,long,long);
Konstruktor der Klasse. Initialisiert
nur die wichtigen Member.
5.4 Davon abgeleitete Klasse(n)
-
keine domänenunabhängigen
Überblick Grundlegende Begriffe
6. Die
Klasse Komponente
6.1 Basisklasse(n)
6.2 Wichtige Member
-
KomponentenTyp Typ;
mögliche Komponententypen (domänenunabhängig)
sind BasisKomponente, NetzKomponente und EinAusgang
-
Netz *VaterNetz;
Zeiger auf Netz, zu dem die Komponente
gehört
-
long Nummer;
Nummer im KomponentenZeigerFeld
des Vaternetzes
-
BrueckenZeiger BrueckenZeigerFeld[MAXBRUECKENANZAHL];
Zeiger auf die Brücken im VaterNetz, die die Komponente mit anderen
verbindet
6.3 Wichtige Memberfunktionen
-
void putBruecke(long index,Bruecke* Zeiger);
trägt den Brückenzeiger
Zeiger in das Brückenzeigerfeld der Komponente mit dem Index index
ein
-
Bruecke* getBruecke(long index);
liefert einen Zeiger auf die Brücke
mit dem Index index im Brückenzeigerfeld der Komponente zurück
-
long getPinNummer(long Knotenindex);
Die Funktion liefert die Pin-Nummer
eines zur Komponente gehörenden Pins nach CADIC-Zählweise.
Die Pins müssen in derselben Reihenfolge
durchnummeriert sein, wie die EinAusgang-Komponenten innerhalb der Komponente,
also unabhängig davon, mit welcher Rotation oder Spiegelung die Komponente
ins Netz eingebaut ist. Lageveränderungen werden deswegen beim Abzählen
der Pins herausgerechnet.
-
char gehoert_dazu(Cnode);
liefert FALSE oder TRUE zurück, je nachdem, ob der übergebene
Knoten zur Komponente gehört oder nicht. Bei realen Komponenten wird
dabei direkt auf die CADIC-Datenstrukturen zugegriffen, um zu ermitteln
ob der Knoten innerhalb der geometrischen Ausdehnung der Komponente liegt.
Diese Funktion ist bei der Brückeninitialiserung
(Aufbau des Netzes) notwendig, um Verbindungen
zwischen Komponenten zu finden.
-
Komponente(Netz*,long,KomponentenTyp);
Der Konstruktor initialisiert wichtige
Member der Instanz.
6.4 Davon abgeleitete Klasse(n)
-
BasisKomponente
-
NetzKomponente
-
EinAusgang
Überblick Grundlegende Begriffe
7.
Die Klasse BasisKomponente
7.1 Basisklasse(n)
7.2 Wichtige Member
-
instance* CadicInstance;
ist ein Zeiger auf die Instanz der
Komponente in der CADIC-Datenstruktur.
-
BasisKomponentenTyp BasisTyp;
ist der domänenabhängige
Typ der BasisKomponente. Die Typdeklaration wird vom DDL-Compiler erstellt.
7.3 Wichtige Memberfunktionen
-
virtual void Eingabemaske();
-
virtual void ShowData();
-
virtual void EnterFehler();
-
virtual void ShowFehler();
-
virtual void Setze_LGS_Zeilen(CMatrix&,
CVector&);
-
virtual void SetzeFehlerStatus();
-
virtual void SetzeFehlerParameter(int,ParameterTyp,Real,Real);
-
virtual void ZeitSchritt();
-
virtual int GetAnzahlLGSZeilen();
-
virtual int GetAnzahlLGSSpalten();
-
virtual Bruecke* getBruecke(int);
-
virtual void putBruecke(long,Bruecke*);
-
virtual void Init(int,int,int,int);
-
virtual int GetAnzahlAusgaben();
-
virtual int VariablenAusgabe(double,CSystemverhalten*);
-
virtual int GetAnzahlVariablen();
-
virtual int GetAnzahlFehlerParameter();
-
virtual void GetVariablen(Variable*,int*);
-
virtual void PutVariablen(Variable*,int*);
-
virtual int GetBrueckenTyp(int);
-
virtual void SaveData(fstream*);
-
virtual void LoadData(fstream*);
-
virtual void SaveFehler(fstream*);
-
virtual void LoadFehler(fstream*);
-
virtual Bruecke* ErzeugeBruecke(Komponente*,long,int,Komponente,long,
int);
-
BasisKomponente(Netz *,instance*,long,BasisKomponentenTyp);
Konstruktor der Klasse, wird bei der Konstruktion der domänenabhängigen
(von BasisKomponente abgeleiteten) Klassen aufgerufen, initialisiert wichtige
Member
7.4 Davon abgeleitete Klasse(n)
-
keine domänenunabhängigen (aber genau eine für jede vom
DDL-Compiler ermittelte Komponentenart)
Überblick Grundlegende Begriffe
8.
Die Klasse NetzKomponente
8.1 Basisklasse(n)
8.2 Wichtige Member
-
instance* CadicInstance;
ist ein Zeiger auf die Instanz der
Komponente in der CADIC-Datenstruktur.
-
Netz* NetzBeschreibung;
ist ein Zeiger auf die Instanz des
Netzes, die den "Inhalt" beschreibt.
8.3 Wichtige Memberfunktionen
-
NetzKomponente(Netz*, instance*, long);
ist Konstruktor der Klasse. Diese
Klasse existiert nur, um das Konzept der Hierarchie sauber zu verwirklichen.
Sie bettet ein Netz als (Netz-)Komponente in ein übergeordnetes Netz
ein.
8.4 Davon abgeleitete Klasse(n)
Überblick Grundlegende Begriffe
9. Die
Klasse EinAusgang
9.1 Basisklasse(n)
9.2 Wichtige Member
-
long NodeIndex;
ist der Index des Knotens in der
Knotenliste (CADIC-Datenstruktur Cgraph), der die EinAusgang-Komponente
repräsentiert. Er wird benötigt, um bei Anwendung der Funktion
Komponente::gehoert_dazu(Cnode
node) der Basisklasse
(siehe Klasse Komponente) entscheiden
zu können, ob der Knoten node
dem der Komponente entspricht oder nicht (zur Erinnerung: EinAusgang-Komponenten
gibt es in CADIC nicht, sie haben deswegen dort auch keine geometrische
Repräsentation, wie die anderen Komponenten)
-
long EinAusgangNummer;
ist die Nummer der EinAusgang-Komponente
bezüglich des Netzes in CADIC-Zählweise.
Diese wird zur späteren Identifikation der EinAusgang-Komponente mit
einem Pin der entsprechenden NetzKomponente im übergeordneten Netz
benutzt.
9.3 Wichtige Memberfunktionen
-
EinAusgang(Netz*,long,long,long);
ist Konstruktor der Klasse. Er wird
nur beim Aufbau eines
Netzes aufgerufen.
9.4 Davon abgeleitete Klasse(n)
Überblick Grundlegende Begriffe
10.
Die Klasse ExpansionsNetz
10.1 Basisklasse(n)
10.2 Wichtige Member
-
Komponente **KomponentenZeigerFeld;
ist ein Feld von Zeigern auf die
im expandierten Netz enthaltenen BasisKomponenten (zur Erinnerung: das
Netz enthält nur noch BasisKomponenten, Netzkomponenten wurden rekursiv
durch ihre Netzbeschreibung ersetzt, wodurch EinAusgang-Komponenten überflüssig
geworden sind, das expandierte Netz als abgeschlossenes System hat keine
EinAusgang-Komponenten)
-
BrueckenZeiger BrueckenZeigerFeld[MAXBRUECKENANZAHL];
ist ein Feld von Zeigern auf die
zwischen BasisKomponenten existierenden Verbindungen (statisch allokierter
Speicher: siehe Netzaufbau)
-
StrukturBaum* StrukturBaumWurzel;
um beim expandieren des Netzes die
Information über die hierarchische Struktur nicht zu verlieren, wird
ein StrukturBaum aufgebaut. Jeder innere Knoten dieses Baumes entspricht
einer NetzKomponente, jedes Kind eines solchen Knotens einer Komponente
des Beschreibungsnetzes. In einem fertigen StrukturBaum entspricht also
jedes Blatt einer BasisKomponente. Repräsentiert wird der Baum durch
einen Zeiger auf seine Wurzel.
10.3 Wichtige Memberfunktionen
-
ExpansionsNetz(Netz*);
Der Konstruktor der Klasse bekommt als Argument einen Zeiger auf das
zu expandierende Netz. Das Netz muß ein abgeschlossenes System repräsentieren
(keine EinAusgang-Komponenten auf höchster Hierarchieebene). Dann
wird das Netz wie folgt expandiert:
-
Strukturbaumaufbau
Durch Aufruf des Konstruktors der Klasse StrukturBaum wird rekursiv
der dem Netz entsprechende StrukturBaum aufgebaut (siehe
Klasse StrukturBaum)
-
Komponenteninitialisierung
Die Blätter des Strukturbaumes werden durchlaufen und die Zeiger
auf die BasisKomponenten in das KomponentenZeigerFeld eingetragen.
-
Brückeninitialisierung
Brücken auf einer Hierarchieebene, die nicht mit EinAusgang-Komponenten
verbunden sind, müssen BasisKomponenten auf gleicher oder tieferer
Hierarchieebene (nicht aber höherer, denn wir haben Durchläufer
untersagt) verbinden. Es genügt deswegen, den Strukturbaum top-down
zu durchlaufen und auf jeder Hierarchieebene Brücken an beiden Enden
solange abwärts in der Hierarchie zu verfolgen, bis man auf eine BasisKomponente
stößt. Ins ExpansionsNetz braucht man dann nur eine Brücke,
die die gefundenen Basiskomponenten verbindet, einzutragen.
Beim Absteigen von einer Hierarchieebene zur nächsttieferen ist
es notwendig den Pin über den man in die NetzKomponente "hineingekommen"
ist mit einer EinAusgang-Komponente zu identifizieren. Hier kommt zum tragen,
daß Pins und EinAusgang-Komponenten gleich (nämlich nach CADIC-Zählweise)
durchnummeriert wurden. Eine Identifikation ist nur deswegen möglich.
Löscht man beim Hinabsteigen
in die einzelnen Hierarchieebenen die (nach dem Finden der tiefergelegenen
Basis- oder auch erstmal nur NetzKomponenten überflüssigen) Brücken
zu den EinAusgang-Komponenten auf denen man abgestiegen ist, so findet
man in jeder Hierarchieebene nur Brücken zu tiefergelegenen Komponenten
vor (zur Erinnerung: auf höchster Hierarchieebene gibt es keine Brücken
zu EinAusgang-Komponenten, weil es keine EinAusgang-Komponenten geben darf,
der StrukturBaum wird top-down abgearbeitet, d.h. auf jeder Ebene werden
erst alle Brücken abgearbeitet, bevor abgestiegen wird). Damit genügt
ein top-down Durchlauf des Baumes, um alle Brücken zu initialisieren.
Dieser kann ausgehend von der Wurzel rekursiv für alle inneren Knoten
durchgeführt werden.
Bemerkung: Da nach
der Initialisierung der Brücken die EinAusgang-Komponenten überflüssig
sind, werden sie während dieses Vorgangs gelöscht.
10.4 Davon abgeleitete Klasse(n)
Überblick Grundlegende Begriffe
11. Die
Klasse StrukturBaum
11.1 Basisklasse(n)
11.2 Wichtige Member
-
StrukturBaumTyp Typ;
gibt an ob es sich bei dieser Instanz
der Klasse um einen Knoten oder ein Blatt des Baumes handelt
-
StrukturBaum* Vorfahre;
ist ein Zeiger auf die Instanz eines
Strukturbaumes, deren Kind diese Instanz ist. Da sowohl Blätter als
auch innere Knoten einen Vorfahren haben müssen, wurde dieser Zeiger
in die Basisklasse übernommen. Bei der Wurzel des Baumes, die als
einziger Knoten keinen Vorfahren hat, aber ebenfalls eine Instanz der Klasse
StrukturBaum (genauer gesagt StrukturBaumKnoten), ist dieser Zeiger auf
NULL gesetzt.
-
int Nummer;
gibt die Nummer der Instanz auf
der jeweiligen Ebene an. Die Kinder eines Knotens mit z.B. 6 Nachfolgern
sind durchnummeriert von 0 bis 5.
-
int Tiefe;
gibt die Tiefe im StrukturBaum an,
in der die Instanz zu finden ist. Dabei hat die Wurzel die Tiefe 0.
-
int MaxTiefe;
ist die maximale Tiefe, die der
Baum an diesem Ast erreicht. Diese Größe wird bei der Breitensuche
im Baum benutzt.
11.3 Wichtige Memberfunktionen
-
virtual int getAnzahlBlaetter();
Dieser Prototyp erzwingt das Vorhandensein
der Memberfunktion in alle abgeleiteten Klassen. Grund dafür ist,
daß von jedem inneren Knoten die Anzahl der Blätter bestimmt
werden können muß. Um diese rekursiv ermitteln zu können,
muß auch jedes StrukturBaumBlatt eine solche Memberfunktion haben,
die 1 zurückliefert.
-
StrukturBaum* next(int Nummer);
ist eine Iterationsfunktion für
eine DFS im StrukturBaum, die StrukturBaumKnoten überspringt. Das
linksabsteigende Suchverfahren sucht, ausgehend von der aktuellen Position
im Baum, das nächste weiter rechts (höher, tiefer oder auf selber
Ebene) liegende StrukturBaumBlatt und liefert einen Zeiger darauf zurück.
Nummer
ist dabei die Position der zuletzt besuchten Instanz auf dieser Ebene (Member
Nummer
der Instanz). Der erste Aufruf der Funktion erfolgt mit Nummer=0 von der
StrukturBaum-Wurzel aus, jeder weitere Aufruf ist von der Art this->next(Nummer)(von
einem StrukturBaumBlatt ausgehend).
-
StrukturBaum* Next(int Nummer,int Depth);
ist eine Iterationsfunktion für
eine BFS im StrukturBaum. Hierbei werden alle Instanzen der Klasse StrukturBaum
(Knoten und Blätter) von links nach rechts durchlaufen. Ausgehend
von der aktuellen Position im Baum wird das nächste weiter rechts
liegenden StrukturBaum-Element auf derselben Ebene gesucht. Erst falls
dies nicht mehr möglich ist, wird abgestiegen. Zurückgeliefert
wird jeweils ein Zeiger auf die gefundene Instanz. Nummer
ist dabei die Position der zuletzt besuchten Instanz auf dieser Ebene (Member
Nummer
der Instanz). Depth
ist die beim Abstieg zu erreichende Tiefe (aktuelle Suchtiefe). Der erste
Aufruf der Funktion erfolgt mit Nummer=-1, Depth=1 von der StrukturBaumWurzel
aus, jeder weitere Aufruf ist von der Art Vorfahre->Next(Nummer,Depth)
(von einer beliebigen StrukturBaum-Instanz aus).
-
StrukturBaum(StrukturBaumKnoten*,int,int);
Der Konstruktor der Klasse initialisiert
wichtige Member.
11.4 Davon abgeleitete Klasse(n)
-
StrukturBaumKnoten
-
StrukturBaumBlatt
Überblick Grundlegende Begriffe
12.
Die Klasse StrukturBaumKnoten
12.1 Basisklasse(n)
12.2 Wichtige Member
-
StrukturBaumZeiger* Nachfahren;
ist ein Feld von Zeigern auf die
Nachfahren des Knotens. Da jeder StrukturBaumKnoten ein Netz des hierarchischen
Designs repräsentiert, entspricht jeder Zeiger auf einen Nachfahren
einer Komponente des Netzes.
-
Netz* Inhalt;
ist ein Zeiger auf die Instanz der
Klasse Netz, die die Hierarchieebene beschreibt, die der StrukturBaumKnoten
repräsentiert.
12.3 Wichtige Memberfunktionen
-
int getAnzahlBlaetter();
ist eine Funktion, die rekursiv
die Anzahl der Blätter an diesem Ast des Baumes bestimmt.
-
StrukturBaumKnoten(StrukturBaumKnoten*,Netz*,int,int);
ist der rekursive Konstruktor der Klasse StrukturBaumKnoten. Für
jede NetzKomponente, die in dem Netz gefunden wird, wird wieder ein StrukturBaumKnoten
konstruiert. Für jede BasisKomponente wird ein StrukturBaumBlatt konstruiert.
Ferner wird in jedem Schritt der Zeiger auf das beschreibende Netz, die
aktuelle Tiefe und die Nummer der Instanz auf dieser Ebene im Baum im Knoten
abgelegt.
12.4 Davon abgeleitete Klasse(n)
Überblick Grundlegende Begriffe
13.
Die Klasse StrukturBaumBlatt
13.1 Basisklasse(n)
13.2 Wichtige Member
-
Komponente* Contents;
ist ein Zeiger auf die Komponente,
die dieses StrukturBaumBlatt repräsentiert
13.3 Wichtige Memberfunktionen
-
StrukturBaumBlatt(StrukturBaumKnoten*,Komponente*,int,int);
ist der Konstruktor der Klasse. Er wird vom Konstruktor der Klasse
StrukturBaumKnoten aufgerufen, wenn dieser beim Absteigen in der Hierarchie
eine BasisKomponente gefunden hat. Die Argumente sind ein Zeiger auf den
Vorfahren, ein Zeiger auf die Komponente, die dieses Blatt repräsentiert,
die aktuelle Tiefe, in der sich das Blatt befindet und die Nummer der Instanz
auf dieser Ebene.
13.4 Davon abgeleitete Klasse(n)
Überblick Grundlegende Begriffe
Author: Thorsten Oelgart
Letzte Änderung: 10.12.1997