[Top] [Prev] [Next] [Bottom]
Diese Arbeit ist Teil der Dissertationen unter http://www2.chemie.uni-erlangen.de/services/dissonline/


8. Realisierung der RICOS-Repräsentation mit einem objektorientierten Modell

Das vorgestellte Modell zur Repräsentation von chemischen Strukturen wurde mit objektorientierten Methoden implementiert. Diese Entscheidung wurde stark durch die Erfahrungen beeinflußt, die in der Arbeitsgruppe mit der Entwicklung der Programmsysteme EROS, FRANZ und MASSIMO gemacht wurden. Diese Programmsysteme wurden mit prozeduralen Sprachen wie Fortran und C programmiert. Ihr Weiterentwicklungen führten dazu, daß ihr Management immer schwieriger wurde. Jede Änderung der zu Grunde liegenden Datenstruktur, die erforderlich war, um neue Bedürfnisse zu befriedigen, zog eine große Anzahl von Änderungen im gesamten System nach sich. Die Integration der hier vorgestellten Repräsentation von chemischen Strukturen wäre nur unter sehr großem Aufwand möglich gewesen.

Daher wurde ein neues Design dieser Programmsysteme erstellt, das auf RCIOS als grundlegender Molekülrepräsentation basiert. Die folgenden Ziele waren für die Entscheidung, eine objektorientierte Klassenbibliothek zu entwickeln, verantwortlich. Die Bibliothek sollte einfach zu benutzen, flexibel und gut wartbar sein. Dies wurde durch den Einsatz von objektorientierten Techniken wie Abstraktion, Kapselung, Vererbung und Polymorphismus erreicht. Ein kurzer Überblick über diese Techniken wird in Kapitel 8.1 gegeben.

Die Klassenbibliothek wurde mit der Programmiersprache C++ implementiert. Sie wurde auf einer Sun-Workstation mit den Compilern von Sun, C++ V. 4.1, und von Gnu, g++ V. 2.7.0, entwickelt. C++ wurde gewählt, da es sich zügig zum de facto Standard für kommerzielle Programmierung entwickelt. Zudem kann C++ mit Fortran oder C gemischt werden. Es ist also in der Übergangsphase möglich, nützliche Module der existierenden Programmsysteme zu integrieren, ohne sie sofort neu implementieren zu müssen. Außerdem erlaubt C++ auch die Optimierung zeitintensiver Teile der Bibliothek.

8.1. Grundbegriffe

Im folgenden werden die wichtigsten Grundbegriffe zu objektorientiertem Programmieren mit C++ erklärt. Lehrbücher, die sich mit dieser Thematik ausführlich beschäftigen, sind [72] , [73] , [74] . Die Entwicklung von objektorientierten Programmen verläuft in der Regel in einem Zyklus aus drei Stufen, Analyse, Design und Programmierung, der mehrfach durchlaufen und dabei verfeinert wird. Während der Analyse wird nach allgemeinen Konzepten, die das zu modellierende System beschreiben, gesucht. Für jedes gefundene Konzept werden dessen notwendige Eigenschaften und Verhaltensweisen sowie seine Beziehungen zu anderen Konzepten bestimmt. Hierbei wird nur die Sprache der zukünftigen Anwendung verwendet, jedoch noch nicht überlegt, wie diese Konzepte in einer Computersprache realisiert werden können. Im zweiten Schritt, dem Design, werden aus den Konzepten Klassen entwickelt und so verändert, daß sie einer Repräsentation mit dem Computer zugänglich werden. Zuletzt werden die Klassen mit einer objektorientierten Programmiersprache implementiert.

Während des Designs soll jedoch nicht nur das gestellte Problem modelliert werden, sondern es muß auch darauf geachtet werden, daß die entwickelten Klassen möglichst flexibel und erweiterungsfähig sind. Denn in der Regel ändern sich die Anforderungen an ein Softwaresystem im Laufe der Benutzungszeit. Dazu stehen die im folgenden beschriebenen Techniken zur Verfügung, die speziell dazu ausgelegt sind, diese Anforderungen zu gewährleisten. Sie werden an einem einfachen Modell für Moleküle verdeutlicht.

Eine Klasse besteht aus einem Datenbereich, in dem die Attribute des zu modellierenden Konzepts abgelegt werden, und einem Satz an Funktionen, die das Verhalten der Klasse bestimmen. Zudem werden die Daten und Funktionen in zwei logische Bereiche unterteilt, einen privaten Bereich, und einen öffentlichen Bereich. Der öffentliche Bereich ist allen Benutzern zugänglich und enthält das Funktionsinterface , welches das Verhalten der Klasse in Bezug auf andere Klassen festlegt. Der private Bereich enthält meist die Attribute der Klasse sowie die Implementation der Funktionen. Diese Trennung von Interface und Implementation nennt man Kapselung . Sie erlaubt es, die Implementation der Funktionalität einer Klasse während des Designprozesses zu verändern, ohne jedoch gleichzeitig das Interface mitzuverändern. So wird gewährleistet, daß sich ein Anwender darauf verlassen kann, daß sich ein Interface nur selten ändert. Ein zweiter Vorteil der Kapselung ist, daß sich der Anwender einer Klasse nicht mit den Implementationsdetails befassen muß. Er muß also weniger über eine Klasse lernen als in prozeduralen Programmiersprachen, wo eine Anwendung nur selten unabhängig von der Implementation möglich ist, und kann sich daher in kürzerer Zeit mit der Klassenbibliothek vertraut machen. Eine Klasse für Moleküle, die aus Atomen und Bindungen bestehen, wird in ihrem Interface Funktionen enthalten, die Auskunft über die Zahl der Atome oder Bindungen aus denen das Molekül besteht, geben. Dabei ist es nicht notwendig, zu wissen, wie diese Information bestimmt wird, ob sie aus einem Datenelement gelesen wird oder bei jeder Abfrage neu berechnet wird, solange die entsprechenden Funktionen immer gültige Werte liefern.

