diff options
Diffstat (limited to 'fuzzylite/src/defuzzifier')
-rw-r--r-- | fuzzylite/src/defuzzifier/Bisector.cpp | 85 | ||||
-rw-r--r-- | fuzzylite/src/defuzzifier/Centroid.cpp | 80 | ||||
-rw-r--r-- | fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp | 53 | ||||
-rw-r--r-- | fuzzylite/src/defuzzifier/LargestOfMaximum.cpp | 75 | ||||
-rw-r--r-- | fuzzylite/src/defuzzifier/MeanOfMaximum.cpp | 88 | ||||
-rw-r--r-- | fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp | 77 | ||||
-rw-r--r-- | fuzzylite/src/defuzzifier/WeightedAverage.cpp | 123 | ||||
-rw-r--r-- | fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp | 178 | ||||
-rw-r--r-- | fuzzylite/src/defuzzifier/WeightedSum.cpp | 121 |
9 files changed, 880 insertions, 0 deletions
diff --git a/fuzzylite/src/defuzzifier/Bisector.cpp b/fuzzylite/src/defuzzifier/Bisector.cpp new file mode 100644 index 0000000..ee4d2fc --- /dev/null +++ b/fuzzylite/src/defuzzifier/Bisector.cpp @@ -0,0 +1,85 @@ +/* + Author: Juan Rada-Vilela, Ph.D. + Copyright (C) 2010-2014 FuzzyLite Limited + All rights reserved + + This file is part of fuzzylite. + + fuzzylite 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 3 of the License, or (at your option) + any later version. + + fuzzylite 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 fuzzylite. If not, see <http://www.gnu.org/licenses/>. + + fuzzylite™ is a trademark of FuzzyLite Limited. + + */ + +#include "fl/defuzzifier/Bisector.h" + +#include "fl/term/Accumulated.h" +#include "fl/term/Term.h" + +namespace fl { + + Bisector::Bisector(int resolution) + : IntegralDefuzzifier(resolution) { + } + + Bisector::~Bisector() { + + } + + std::string Bisector::className() const { + return "Bisector"; + } + + scalar Bisector::defuzzify(const Term* term, scalar minimum, scalar maximum) const { + if (not fl::Op::isFinite(minimum + maximum)) { + return fl::nan; + } + if (maximum - minimum > _resolution) { + FL_DBG("[accuracy warning] the resolution <" << _resolution << "> " + "is smaller than the range <" << minimum << ", " << maximum << ">. In order to " + "improve the accuracy, the resolution should be at least equal to the range."); + } + scalar dx = (maximum - minimum) / _resolution; + + int counter = _resolution; + int left = 0, right = 0; + scalar leftArea = 0, rightArea = 0; + scalar xLeft = minimum, xRight = maximum; + while (counter-- > 0) { + if (fl::Op::isLE(leftArea, rightArea)) { + xLeft = minimum + (left + 0.5) * dx; + leftArea += term->membership(xLeft); + left++; + } else { + xRight = maximum - (right + 0.5) * dx; + rightArea += term->membership(xRight); + right++; + } + } + + //Inverse weighted average to compensate + scalar bisector = (leftArea * xRight + rightArea * xLeft) / (leftArea + rightArea); + return bisector; + } + + Bisector* Bisector::clone() const { + return new Bisector(*this); + } + + Defuzzifier* Bisector::constructor() { + return new Bisector; + } + + +} diff --git a/fuzzylite/src/defuzzifier/Centroid.cpp b/fuzzylite/src/defuzzifier/Centroid.cpp new file mode 100644 index 0000000..01490d3 --- /dev/null +++ b/fuzzylite/src/defuzzifier/Centroid.cpp @@ -0,0 +1,80 @@ +/* + Author: Juan Rada-Vilela, Ph.D. + Copyright (C) 2010-2014 FuzzyLite Limited + All rights reserved + + This file is part of fuzzylite. + + fuzzylite 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 3 of the License, or (at your option) + any later version. + + fuzzylite 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 fuzzylite. If not, see <http://www.gnu.org/licenses/>. + + fuzzylite™ is a trademark of FuzzyLite Limited. + + */ + +#include "fl/defuzzifier/Centroid.h" + +#include "fl/term/Accumulated.h" +#include "fl/term/Term.h" + + +namespace fl { + + Centroid::Centroid(int resolution) + : IntegralDefuzzifier(resolution) { + } + + Centroid::~Centroid() { + + } + + std::string Centroid::className() const { + return "Centroid"; + } + + scalar Centroid::defuzzify(const Term* term, scalar minimum, scalar maximum) const { + if (not fl::Op::isFinite(minimum + maximum)) { + return fl::nan; + } + if (maximum - minimum > _resolution) { + FL_DBG("[accuracy warning] the resolution <" << _resolution << "> " + "is smaller than the range <" << minimum << ", " << maximum << ">. In order to " + "improve the accuracy, the resolution should be at least equal to the range."); + } + scalar dx = (maximum - minimum) / _resolution; + scalar x, y; + scalar area = 0, xcentroid = 0, ycentroid = 0; + for (int i = 0; i < _resolution; ++i) { + x = minimum + (i + 0.5) * dx; + y = term->membership(x); + + xcentroid += y * x; + ycentroid += y * y; + area += y; + } + xcentroid /= area; + ycentroid /= 2 * area; + area *= dx; //total area... unused, but for future reference. + return xcentroid; + } + + Centroid* Centroid::clone() const { + return new Centroid(*this); + } + + Defuzzifier* Centroid::constructor() { + return new Centroid; + } + + +} diff --git a/fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp b/fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp new file mode 100644 index 0000000..2badf14 --- /dev/null +++ b/fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp @@ -0,0 +1,53 @@ +/* + Author: Juan Rada-Vilela, Ph.D. + Copyright (C) 2010-2014 FuzzyLite Limited + All rights reserved + + This file is part of fuzzylite. + + fuzzylite 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 3 of the License, or (at your option) + any later version. + + fuzzylite 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 fuzzylite. If not, see <http://www.gnu.org/licenses/>. + + fuzzylite™ is a trademark of FuzzyLite Limited. + + */ + +#include "fl/defuzzifier/IntegralDefuzzifier.h" + +namespace fl { + + int IntegralDefuzzifier::_defaultResolution = 200; + + void IntegralDefuzzifier::setDefaultResolution(int defaultResolution) { + _defaultResolution = defaultResolution; + } + + int IntegralDefuzzifier::defaultResolution() { + return _defaultResolution; + } + + IntegralDefuzzifier::IntegralDefuzzifier(int resolution) + : Defuzzifier(), _resolution(resolution) { + } + + IntegralDefuzzifier::~IntegralDefuzzifier() { + } + + void IntegralDefuzzifier::setResolution(int resolution) { + this->_resolution = resolution; + } + + int IntegralDefuzzifier::getResolution() const { + return this->_resolution; + } +} diff --git a/fuzzylite/src/defuzzifier/LargestOfMaximum.cpp b/fuzzylite/src/defuzzifier/LargestOfMaximum.cpp new file mode 100644 index 0000000..470af52 --- /dev/null +++ b/fuzzylite/src/defuzzifier/LargestOfMaximum.cpp @@ -0,0 +1,75 @@ +/* + Author: Juan Rada-Vilela, Ph.D. + Copyright (C) 2010-2014 FuzzyLite Limited + All rights reserved + + This file is part of fuzzylite. + + fuzzylite 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 3 of the License, or (at your option) + any later version. + + fuzzylite 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 fuzzylite. If not, see <http://www.gnu.org/licenses/>. + + fuzzylite™ is a trademark of FuzzyLite Limited. + + */ + +#include "fl/defuzzifier/LargestOfMaximum.h" + +#include "fl/Exception.h" +#include "fl/term/Term.h" + +namespace fl { + + LargestOfMaximum::LargestOfMaximum(int resolution) + : IntegralDefuzzifier(resolution) { + } + + LargestOfMaximum::~LargestOfMaximum() { + } + + std::string LargestOfMaximum::className() const { + return "LargestOfMaximum"; + } + + scalar LargestOfMaximum::defuzzify(const Term* term, scalar minimum, scalar maximum) const { + if (not fl::Op::isFinite(minimum + maximum)) { + return fl::nan; + } + if (maximum - minimum > _resolution) { + FL_DBG("[accuracy warning] the resolution <" << _resolution << "> " + "is smaller than the range <" << minimum << ", " << maximum << ">. In order to " + "improve the accuracy, the resolution should be at least equal to the range."); + } + scalar dx = (maximum - minimum) / _resolution; + scalar x, y; + scalar ymax = -1.0, xlargest = maximum; + for (int i = 0; i < _resolution; ++i) { + x = minimum + (i + 0.5) * dx; + y = term->membership(x); + + if (Op::isGE(y, ymax)) { + ymax = y; + xlargest = x; + } + } + return xlargest; + } + + LargestOfMaximum* LargestOfMaximum::clone() const { + return new LargestOfMaximum(*this); + } + + Defuzzifier* LargestOfMaximum::constructor() { + return new LargestOfMaximum; + } + +} diff --git a/fuzzylite/src/defuzzifier/MeanOfMaximum.cpp b/fuzzylite/src/defuzzifier/MeanOfMaximum.cpp new file mode 100644 index 0000000..7c40527 --- /dev/null +++ b/fuzzylite/src/defuzzifier/MeanOfMaximum.cpp @@ -0,0 +1,88 @@ +/* + Author: Juan Rada-Vilela, Ph.D. + Copyright (C) 2010-2014 FuzzyLite Limited + All rights reserved + + This file is part of fuzzylite. + + fuzzylite 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 3 of the License, or (at your option) + any later version. + + fuzzylite 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 fuzzylite. If not, see <http://www.gnu.org/licenses/>. + + fuzzylite™ is a trademark of FuzzyLite Limited. + + */ + +#include "fl/defuzzifier/MeanOfMaximum.h" + +#include "fl/Exception.h" +#include "fl/term/Term.h" + + +namespace fl { + + MeanOfMaximum::MeanOfMaximum(int resolution) + : IntegralDefuzzifier(resolution) { + } + + MeanOfMaximum::~MeanOfMaximum() { + } + + std::string MeanOfMaximum::className() const { + return "MeanOfMaximum"; + } + + scalar MeanOfMaximum::defuzzify(const Term* term, scalar minimum, scalar maximum) const { + if (not fl::Op::isFinite(minimum + maximum)) { + return fl::nan; + } + if (maximum - minimum > _resolution) { + FL_DBG("[accuracy warning] the resolution <" << _resolution << "> " + "is smaller than the range <" << minimum << ", " << maximum << ">. In order to " + "improve the accuracy, the resolution should be at least equal to the range."); + } + scalar dx = (maximum - minimum) / _resolution; + scalar x, y; + scalar ymax = -1.0; + scalar xsmallest = minimum; + scalar xlargest = maximum; + bool samePlateau = false; + for (int i = 0; i < _resolution; ++i) { + x = minimum + (i + 0.5) * dx; + y = term->membership(x); + + if (Op::isGt(y, ymax)) { + ymax = y; + + xsmallest = x; + xlargest = x; + + samePlateau = true; + } else if (Op::isEq(y, ymax) and samePlateau) { + xlargest = x; + } else if (Op::isLt(y, ymax)) { + samePlateau = false; + } + } + + return (xlargest + xsmallest) / 2.0; + } + + MeanOfMaximum* MeanOfMaximum::clone() const { + return new MeanOfMaximum(*this); + } + + Defuzzifier* MeanOfMaximum::constructor() { + return new MeanOfMaximum; + } + +} diff --git a/fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp b/fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp new file mode 100644 index 0000000..1e67395 --- /dev/null +++ b/fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp @@ -0,0 +1,77 @@ +/* + Author: Juan Rada-Vilela, Ph.D. + Copyright (C) 2010-2014 FuzzyLite Limited + All rights reserved + + This file is part of fuzzylite. + + fuzzylite 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 3 of the License, or (at your option) + any later version. + + fuzzylite 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 fuzzylite. If not, see <http://www.gnu.org/licenses/>. + + fuzzylite™ is a trademark of FuzzyLite Limited. + + */ + +#include "fl/defuzzifier/SmallestOfMaximum.h" + +#include "fl/Exception.h" +#include "fl/term/Term.h" + + +namespace fl { + + SmallestOfMaximum::SmallestOfMaximum(int resolution) + : IntegralDefuzzifier(resolution) { + } + + SmallestOfMaximum::~SmallestOfMaximum() { + } + + std::string SmallestOfMaximum::className() const { + return "SmallestOfMaximum"; + } + + scalar SmallestOfMaximum::defuzzify(const Term* term, scalar minimum, scalar maximum) const { + if (not fl::Op::isFinite(minimum + maximum)) { + return fl::nan; + } + if (maximum - minimum > _resolution) { + FL_DBG("[accuracy warning] the resolution <" << _resolution << "> " + "is smaller than the range <" << minimum << ", " << maximum << ">. In order to " + "improve the accuracy, the resolution should be at least equal to the range."); + } + scalar dx = (maximum - minimum) / _resolution; + scalar x, y; + scalar ymax = -1.0, xsmallest = minimum; + for (int i = 0; i < _resolution; ++i) { + x = minimum + (i + 0.5) * dx; + y = term->membership(x); + + if (Op::isGt(y, ymax)) { + xsmallest = x; + ymax = y; + } + } + return xsmallest; + } + + SmallestOfMaximum* SmallestOfMaximum::clone() const { + return new SmallestOfMaximum(*this); + } + + Defuzzifier* SmallestOfMaximum::constructor() { + return new SmallestOfMaximum; + } + +} + diff --git a/fuzzylite/src/defuzzifier/WeightedAverage.cpp b/fuzzylite/src/defuzzifier/WeightedAverage.cpp new file mode 100644 index 0000000..105c9d4 --- /dev/null +++ b/fuzzylite/src/defuzzifier/WeightedAverage.cpp @@ -0,0 +1,123 @@ +/* + Author: Juan Rada-Vilela, Ph.D. + Copyright (C) 2010-2014 FuzzyLite Limited + All rights reserved + + This file is part of fuzzylite. + + fuzzylite 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 3 of the License, or (at your option) + any later version. + + fuzzylite 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 fuzzylite. If not, see <http://www.gnu.org/licenses/>. + + fuzzylite™ is a trademark of FuzzyLite Limited. + + */ + +#include "fl/defuzzifier/WeightedAverage.h" + +#include "fl/term/Accumulated.h" +#include "fl/term/Activated.h" +#include "fl/norm/Norm.h" +#include "fl/norm/SNorm.h" +#include "fl/norm/TNorm.h" + +#include <map> + +namespace fl { + + WeightedAverage::WeightedAverage(Type type) : WeightedDefuzzifier(type) { + } + + WeightedAverage::WeightedAverage(const std::string& type) : WeightedDefuzzifier(type) { + } + + WeightedAverage::~WeightedAverage() { + } + + std::string WeightedAverage::className() const { + return "WeightedAverage"; + } + + scalar WeightedAverage::defuzzify(const Term* term, + scalar minimum, scalar maximum) const { + const Accumulated* fuzzyOutput = dynamic_cast<const Accumulated*> (term); + if (not fuzzyOutput) { + std::ostringstream ss; + ss << "[defuzzification error]" + << "expected an Accumulated term instead of" + << "<" << term->toString() << ">"; + throw fl::Exception(ss.str(), FL_AT); + } + + minimum = fuzzyOutput->getMinimum(); + maximum = fuzzyOutput->getMaximum(); + + scalar sum = 0.0; + scalar weights = 0.0; + + if (not fuzzyOutput->getAccumulation()) { + Type type = _type; + for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) { + Activated* activated = fuzzyOutput->getTerm(i); + scalar w = activated->getDegree(); + + if (type == Automatic) type = inferType(activated->getTerm()); + + scalar z = (type == TakagiSugeno) + //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work. + ? activated->getTerm()->membership(w) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions + : tsukamoto(activated->getTerm(), w, minimum, maximum); + + sum += w * z; + weights += w; + } + } else { + typedef std::map<const Term*, std::vector<Activated*> > TermGroup; + TermGroup groups; + for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) { + Activated* value = fuzzyOutput->getTerm(i); + const Term* key = value->getTerm(); + groups[key].push_back(value); + } + TermGroup::const_iterator it = groups.begin(); + Type type = _type; + while (it != groups.end()) { + const Term* activatedTerm = it->first; + scalar accumulatedDegree = 0.0; + for (std::size_t i = 0; i < it->second.size(); ++i) + accumulatedDegree = fuzzyOutput->getAccumulation()->compute( + accumulatedDegree, it->second.at(i)->getDegree()); + + if (type == Automatic) type = inferType(activatedTerm); + + scalar z = (type == TakagiSugeno) + //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work. + ? activatedTerm->membership(accumulatedDegree) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions + : tsukamoto(activatedTerm, accumulatedDegree, minimum, maximum); + + sum += accumulatedDegree * z; + weights += accumulatedDegree; + + ++it; + } + } + return sum / weights; + } + + WeightedAverage* WeightedAverage::clone() const { + return new WeightedAverage(*this); + } + + Defuzzifier* WeightedAverage::constructor() { + return new WeightedAverage; + } +} diff --git a/fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp b/fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp new file mode 100644 index 0000000..760a5dc --- /dev/null +++ b/fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp @@ -0,0 +1,178 @@ +/* + Author: Juan Rada-Vilela, Ph.D. + Copyright (C) 2010-2014 FuzzyLite Limited + All rights reserved + + This file is part of fuzzylite. + + fuzzylite 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 3 of the License, or (at your option) + any later version. + + fuzzylite 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 fuzzylite. If not, see <http://www.gnu.org/licenses/>. + + fuzzylite™ is a trademark of FuzzyLite Limited. + + */ + +#include "fl/defuzzifier/WeightedDefuzzifier.h" + +#include "fl/term/Activated.h" +#include "fl/term/Concave.h" +#include "fl/term/Constant.h" +#include "fl/term/Function.h" +#include "fl/term/Linear.h" +#include "fl/term/Ramp.h" +#include "fl/term/Sigmoid.h" +#include "fl/term/SShape.h" +#include "fl/term/ZShape.h" + +namespace fl { + + WeightedDefuzzifier::WeightedDefuzzifier(Type type) : _type(type) { + + } + + WeightedDefuzzifier::WeightedDefuzzifier(const std::string& type) { + if (type == "Automatic") _type = Automatic; + else if (type == "TakagiSugeno") _type = TakagiSugeno; + else if (type == "Tsukamoto") _type = Tsukamoto; + else { + _type = Automatic; + FL_LOG("[warning] incorrect type <" + type + "> of WeightedDefuzzifier" + + " has been defaulted to <Automatic>"); + } + } + + WeightedDefuzzifier::~WeightedDefuzzifier() { + + } + + std::string WeightedDefuzzifier::typeName(Type type) { + switch (type) { + case Automatic: return "Automatic"; + case TakagiSugeno: return "TakagiSugeno"; + case Tsukamoto: return "Tsukamoto"; + default: return ""; + } + } + + void WeightedDefuzzifier::setType(Type type) { + this->_type = type; + } + + WeightedDefuzzifier::Type WeightedDefuzzifier::getType() const { + return this->_type; + } + + std::string WeightedDefuzzifier::getTypeName() const { + return typeName(this->_type); + } + + WeightedDefuzzifier::Type WeightedDefuzzifier::inferType(const Term* term) const { + if (dynamic_cast<const Constant*> (term) + or dynamic_cast<const Linear*> (term) + or dynamic_cast<const Function*> (term)) { + return TakagiSugeno; + } + return Tsukamoto; + } + + bool WeightedDefuzzifier::isMonotonic(const Term* term) const { + return (dynamic_cast<const Concave*> (term)) or + (dynamic_cast<const Ramp*> (term)) or + (dynamic_cast<const Sigmoid*> (term)) or + (dynamic_cast<const SShape*> (term)) or + (dynamic_cast<const ZShape*> (term)); + } + + /** + * Instead of computing y=f(x), the goal of Tsukamoto is to find x=f(w), + * where f is monotonic. + */ + scalar WeightedDefuzzifier::tsukamoto(const Term* monotonic, scalar activationDegree, + scalar minimum, scalar maximum) const { + scalar w = activationDegree; + scalar z = fl::nan; //result; + bool isTsukamoto = true; + if (const Ramp* ramp = dynamic_cast<const Ramp*> (monotonic)) { + z = Op::scale(w, 0, 1, ramp->getStart(), ramp->getEnd()); + + } else if (const Sigmoid* sigmoid = dynamic_cast<const Sigmoid*> (monotonic)) { + if (Op::isEq(w, 1.0)) { + if (Op::isGE(sigmoid->getSlope(), 0.0)) { + z = maximum; + } else { + z = minimum; + } + + } else if (Op::isEq(w, 0.0)) { + if (Op::isGE(sigmoid->getSlope(), 0.0)) { + z = minimum; + } else { + z = maximum; + } + } else { + scalar a = sigmoid->getSlope(); + scalar b = sigmoid->getInflection(); + z = b + (std::log(1.0 / w - 1.0) / -a); + } + + } else if (const SShape* sshape = dynamic_cast<const SShape*> (monotonic)) { + scalar difference = sshape->getEnd() - sshape->getStart(); + scalar a = sshape->getStart() + std::sqrt(w * difference * difference / 2.0); + scalar b = sshape->getEnd() + std::sqrt(difference * difference * (w - 1.0) / -2.0); + if (std::fabs(w - monotonic->membership(a)) < + std::fabs(w - monotonic->membership(b))) { + z = a; + } else { + z = b; + } + + } else if (const ZShape* zshape = dynamic_cast<const ZShape*> (monotonic)) { + scalar difference = zshape->getEnd() - zshape->getStart(); + scalar a = zshape->getStart() + std::sqrt(difference * difference * (w - 1.0) / -2.0); + scalar b = zshape->getEnd() + std::sqrt(w * difference * difference / 2.0); + if (std::fabs(w - monotonic->membership(a)) < + std::fabs(w - monotonic->membership(b))) { + z = a; + } else { + z = b; + } + + } else if (const Concave* concave = dynamic_cast<const Concave*> (monotonic)) { + scalar i = concave->getInflection(); + scalar e = concave->getEnd(); + z = (i - e) / concave->membership(w) + 2 * e - i; + } else { + isTsukamoto = false; + } + + if (isTsukamoto) { + //Compare difference between estimated and true value + scalar fz = monotonic->membership(z); + if (not Op::isEq(w, fz, 1e-2)) { + FL_DBG("[tsukamoto warning] difference <" << Op::str(std::abs(w - fz)) << "> " + "might suggest an inaccurate computation of z because it is " + "expected w=f(z) in " << monotonic->className() << + " term <" << monotonic->getName() << ">, but " + "w=" << w << " " + "f(z)=" << fz << " and " + "z=" << Op::str(z)); + } + } else { + // else fallback to the regular Takagi-Sugeno or inverse Tsukamoto (according to term) + z = monotonic->membership(w); + } + return z; + } + + +} diff --git a/fuzzylite/src/defuzzifier/WeightedSum.cpp b/fuzzylite/src/defuzzifier/WeightedSum.cpp new file mode 100644 index 0000000..fb3e2e3 --- /dev/null +++ b/fuzzylite/src/defuzzifier/WeightedSum.cpp @@ -0,0 +1,121 @@ +/* + Author: Juan Rada-Vilela, Ph.D. + Copyright (C) 2010-2014 FuzzyLite Limited + All rights reserved + + This file is part of fuzzylite. + + fuzzylite 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 3 of the License, or (at your option) + any later version. + + fuzzylite 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 fuzzylite. If not, see <http://www.gnu.org/licenses/>. + + fuzzylite™ is a trademark of FuzzyLite Limited. + + */ + +#include "fl/defuzzifier/WeightedSum.h" + +#include "fl/term/Accumulated.h" +#include "fl/term/Activated.h" +#include "fl/norm/SNorm.h" +#include "fl/norm/TNorm.h" + +#include <map> +namespace fl { + + WeightedSum::WeightedSum(Type type) : WeightedDefuzzifier(type) { + } + + WeightedSum::WeightedSum(const std::string& type) : WeightedDefuzzifier(type) { + + } + + WeightedSum::~WeightedSum() { + } + + std::string WeightedSum::className() const { + return "WeightedSum"; + } + + scalar WeightedSum::defuzzify(const Term* term, + scalar minimum, scalar maximum) const { + const Accumulated* fuzzyOutput = dynamic_cast<const Accumulated*> (term); + if (not fuzzyOutput) { + std::ostringstream ss; + ss << "[defuzzification error]" + << "expected an Accumulated term instead of" + << "<" << term->toString() << ">"; + throw fl::Exception(ss.str(), FL_AT); + } + + minimum = fuzzyOutput->getMinimum(); + maximum = fuzzyOutput->getMaximum(); + + + scalar sum = 0.0; + + if (not fuzzyOutput->getAccumulation()) { + Type type = _type; + for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) { + Activated* activated = fuzzyOutput->getTerm(i); + scalar w = activated->getDegree(); + + if (type == Automatic) type = inferType(activated->getTerm()); + + scalar z = (type == TakagiSugeno) + //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work. + ? activated->getTerm()->membership(w) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions + : tsukamoto(activated->getTerm(), w, minimum, maximum); + + sum += w * z; + } + } else { + typedef std::map<const Term*, std::vector<Activated*> > TermGroup; + TermGroup groups; + for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) { + Activated* value = fuzzyOutput->getTerm(i); + const Term* key = value->getTerm(); + groups[key].push_back(value); + } + TermGroup::const_iterator it = groups.begin(); + Type type = _type; + while (it != groups.end()) { + const Term* activatedTerm = it->first; + scalar accumulatedDegree = 0.0; + for (std::size_t i = 0; i < it->second.size(); ++i) + accumulatedDegree = fuzzyOutput->getAccumulation()->compute( + accumulatedDegree, it->second.at(i)->getDegree()); + + if (type == Automatic) type = inferType(activatedTerm); + + scalar z = (type == TakagiSugeno) + //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work. + ? activatedTerm->membership(accumulatedDegree) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions + : tsukamoto(activatedTerm, accumulatedDegree, minimum, maximum); + + sum += accumulatedDegree * z; + + ++it; + } + } + return sum; + } + + WeightedSum* WeightedSum::clone() const { + return new WeightedSum(*this); + } + + Defuzzifier* WeightedSum::constructor() { + return new WeightedSum; + } + +} |