Pila
Anmeldungsdatum: 2. April 2009
Beiträge: 76
|
Hallo zusammen, Ich habe folgendes Problem: Es existieren 5 Klassen und zwar: Coloring (enthält Variablen und Funktionen um einen Graphen zu färben) EqColoring (Funktionen und Variablen um einen Graphen equitabel (in gleich grosse Farbklassen) zu färben) Network (enthält Funktionen zum Lösen für Flussprobleme, sowie die Transformation des Lösen eines Graphen in einen Fluss, und weitere Hilfsfunktionen wie Tiefen- und Breitensuche, etc.) Heuristic (sie enthält Heurstiken um obere und untere Schranken für die Anzahl Farben zu bekommen, die ich benötige um den Graph zu färben, um eine max. Clique zu finden, etc.) Input (liest Graphen, Cliquen etc. ein)
EqColoring erbt von Coloring. Sonst gibt es in dem Sinne keine einprogrammierten Abhängigkeiten, was auch das Problem irgendwie ist.
Nachdem das Projekt ziemlich groß geworden ist habe ich mich entschlossen ein Klassendesign zu entwerfen und zu implementieren, was ich oben vorgestellt habe. Soweit klappt auch alles, nur es gibt Probleme beim Zugriff auf Methoden u. Variablen und ich weiß nicht wie ich es lösen soll. Sagen wir besser mal, ich weiß nicht wie ich es schön lösen kann. Ich habe in Network eine Funktion FF, diese möchte ich gerne in einer Funktion von EqColoring aufrufen.
In Heuristic und in Network existieren Funktionen, die jedoch auf Variablen von EqColoring/Coloring zugreifen, bzw. sie lesen müssen. Ich habe get/setter Methoden geschrieben. Das Programm an sich ist in C++ implementiert. Eine Lösung für mich wäre es als Paramterübergabe zu realisieren, jedoch finde ich das nicht so schön. Anderseits könnte man die anderen Klassen wie Heuristic und Network in die Vererbungshierachie mit einbauen, jedoch finde ich nicht, dass sie dahin gehören. Wie könnte man mein Problem lösen? Irgendwelche Ansätze? 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 | class EqColoring : Coloring{
private:
std::size_t vClique;
public:
void doSmth(..);
};
void EqColoring::doSmth(..){
int flow = FF(..);
}
class Coloring{
protected:
std::size_t uncoloredVertices;
std::size_t UB;
..
};
class Network{
public
int FF(Graph g);
};
int Network::FF(Graph g){
int n = vClique + uncoloredVertices ..
}
class Heuristic{
int upperBound(..);
};
int Heuristic::upperBound(..){
int n = UB + ..;
}
|
Hier habe ich die 3 Probleme veranschaulicht. Das Aufrufen von FF in EqColoring, das Nichtvorhandensein von UB in upperBound in Heuristic, und das Nichtvorhandensein von vClique in FF der Network Klasse. Über Argumente möchte ich es nicht lösen, da ich 5-10 solcher Variablen habe. ☺ Und das zusammenfassen per Struct und dann per Argument übergeben finde ich auch nicht so toll. Muss doch was besseres geben oder? Bearbeitet von rklm: Formatierung.
|
Dee
Anmeldungsdatum: 9. Februar 2006
Beiträge: 20087
Wohnort: Schwabenländle
|
Und das zusammenfassen per Struct und dann per Argument übergeben finde ich auch nicht so toll. Muss doch was besseres geben oder?
Warum findest Du es denn nicht toll? Also schreibe doch einmal auf, was dafür und was dagegen spricht.
class EqColoring : Coloring
Hat es einen Grund, dass Du private ableitest?
Das Aufrufen von FF in EqColoring, das Nichtvorhandensein von UB in upperBound in Heuristic, und das Nichtvorhandensein von vClique in FF der Network Klasse.
Löst man normalerweise durch nutzerspezifische Interfaces, wo es sinnvoll ist. Ich kenne die Details Deiner Anwendung nicht, aber die gegenseitige Verwendung von Klassen (EqColoring und Network brauchen sich gegenseitig) sollte Dir zeigen, dass Deine Klassen ggf. falsch geschnitten sind. Mein Vorschlag: Schreibe Dir unabhängig von Deinem aktuellen Design auf, welche Nutzer und welche Daten Du hast und wie diese miteinander kommunizieren sollen (wer nutzt was). Das sollte natürlich zyklenfrei sein. Und dann schau nach, wie Du Dein aktuelles Design so anpassen kannst, dass es Deinem neuen Bild entspricht. Wenn die Anwendung wichtig ist, solltest Du natürlich vorher Tests geschrieben haben, die sicherstellen, dass Du nichts kaputt machst beim Umbau. Gruß Dee
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
FF für einen Funktionsnamen halte ich ja für fragwürdig - unabhängig davon, ob man pascalCase oder CamelCase verwendet. Wofür steht FF? "Fast Fourier"?
Wenn Network::FF wirklich ein Objekt vom Typ EqColoring benötigt, dann musst Du eben einen übergeben. Punkt ☺ Die Frage ist eher, ob das nicht besser eine Abstraktion sein sollte, damit FF universeller bleibt. Grundsätzlich musst Du Dir aber die Frage stellen, welches Objekt die treibende, algorithmische Rolle inne hat. Sollte das EqColoring sein, so könnte man sich schon fragen, wieso eine Service-Klasse (Network und Heuristic ) so viel von der aufrufenden wissen muss. Vielleicht fehlt da wirklich eine zentrale Datenstruktur, die man stattdessen übergeben muss?
|
Pila
(Themenstarter)
Anmeldungsdatum: 2. April 2009
Beiträge: 76
|
Der Funktionsname FF war nur ein Beispiel. In der Anwendung heißt sie fordFulkersonClique(). Ja, das Klassendesign wird wahrscheinlich wirklich schlecht von mir gemacht worden sein. Ich mache das zum ersten Mal im praktischen Sinne, sonst haben wir es nur in der Theorie in einigen Vorlesungen durch gearbeitet. Die treibende, algorithmische Rolle hat die Klasse Coloring bzw. EqColoring inne. Es geht nämlich um die Färbung eines Graphen. Nein, es hat keinen bestimmten Grund dass ich es private ableite. Die Klasse Coloring besitzt als Membervariablen eigentlich alles wichtige: den Graphen, die Farbklassen, aktuellen Knoten, einige Bounds, etc.
Die anderen Klassen brauchen einige Informationen von dieser um ihre speziellen Methoden aufzurufen. Eine Methode errechnet zum Beispiel Cliquen auf dem Graphen, aber nur für ungefärbte Knoten. Deswegen muss er natürlich Zugriff auf den Graphen haben. Vorher hatte ich alles in entsprechende Header/Cpp-Files. Da habe ich keine Klassen benutzt. Jedoch war das teilweise sehr unschön, weil ich sehr viele Argumente übergeben musste. Dann hat mir jemand Tipps gegeben warum ich es mal mit Klassen versuchen sollte, das habe ich gemacht, aber wie gesagt es ist das erste Mal für mich. Also eigentlich sind die Abhängigkeiten vom jetzigen Klassendesign recht einfach zu erklären. Coloring/EqColoring müssen Methoden von Heuristics/Network/Input benutzen um Eigenschaften von dem Graphen zur Färbarkeit zu errechnen/setzen.
Die Methoden der Klassen Heuristics/Network/Input brauchen jedoch einige Informationen des Graphens.
Zum Beispiel wieviele Knoten im Moment ungefärbt sind, wieviele Farben aktuell benutzt werden, etc. und diese Informationen habe ich als Membervariablen der Klasse Coloring/EqColoring realisiert. Das sind die Abhängigkeiten untereinander. Um die Funktionen der Klasse aufzurufen brauche ich ja ein Objekt dieser, falls diese nicht static sind. Sollte ich eventuell ein Objekt von diesen Klassen wie Input/Heuristic, etc. in Coloring/EqColoring als Membervariable erstellen?
|
Dee
Anmeldungsdatum: 9. Februar 2006
Beiträge: 20087
Wohnort: Schwabenländle
|
Sollte ich eventuell ein Objekt von diesen Klassen wie Input/Heuristic, etc. in Coloring/EqColoring als Membervariable erstellen?
Wenn Du an einen guten Software-Designer bzw. -Architekten gerätst, wird der Dir nicht sagen: "Mach es so oder mach es so.", sondern er wird Dich solange nach den Hintergründen und dem Warum fragen, bis Dir selbst die Idee kommt, wie man es machen kann. (Das nur als warnendes Vorwort. ☺) Du schreibst "Die treibende, algorithmische Rolle hat die Klasse Coloring bzw. EqColoring inne. Es geht nämlich um die Färbung eines Graphen." und "Die Klasse Coloring besitzt als Membervariablen eigentlich alles wichtige: den Graphen, die Farbklassen, aktuellen Knoten, einige Bounds, etc." Da würde ich jetzt hinterfragen, wieso der Graph in der Coloring-Klasse liegt. Bzw. tut er das, also habe ich das korrekt verstanden? Ich stelle mir unter "Coloring" und Deiner Beschreibung eher eine Dienstleistung vor, die Graphen einfärbt. Rein sprachlich würde ich also eher erwarten, das ich der Klasse Coloring den Graphen übergebe und sie nur auf ihm operiert. Kommt dieses Bild dem nahe, was Coloring tun soll? Operiert Coloring denn immer auf ein und denselben Graphen oder ändert sich das zur Laufzeit? Wer legt denn die Instanz zu Coloring an und wer steuert die Klasse aus (irgendwer muss das Einfärben ja anstoßen)? "Coloring/EqColoring müssen Methoden von Heuristics/Network/Input benutzen um Eigenschaften von dem Graphen zur Färbarkeit zu errechnen/setzen." - Wenn es Eigenschaften des Graphen sind, wieso liegen diese dann nicht im Graphen? Kannst Du eine Analyse bereit stellen, welche Methoden von Heuristics/Network/Input die Klasse braucht? Sind dies sehr viele verschiedene oder vielleicht nur ganz wenige? Umgekehrt die Frage, welche Methoden oder Informationen die Klassen Heuristics/Network/Input wiederum von den Graphen brauchen. Ist es immer der ganze Graph oder nur einzelne Bestandteile? (Falls die Frage mit Deinem ersten Beispielcode beantwortet war, einfach schreiben. Ich bin nicht sicher, ob der Code oben alles enthält oder nur ein kleiner Auszug ist.) Hintergrund der Frage ist, dass Du vielleicht schon siehst, wo man ggf. Klassen anders schneiden kann, sodass die Verwender wirklich nur das holen bzw. erhalten, was sie zum Arbeiten brauchen. (siehe Interface-Segregation-Prinzip - mit Interface ist jede Art von Schnittstelle, also auch Methoden/Operationen und Member/Attribute gemeint). Könntest Du im Übrigen noch einmal versuchen ein "Wunschdesign" aufzuzeichnen? Also wenn Du komplett freie Wahl hättest, alles neu zu machen, die Klasse neu aufteilen darfst etc. welche Objekte gäbe es dann bei Dir aktuell, welche Informationen bräuchten sie, um arbeiten zu können, und mit wem würdest Du sie kommunizieren lassen? Das muss kein ausgefeiltes Klassendesign sein, eine kurze Beschreibung jedes Objekts und seiner Tätigkeit und den Beziehungen reicht da völlig.
Vielleicht fehlt da wirklich eine zentrale Datenstruktur, die man stattdessen übergeben muss?
Den Gedanken von Lysander solltest Du im übrigen ebenfalls im Kopf behalten. Versuche, wenn möglich, die Logik von Daten zu trennen (also in getrennte Klassen). So kannst Du die Daten nämlich ohne Probleme durch die Gegend reichen, sodass andere damit arbeiten können, ohne dass jeder gleich die ganze Logik kennen muss. Gruß Dee PS: Ich finde das im Übrigen eine spannende Diskussion, weil ich von den Hintergründen keine Ahnung habe. ☺
|
Pila
(Themenstarter)
Anmeldungsdatum: 2. April 2009
Beiträge: 76
|
Mhm, Ich das Problem jetzt lange genug vor mir herum geschoben. Die letzten Monate habe ich das Programm mit vielen weiteren nützlichen Funktionen ausgestattet, jedoch wird es von Woche zu Woche weiter unübersichtlich weil die grundlegende Struktur fehlt. Jetzt will ich es vor dem nächsten Feature wirklich ändern. Im Moment besitzt es eigentlich immer noch ca. 1 Headerfile und 1 Quelldatei. Ich habe eben nochmal 3-4 Stunden an einem passenden Klassendesign überlegt und finde selbst einfach keine Lösung.. ☹ Mir fällt keine andere Lösung ein, als alles in einer Datei reinzupacken. Bei einer Klasse bin ich mir jedenfalls sicher, ich benötige eine "Input Class" zum Einlesen des Graphen, etc. Die braucht keinerlei Informationen, theorethisch jedoch eine Variable wo sie den Graph hineinschreiben kann. Sie wird eigentlich nur begrenzt minimal benutzt. Bisher nur zum Beginn des Algorithmus. Das Ziel meines Programms ist es eine Zahl zu berechnen, die mir sagt mit wievielen Farben ich den Graph mindestens färben muss. Ebenfalls wird zu Beginn eine obere und untere Zahl (UpperBound u. LowerBound) als Schranke durch verschiedene Heuristiken errechnet. Dazu benötigen sie nur den Graphen und verändern diesen auch nicht.
Nun beginnt das Programm die UpperBound schrittweise zu verringern bis man zu der minimalen Anzahl an Farben gekommen ist, die benötigt werden um den Graphen zu färben. Dieses schrittweise Verringern der UpperBound passiert in der Node-Funktion. Die Idee mit der Klasse Coloring/EqColoring habe ich wieder verworfen. Das Färben des Graphen wird rekursiv durch die Node-Funktion durchgeführt. Der Graph ändert sich dabei natürlich bei jedem Aufruf der Node-Funktion. Die Node-Funktion ist der wichtigste Teil des ganzen Programms. Innerhalb der Node-Funktionen werden die Fluss-Algorithmen und eine Heuristik zum Finden von Cliquen aufgerufen.
Wie der Name schon sagt beinhalten die Fluss-Algorithmen die bekannten Verfahren zum Lösen von speziellen Flussnetzwerken, wie z.B. Ford Fulkerson, Lösen von Matchings, etc. Da die Node-Funktion rekursiv und im Programm zig tausend Mal (bei genügend großen Graphen) aufgerufen wird, passiert dies ebenfalls mit den Fluss-Algorithmen (sogar noch öfter). Als Daten benötigen sie nur den Graphen (den sie nicht ändern). Das ist nicht ganz richtig. Sie benötigen eigentlich "nur" die Knoten, die ungefärbt sind und die möglichen Farben, die dieser Knoten dementsprechend annehmen kann und dazu noch ob und falls ja, zu welcher Clique dieser Knoten gehört. Die UpperBound wird auch benötigt.
Die Heuristik zum Berechnen der Cliquen benötigt alle ungefärbten Knoten. Jedoch beschreibt er den Graphen. Wieso? Das ist recht schnell erklärt und mir fällt gerade beim Schreiben auf, das womöglich bei der Datenstruktur des Graphen das ganze Problem liegen könnte, weswegen ich es nicht gut strukturieren kann. Zuerst einmal benutze ich die Graphenbibliothek Boost. Ein Graph besteht bekannterweise aus 2 Komponenten. Aus einer Menge von Knoten und Kanten. Boost vergibt von sich aus an den Knoten und Kanten Eigenschaften. Beispielsweise jeder Knoten hat einen Index, etc. Man kann sogar zusätzliche vordefinierte Eigenschaften für Knoten u. Kanten von Boost aktivieren. Zum Beispiel kann man aktivieren dass jeder Knoten eine Farbe hat. Ich benötige nun folgende Eigenschaften:
Farbe eines Knoten Clique eines Knoten Für jeden Knoten einen Vektor der Nachbarn Für jeden Knoten einen Vektor der Farben, die er nicht annehmen darf, bzw. die verboten sind. (Bit-Vektor) den Rang des Knoten. Damit meine ich die Stelle an dem der Knoten gefärbt wurde
Punkt 3. und 4. waren ursprünglich nicht vorgesehen und implementiert. Die habe ich später hinzugefügt zur Verbesserung der Laufzeit, davor habe ich es sehr ineffizient im Vergleich zur jetzigen Lösung implementiert, da ich dort jedes Mal die Farben, die benutzt werden durften neu gerechnet habe.
Jetzt wird sobald ein Knoten gefärbt wird in dem Bit-Vektor der Nachbarn überall das Bit gesetzt, falls es noch nicht gesetzt war. Ich habe den Graphen von Boost so bearbeitet bzw. erweitert, dass er mir diese Eigenschaften unterstützt.
Jedoch benötigt ich daher zum Beispiel bei der Heuristik zum Finden der Cliquen auch Schreibrecht auf den Graphen. Die anderen Funktionen kann man jetzt eher als Hilfsfunktionen verstehen, die von den Heuristiken oder Algorithmen von Flussnetzwerken benutzt werden, wie beispielsweise Tiefensuche, Breitensuche. Am liebsten würde ich ein ganz neues Design anstreben. Von dem anfangs hier erklärten Design würde ich mich gerne fern halten, ich glaube das war einfach nur eine schlechte Idee. Im Prinzip haben wir folgende wichtige Datensätze:
Graphen inkl. Eigenschaften wie Clique, Farbe, verbotene Farben (Vektor), Nachbarn (Vekor) eines Knoten benötigt. die Bounds Aktuelle Knoten und Farbe, die in diesem Schritt betrachtet werden (werden aber nur von der Node-Funktion benötigt)
und folgende Hauptunktionen:
Node: Mittelpunkt des Programms, hier werden die anderen Funktionen wie Flussalgo. und die Heuristik zum Auffinden der Cliquen gestartet und die Ergebnisse dann weiter verarbeitet Flussalgorithmen: Benötigen de Graphen bzw. Cliquen der Knoten und die verbotenen Farben von ungefärbten Knoten. Returnen nur ein Int/Bool und ändern nix am Graphen. Heurstiken: Ein Teil davon werden benötigt um die Bounds zu Beginn zu errechnen. Und der andere Teil (das Finden der Cliquen) wird häufiger aufgerufen und zwar ebenfalls zu Beginn, sowie bei jedem Aufruf der Node-Funktionen. Es benötigt die Menge der ungefärbten Knoten, sowie ihre Verbindungen untereinander, also die Menge der Nachbarn.
Ich hoffe ich konnte es einigermaßen gut erklären und verständlich skizzieren.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12802
|
Pila schrieb:
Ich das Problem jetzt lange genug vor mir herum geschoben. Die letzten Monate habe ich das Programm mit vielen weiteren nützlichen Funktionen ausgestattet, jedoch wird es von Woche zu Woche weiter unübersichtlich weil die grundlegende Struktur fehlt. Jetzt will ich es vor dem nächsten Feature wirklich ändern.
👍
Im Moment besitzt es eigentlich immer noch ca. 1 Headerfile und 1 Quelldatei. Ich habe eben nochmal 3-4 Stunden an einem passenden Klassendesign überlegt und finde selbst einfach keine Lösung.. ☹ Mir fällt keine andere Lösung ein, als alles in einer Datei reinzupacken.
Das hat ja erst mal nichts mit Klassendesign zu tun. In der Praxis hat man natürlich meist eine Klasse pro Header und Quelle, aber das ist kein Muss. Denk erst mal abstrakt über die Klassen nach, das Verteilen auf Dateien kann man dann später noch machen.
Bei einer Klasse bin ich mir jedenfalls sicher, ich benötige eine "Input Class" zum Einlesen des Graphen, etc. Die braucht keinerlei Informationen, theorethisch jedoch eine Variable wo sie den Graph hineinschreiben kann. Sie wird eigentlich nur begrenzt minimal benutzt. Bisher nur zum Beginn des Algorithmus.
Ja, Command-Pattern u.ä. Pattern: die Klasse repräsentiert keine Struktur sondern eine Aktivität. Sehr angenehm bei komplexeren Operationen, weil man dann Zustand, den man für die Aktivität braucht, in die Klasse als Member packen kann. Dadurch muss man ihn nicht ständig an Methoden übergeben.
Wieso? Das ist recht schnell erklärt und mir fällt gerade beim Schreiben auf, das womöglich bei der Datenstruktur des Graphen das ganze Problem liegen könnte, weswegen ich es nicht gut strukturieren kann.
☺ Du solltest es auf jeden Fall so machen, dass die Methoden an den passenden Klassen aufgehängt werden: Informationen über einen Knoten beschaffen → Knoten-Klasse, Informationen über den Graphen insgesamt beschaffen → Graph-Klasse usw.
Ich habe den Graphen von Boost so bearbeitet bzw. erweitert, dass er mir diese Eigenschaften unterstützt.
Jedoch benötigt ich daher zum Beispiel bei der Heuristik zum Finden der Cliquen auch Schreibrecht auf den Graphen.
U.U. ist es sinnvoll, den Graphen aufzuteilen in den ursprünglichen Graphen, der nach dem Einlesen nicht oder wenig verändert wird, und eine bzw. mehrere Klassen, die Informationen über den Graphen enthalten, die nur von einem bestimmten Algorithmus benötigt werden. Ich habe jetzt keine Zeit, mir die Details Deines Algorithmus anzuschauen, aber ich würde das zumindest mal erwägen.
Am liebsten würde ich ein ganz neues Design anstreben. Von dem anfangs hier erklärten Design würde ich mich gerne fern halten, ich glaube das war einfach nur eine schlechte Idee.
Manchmal funktioniert das besser, wenn man noch mal komplett neu anfängt. 👍
Im Prinzip haben wir folgende wichtige Datensätze:
Graphen inkl. Eigenschaften wie Clique, Farbe, verbotene Farben (Vektor), Nachbarn (Vekor) eines Knoten benötigt. die Bounds Aktuelle Knoten und Farbe, die in diesem Schritt betrachtet werden (werden aber nur von der Node-Funktion benötigt)
und folgende Hauptunktionen:
Node: Mittelpunkt des Programms, hier werden die anderen Funktionen wie Flussalgo. und die Heuristik zum Auffinden der Cliquen gestartet und die Ergebnisse dann weiter verarbeitet Flussalgorithmen: Benötigen de Graphen bzw. Cliquen der Knoten und die verbotenen Farben von ungefärbten Knoten. Returnen nur ein Int/Bool und ändern nix am Graphen. Heurstiken: Ein Teil davon werden benötigt um die Bounds zu Beginn zu errechnen. Und der andere Teil (das Finden der Cliquen) wird häufiger aufgerufen und zwar ebenfalls zu Beginn, sowie bei jedem Aufruf der Node-Funktionen. Es benötigt die Menge der ungefärbten Knoten, sowie ihre Verbindungen untereinander, also die Menge der Nachbarn.
Wenn Du Dich mit dem Gedanken anfreundest, auch komplexere Operationen / Algorithmen durch eine oder mehrere Klassen zu repräsentieren, dann wird es vielleicht leichter. Im Prinzip kannst Du Deine aufgezählten Entitäten bereits als Klassen oder Basisklassen ("Flussalgorithmus") verwenden.
|
Pila
(Themenstarter)
Anmeldungsdatum: 2. April 2009
Beiträge: 76
|
☺ Du solltest es auf jeden Fall so machen, dass die Methoden an den passenden Klassen aufgehängt werden: Informationen über einen Knoten beschaffen → Knoten-Klasse, Informationen über den Graphen insgesamt beschaffen → Graph-Klasse usw.
Aber dann ist die Benutzung von Boost doch total überflüssig, weil ich ja eh nicht die gegebenen Strukturen verwende/erweitere!?
Ja, Command-Pattern u.ä. Pattern: die Klasse repräsentiert keine Struktur sondern eine Aktivität. Sehr angenehm bei komplexeren Operationen, weil man dann Zustand, den man für die Aktivität braucht, in die Klasse als Member packen kann. Dadurch muss man ihn nicht ständig an Methoden übergeben.
Der Graph also als Member? Irgendwann muss ich den dann trz. wieder zurückliefern, weil ich ja damit weiter arbeiten muss.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12802
|
Pila schrieb: ☺ Du solltest es auf jeden Fall so machen, dass die Methoden an den passenden Klassen aufgehängt werden: Informationen über einen Knoten beschaffen → Knoten-Klasse, Informationen über den Graphen insgesamt beschaffen → Graph-Klasse usw.
Aber dann ist die Benutzung von Boost doch total überflüssig, weil ich ja eh nicht die gegebenen Strukturen verwende/erweitere!?
Ich weiß nicht, wie Boost das gemacht hat. Ich nehme mal an, dass sie die Möglichkeit vorsehen, die Typen zu erweitern - oder Daten beliebigen Typs an den Graphen und die Knoten anzuhängen.
Ja, Command-Pattern u.ä. Pattern: die Klasse repräsentiert keine Struktur sondern eine Aktivität. Sehr angenehm bei komplexeren Operationen, weil man dann Zustand, den man für die Aktivität braucht, in die Klasse als Member packen kann. Dadurch muss man ihn nicht ständig an Methoden übergeben.
Der Graph also als Member? Irgendwann muss ich den dann trz. wieder zurückliefern, weil ich ja damit weiter arbeiten muss.
Ja und?
|
Pila
(Themenstarter)
Anmeldungsdatum: 2. April 2009
Beiträge: 76
|
Ich weiß nicht, wie Boost das gemacht hat. Ich nehme mal an, dass sie die Möglichkeit vorsehen, die Typen zu erweitern - oder Daten beliebigen Typs an den Graphen und die Knoten anzuhängen.
Richtig, das habe ich auch so umgesetzt. Also Den Graph erweitert mit den entsprechenden Eigenschaften. ☺
|
Dee
Anmeldungsdatum: 9. Februar 2006
Beiträge: 20087
Wohnort: Schwabenländle
|
Lang nicht reingeschaut, aber ist hier noch was offen? Gruß Dee
|
Pila
(Themenstarter)
Anmeldungsdatum: 2. April 2009
Beiträge: 76
|
Jo, gleiches Problem. Immer noch nix geändert, weil ich keine Lösung finde. Meine Assistenten verstehen das Problem nicht und können mir ebenfalls nicht weiterhelfen. Nichtsdestotrotz ist das Programm wesentlich erweitert, die nächste Erweiterung kann ich leider nicht mehr umsetzen, da es rein strukturell so völligem Chaos führt. 😀 Ich verzweifel irgendwie, und mir vergeht komplett die Lust am Projekt gerade.
|
Pila
(Themenstarter)
Anmeldungsdatum: 2. April 2009
Beiträge: 76
|
Ich habe jetzt mal ein Diagramm gemacht. Ich fände es cool wenn es dazu Comments gibt. Viele Structs natürlich. Ich habe die einfach hinzugefügt damit ihr wisst was ich meine. Notfalls kann ich auch mal ein richtiges UML-Diagramm machen falls es noch unklar ist. Es gibt dann eigt. nur 4 Klassen, 2 davon static.. Eigt. keine wirkliche Objektorientierte Programmierung.. 😀 fixed Link http://fs1.directupload.net/images/150804/6k7d5kmv.png EDIT: Ich habe mir gerade gedacht, dass ich es auch noch weiter aufsplitten kann.
In der Heuristic habe ich 3 Methoden. Zwei davon haben mit dem Thema Cliquen zu tun und das andere um einen Zufallsgraph zu erzeugen.
Nun könnte ich Subklassen machen, die von Heuristic erben. Einmal die Klasse Clique und einmal die Klasse RandomGraph und packe die entsprechenden Methoden da rein. Anderseits könnte Clique dann auch noch von Input erben und die dort geschriebene Methode zum Einlesen von Cliquen implementieren oder!? Anderseits würde dagegen sprechen dass die Klasse Clique dann nicht im eigentlichen Sinne was mit Clique zu tun hat, da keine Clique gespeichert wird, etc.
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Ich fürchte das Pseudo-UML Diagramm sagt nicht so wirklich viel alleine aus. Ich habe immer noch meine Schwierigkeiten, die fachliche Ebene zu verstehen. Das ist aber leider essenziell, wenn man Dir helfen soll, einen gut strukturierten Ansatz zu finden. Hast Du Dir evtl. einfach mal existierende Rahmenwerke / Programme angeguckt? Ich würde mal vermuten, dass da die Graphenstruktur an sich im Mittelpunkt steht. Das "Färben" scheint mir hingegen eher eine Operation zu sein, die auf einem Graphen operiert und dazu ggf. andere gängige Algorithmen nutzt. Wo man da Vererbung und wo Komposition und dann in welchem Maße usw. einsetzt, ergibt sich erst aus einer guten fachlichen Beschreibung. Vielleicht muss ich mir noch mal Deine einführenden Kommentare durchlesen, damit mir etwas schlaues einfällt ☺ (Weiß nur nicht, ob ich am WE Zeit finde...) Ist es denn eine Prämisse, dass Du das alles selber machst? Oder könntest Du ggf. fertige Graphen-Frameworks nutzen? Evtl. erleichtert das schon einiges, denn davon solltes viele geben und die sind dann hoffentlich gut durchdacht und schon zig mal bewährt 😉
|
Pila
(Themenstarter)
Anmeldungsdatum: 2. April 2009
Beiträge: 76
|
Das Problem ist halt einfach. Wenn ich es detaillierter erkläre wird fachliches Vorwissen verlangt. Bzw. man kann es eigt. nur richtig schön und elegant in mathematischer Form ausdrücken. Aber wie ich als Mathematiker und Informatiker weiß, fürchten die meisten Informatiker Mathematik.. Deswegen habe ich das von Anfang an vermieden. ☺
Erkläre ich es grob, dann versteht es keiner. Das sollte auch kein UML-Diagramm sein, was es auch nicht ist. Es sollten nur schnell u. grob die Abhängigkeiten und Vererbungen, wovon es kaum welche gibt, gezeigt werden. Und natürlich die Structs, Variablen u. Methoden, die ich in den versch. Klassen hinzufügen würde. Ja, ich programmiere alleine. Ja, ich benutze ein Graphen-Framkework wie mehrfach hier schon angemerkt. Ich verwende Boost (spz. Graphen davon, ähneln einer STL Struktur). Ja, Färben ist eine Operation auf Graphen. Das ist das was ich machen muss. Also das Färben eines Graphen. Dazu müssen aber Bedingungen überprüft werden, Flüsse berechnet werden, neue Graphen erstellt werden, Graphen erweitert/reduziert werden, etc.
|