Es gibt drei Arten von Beziehungen zwischen Klassen, die zusammen entwickelt werden, Komposition , Verwendung und Vererbung .

In komplexen Systemen gibt es meist Grundbausteine, die immer wieder miteinander kombiniert werden, um verschiedene größere Einheiten zu bilden. Solche Beziehungen werden durch Komposition modelliert. Objekte einer Klasse, die aus mehreren Komponenten zusammengesetzt werden sollen, können Objekte von anderen Klassen enthalten, die diese Komponenten repräsentieren. Dabei können die Klassen, die die Grundbausteine repräsentieren, immer wieder verwendet werden, um neue Klassen zu bilden. So sind Atome die Grundbausteine von Bindungen und Molekülen. Sie könnten aber auch in anderem Zusammenhang als Bausteine eines Salzkristallgitters oder einer Legierung dienen.

Als Verwendung wird bezeichnet, wenn Objekte einer Klasse Objekte einer anderen Klasse zwar verwenden, um ein bestimmtes Verhalten zu erzielen, sie jedoch nicht durch Komposition enthalten.

Bei der Analyse des zu modellierenden Problems werden oft zunächst allgemeine Konzepte entwickelt, die als Grundlage für vefeinerte Modelle dienen. Vererbung ist die Methode, diese Beziehungen mit Klassen zu verwirklichen. So enthält eine allgemeine Klasse, eine sogenannte Basisklasse, die Daten und Funktionen, die dem allgemeinen Konzept entsprechen. Von ihr können durch Vererbung verschiedene Klassen abgeleitet werden, die zusätzliche Datenelemente und Funktionen zur Behandlung der speziellen Lösungen bieten. Sie erhalten gleichzeitig automatisch auch das Interface der Basisklasse. So können zwei Effekte erzielt werden. Einerseits wird schon entwickelter Code der Basisklasse wiederverwendet, andererseits ist es vorteilhaft, wenn miteinander verwandte Klassen das gleiche Interface besitzen, da sie dann einfacher zu verwenden sind. In Modellen, die Moleküle beschreiben, werden oft verschiedene Bindungstypen verwendet. Es ist dann sinnvoll, eine Basisklasse für Bindungen zu entwickeln, deren Interface die Behandlung der in der Bindung enthaltenen Atome und Elektronen beschreibt. Davon abgeleitete Klassen für spezielle Bindungstypen wie - oder -Bindungen können nun zusätzliche Funktionen definieren.

Beim Design von Basisklassen werden häufig sogenannte virtuelle Funktionen entwickelt. Dies sind Funktionen, die von abgeleiteten Klassen überschrieben werden können. Das bedeutet, für eine abgeleitete Klasse kann eine virtuelle Funktion so implementiert werden, daß der spezielle Typ der abgeleiteten Klasse berücksichtigt wird, um die gewünschte Funktionalität zu erhalten. Die Implementation der Basisklasse für diese Funktion wird dann für alle Objekte der abgeleiteten Klasse nicht mehr berücksichtigt. Wenn in einer Anwendung Objekte der Basisklasse referenziert werden und deren virtuelle Funktionen aufgerufen werden, dann wird das gewünschte Ergebnis auch dann erzielt, wenn zum Zeitpunkt des Designs noch nicht alle abgeleiteten Klassen bekannt sind. Denn diese neu eingeführten Klassen können die virtuellen Funktionen der Basisklasse ebenfalls überschreiben. Die Anwendung selbst muß aber nicht geändert werden. Diese Technik wird Polymorphismus genannt. Sie ist einer der großen Pluspunkte von objektorientierten Programmiersprachen, da sie es erlaubt, daß neu eingeführte Subklassen in ein Anwendungsprogramm integriert werden können, ohne daß es stark geändert werden muß. Dies vereinfacht die Handhabung von großen Programmen sehr, da Änderungen nur noch an wenigen Stellen durchgeführt werden müssen. Eine Klassenfunktion einer Basisklasse für Bindungen, die verantwortlich ist, eine Bindung zu zeichnen, sollte virtuell sein und von jeder abgeleiteten Klasse überschrieben werden. - und -Bindungen haben eine unterschiedliche Gestalt, die dann jeweils beim Aufruf dieser Funktion gezeichnet wird. Wenn nun ein Programm zur Darstellung von Molekülen entwickelt werden soll, ist es sinnvoll, beim Zeichnen von Bindungen nur Referenzen auf die Basisklasse zu verwenden. Falls später neue Bindungstypen entwickelt werden, müssen für diese die Zeichenroutinen ebenfalls überschrieben werden. Aber das Programm zum Zeichnen der Moleküle braucht nicht verändert werden, da durch den Einsatz von Referenzen auf die Basisklasse und virtueller Funktionen zum Zeichnen von Bindungen auch die neu eingeführtem Bindungen automatisch richtig gezeichnet werden.

