Commit 5779b62d authored by Falko Schumann's avatar Falko Schumann
Browse files

Refaktorisierung

parent 2c62c656
Loading
Loading
Loading
Loading
+105 −0
Original line number Diff line number Diff line
/*
 * Segment 5 Intelligente Analyseverfahren, SWE 5.4 Funktionen Fuzzy
 * Copyright (C) 2007-2018 BitCtrl Systems GmbH
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
 *
 * Contact Information:
 * BitCtrl Systems GmbH
 * Weißenfelser Straße 67
 * 04229 Leipzig
 * Phone: +49 341-490670
 * mailto: info@bitctrl.de
 */

package de.bsvrz.iav.fuzzylib.fuzzylib;

import java.util.*;
import java.util.stream.*;

class Defuzzyfizierung {

    private final LinguistischeVariable linguistischeVariable;

    Defuzzyfizierung(LinguistischeVariable linguistischeVariable) {
        this.linguistischeVariable = linguistischeVariable;
    }

    double defuzzyfiziere(FuzzyVariable fuzzyWert) {
        List<FuzzySet> fuzzySets = bestimmeRelevanteFuzzySets(fuzzyWert);
        if (fuzzySets.isEmpty()) {
            return Double.NaN;
        }
        Wertebereich intervall = bestimmeIntervall(fuzzySets);
        return bestimmeFlaechenschwerpunkt(fuzzyWert, fuzzySets, intervall);
    }

    private List<FuzzySet> bestimmeRelevanteFuzzySets(FuzzyVariable fuzzyWert) {
        List<String> gemeinsameTerme = bestimmeGemeinsameTerme(fuzzyWert);
        return gemeinsameTerme.stream()
                .map(t -> linguistischeVariable.gibFuzzySet(t))
                .sorted(Comparator.comparingDouble(FuzzySet::getT1))
                .collect(Collectors.toList());
    }

    private Wertebereich bestimmeIntervall(List<FuzzySet> fuzzySets) {
        double min = fuzzySets.stream()
                .mapToDouble(FuzzySet::getT1)
                .min()
                .getAsDouble();
        double max = fuzzySets.stream()
                .mapToDouble(FuzzySet::getT4)
                .max()
                .getAsDouble();
        return new Wertebereich(min, max);
    }

    private double bestimmeFlaechenschwerpunkt(FuzzyVariable fuzzyWert, List<FuzzySet> fuzzySets, Wertebereich intervall) {
        double min = intervall.getMinimum();
        double max = intervall.getMaximum();
        double minSchrittweite = 0.5;
        int maxAnzahlStuetzpunkte = 100;
        int anzahlStuetzpunkte = (int) Math.min((max - min) / minSchrittweite, maxAnzahlStuetzpunkte);

        double a = 0;
        double l = 0;
        for (int i = 0; i <= anzahlStuetzpunkte; i++) {
            double stuetzpunkt = min + i * (max - min) / anzahlStuetzpunkte;
            double zugehoerigkeit = Double.NEGATIVE_INFINITY;
            for (FuzzySet fs : fuzzySets) {
                double zugehoerigkeitFuzzySet = fs.bestimmeZugehoerigkeit(stuetzpunkt);
                double zugehoerigkeitTerm = fuzzyWert.gibTerm(fs.getName()).getZugehoerigkeit().getWert();
                double z = Math.min(zugehoerigkeitFuzzySet, zugehoerigkeitTerm);
                if (z > zugehoerigkeit) {
                    zugehoerigkeit = z;
                }
            }
            a += stuetzpunkt * zugehoerigkeit;
            l += zugehoerigkeit;
        }
        return a / l;
    }

    private List<String> bestimmeGemeinsameTerme(FuzzyVariable fuzzyVariable) {
        List<String> nonNullTerme = fuzzyVariable.getTerme().stream()
                .filter(t -> t.getZugehoerigkeit().nonNull())
                .filter(t -> t.getZugehoerigkeit().getWert() > 0)
                .map(Term::getName)
                .collect(Collectors.toList());
        nonNullTerme.retainAll(linguistischeVariable.getTerme());
        return nonNullTerme;
    }

}
+81 −0
Original line number Diff line number Diff line
/*
 * Segment 5 Intelligente Analyseverfahren, SWE 5.4 Funktionen Fuzzy
 * Copyright (C) 2007-2018 BitCtrl Systems GmbH
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
 *
 * Contact Information:
 * BitCtrl Systems GmbH
 * Weißenfelser Straße 67
 * 04229 Leipzig
 * Phone: +49 341-490670
 * mailto: info@bitctrl.de
 */

package de.bsvrz.iav.fuzzylib.fuzzylib;

