kramann.info
© Guido Kramann

Login: Passwort:










kramann.info
© Guido Kramann

Login: Passwort:




Objektorientierte Implementierung von Eingangs- und Ausgangsfuzzysets

  • Da die Ausgangsgrößen meistens bedingt durch das zu steuernde physikalische System begrenzt sind (z.B. PWM-Signal 0..1023), sind bei Ausgangsfuzzysets die Fuzzygrößen am Rand meistens begrenzt.
  • Da jeder beliebige Wert für eine Eingangsgröße sinnvoll verarbeitet werden soll, sind die Fuzzygrößen am Rand eines Fuzzyeingangssets in der Regel unbegrenzt.
  • Diese beiden Eigenschaften werden bei den folgenden Implementierungen für Ausgangs- und Eingangsfuzzysets als gegeben betrachtet.

Implementierung eines Eingangsfuzzysets

  • Da das Maxima einer inneren Fuzzygröße immer mit dem Null werden der benachbarten Größen zusammenfällt und die Ränder unbegrenzt sind, ist eine Eingangsfuzzygröße eindeutig durch Angabe der Punkte p1 der Fuzzygrößen bestimmt.
  • Die Übergabeparameter für R und T aus Übung 9 müßten dann jeweils lauten:
  • R: 5,10,20
  • T: 5,20
  • Da p1 redundant zu p0 des rechten Nachbars ist und
  • da p2 redundant zu p1 des rechten Nachbars ist und
  • da p1 redundant zu p2 des linken Nachbars ist und
  • da p0 redundant zu p1 des linken Nachbars ist,
  • muß dies in der Methode "setzeStellen(double* stelle)" der folgenden Klasse berücksichtigt werden.
class Eingangsfuzzyset
{
    public:
        int fg_anzahl;
        Fuzzygroesse** fg;
        double* zwerte;
        Eingangsfuzzyset(int fg_anzahl)
        {
            this->fg_anzahl = fg_anzahl;
            fg = new Fuzzygroesse*[fg_anzahl];
            //Dummywerte eintragen:
            fg[0] = new Fuzzygroesse(0.0,1.0,2.0,true,false);
            for(int i=1;i<fg_anzahl-1;i++)
                fg[i] = new Fuzzygroesse((double)i,(double)(i+1),(double)(i+2),false,false);
            fg[fg_anzahl-1] = new Fuzzygroesse((double)(fg_anzahl-1),(double)(fg_anzahl),
                                               (double)(fg_anzahl+1),false,true);
            zwerte = new double[fg_anzahl];
        }
        void setzeStellen(double* stelle)
        {
            fg[0]->p[0] = stelle[0]-1.0; //Dummy-Wert
            fg[0]->p[1] = stelle[0];
            fg[0]->p[2] = stelle[1];
            for(int i=1;i<fg_anzahl-1;i++)
            {
                fg[i]->p[0] = stelle[i-1];
                fg[i]->p[1] = stelle[i];
                fg[i]->p[2] = stelle[i+1];
            }
            fg[fg_anzahl-1]->p[0] = stelle[fg_anzahl-2];
            fg[fg_anzahl-1]->p[1] = stelle[fg_anzahl-1];
            fg[fg_anzahl-1]->p[2] = stelle[fg_anzahl-1]+1.0; //Dummy-Wert
        }
        double* berechneZugehoerigkeitswerte(double x)
        {
            for(int i=0;i<fg_anzahl;i++)
                zwerte[i] = fg[i]->berechneZugehoerigkeitswert(x);
            return zwerte;
        }
};

Code 0-1: Quellcode der Klasse Eingangsfuzzyset aus der Datei Eingangsfuzzyset.h

Übungsaufgabe b): Bestimmen Sie die gleichen Größen, wie in Übungsaufgabe a), aber verwenden Sie dazu jetzt die Klasse Eingangsfuzzyset.