Eine Besonderheit von C++ im Vergleich zu anderen objektorientierten Programmiersprache sind die sogenannten Templates . Sie stellen die Implementation eines häufig verwendeten Konzepts zur Verfügung, in dem jedoch der Datentyp, auf den das Konzept angewendet wird, nicht spezifiziert ist. Templates werden häufig zur Verwaltung von mehreren Objekten einer Klasse verwendet, z. B. in Arrays, Listen oder Graphen.

Die Abbildungen zur Erläuterung der Beziehungen zwischen Klassen in den folgenden Abschnitten verwenden die von Booch [73] entwickelten Symbole. Eine kurze Übersicht über diese Symbole zeigt Anhang C .

8.2. Allgemeine Klassen

In diesem Abschnitt werden allgemeine Klassen vorgestellt, die für die Entwicklung der Klassen zur Repräsentation chemischer Information als Grundlage dienten, selbst aber universell auch in anderen Bereichen einsetzbar sind. Sie gehören nicht zu den Standardklassen, die allgemein mit jedem Compiler mitgeliefert werden, und werden daher extra erläutert. Die meisten dieser Klassen sind sogenannte Containerklassen. Containerklassen dienen dazu, bestimmte Modelle zur Speicherung von Objekten zur Verfügung zu stellen. Sie enthalten Methoden zur Speicherung und zum Zugriff auf Objekte des gleichen Typs, sind jedoch allgemein auf beliebige Klassen anwendbar. Sie sind meist als Templates realisiert.

In Tabelle 8-1 ist eine Übersicht der verwendeten Containerklassen gegeben.

Außer diesen Containerklassen wurden noch zwei allgemeine Klassen für Datentypen verwendet. Da zum Zeitpunkt des Beginn der Entwicklung noch keine standardisierte Klasse zur Behandlung von Charakterarrays als Strings erhältlich war, wurde die String Klasse der C++-Klassenbibliothek von Gnu [75] verwendet. Eine weitere Klasse, e_bit64, implementiert die betriebsystemunabhängige Bitvektoren der Länge 64 und stellt die entsprechenden logischen Operatoren zur Verfügung.

Tab. 8-1: Übersicht über verwendete Containerklassen.

Art des Containers Klassenname Beschreibung, Bedingung
einfach verkettete Liste e_Slist<T> Objekte vom Typ T
e_Splist<T> Zeiger auf Objekte vom Typ T
assoziativer Array e_Map<K,V> Objektpaare mit Objekten vom Typ K als Schlüssel und Objekten vom Typ V als Werte
Array vector<T> beliebige Objekte vom Typ T (nicht nur double, int)
Beginn des Laufindex bei 0
e_varlb_vector<T> Unter- und Obergrenze des Bereichs frei wählbar
zweidimensionaler Array e_matrix<T> beliebige Objekte vom Typ T Beginn der Laufindices bei 0
dreidimensionaler Array e_3dim_array<T> beliebige Objekte vom Typ T Beginn der Laufindices bei 0

8.3. Klassenhierarchie der Hauptklassen

In Kapitel 4 wurden die Komponenten, aus denen sich ein Ensemble zusammensetzen kann, vorgestellt. Es besteht aus Aggregaten und Molekülen, die sich ihrerseits aus Atomen, Elektronensystemen und Wechselwirkungs- bzw. topologischen Gruppen zusammensetzen. Diese chemischen Begriffe wurden nun als Grundlage zur Entwicklung der Klassen genommen, mit denen RICOS implementiert werden soll. Tabelle 8-2 zeigt die Namen der Klassen, die für die jeweiligen Begriffe definiert wurden.

Tab. 8-2: Namen der Klassen, die zur Implementation von RICOS entwickelt wurden.

Chemischer Begriff Klassenname
Ensemble ds_ensemble
Aggregat ds_aggregate
Molekül ds_molecule
Atom ds_atom
Elektronensystem ds_elecsys
-Elektronensystem ds_sigmasys
-Elektronensystem ds_pisys
koordinative Bindung ds_coordsys
Gruppe ds_group
Nachbaratompaare ds_neighbors

Ensembles, Aggregate, Moleküle und Atome wurden jeweils direkt in Klassen umgesetzt. Für Elektronensysteme wurde eine gemeinsame Klasse, ds_elecsys, entwickelt, von der drei Klassen zur Beschreibung der speziellen Elektronensystemtypen abgeleitet wurden. Wechselwirkungsgruppen und topologische Gruppen wurden zu einer gemeinsamen Klasse zusammengefaßt. Zusätzlich zu den zuvor vorgestellten Konzepten wurde noch eine Klasse ds_neighbors definiert, die jeweils ein Paar benachbarter Atome zusammenfaßt. All diese Klassen haben jedoch Gemeinsamkeiten. Um diese nicht mehrfach implementieren zu müssen, wurden zwei Basisklassen gebildet, von denen alle Klassen aus Tabelle 8-2 abgeleitet wurden. Die Klasse ds_chem_obj beinhaltet die Funktionen, die die allgemeinen Aufgaben aller chemischen Klassen erfüllen, die Klasse ds_chem_obj_w_groups ist von ihr abgeleitet und enthält zusätzlich Funktionen, die sich mit der Behandlung von Gruppen befassen. Die gesamte Vererbungshierarchie ist in Abbildung 8-1 dargestellt. Die Basisklasse ds_chem_obj befindet sich an der Spitze, Subklassen sind jeweils durch einen Pfeil mit ihrer Basisklasse verbunden.