import java.util.*;
import java.util.stream.*;

class Fuzzyfizierung {

    private final LinguistischeVariable linguistischeVariable;

    Fuzzyfizierung(LinguistischeVariable linguistischeVariable) {
        this.linguistischeVariable = linguistischeVariable;
    }

    FuzzyVariable fuzzyfiziere(double wert) {
        // TODO Wenn nur t2 und t3 der Fuzzy-Sets angegeben sind, t1 und t4 so berechnen, das fließende Übergänge entstehen
        // TODO Wenn nur t2 und t3 der Fuzzy-Sets angegeben sind, für erstes und letztes Fuzzy-Set im Wertebereich Rampen annehmen

        List<Term> terme = fuzzyfiziere(linguistischeVariable.getFuzzySets(), wert);
        terme = fasseGleicheTermeZusammen(terme);
        return new FuzzyVariable(linguistischeVariable.getName(), terme);
    }

    private List<Term> fuzzyfiziere(List<FuzzySet> fuzzySets, double wert) {
        return fuzzySets.stream()
                .map(fs -> bestimmeTerm(fs, wert))
                .collect(Collectors.toList());
    }

    private List<Term> fasseGleicheTermeZusammen(List<Term> terme) {
        List<Term> zusammengefasst = new ArrayList<>();
        for (Term t : terme) {
            boolean neuerTerm = true;
            for (int i = 0; i < zusammengefasst.size(); i++) {
                if (t.getName().equals(zusammengefasst.get(i).getName())) {
                    double z1 = t.getZugehoerigkeit().getWert();
                    double z2 = zusammengefasst.get(i).getZugehoerigkeit().getWert();
                    double z = Math.max(z1, z2);
                    zusammengefasst.set(i, new Term(t.getName(), Zugehoerigkeit.von(z)));
                    neuerTerm = false;
                    break;
                }
            }
            if (neuerTerm) {
                zusammengefasst.add(t);
            }
        }
        return zusammengefasst;
    }

    private Term bestimmeTerm(FuzzySet fuzzySet, double wert) {
        double z = fuzzySet.bestimmeZugehoerigkeit(wert);
        return new Term(fuzzySet.getName(), Zugehoerigkeit.von(z));
    }

}
+4 −82
Original line number Diff line number Diff line
@@ -37,8 +37,7 @@ import java.util.stream.*;
 * <p>
 * Durch Fuzzyfizierung wird für einen scharfen Messwert eine Fuzzy-Variable
 * bestimmt. Durch Defuzzyfizierung wird für eine Fuzzy-Variable ein scharfer
 * Messwert bestimmt. Fuzzyfizierung und Defuzzyfizierung finden nur im
 * Wertebereich der Messgröße statt.
 * Messwert bestimmt.
 *
 * @author BitCtrl Systems GmbH, Falko Schumann
 * @see FuzzySet
