summaryrefslogtreecommitdiff
path: root/fuzzylite/src/defuzzifier
diff options
context:
space:
mode:
Diffstat (limited to 'fuzzylite/src/defuzzifier')
-rw-r--r--fuzzylite/src/defuzzifier/Bisector.cpp85
-rw-r--r--fuzzylite/src/defuzzifier/Centroid.cpp80
-rw-r--r--fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp53
-rw-r--r--fuzzylite/src/defuzzifier/LargestOfMaximum.cpp75
-rw-r--r--fuzzylite/src/defuzzifier/MeanOfMaximum.cpp88
-rw-r--r--fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp77
-rw-r--r--fuzzylite/src/defuzzifier/WeightedAverage.cpp123
-rw-r--r--fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp178
-rw-r--r--fuzzylite/src/defuzzifier/WeightedSum.cpp121
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;
+ }
+
+}