Abb. 8-1: Vererbungshierarchie der chemischen Klassen.

Die chemischen Klassen werden verwendet, um die Konnektivität und Assoziation von Molekülen zu beschreiben. Viele Programme nutzen aber nicht nur diese Information, sondern auch physikochemische Eigenschaften der Atome, Elektronensysteme oder Moleküle zur Lösung der gestellten Aufgaben. Es ist daher notwendig, eine Möglichkeit zur allgemeinen Behandlung von Eigenschaften eines chemischen Objektes zur Verfügung zu stellen. Da für alle chemischen Klassen Eigenschaften berechnet werden sollen, die Art und Menge der verwendeten Eigenschaften aber nicht begrenzt werden sollte, wurde die Klasse ds_chem_obj entwickelt, deren Aufgabe die dynamische Verwaltung dieser Eigenschaften ist und von der alle anderen chemischen Klassen abgeleitet werden. Dies bietet zwei Vorteile. Einerseits muß die Eigenschaftsverwaltung nur einmal implementiert werden und andererseits ist dadurch gewährleitet, daß der Zugriffsmechanismus für alle Klassen gleich ist, was eine einfache Handhabung erlaubt. Bei der Definition der chemischen Klassen wurden nur Attribute, die unbedingt zur Beschreibung eines Objekts dieser Klasse notwendig sind, als Klassenattribute abgelegt, alle anderen Eigenschaften werden über den allgemeinen Mechanismus verwaltet.

Auch Gruppen können chemischen Objekten unterschiedlichen Typs zugeordnet sein. Gruppen, die intramolekulare Wechselwirkungen darstellen, gehören zu dem entsprechenden Molekül, Gruppen, die für intermolekulare Wechselwirkungen verantwortlich sind, werden dem entsprechenden Aggregat zugeordnet. Topologische Gruppen können die Umgebung von bestimmten Atomen oder Elektronensystemen beschreiben und werden diesen daher speziell zugeordnet. Um auch für die Behandlung von Gruppen einen allgemeinen Mechanismus zur Verfügung stellen zu können, wurde daher von der Klasse, ds_chem_obj die Klasse ds_chem_obj_w_groups abgeleitet, die für die Verwaltung von Gruppen zuständig ist.

8.4. Chemische Klassen

Bevor alle chemischen Klassen im Detail beschrieben werden, soll zunächst ein Überblick darüber gegeben werden, in welchen Beziehungen sie zueinander stehen. Abbildung 8-2 zeigt, wie sich die Objekte der Klassen gegenseitig referenzieren. Alle Klassen, die durch Linien miteinander verbunden sind, stehen direkt miteinander in Beziehung. Dabei markiert ein schwarzer Punkt die Klasse, die einen Verweis enthält, und ein leeres Quadrat die Klasse, auf die verwiesen wird. Die Zahlen neben den Punkten geben an, wieviele Objekte referenziert werden können. Ein Ensemble kann beliebig viele Aggregate oder Moleküle enthalten. Jedes Aggregat oder Molekül enthält einen Verweis auf das Ensemble, dem es angehört. Wenn sich ein Molekül in einem Aggregat befindet, enthält es zusätzlich eine Referenz darauf. Ein Molekül enthält Verweise auf seine Atome und Elektronensysteme, jedes Atom und Elektronensystem einen Verweis auf das Molekül zu dem es gehört. Da es häufig notwendig ist, alle Atome eines Elektronensystems bzw. alle Elektronensysteme, an denen ein Atom Teil hat, anzusprechen, sind sie gegenseitig referenziert, um einen schnellen Zugang zu dieser Information zu schaffen. Jedes Molekül kann zusätzlich einen Container mit allen Paaren aus Nachbaratomen besitzen. Die Beziehungen, die Gruppen zu den anderen Klassen haben, wurden in Abbildung 8-2 der Übersichtlichkeit wegen nicht dargestellt. Sie werden jedoch in den nächsten Abschnitten erläutert.

Abb. 8-2: Beziehungen zwischen den chemischen Klassen.

Für alle chemischen Klassen wurden Konstruktoren und Destruktoren implementiert sowie Funktionen zum Kopieren von Objekten chemischer Klassen bereitgestellt, sie werden im folgenden nicht mehr extra erwähnt.

8.4.1. Die Atomklasse

Es wird nicht nur die Funktionalität der Klasse ds_atom beschrieben, sondern stellvertretend für alle Chemieklassen auch deren interner Aufbau erläutert. Alle anderen Klassen sind aus entsprechenden Komponenten zusammengesetzt. Der Zugriff auf Objekte anderer Chemieklassen, die von der Atomklasse referenziert werden, erfolgt über Iteratoren. Deren Mechanismus wird am Beispiel des Iterators für Elektronensysteme erklärt. Die Iteratoren für die anderen Klassen sind analog definiert und implementiert und werden daher ebenfalls nicht weiter erläutert.