@@ -125,88 +124,11 @@ public final class LinguistischeVariable {
    }

    public FuzzyVariable fuzzyfiziere(double wert) {
        // TODO Wenn nur t2 und t3 der Fuzzy-Sets angegeben sind, t1 und t4 so berechnen, das fließende Übergänge entstehen
        // TODO Wenn nur t2 und t3 der Fuzzy-Sets angegeben sind, für erstes und letztes Fuzzy-Set im Wertebereich Rampen annehmen

        List<Term> terme = fuzzyfiziere(fuzzySets, wert);
        terme = fasseGleicheTermeZusammen(terme);
        return new FuzzyVariable(name, terme);
        return new Fuzzyfizierung(this).fuzzyfiziere(wert);
    }

    private static List<Term> fuzzyfiziere(List<FuzzySet> fuzzySets, double wert) {
        return fuzzySets.stream()
                .map(fs -> bestimmeTerm(fs, wert))
                .collect(Collectors.toList());
    }

    private static Term bestimmeTerm(FuzzySet fuzzySet, double wert) {
        double z = fuzzySet.bestimmeZugehoerigkeit(wert);
        return new Term(fuzzySet.getName(), Zugehoerigkeit.von(z));
    }

    private List<Term> fasseGleicheTermeZusammen(List<Term> terme) {
        List<Term> zusammengefasst = new ArrayList<>();
        for (Term t : terme) {
            boolean neuerTerm = true;
            for (int i = 0; i < zusammengefasst.size(); i++) {
                if (t.getName().equals(zusammengefasst.get(i).getName())) {
                    double z1 = t.getZugehoerigkeit().getWert();
                    double z2 = zusammengefasst.get(i).getZugehoerigkeit().getWert();
                    double z = Math.max(z1, z2);
                    zusammengefasst.set(i, new Term(t.getName(), Zugehoerigkeit.von(z)));
                    neuerTerm = false;
                    break;
                }
            }
            if (neuerTerm) {
                zusammengefasst.add(t);
            }
        }
        return zusammengefasst;
    }

    public double defuzzyfiziere(FuzzyVariable variable) {
        List<String> terme = variable.getTerme().stream()
                .filter(t -> t.getZugehoerigkeit().nonNull())
                .map(Term::getName)
                .collect(Collectors.toList());
        terme.retainAll(getTerme());

        List<FuzzySet> fuzzySets = getFuzzySets().stream()
                .filter(fs -> terme.contains(fs.getName()))
                .filter(fs -> variable.gibTerm(fs.getName()).getZugehoerigkeit().getWert() > 0)
                .sorted(Comparator.comparingDouble(FuzzySet::getT1))
                .collect(Collectors.toList());
        double min = fuzzySets.stream()
                .mapToDouble(FuzzySet::getT1)
                .min()
                .getAsDouble();
        double max = fuzzySets.stream()
                .mapToDouble(FuzzySet::getT4)
                .max()
                .getAsDouble();

        double minSchrittweite = 0.5;
        int maxAnzahlStuetzpunkte = 100;
        int anzahlStuetzpunkte = (int) Math.min((max - min) / minSchrittweite, maxAnzahlStuetzpunkte);

        double a = 0;
        double l = 0;
        for (int i = 0; i <= anzahlStuetzpunkte; i++) {
            double stuetzpunkt = min + i * (max - min) / anzahlStuetzpunkte;
            double zugehoerigkeit = Double.NEGATIVE_INFINITY;
            for (FuzzySet fs : fuzzySets) {
                double zugehoerigkeitFuzzySet = fs.bestimmeZugehoerigkeit(stuetzpunkt);
                double zugehoerigkeitTerm = variable.gibTerm(fs.getName()).getZugehoerigkeit().getWert();
                double z = Math.min(zugehoerigkeitFuzzySet, zugehoerigkeitTerm);
                if (z > zugehoerigkeit) {
                    zugehoerigkeit = z;
                }
            }
            a += stuetzpunkt * zugehoerigkeit;
            l += zugehoerigkeit;
        }
        return a / l;
    public double defuzzyfiziere(FuzzyVariable fuzzyWert) {
        return new Defuzzyfizierung(this).defuzzyfiziere(fuzzyWert);
    }

    @Override
+27 −15
Original line number Diff line number Diff line
@@ -195,34 +195,46 @@ public class LinguistischeVariableTests {
                FuzzySet.dreieck("c", 16, 24, 32),
                FuzzySet.aufsteigendeRampe("d", 24, 32, 36)
        );

        double wert = linguistischeVariable.defuzzyfiziere(
                new FuzzyVariable("x",
        FuzzyVariable fuzzyWert = new FuzzyVariable("x",
                new Term("a", Zugehoerigkeit.von(0.0)),
                new Term("b", Zugehoerigkeit.von(0.15)),
                new Term("c", Zugehoerigkeit.von(0.75)),
                new Term("d", Zugehoerigkeit.von(0.0))
                )
        );

        double wert = linguistischeVariable.defuzzyfiziere(fuzzyWert);

        assertEquals(22.43, wert, 0.01);
    }

    @Test
    public void defuzzyfiziere_Normalfall() {
        LinguistischeVariable linguistischeVariable = erzeugeLinguistischeVariable();

        double wert = linguistischeVariable.defuzzyfiziere(
                new FuzzyVariable("Geschwindigkeit",
        FuzzyVariable fuzzyWert = new FuzzyVariable("Geschwindigkeit",
                new Term("niedrig", Zugehoerigkeit.von(0.5)),
                new Term("mittel", Zugehoerigkeit.von(0.5)),
                new Term("hoch", Zugehoerigkeit.von(0.0))
                )
        );

        double wert = linguistischeVariable.defuzzyfiziere(fuzzyWert);

        assertEquals(41.04, wert, 0.01);
    }

    @Test
    public void defuzzyfiziere_TermePassenNicht() {
        LinguistischeVariable linguistischeVariable = erzeugeLinguistischeVariable();
        FuzzyVariable fuzzyWert = new FuzzyVariable("Geschwindigkeit",
                new Term("x", Zugehoerigkeit.von(0.5)),
                new Term("y", Zugehoerigkeit.von(0.5)),
                new Term("z", Zugehoerigkeit.von(0.0))
        );

        double wert = linguistischeVariable.defuzzyfiziere(fuzzyWert);

        assertTrue(Double.isNaN(wert));
    }

    @Test
    public void formattierterText() {
        LinguistischeVariable geschwindigkeit = erzeugeLinguistischeVariable();