Implementierung eines Ausgangsfuzzysets

  • Da das Maxima einer inneren Fuzzygröße immer mit dem Null werden der benachbarten Größen zusammenfällt und die Ränder begrenzt sind, ist eine Ausgangsfuzzygröße eigentlich erst eindeutig durch Angabe der Punkte p1 der Fuzzygrößen bestimmt und zusätzlich durch p0 der ganz links und p2 der ganz rechts.
  • Angenommen, p1 der Fuzzygröße ganz links und p1 der ganz rechts markieren die Grenzen des Wertebereichs der kontinuierlichen Ausgangsgröße.
  • Da wegen der Begrenztheit der kontinuierlichen Ausgangsgröße, der Schwerpunkt der äußeren Fuzzysets dann nie diese Grenzen verletzen darf, sollten die äußeren Fuzzygrößen symmetrische Dreiecke sein.
  • Dadurch sind dann aber p0 der Fuzzygröße ganz links und p2 der ganz rechts eindeutig bestimmt und müssen nicht extra übergeben werden.
  • Das in Übung 9 verwendete Ausgangsfuzzyset macht unter diesen Gesichtspunkten keinen Sinn.
  • Eine sinnvolle Anpassung könnte folgendermaßen aussehen (Dreiecksfunktionen der Fuzzygrößen am Rand sind nun symmetrisch):
Anpassung der Aufgabe aus Übung 9

Bild 0-1: Anpassung der Aufgabe aus Übung 9

  • Als Übergabeparameter, um das Ausgangsfuzzyset dann zu beschreiben reicht nach dieser Anpassung:
  • A: 5, 20
class Ausgangsfuzzyset
{
    public:
        int fg_anzahl;
        Fuzzygroesse** fg;
        double* zwerte;
        Ausgangsfuzzyset(int fg_anzahl)
        {
            this->fg_anzahl = fg_anzahl;
            fg = new Fuzzygroesse*[fg_anzahl];
            //Dummywerte eintragen:
            for(int i=0;i<fg_anzahl;i++)
                fg[i] = new Fuzzygroesse((double)i,(double)(i+1),(double)(i+2),false,false);
            zwerte = new double[fg_anzahl];
        }
        void setzeStellen(double* stelle) //auch hier nur p1-Werte übergeben
        {
            fg[0]->p[0] = stelle[0]-(stelle[1]-stelle[0]); //p2 an p1 spiegeln
            fg[0]->p[1] = stelle[0];
            fg[0]->p[2] = stelle[1];
            for(int i=1;i<fg_anzahl-1;i++)
            {
                fg[i]->p[0] = stelle[i-1];
                fg[i]->p[1] = stelle[i];
                fg[i]->p[2] = stelle[i+1];
            }
            fg[fg_anzahl-1]->p[0] = stelle[fg_anzahl-2];
            fg[fg_anzahl-1]->p[1] = stelle[fg_anzahl-1];
            fg[fg_anzahl-1]->p[2] = stelle[fg_anzahl-1]+(stelle[fg_anzahl-1]-stelle[fg_anzahl-2]); //p0 an p1 spiegeln
        }
        double berechneAusgang(int* fg_indices, double* fg_aktivierungen,int regel_anzahl)
        {
            double Ages=0.0;
            double sges=0.0;
            double Aaktuell=0.0;
            for(int i=0;i<regel_anzahl;i++)
            {
                Aaktuell = fg[fg_indices[i]]->berechneFlaeche(fg_aktivierungen[i]);
                Ages+=Aaktuell;
                sges+=Aaktuell*fg[fg_indices[i]]->berechneSchwerpunkt(fg_aktivierungen[i]);
            }
            return sges/Ages;
        }
};

Code 0-2: Quellcode der Klasse Ausgangsfuzzyset aus der Datei Ausgangsfuzzyset.h

Übungsaufgabe c): Lösen Sie nun vollends die Übung 9 mit Hilfe eines selbstgeschriebenen Programms unter Verwendung der hier dargestellten Klassen.
R=7 und T=12.5, =>
Rkalt   = 0.6
Rmittel = 0.4
Rwarm   = 0
Tkalt   = 0.5
Twarm   = 0.5
Ausgangsaktivieurng bei R=7 und T=12.5: A=13.0935
R=5 und T=7, =>
Rkalt   = 1
Rmittel = 0
Rwarm   = 0
Tkalt   = 0.866667
Twarm   = 0.133333
Ausgangsaktivieurng bei R=5 und T=7.5: A=20

Code 0-3: Kontrollausgabe zu Übungsaufgabe c) - Rechnen Sie die Ergebnisse zur Übung auch von Hand nach.

Übungsaufgabe d): Vereinfachen Sie die Defuzzifizierung in dem Programmbeispiel durch Verwendung von Nadelförmigen Zugehörigkeitsfunktion, wie eingangsbeschrieben.