Die Klasse ds_atom besitzt Variablen zur Speicherung der Ordnungszahl, eines Laufindizes und eines Labels zur Kennzeichnung der Identität jedes Atoms. Sie enthält einen Container zur Speicherung der Elektronensysteme, an denen es beteiligt ist, sowie einen Container zur Speicherung der Gruppen von denen es ein Teil ist. Beide sind private, d. h. nicht ohne Zugriffsfunktionen zugängliche Bestandteile der Klasse ds_atom. Da ein Atom in der Regel nur an wenigen Elektronensystemen beteiligt ist, diese sich in Reaktionen jedoch häufig ändern, wurde das Template für verkettete Listen zur Speicherung der Elektronensysteme gewählt. Zusätzlich zu den Funktionen, die den Zugriff auf die Klassenvariablen gewährleisten, hat ds_atom Funktionen, die es erlauben, Elektronensysteme an ein Atom zu addieren bzw. zu entfernen. Außerdem kann abgefragt werden, wieviele Elektronensysteme ein Atom enthält. Mit einer Instanz der Klasse ds_elecsys_iter kann die Liste der Elektronensysteme eines Atoms traversiert werden. Sie stellt Funktionen zur Verfügung, die das erste und das aktuelle Element der Liste zurückgeben sowie je eine Funktion zum Vorwärtsgehen und zur Abfrage, ob der Iterator sich noch auf einem gültigen Element befindet. Im Gruppencontainer werden alle Gruppen festgehalten, von denen das Atom ein Bestandteil ist. Der Inhalt dieses Containers wird automatisch erzeugt und kann über einen Gruppeniterator abgefragt werden. Die Linien zwischen den Containerklassen und ihren Iteratoren, die in Abbildung 8-3 mit einem F (für Freund) markiert sind, kennzeichnen, daß die Iteratoren auch den privaten Bereich der Containerklassen benutzen dürfen. Zudem besitzt die Klasse ds_atom einen Container mit den Definitionen aller Atomeigenschaften, die während eines Programmlaufs zur Verfügung stehen. Dieser Container ist statisch deklariert, das bedeutet, er ist nur einmal für alle Objekte der Klasse ds_atom vorhanden. Alle anderen Chemieklassen besitzen ebenfalls einen Container mit den Definitionen der für sie vorhandenen Eigenschaften. Er wird daher im folgenden nicht mehr weiter erwähnt.

Abb. 8-3: Klassendiagramm der Atomklasse ds_atom.

8.4.2. Die Klassen für Elektronensysteme

Zur Behandlung von Elektronensystemen wurde eine Basisklasse ds_elecsys definiert, die die gemeinsamen Aufgaben aller Arten Elektronensysteme übernimmt. Sie enthält einen Laufindex und ein Label zur Identifizierung sowie je einen Container zur Speicherung der Atome, die in einer Instanz dieser Klasse enthalten sind, und der Gruppen, deren Bestandteil sie ist. Zudem enthält es eine Variable zur Speicherung des aktuellen Elektronensystemtyps. Von dieser Klasse sind die Klassen zur Behandlung der speziellen Elektronensysteme abgeleitet, ds_sigmasys, ds_pisys und ds_coordsys. ds_sigmasys ist um eine private Variable für den Geometrietyp, regulär, verbrückt oder geschlossen, und eine Referenz auf ein zentrales Atom, erweitert. Die Klassen ds_pisys und ds_coordsys haben keine zusätzlichen Attribute, sind aber notwendig, um virtuelle Funktionen der Basisklasse zu überschreiben und damit ein ihnen angepaßtes Verhalten zu ermöglichen.

8.4.3. Die Molekülklasse

Die Klasse zur Repräsentation von Molekülen, ds_molecule, enthält drei Container zur Speicherung von Atomen, Elektronensystemen und Nachbaratompaaren. Sie stellt Funktionen und Iteratoren zur Verfügung, um Atome und Elektronensysteme eines Moleküls anzusprechen und ihre Zusammensetzung zu modifizieren. Aus der Konnektivität kann der vollständige Satz an Nachbaratompaaren abgeleitet werden.

Sie enthält zusätzlich Container und Funktionen, die sich mit der Gültigkeit von Atom-, Elektronensystem-, Nachbaratompaar- und Moleküleigenschaften befassen. Die Verwaltung der Eigenschaften ist zwar grundsätzlich eine Aufgabe der Basisklasse ds_chem_obj. Da es aber einen zu großen Aufwand bedeutet, die Gültigkeit jeder Eigenschaft jeden Atoms etc. zu speichern, erhalten jeweils alle Eigenschaftswerte der gleichen Eigenschaft in allen Atomen etc. eines Moleküls einen gemeinsamen Status, der mit dem Molekül gespeichert wird.

8.4.4. Die Aggregatklasse

Die Klasse ds_aggregate enthält einen Container mit den in ihr enthaltenen Molekülen und stellt Funktionen und einen Iterator für deren Zugriff zur Verfügung. Es ist nicht zwingend erforderlich, daß ein Aggregat aus mindestens zwei Molekülen mit einer Wechselwirkung bestehen muß. Um eine konstante Hierarchie des Aufbaus eines Ensembles zu gewährleisten, wurde erlaubt, daß ein Aggregat auch nur aus einem Molekül besteht. Es darf dann allerdings keine Gruppen enthalten.

8.4.5. Die Ensembleklasse

Die Klasse ds_ensemble enthält je einen Container für Aggregate und Moleküle. Sie stellt einen Iterator zum Zugriff auf alle Aggregate sowie zwei Iteratoren für Moleküle zur Verfügung. Mit dem einen Iterator kann nur auf die direkt im Ensemble gespeicherten Moleküle zugegriffen werden, mit dem anderen Iterator werden auch die Moleküle innerhalb von Aggregaten angesprochen.

8.4.6. Die Gruppenklasse

Wechselwirkungs- und topologische Gruppen werden in Objekten der Klasse ds_group gespeichert. ds_group enthält je einen Container für die an der Gruppe beteiligten Atome und Elektronensysteme sowie Funktionen zum Eintragen und Löschen von Atomen und Elektronensystemen. Es gibt zwei Möglichkeiten, wie die Atome bzw. Elektronensysteme, die eine Gruppe bilden, bestimmt werden. Eine Möglichkeit ist die Festlegung durch einen Benutzer, die zweite Möglichkeit ist, von ds_group eine Klasse abzuleiten, die eine Vorschrift zur Suche der in die Gruppe gehörigen Atome enthält. Dies ist für topologische Gruppen wie die Bestimmung des Satzes an Ringen in einem Molekül sinnvoll. Die Klasse ds_group ist von ds_chem_obj_w_groups abgeleitet, sie kann also ebenfalls Gruppen enthalten. Die Tiefe der Hierarchie ist momentan auf zwei begrenzt. Eine Gruppe kann einen Satz von Gruppen der gleichen Art enthalten, die sich aus Atomen und Elektronensystemen zusammensetzen müssen.

Jede Gruppe erhält einen Namen, durch den ihr Typ festgelegt wird. Wechselwirkungsgruppen unterscheiden sich von topologischen Gruppen durch die Wechselwirkung. Wenn deren Stärke spezifiziert werden soll, so kann der Wert in einer Gruppeneigenschaft abgelegt werden.

Die Klassenbibliothek enthält bisher zwei Subklassen, die spezielle topologische Gruppen implementieren. Mit der Klasse ds_rings wird der der kleinste Satze an kleinen Ringen eines Moleküls abgeleitet. Dazu wurde ein Algorithmus von Sorkau [76] verwendet. Die Klasse ds_atom_neighbors macht alle Nachbaratome eines gegebenen Atoms zugänglich.

8.4.7. Die Nachbarschaftsklasse

Aus dem VB-Modell zur Beschreibung von Molekülen folgt, daß Atome, die an einer Bindung beteiligt sind, Nachbaratome sind. Die physikochemischen Eigenschaften, die Bindungen zugeordnet werden, sind häufig Eigenschaften, die sich auf zwei benachbarte Atome beziehen. In RICOS ist diese direkte Beziehung zwischen Elektronensystemen und Nachbarschaftsatomen nicht mehr gegeben, da die Zahl der Atome pro Elektronensystem nicht auf zwei festgelegt ist. Da aber auch in diesem Modell Eigenschaften benachbarter Atompaare zur Verfügung gestellt werden sollen, wurde für diese Zwecke die Klasse ds_neighbors entwickelt. Sie ist von ds_chem_obj direkt abgeleitet, Instanzen dieser Klasse können keine Gruppen zugewiesen werden. Die Klasse ds_neighbors enthält zwei Referenzen auf die beiden benachbarten Atome sowie Funktionen zu ihrem Zugriff.

8.5. Basisklassen

8.5.1. Chemische Objekte

Die Basisklasse ds_chem_obj stellt hauptsächlich Funktionen zum Setzen und Abfragen der Eigenschaften eines chemischen Objekts zur Verfügung. Jedes chemische Objekt enthält einen Eigenschaftscontainer (ds_prop_container) mit allen seiner Eigenschaften ( Abbildung 8-4 ). Der Zugriff erfolgt über Objekte des Typs ds_prop_entry. Für jede Eigenschaft gibt es einen eindeutigen Eintrag, der aus dem Namen und dem Typ der Eigenschaft sowie dem Typ des aktuellen Chemieobjekts abgeleitet wird. Objekte der Klasse ds_prop enthalten den Wert der Eigenschaft. Um mit Eigenschaften sinnvoll arbeiten zu können, wurden zwei weitere Klassen entwickelt. Mit Objekten der Klasse ds_prop_definit wird jede Eigenschaft definiert. Die Definition enthält den Namen der Eigenschaft, die Art des Wertes, die Berechnungsmethode, Defaultwerte, für welche chemische Klasse sie definiert ist, und unter welchen Bedingungen sie ungültig wird. Tabelle 8-3 enthält die momentan gültigen Typen für Eigenschaftswerte. Einige der Berechnungsmethoden sind in Kapitel 5 erläutert.

Tab. 8-3: Gültige Typen für Eigenschaftswerte.

Zugriffsschlüssel Inhalt
PT_UNDEF nicht definiert
PT_INT int
PT_LONG long int
PT_FLOAT float
PT_DOUBLE double
PT_CHAR char
PT_STRING String
PT_INTVEC integer vector
PT_LONGVEC long int vector
PT_FLOATVEC float vector
PT_DOUBLEVEC double vector
PT_CHARVEC char vector
PT_STRINGVEC String vector
PT_BIT64 e_bit64
PT_PROPENTRY ds_prop_entry

In Objekten der Klasse ds_pg_status wird festgehalten, ob eine Eigenschaft momentan gültig ist oder nicht. Wenn der Wert einer ungültigen Eigenschaft abgefragt wird, wird anhand der Definition entweder eine Neuberechnung gestartet, oder falls keine Berechnungsmethode zur Verfügung steht, ein Defaultwert eingesetzt, bevor die Abfrage beantwortet wird. Alle Definitionen von Eigenschaften einer Art chemischer Objekte werden in einem Container (ds_propdef_container) gesammelt. Wie schon in Kapitel 8.4.3 erläutert, wird die Information, ob die Eigenschaften eines chemischen Objekts gültig sind, nicht immer mit dem chemischen Objekt gespeichert. Jedes chemische Objekt hat jedoch über virtuelle Funktionen die Möglichkeit, diese Information abzufragen, wenn der Wert einer Eigenschaft angefordert wird.

Abb. 8-4: Klassendiagramm für die Klassen zur Behandlung von Eigenschaften.

8.5.2. Chemische Objekte mit Gruppen

Die Klasse ds_chem_obj_w_groups ist von ds_chem_obj abgeleitet. Sie enthält im wesentlichen Funktionen zur Speicherung von Gruppen eines Chemieobjekts. Die Klassen zur Definition und Speicherung von Gruppen sind denen zur Behandlung von Eigenschaften in ds_chem_obj ähnlich. Die Klasse enthält einen Container zur Speicherung der Gruppen. Der Zugriff auf bestimmte Gruppen erfolgt über Klassenfunktionen mit einem Zugriffscode, einem Objekt der Klasse ds_group_entry. Es wird aus dem Namen der Gruppe und dem Typ des chemischen Objekts, mit dem die Gruppe verknüpft ist, generiert. Zudem verfügt die Klasse ds_chem_obj_w_groups über einen Iterator, mit dem alle Gruppen traversiert werden können. In der neuentwicklung des Programmsystems EROS wird es möglich sein, in den Reaktionsregeln neue Gruppentypen zu definieren und zu den schon vorhandenen Gruppendefinitionen zu addieren. Da die Reaktionsregeln hauptsächlich mit der der Scriptsprache Tcl [78] kodiert werden sollen, ist es in dieser Anwendung nicht möglich, neue Gruppenklassen durch Vererbung zu erzeugen. Daher wurde die Klasse ds_group_definit entwickelt. Sie speichert alle Informationen, die zur Beschreibung einer bestimmten Gruppe notwendig sind. Darunter fallen der Name, ein String mit einer Kurzbeschreibung und ein Attribut, mit dem festgelegt, wie eine Gruppe am ende einer Reaktionssequenz weiterbehandelt werden soll. Wenn die Atome einer Gruppe eines Moleküls nach einer Reaktion durch Spaltung auf mehrere Moleküle verteilt sind, gibt es dafür drei Möglichkeiten. Sie kann gelöscht werden, sie kann in zwei unabhängige Gruppen getrennt werden, die mit den beiden Reaktionsprodukten verbunden sind, oder sie bleibt bestehen, und aus den beiden Molekülen wird ein Aggregat gebildet. Alle Gruppendefinitionen werden in einem Container gesammelt. Sie können über den Namen oder den Zugriffscode abgefragt werden.

Abb. 8-5: Klassendiagramm für die Klassen zur Behandlung von Gruppen.

8.6. Repräsentation von Molekülen in VB-Darstellung

In Kapitel 7 wurden Verfahren vorgestellt, wie Moleküle in VB-Repräsentation und RICOS-Repräsentation ineinander umgewandelt werden können. Die Klassenbibliothek wurde dahingehend erweitert, daß auch Moleküle in VB-Repräsentation als Bindungslisten kodierbar sind. Dabei war es nicht notwendig, einen vollständig neuen Satz an Klassen zur Repräsentation von Molekülen zu entwickeln. Es konnte auf viele der bereits vorhandenen chemischen Klassen zurückgegriffen werden. Wie in Abbildung 8-2 gezeigt ist, setzt sich ein Molekül aus Objekten der Klassen ds_elecsys und ds_atom zusammen, unabhängig davon, welcher Subklasse diese Objekte angehören. Es ist daher möglich, diese Klassen zur Repräsentation eines Moleküls in VB-Darstellung wiederzuverwenden. Um den speziellen Anforderungen dieser Repräsentation gerecht zu werden, wurden für deren Atome und Bindungen zwei neue Subklassen entwickelt. Von der Klasse ds_atom wurde die Klasse ds_vbatom abgeleitet, von der Klasse ds_elecsys, die Klasse ds_vbbond. In Bindungslisten werden freie Elektronen Atomen als Eigenschaften zugeordnet. Daher enthält die Klasse ds_vbatom ein zusätzliches Attribut, in dem die Zahl der freien Elektronen eines Atoms gespeichert wird, sowie Funktionen zu deren Änderung. Die Klasse ds_vbbond dient zur Kodierung von Einfach- und Mehrfachbindungen zwischen Atompaaren. Ein Objekt dieser Klasse muß daher zwei Atome enthalten. Zudem stellt sie Funktionen zur Änderung der Bindungsmultiplizität bereit. In Abbildung 8-6 ist die Zusammensetzung eines Moleküls aus Objekten der Klassen ds_vbatom und ds_vbbond gezeigt.

Abb. 8-6: Zusammensetzung eines Moleküls in VB-Repräsentation.

8.7. Reaktionen

Um die Modellierung von Reaktionen möglichst einfach zu gestalten, wurden für die in Kapitel 6 beschriebenen Elementarschritte zur Veränderung eines Ensembles und für die Valenzüberprüfung von Molekülen zwei Klassen entwickelt. Die Klasse ds_modify ist für die Reaktionsschritte verantwortlich, die Klasse ds_valence wird zum Test auf valenzchemische Gültigkeit eingesetzt.

Jede chemische Klasse enthält Funktionen, die es erlauben, andere chemische Objekte zu einem Objekt zu addieren oder zu entfernen. Diese Funktionen eignen sich jedoch nicht direkt für die Modifikation von chemischen Objekten in Reaktionen, da sie keine Konsistenzüberprüfung eines Ensembles umfassen. Als Schnittstelle zur Generierung von Reaktionen wurde daher die Klasse ds_modify entworfen. Jeder der in Kapitel 6 beschriebenen Elementarschritte wird durch eine Klassenfunktion implementiert. Neben der Durchführung der einzelnen Elementarschritte hat die Klasse ds_modify die Aufgabe, für Konsistenz innerhalb des Reaktionsensemble zu sorgen. Dies geschieht in mehreren Stufen. Während jeden Reaktionsschritts werden nur die an einem Reaktionsschritt beteiligten Atome, Elektronensysteme und Gruppen neu gebildet, modifiziert oder gelöscht. Die korrespondierenden Moleküle und Aggregate werden nicht umgeordnet, da in einer Reaktionssequenz häufig Zwischenprodukte gebildet werden, die später wieder gebrochen werden und die Zuordnung zu Molekülen sehr zeitaufwendig ist. Es wird jedoch mitverfolgt, welche Art von chemischen Objekten des Reaktionsensembles geändert wurden. Am Ende einer Reaktionssequenz werden ungültig gewordene Referenzen gelöscht und alle Atome, Elektronensysteme und Gruppen den richtigen Molekülen und Aggregaten zugeordnet. Die Behandlung von Wechselwirkungs- und topologischen Gruppen umfaßt drei Möglichkeiten, wie mit einer Gruppe verfahren werden kann. Gruppen, die durch die Änderung der Konnektivität der an ihnen beteiligten Atome oder Elektronensysteme ungültig werden, werden gelöscht. Ein Beispiel hierfür sind Ringsysteme, die während einer Reaktion aufgebrochen werden ( Abbildung 8-7 a). Gruppen, die Wechselwirkungen beschreiben, die von der durchgeführten Reaktion nicht betroffen sind, bleiben bestehen. Dabei kann es sein, daß sich intramolekulare Wechselwirkungen in intermolekulare Wechselwirkungen umgewandelt haben, was eine weitere Umordnung der Moleküle in Aggregaten nach sich zieht ( Abbildung 8-7 b). Die letzte Möglichkeit betrifft Gruppen, die verwendet werden, um bestimmte Atome zu markieren ( Abbildung 8-7 c). Wenn sich die Atome einer solchen Gruppe am Ende der Reaktion nicht mehr innerhalb eines Moleküls befinden, wird die Gruppe geteilt und auf die neu entstandenen Moleküle verteilt.

Zuletzt werden alle Eigenschaften aller chemischen Objekte darauf hin geprüft, ob sie ihre Gültigkeit durch einen der angewendeten Reaktionsschritte verloren haben und gegebenenfalls als ungültig markiert.

Die Klasse ds_valence führt einen Konsistenztest auf einem chemischen Objekt durch. Dies kann ein Ensemble, Aggregat, Molekül oder Atom sein. Sie überprüft das chemische Objekt anhand der in Kapitel 6.4 vorgestellten Kriterien für eine der vier Kategorien. Es wird geprüft, ob die Besetztung der Elektronensysteme mit Elektronen, die Kombination der Elektronensysteme sowie die äquilibrierten Ladungen in dem jeweils vorgegebenen Bereich liegen. Falls nicht, so wird für das entsprechende chemische Objekt ein Fehlerwert zurückgegeben, der von Art des aufgetretenen Fehlers abhängt.

Abb. 8-7: Auswirkungen von Reaktionen auf die Zusammensetzung von Gruppen, (a) die Gruppe wird nach einer Reaktion ungültig und damit gelöscht, (b) intramolekulare Wechselwirkungen werden zu intermolekularen Wechselwirkungen, die die Bildung eines Aggreagts zur Folge haben, (c) eine Gruppe wird in mehrere Gruppen gepalten.



[Top] [Prev] [Next] [Bottom]
Diese Arbeit ist Teil der Dissertationen unter http://www2.chemie.uni-erlangen.de/services/dissonline/