summaryrefslogtreecommitdiff
path: root/fuzzylite/src/term
diff options
context:
space:
mode:
Diffstat (limited to 'fuzzylite/src/term')
-rw-r--r--fuzzylite/src/term/Accumulated.cpp211
-rw-r--r--fuzzylite/src/term/Activated.cpp80
-rw-r--r--fuzzylite/src/term/Aggregated.cpp247
-rw-r--r--fuzzylite/src/term/Bell.cpp40
-rw-r--r--fuzzylite/src/term/Binary.cpp96
-rw-r--r--fuzzylite/src/term/Concave.cpp68
-rw-r--r--fuzzylite/src/term/Constant.cpp34
-rw-r--r--fuzzylite/src/term/Cosine.cpp49
-rw-r--r--fuzzylite/src/term/Discrete.cpp194
-rw-r--r--fuzzylite/src/term/Function.cpp266
-rw-r--r--fuzzylite/src/term/Gaussian.cpp48
-rw-r--r--fuzzylite/src/term/GaussianProduct.cpp59
-rw-r--r--fuzzylite/src/term/Linear.cpp94
-rw-r--r--fuzzylite/src/term/PiShape.cpp78
-rw-r--r--fuzzylite/src/term/Ramp.cpp73
-rw-r--r--fuzzylite/src/term/Rectangle.cpp44
-rw-r--r--fuzzylite/src/term/SShape.cpp74
-rw-r--r--fuzzylite/src/term/Sigmoid.cpp78
-rw-r--r--fuzzylite/src/term/SigmoidDifference.cpp44
-rw-r--r--fuzzylite/src/term/SigmoidProduct.cpp43
-rw-r--r--fuzzylite/src/term/Spike.cpp42
-rw-r--r--fuzzylite/src/term/Term.cpp55
-rw-r--r--fuzzylite/src/term/Trapezoid.cpp56
-rw-r--r--fuzzylite/src/term/Triangle.cpp58
-rw-r--r--fuzzylite/src/term/ZShape.cpp74
25 files changed, 1157 insertions, 1048 deletions
diff --git a/fuzzylite/src/term/Accumulated.cpp b/fuzzylite/src/term/Accumulated.cpp
deleted file mode 100644
index 979af9f..0000000
--- a/fuzzylite/src/term/Accumulated.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- 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/term/Accumulated.h"
-
-#include "fl/imex/FllExporter.h"
-#include "fl/norm/SNorm.h"
-#include "fl/norm/s/Maximum.h"
-#include "fl/term/Activated.h"
-
-
-namespace fl {
-
- Accumulated::Accumulated(const std::string& name, scalar minimum, scalar maximum,
- SNorm* accumulation)
- : Term(name), _minimum(minimum), _maximum(maximum), _accumulation(accumulation) {
- }
-
- Accumulated::Accumulated(const Accumulated& other) : Term(other) {
- copyFrom(other);
- }
-
- Accumulated& Accumulated::operator=(const Accumulated& other) {
- if (this != &other) {
- clear();
- _accumulation.reset(fl::null);
-
- Term::operator=(other);
- copyFrom(other);
- }
- return *this;
- }
-
- Accumulated::~Accumulated() {
- clear();
- }
-
- void Accumulated::copyFrom(const Accumulated& source) {
- _minimum = source._minimum;
- _maximum = source._maximum;
-
- if (source._accumulation.get())
- _accumulation.reset(source._accumulation->clone());
-
- for (std::size_t i = 0; i < source._terms.size(); ++i) {
- _terms.push_back(source._terms.at(i)->clone());
- }
- }
-
- std::string Accumulated::className() const {
- return "Accumulated";
- }
-
- scalar Accumulated::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- if (not (_terms.empty() or _accumulation.get())) { //Exception for IntegralDefuzzifiers
- throw fl::Exception("[accumulation error] "
- "accumulation operator needed to accumulate " + toString(), FL_AT);
- }
- scalar mu = 0.0;
- for (std::size_t i = 0; i < _terms.size(); ++i) {
- mu = _accumulation->compute(mu, _terms.at(i)->membership(x));
- }
- return mu;
- }
-
- scalar Accumulated::activationDegree(const Term* forTerm) const {
- scalar result = 0.0;
- for (std::size_t i = 0; i < _terms.size(); ++i) {
- Activated* activatedTerm = _terms.at(i);
- if (activatedTerm->getTerm() == forTerm) {
- if (_accumulation.get()) result = _accumulation->compute(result, activatedTerm->getDegree());
- else result += activatedTerm->getDegree(); //Default for WeightDefuzzifier
- }
- }
- return result;
- }
-
- std::string Accumulated::parameters() const {
- FllExporter exporter;
- std::ostringstream ss;
- ss << exporter.toString(_accumulation.get());
- ss << " " << Op::str(_minimum) << " " << Op::str(_maximum) << " ";
- for (std::size_t i = 0; i < _terms.size(); ++i) {
- ss << " " << exporter.toString(_terms.at(i));
- }
- return ss.str();
- }
-
- void Accumulated::configure(const std::string& parameters) {
- (void) parameters;
- }
-
- Accumulated* Accumulated::clone() const {
- return new Accumulated(*this);
- }
-
- std::string Accumulated::toString() const {
- std::vector<std::string> accumulate;
- for (std::size_t i = 0; i < _terms.size(); ++i) {
- accumulate.push_back(_terms.at(i)->toString());
- }
- FllExporter exporter;
- std::ostringstream ss;
- ss << _name << ": " << className() << " "
- << exporter.toString(_accumulation.get()) << "["
- << fl::Op::join(accumulate, ",") << "]";
- return ss.str();
- }
-
- void Accumulated::setMinimum(scalar minimum) {
- this->_minimum = minimum;
- }
-
- scalar Accumulated::getMinimum() const {
- return this->_minimum;
- }
-
- void Accumulated::setMaximum(scalar maximum) {
- this->_maximum = maximum;
- }
-
- scalar Accumulated::getMaximum() const {
- return this->_maximum;
- }
-
- void Accumulated::setRange(scalar minimum, scalar maximum) {
- setMinimum(minimum);
- setMaximum(maximum);
- }
-
- scalar Accumulated::range() const {
- return this->_maximum - this->_minimum;
- }
-
- void Accumulated::setAccumulation(SNorm* accumulation) {
- this->_accumulation.reset(accumulation);
- }
-
- SNorm* Accumulated::getAccumulation() const {
- return this->_accumulation.get();
- }
-
- /**
- * Operations for std::vector _terms
- */
-
-
- void Accumulated::addTerm(const Term* term, scalar degree, const TNorm* activation) {
- this->_terms.push_back(new Activated(term, degree, activation));
- }
-
- void Accumulated::addTerm(Activated* term) {
- this->_terms.push_back(term);
- }
-
- Activated* Accumulated::removeTerm(int index) {
- Activated* term = this->_terms.at(index);
- this->_terms.erase(this->_terms.begin() + index);
- return term;
- }
-
- void Accumulated::clear() {
- for (std::size_t i = 0; i < _terms.size(); ++i) {
- delete _terms.at(i);
- }
- _terms.clear();
- }
-
- Activated* Accumulated::getTerm(int index) const {
- return this->_terms.at(index);
- }
-
- const std::vector<Activated*>& Accumulated::terms() const {
- return this->_terms;
- }
-
- std::vector<Activated*>& Accumulated::terms() {
- return this->_terms;
- }
-
- int Accumulated::numberOfTerms() const {
- return _terms.size();
- }
-
- bool Accumulated::isEmpty() const {
- return _terms.empty();
- }
-
-}
diff --git a/fuzzylite/src/term/Activated.cpp b/fuzzylite/src/term/Activated.cpp
index 9a27b4b..80eda6c 100644
--- a/fuzzylite/src/term/Activated.cpp
+++ b/fuzzylite/src/term/Activated.cpp
@@ -1,71 +1,81 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Activated.h"
#include "fl/imex/FllExporter.h"
-#include "fl/norm/TNorm.h"
namespace fl {
- Activated::Activated(const Term* term, scalar degree, const TNorm* activation)
- : Term(""), _term(term), _degree(degree), _activation(activation) {
- if (term) this->_name = term->getName();
+ Activated::Activated(const Term* term, scalar degree, const TNorm* implication)
+ : Term(""), _term(term), _degree(degree), _implication(implication) {
+ if (term) setName(term->getName());
}
- Activated::~Activated() {
- }
+ Activated::~Activated() { }
std::string Activated::className() const {
return "Activated";
}
+ Complexity Activated::complexity() const {
+ Complexity result;
+ result.comparison(3);
+ if (_implication) {
+ result += _implication->complexity();
+ }
+ if (_term) {
+ result += _term->complexity();
+ }
+ return result;
+ }
+
scalar Activated::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- if (not _activation) throw fl::Exception("[activation error] "
- "activation operator needed to activate " + _term->toString(), FL_AT);
- return _activation->compute(this->_term->membership(x), _degree);
+ if (Op::isNaN(x)) return fl::nan;
+ if (not _term)
+ throw Exception("[activation error] no term available to activate", FL_AT);
+ if (not _implication)
+ throw Exception("[implication error] implication operator needed "
+ "to activate " + getTerm()->toString(), FL_AT);
+ return _implication->compute(_term->membership(x), _degree);
}
std::string Activated::parameters() const {
FllExporter exporter;
std::ostringstream ss;
- ss << Op::str(_degree) << " " << exporter.toString(_activation) << " "
- << exporter.toString(_term);
+ ss << Op::str(getDegree()) << " " << exporter.toString(getImplication()) << " "
+ << exporter.toString(getTerm());
return ss.str();
}
void Activated::configure(const std::string& parameters) {
- (void) parameters;
+ FL_IUNUSED(parameters);
}
std::string Activated::toString() const {
FllExporter exporter;
std::ostringstream ss;
- ss << exporter.toString(_activation) << "("
- << Op::str(_degree) << ","
- << _term->getName() << ")";
+ if (getImplication()) {
+ ss << exporter.toString(getImplication()) << "("
+ << Op::str(getDegree()) << ","
+ << getTerm()->getName() << ")";
+ } else {
+ ss << "(" << Op::str(getDegree()) << "*" //"\u2297: (*)"
+ << getTerm()->getName() << ")";
+ }
return ss.str();
}
@@ -85,12 +95,12 @@ namespace fl {
return this->_degree;
}
- void Activated::setActivation(const TNorm* activation) {
- this->_activation = activation;
+ void Activated::setImplication(const TNorm* implication) {
+ this->_implication = implication;
}
- const TNorm* Activated::getActivation() const {
- return this->_activation;
+ const TNorm* Activated::getImplication() const {
+ return this->_implication;
}
Activated* Activated::clone() const {
diff --git a/fuzzylite/src/term/Aggregated.cpp b/fuzzylite/src/term/Aggregated.cpp
new file mode 100644
index 0000000..d1e2c89
--- /dev/null
+++ b/fuzzylite/src/term/Aggregated.cpp
@@ -0,0 +1,247 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/term/Aggregated.h"
+
+#include "fl/imex/FllExporter.h"
+#include "fl/norm/s/Maximum.h"
+
+namespace fl {
+
+ Aggregated::Aggregated(const std::string& name, scalar minimum, scalar maximum,
+ SNorm* aggregation)
+ : Term(name), _minimum(minimum), _maximum(maximum), _aggregation(aggregation) { }
+
+ Aggregated::Aggregated(const Aggregated& other) : Term(other) {
+ copyFrom(other);
+ }
+
+ Aggregated& Aggregated::operator=(const Aggregated& other) {
+ if (this != &other) {
+ clear();
+ _aggregation.reset(fl::null);
+
+ Term::operator=(other);
+ copyFrom(other);
+ }
+ return *this;
+ }
+
+ Aggregated::~Aggregated() { }
+
+ void Aggregated::copyFrom(const Aggregated& source) {
+ _minimum = source._minimum;
+ _maximum = source._maximum;
+
+ if (source._aggregation.get())
+ _aggregation.reset(source._aggregation->clone());
+
+ for (std::size_t i = 0; i < source._terms.size(); ++i) {
+ _terms.push_back(source._terms.at(i));
+ }
+ }
+
+ std::string Aggregated::className() const {
+ return "Aggregated";
+ }
+
+ Complexity Aggregated::complexity() const {
+ return complexityOfMembership();
+ }
+
+ Complexity Aggregated::complexityOfMembership() const {
+ Complexity result;
+ result.comparison(3);
+ if (_aggregation.get()) {
+ result += _aggregation->complexity().multiply(scalar(_terms.size()));
+ }
+ for (std::size_t i = 0; i < _terms.size(); ++i) {
+ result += _terms.at(i).complexity();
+ }
+ return result;
+ }
+
+ scalar Aggregated::membership(scalar x) const {
+ if (Op::isNaN(x)) return fl::nan;
+ if (not (_terms.empty() or _aggregation.get())) { //Exception for IntegralDefuzzifiers
+ throw Exception("[aggregation error] "
+ "aggregation operator needed to aggregate variable "
+ "<" + getName() + ">", FL_AT);
+ }
+ scalar mu = 0.0;
+ for (std::size_t i = 0; i < _terms.size(); ++i) {
+ mu = _aggregation->compute(mu, _terms.at(i).membership(x));
+ }
+ return mu;
+ }
+
+ Complexity Aggregated::complexityOfActivationDegree() const {
+ Complexity result;
+ result.comparison(2);
+ if (_aggregation.get()) {
+ result += _aggregation->complexity();
+ } else result.arithmetic(1);
+ result.multiply(scalar(_terms.size()));
+ return result;
+ }
+
+ scalar Aggregated::activationDegree(const Term* forTerm) const {
+ scalar result = 0.0;
+ for (std::size_t i = 0; i < _terms.size(); ++i) {
+ const Activated& activatedTerm = _terms.at(i);
+ if (activatedTerm.getTerm() == forTerm) {
+ if (_aggregation.get())
+ result = _aggregation->compute(result, activatedTerm.getDegree());
+ else
+ result += activatedTerm.getDegree(); //Default for WeightDefuzzifier
+ }
+ }
+ return result;
+ }
+
+ const Activated* Aggregated::highestActivatedTerm() const {
+ const Activated* maximumTerm = fl::null;
+ scalar maximumActivation = -fl::inf;
+ for (std::size_t i = 0; i < _terms.size(); ++i) {
+ const Activated& activated = _terms.at(i);
+ if (Op::isGt(activated.getDegree(), maximumActivation)) {
+ maximumActivation = activated.getDegree();
+ maximumTerm = &activated;
+ }
+ }
+ return maximumTerm;
+ }
+
+ std::string Aggregated::parameters() const {
+ FllExporter exporter;
+ std::ostringstream ss;
+ ss << exporter.toString(getAggregation());
+ ss << " " << Op::str(getMinimum()) << " " << Op::str(getMaximum()) << " ";
+ for (std::size_t i = 0; i < terms().size(); ++i) {
+ ss << " " << exporter.toString(&terms().at(i));
+ }
+ return ss.str();
+ }
+
+ void Aggregated::configure(const std::string& parameters) {
+ FL_IUNUSED(parameters);
+ }
+
+ Aggregated* Aggregated::clone() const {
+ return new Aggregated(*this);
+ }
+
+ std::string Aggregated::toString() const {
+ std::vector<std::string> aggregate;
+ for (std::size_t i = 0; i < terms().size(); ++i) {
+ aggregate.push_back(terms().at(i).toString());
+ }
+ FllExporter exporter;
+ std::ostringstream ss;
+ if (getAggregation()) {
+ ss << getName() << ": " << className() << " "
+ << exporter.toString(getAggregation()) << "["
+ << Op::join(aggregate, ",") << "]";
+ } else {
+ ss << getName() << ": " << className() << " " << "["
+ << Op::join(aggregate, "+") << "]"; //\u2295: (+)
+ }
+ return ss.str();
+ }
+
+ void Aggregated::setMinimum(scalar minimum) {
+ this->_minimum = minimum;
+ }
+
+ scalar Aggregated::getMinimum() const {
+ return this->_minimum;
+ }
+
+ void Aggregated::setMaximum(scalar maximum) {
+ this->_maximum = maximum;
+ }
+
+ scalar Aggregated::getMaximum() const {
+ return this->_maximum;
+ }
+
+ void Aggregated::setRange(scalar minimum, scalar maximum) {
+ setMinimum(minimum);
+ setMaximum(maximum);
+ }
+
+ scalar Aggregated::range() const {
+ return getMaximum() - getMinimum();
+ }
+
+ void Aggregated::setAggregation(SNorm* aggregation) {
+ this->_aggregation.reset(aggregation);
+ }
+
+ SNorm* Aggregated::getAggregation() const {
+ return this->_aggregation.get();
+ }
+
+ /**
+ * Operations for std::vector _terms
+ */
+
+
+ void Aggregated::addTerm(const Term* term, scalar degree, const TNorm* implication) {
+ _terms.push_back(Activated(term, degree, implication));
+ FL_DBG("Aggregating " << _terms.back().toString());
+ }
+
+ void Aggregated::addTerm(const Activated& term) {
+ _terms.push_back(term);
+ FL_DBG("Aggregating " << _terms.back().toString());
+ }
+
+ const Activated& Aggregated::removeTerm(std::size_t index) {
+ const Activated& term = _terms.at(index);
+ _terms.erase(_terms.begin() + index);
+ return term;
+ }
+
+ void Aggregated::clear() {
+ _terms.clear();
+ }
+
+ const Activated& Aggregated::getTerm(std::size_t index) const {
+ return _terms.at(index);
+ }
+
+ void Aggregated::setTerms(const std::vector<Activated>& terms) {
+ this->_terms = terms;
+ }
+
+ const std::vector<Activated>& Aggregated::terms() const {
+ return this->_terms;
+ }
+
+ std::vector<Activated>& Aggregated::terms() {
+ return this->_terms;
+ }
+
+ std::size_t Aggregated::numberOfTerms() const {
+ return _terms.size();
+ }
+
+ bool Aggregated::isEmpty() const {
+ return _terms.empty();
+ }
+
+}
diff --git a/fuzzylite/src/term/Bell.cpp b/fuzzylite/src/term/Bell.cpp
index fc0b215..bd63753 100644
--- a/fuzzylite/src/term/Bell.cpp
+++ b/fuzzylite/src/term/Bell.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Bell.h"
@@ -27,24 +19,26 @@
namespace fl {
Bell::Bell(const std::string& name, scalar center, scalar width, scalar slope, scalar height)
- : Term(name, height), _center(center), _width(width), _slope(slope) {
- }
+ : Term(name, height), _center(center), _width(width), _slope(slope) { }
- Bell::~Bell() {
- }
+ Bell::~Bell() { }
std::string Bell::className() const {
return "Bell";
}
+ Complexity Bell::complexity() const {
+ return Complexity().comparison(1).arithmetic(6).function(2);
+ }
+
scalar Bell::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- return _height * (1.0 / (1.0 + std::pow(std::abs((x - _center) / _width), 2 * _slope)));
+ if (Op::isNaN(x)) return fl::nan;
+ return Term::_height * (1.0 / (1.0 + std::pow(std::abs((x - _center) / _width), 2.0 * _slope)));
}
std::string Bell::parameters() const {
return Op::join(3, " ", _center, _width, _slope) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Bell::configure(const std::string& parameters) {
@@ -55,7 +49,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setCenter(Op::toScalar(values.at(0)));
setWidth(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Binary.cpp b/fuzzylite/src/term/Binary.cpp
new file mode 100644
index 0000000..368530b
--- /dev/null
+++ b/fuzzylite/src/term/Binary.cpp
@@ -0,0 +1,96 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/term/Binary.h"
+
+namespace fl {
+
+ Binary::Binary(const std::string& name, scalar start, scalar direction, scalar height)
+ : Term(name, height), _start(start), _direction(direction) { }
+
+ Binary::~Binary() { }
+
+ std::string Binary::className() const {
+ return "Binary";
+ }
+
+ Complexity Binary::complexity() const {
+ return Complexity().comparison(5).arithmetic(1);
+ }
+
+ scalar Binary::membership(scalar x) const {
+ if (Op::isNaN(x)) return fl::nan;
+ if (_direction > _start and Op::isGE(x, _start)) {
+ return Term::_height * 1.0;
+ }
+ if (_direction < _start and Op::isLE(x, _start)) {
+ return Term::_height * 1.0;
+ }
+ return Term::_height * 0.0;
+ }
+
+ std::string Binary::parameters() const {
+ return Op::join(2, " ", _start, _direction) +
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
+ }
+
+ void Binary::configure(const std::string& parameters) {
+ if (parameters.empty()) return;
+ std::vector<std::string> values = Op::split(parameters, " ");
+ std::size_t required = 2;
+ if (values.size() < required) {
+ std::ostringstream ex;
+ ex << "[configuration error] term <" << className() << ">"
+ << " requires <" << required << "> parameters";
+ throw Exception(ex.str(), FL_AT);
+ }
+ setStart(Op::toScalar(values.at(0)));
+ setDirection(Op::toScalar(values.at(1)));
+ if (values.size() > required)
+ setHeight(Op::toScalar(values.at(required)));
+ }
+
+ void Binary::setStart(scalar minimum) {
+ this->_start = minimum;
+ }
+
+ scalar Binary::getStart() const {
+ return this->_start;
+ }
+
+ void Binary::setDirection(scalar direction) {
+ this->_direction = direction;
+ }
+
+ scalar Binary::getDirection() const {
+ return this->_direction;
+ }
+
+ Binary::Direction Binary::direction() const {
+ if (this->_direction > _start) return Positive;
+ if (this->_direction < _start) return Negative;
+ return Undefined;
+ }
+
+ Binary* Binary::clone() const {
+ return new Binary(*this);
+ }
+
+ Term* Binary::constructor() {
+ return new Binary;
+ }
+
+}
diff --git a/fuzzylite/src/term/Concave.cpp b/fuzzylite/src/term/Concave.cpp
index 37679ae..c585edc 100644
--- a/fuzzylite/src/term/Concave.cpp
+++ b/fuzzylite/src/term/Concave.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Concave.h"
@@ -27,35 +19,47 @@
namespace fl {
Concave::Concave(const std::string& name, scalar inflection, scalar end, scalar height)
- : Term(name, height), _inflection(inflection), _end(end) {
-
- }
+ : Term(name, height), _inflection(inflection), _end(end) { }
- Concave::~Concave() {
-
- }
+ Concave::~Concave() { }
std::string Concave::className() const {
return "Concave";
}
+ Complexity Concave::complexity() const {
+ return Complexity().comparison(1 + 3).arithmetic(1 + 5);
+ }
+
scalar Concave::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- if (fl::Op::isLE(_inflection, _end)) { //Concave increasing
- if (fl::Op::isLt(x, _end)) {
- return _height * (_end - _inflection) / (2 * _end - _inflection - x);
+ if (Op::isNaN(x)) return fl::nan;
+ if (Op::isLE(_inflection, _end)) { //Concave increasing
+ if (Op::isLt(x, _end)) {
+ return Term::_height * (_end - _inflection) / (2.0 * _end - _inflection - x);
}
} else { //Concave decreasing
- if (fl::Op::isGt(x, _end)) {
- return _height * (_inflection - _end) / (_inflection - 2 * _end + x);
+ if (Op::isGt(x, _end)) {
+ return Term::_height * (_inflection - _end) / (_inflection - 2.0 * _end + x);
}
}
- return _height * 1.0;
+ return Term::_height * 1.0;
+ }
+
+ scalar Concave::tsukamoto(scalar activationDegree, scalar minimum, scalar maximum) const {
+ FL_IUNUSED(minimum);
+ FL_IUNUSED(maximum);
+ scalar i = _inflection;
+ scalar e = _end;
+ return (i - e) / membership(activationDegree) + 2 * e - i;
+ }
+
+ bool Concave::isMonotonic() const {
+ return true;
}
std::string Concave::parameters() const {
return Op::join(2, " ", _inflection, _end) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
@@ -67,7 +71,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setInflection(Op::toScalar(values.at(0)));
setEnd(Op::toScalar(values.at(1)));
@@ -100,8 +104,4 @@ namespace fl {
return new Concave;
}
-
-
-
-
}
diff --git a/fuzzylite/src/term/Constant.cpp b/fuzzylite/src/term/Constant.cpp
index d52f8ec..7c0422e 100644
--- a/fuzzylite/src/term/Constant.cpp
+++ b/fuzzylite/src/term/Constant.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Constant.h"
@@ -27,18 +19,20 @@
namespace fl {
Constant::Constant(const std::string& name, scalar value)
- : Term(name), _value(value) {
- }
+ : Term(name), _value(value) { }
- Constant::~Constant() {
- }
+ Constant::~Constant() { }
std::string Constant::className() const {
return "Constant";
}
+ Complexity Constant::complexity() const {
+ return Complexity();
+ }
+
scalar Constant::membership(scalar x) const {
- (void) x;
+ FL_IUNUSED(x);
return this->_value;
}
diff --git a/fuzzylite/src/term/Cosine.cpp b/fuzzylite/src/term/Cosine.cpp
index a1402ad..78162ea 100644
--- a/fuzzylite/src/term/Cosine.cpp
+++ b/fuzzylite/src/term/Cosine.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Cosine.h"
@@ -27,13 +19,9 @@
namespace fl {
Cosine::Cosine(const std::string& name, scalar center, scalar width, scalar height)
- : Term(name, height), _center(center), _width(width) {
+ : Term(name, height), _center(center), _width(width) { }
- }
-
- Cosine::~Cosine() {
-
- }
+ Cosine::~Cosine() { }
std::string Cosine::className() const {
return "Cosine";
@@ -41,7 +29,7 @@ namespace fl {
std::string Cosine::parameters() const {
return Op::join(2, " ", _center, _width) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Cosine::configure(const std::string& parameters) {
@@ -52,7 +40,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setCenter(Op::toScalar(values.at(0)));
setWidth(Op::toScalar(values.at(1)));
@@ -61,13 +49,17 @@ namespace fl {
}
+ Complexity Cosine::complexity() const {
+ return Complexity().comparison(3).arithmetic(4 + 1 + 7).function(2);
+ }
+
scalar Cosine::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- if (fl::Op::isLt(x, _center - _width / 2.0)
- or fl::Op::isGt(x, _center + _width / 2.0))
- return _height * 0.0;
+ if (Op::isNaN(x)) return fl::nan;
+ if (Op::isLt(x, _center - 0.5 * _width)
+ or Op::isGt(x, _center + 0.5 * _width))
+ return Term::_height * 0.0;
const scalar pi = 4.0 * std::atan(1.0);
- return _height * (0.5 * (1.0 + std::cos(2.0 / _width * pi * (x - _center))));
+ return Term::_height * (0.5 * (1.0 + std::cos(2.0 / _width * pi * (x - _center))));
}
void Cosine::setCenter(scalar center) {
@@ -93,4 +85,5 @@ namespace fl {
Term* Cosine::constructor() {
return new Cosine;
}
+
}
diff --git a/fuzzylite/src/term/Discrete.cpp b/fuzzylite/src/term/Discrete.cpp
index 212ada2..9951867 100644
--- a/fuzzylite/src/term/Discrete.cpp
+++ b/fuzzylite/src/term/Discrete.cpp
@@ -1,88 +1,89 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Discrete.h"
-#include <cstdarg>
-
namespace fl {
Discrete::Discrete(const std::string& name, const std::vector<Pair>& xy, scalar height)
- : Term(name, height), _xy(xy) {
- }
+ : Term(name, height), _xy(xy) { }
- Discrete::~Discrete() {
- }
+ Discrete::~Discrete() { }
std::string Discrete::className() const {
return "Discrete";
}
- scalar Discrete::membership(scalar _x_) const {
- if (fl::Op::isNaN(_x_)) return fl::nan;
+ bool compare(const Discrete::Pair& a, const Discrete::Pair& b) {
+ return a.first < b.first;
+ }
+
+ void Discrete::sort(std::vector<Pair>& pairs) {
+ std::sort(pairs.begin(), pairs.end(), compare);
+ }
+
+ void Discrete::sort() {
+ std::sort(_xy.begin(), _xy.end(), compare);
+ }
+
+ Complexity Discrete::complexity() const {
+ return Complexity().comparison(1 + 4).arithmetic(1 + 1 + 1).function(1)
+ .function(2 * std::log(scalar(_xy.size())));
+ }
+
+ scalar Discrete::membership(scalar x) const {
+ if (Op::isNaN(x)) return fl::nan;
if (_xy.empty())
- throw fl::Exception("[discrete error] term is empty", FL_AT);
+ throw Exception("[discrete error] term is empty", FL_AT);
/* ______________________
- * / \
- * / \
- * ____________/ \____________
- * x[0] x[n-1]
+ / \
+ / \
+ ____________/ \____________
+ x[0] x[n-1]
*/
+ if (Op::isLE(x, _xy.front().first))
+ return Term::_height * _xy.front().second;
+ if (Op::isGE(x, _xy.back().first))
+ return Term::_height * _xy.back().second;
- if (fl::Op::isLE(_x_, _xy.front().first)) return _height * _xy.front().second;
- if (fl::Op::isGE(_x_, _xy.back().first)) return _height * _xy.back().second;
-
- int lower = -1, upper = -1;
+ const Pair value(x, fl::nan);
+ typedef std::vector<Discrete::Pair>::const_iterator Bound;
+ //std::lower_bound finds the first number greater than or equal to x
+ Bound lowerBound(std::lower_bound(_xy.begin(), _xy.end(), value, compare));
- for (std::size_t i = 0; i < _xy.size(); ++i) {
- if (Op::isEq(_xy.at(i).first, _x_)) return _height * _xy.at(i).second;
- //approximate on the left
- if (Op::isLt(_xy.at(i).first, _x_)) {
- lower = i;
- }
- //get the immediate next one on the right
- if (Op::isGt(_xy.at(i).first, _x_)) {
- upper = i;
- break;
- }
+ //if the lower bound is equal to x
+ if (Op::isEq(x, lowerBound->first)) {
+ return Term::_height * lowerBound->second;
}
- if (upper < 0) upper = _xy.size() - 1;
- if (lower < 0) lower = 0;
-
- return _height * Op::scale(_x_, _xy.at(lower).first, _xy.at(upper).first,
- _xy.at(lower).second, _xy.at(upper).second);
+ //find the upper bound starting from a copy of lowerBound
+ const Bound upperBound(std::upper_bound(_xy.begin(), _xy.end(), value, compare));
+ --lowerBound; //One arithmetic
+ return Term::_height * Op::scale(x, lowerBound->first, upperBound->first,
+ lowerBound->second, upperBound->second);
}
std::string Discrete::parameters() const {
std::ostringstream ss;
for (std::size_t i = 0; i < _xy.size(); ++i) {
- ss << fl::Op::str(_xy.at(i).first) << " " << fl::Op::str(_xy.at(i).second);
+ ss << Op::str(_xy.at(i).first) << " " << Op::str(_xy.at(i).second);
if (i + 1 < _xy.size()) ss << " ";
}
- if (not Op::isEq(_height, 1.0)) ss << " " << Op::str(_height);
+ if (not Op::isEq(getHeight(), 1.0)) ss << " " << Op::str(getHeight());
return ss.str();
}
@@ -102,36 +103,8 @@ namespace fl {
this->_xy = toPairs(values);
}
- template <typename T>
- Discrete* Discrete::create(const std::string& name, int argc,
- T x1, T y1, ...) { // throw (fl::Exception) {
- std::vector<scalar> xy(argc);
- xy.at(0) = x1;
- xy.at(1) = y1;
- va_list args;
- va_start(args, y1);
- for (int i = 2; i < argc; ++i) {
- xy.at(i) = (scalar) va_arg(args, T);
- }
- va_end(args);
-
- FL_unique_ptr<Discrete> result(new Discrete(name));
- if (xy.size() % 2 != 0) {
- result->setHeight(xy.back());
- xy.pop_back();
- }
- result->setXY(toPairs(xy));
- return result.release();
- }
-
- template FL_API Discrete* Discrete::create(const std::string& name, int argc,
- double x1, double y1, ...); // throw (fl::Exception);
- //double, not scalar because variadic promotes floats to double
- template FL_API Discrete* Discrete::create(const std::string& name, int argc,
- int x1, int y1, ...); // throw (fl::Exception);
-
- void Discrete::setXY(const std::vector<Pair>& pairs) {
- this->_xy = pairs;
+ void Discrete::setXY(const std::vector<Pair>& xy) {
+ this->_xy = xy;
}
const std::vector<Discrete::Pair>& Discrete::xy() const {
@@ -142,19 +115,51 @@ namespace fl {
return this->_xy;
}
- const Discrete::Pair& Discrete::xy(int index) const {
+ const Discrete::Pair& Discrete::xy(std::size_t index) const {
return this->_xy.at(index);
}
- Discrete::Pair& Discrete::xy(int index) {
+ Discrete::Pair& Discrete::xy(std::size_t index) {
return this->_xy.at(index);
}
+ std::vector<scalar> Discrete::x() const {
+ std::vector<scalar> result(_xy.size());
+ for (std::size_t i = 0; i < result.size(); ++i) {
+ result.at(i) = _xy.at(i).first;
+ }
+ return result;
+ }
+
+ std::vector<scalar> Discrete::y() const {
+ std::vector<scalar> result(_xy.size());
+ for (std::size_t i = 0; i < result.size(); ++i) {
+ result.at(i) = _xy.at(i).second;
+ }
+ return result;
+ }
+
+ scalar Discrete::x(std::size_t index) const {
+ return _xy.at(index).first;
+ }
+
+ scalar& Discrete::x(std::size_t index) {
+ return _xy.at(index).first;
+ }
+
+ scalar Discrete::y(std::size_t index) const {
+ return _xy.at(index).second;
+ }
+
+ scalar& Discrete::y(std::size_t index) {
+ return _xy.at(index).second;
+ }
+
std::vector<Discrete::Pair> Discrete::toPairs(const std::vector<scalar>& xy) {
if (xy.size() % 2 != 0) {
std::ostringstream os;
os << "[discrete error] missing value in set of pairs (|xy|=" << xy.size() << ")";
- throw fl::Exception(os.str(), FL_AT);
+ throw Exception(os.str(), FL_AT);
}
std::vector<Pair> result((xy.size() + 1) / 2);
@@ -188,16 +193,32 @@ namespace fl {
return result;
}
- std::string Discrete::formatXY(const std::vector<Pair>& xy, const std::string& prefix, const std::string& innerSeparator, const std::string& postfix, const std::string& outerSeparator) {
+ std::string Discrete::formatXY(const std::vector<Pair>& xy, const std::string& prefix,
+ const std::string& innerSeparator, const std::string& suffix, const std::string& outerSeparator) {
std::ostringstream os;
for (std::size_t i = 0; i < xy.size(); ++i) {
- os << prefix << fl::Op::str(xy.at(i).first) << innerSeparator
- << fl::Op::str(xy.at(i).second) << postfix;
+ os << prefix << Op::str(xy.at(i).first) << innerSeparator
+ << Op::str(xy.at(i).second) << suffix;
if (i + 1 < xy.size()) os << outerSeparator;
}
return os.str();
}
+ Discrete* Discrete::discretize(const Term* term, scalar start, scalar end, int resolution,
+ bool boundedMembershipFunction) {
+ FL_unique_ptr<Discrete> result(new Discrete(term->getName()));
+ scalar dx = (end - start) / resolution;
+ scalar x, y;
+ for (int i = 0; i <= resolution; ++i) {
+ x = start + i * dx;
+ y = term->membership(x);
+ if (boundedMembershipFunction)
+ y = Op::bound(y, scalar(0.0), scalar(1.0));
+ result->xy().push_back(Discrete::Pair(x, y));
+ }
+ return result.release();
+ }
+
Discrete* Discrete::clone() const {
return new Discrete(*this);
}
@@ -206,5 +227,4 @@ namespace fl {
return new Discrete;
}
-
}
diff --git a/fuzzylite/src/term/Function.cpp b/fuzzylite/src/term/Function.cpp
index c0f54b8..42f4aaa 100644
--- a/fuzzylite/src/term/Function.cpp
+++ b/fuzzylite/src/term/Function.cpp
@@ -1,43 +1,30 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Function.h"
#include "fl/Engine.h"
#include "fl/factory/FactoryManager.h"
-#include "fl/factory/FunctionFactory.h"
#include "fl/rule/Rule.h"
#include "fl/variable/InputVariable.h"
#include "fl/variable/OutputVariable.h"
-#include <cctype>
-#include <functional>
#include <queue>
-#include <signal.h>
#include <stack>
-
namespace fl {
/**
@@ -47,32 +34,26 @@ namespace fl {
Function::Element::Element(const std::string& name, const std::string& description, Type type)
: name(name), description(description), type(type), unary(fl::null), binary(fl::null), arity(0),
- precedence(0), associativity(-1) {
-
- }
+ precedence(0), associativity(-1) { }
Function::Element::Element(const std::string& name, const std::string& description,
Type type, Unary unary, int precedence, int associativity)
: name(name), description(description), type(type), unary(unary), binary(fl::null), arity(1),
- precedence(precedence), associativity(associativity) {
- }
+ precedence(precedence), associativity(associativity) { }
Function::Element::Element(const std::string& name, const std::string& description,
Type type, Binary binary, int precedence, int associativity)
: name(name), description(description), type(type), unary(fl::null), binary(binary), arity(2),
- precedence(precedence), associativity(associativity) {
- }
+ precedence(precedence), associativity(associativity) { }
- Function::Element::~Element() {
-
- }
+ Function::Element::~Element() { }
bool Function::Element::isOperator() const {
- return type == OPERATOR;
+ return type == Operator;
}
bool Function::Element::isFunction() const {
- return type == FUNCTION;
+ return type == Function;
}
Function::Element* Function::Element::clone() const {
@@ -82,7 +63,7 @@ namespace fl {
std::string Function::Element::toString() const {
std::ostringstream ss;
- if (type == OPERATOR) {
+ if (type == Operator) {
ss << "Operator (name=" << name << ", "
<< "description=" << description << ", "
<< "precedence=" << precedence << ", "
@@ -92,7 +73,7 @@ namespace fl {
else if (arity == 2) ss << "pointer=" << binary;
else ss << "pointer=error";
ss << ")";
- } else if (type == FUNCTION) {
+ } else if (type == Function) {
ss << "Function (name=" << name << ", "
<< "description=" << description << ", "
<< "arity=" << arity << ", "
@@ -110,16 +91,13 @@ namespace fl {
******************************/
Function::Node::Node(Element* element, Node* left, Node* right)
- : element(element), left(left), right(right), variable(""), value(fl::nan) {
- }
+ : element(element), left(left), right(right), variable(""), value(fl::nan) { }
Function::Node::Node(const std::string& variable)
- : element(fl::null), left(fl::null), right(fl::null), variable(variable), value(fl::nan) {
- }
+ : element(fl::null), left(fl::null), right(fl::null), variable(variable), value(fl::nan) { }
Function::Node::Node(scalar value)
- : element(fl::null), left(fl::null), right(fl::null), variable(""), value(value) {
- }
+ : element(fl::null), left(fl::null), right(fl::null), variable(""), value(value) { }
Function::Node::Node(const Node& other)
: element(fl::null), left(fl::null), right(fl::null), variable(""), value(fl::nan) {
@@ -145,8 +123,7 @@ namespace fl {
value = other.value;
}
- Function::Node::~Node() {
- }
+ Function::Node::~Node() { }
scalar Function::Node::evaluate(const std::map<std::string, scalar>* variables) const {
scalar result = fl::nan;
@@ -160,17 +137,17 @@ namespace fl {
ex << "[function error] arity <" << element->arity << "> of "
<< (element->isOperator() ? "operator" : "function") <<
" <" << element->name << "> is fl::null";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
} else if (not variable.empty()) {
if (not variables) {
- throw fl::Exception("[function error] "
+ throw Exception("[function error] "
"expected a map of variables, but none was provided", FL_AT);
}
std::map<std::string, scalar>::const_iterator it = variables->find(variable);
if (it != variables->end()) result = it->second;
- else throw fl::Exception("[function error] "
+ else throw Exception("[function error] "
"unknown variable <" + variable + ">", FL_AT);
} else {
result = value;
@@ -178,6 +155,36 @@ namespace fl {
return result;
}
+ std::size_t Function::Node::treeSize(const Node* root) const {
+ if (not root) root = this;
+ std::size_t result = 0;
+ if (root->left.get()) {
+ result += treeSize(root->left.get());
+ }
+ if (root->right.get()) {
+ result += treeSize(root->right.get());
+ }
+ if (root->element.get()) {
+ result += 1;
+ }
+ return result;
+ }
+
+ std::size_t Function::Node::treeSize(Element::Type type, const Node* root) const {
+ if (not root) root = this;
+ std::size_t result = 0;
+ if (root->left.get()) {
+ result += treeSize(type, root->left.get());
+ }
+ if (root->right.get()) {
+ result += treeSize(type, root->right.get());
+ }
+ if (root->element.get() and root->element->type == type) {
+ result += 1;
+ }
+ return result;
+ }
+
Function::Node* Function::Node::clone() const {
return new Node(*this);
}
@@ -186,14 +193,14 @@ namespace fl {
std::ostringstream ss;
if (element.get()) ss << element->name;
else if (not variable.empty()) ss << variable;
- else ss << fl::Op::str(value);
+ else ss << Op::str(value);
return ss.str();
}
std::string Function::Node::toPrefix(const Node* node) const {
if (not node) node = this;
- if (not fl::Op::isNaN(node->value)) { //is terminal
- return fl::Op::str(node->value);
+ if (not Op::isNaN(node->value)) { //is terminal
+ return Op::str(node->value);
}
if (not node->variable.empty()) {
return node->variable;
@@ -210,8 +217,8 @@ namespace fl {
std::string Function::Node::toInfix(const Node* node) const {
if (not node) node = this;
- if (not fl::Op::isNaN(node->value)) { //is proposition
- return fl::Op::str(node->value);
+ if (not Op::isNaN(node->value)) { //is proposition
+ return Op::str(node->value);
}
if (not node->variable.empty()) {
return node->variable;
@@ -228,8 +235,8 @@ namespace fl {
std::string Function::Node::toPostfix(const Node* node) const {
if (not node) node = this;
- if (not fl::Op::isNaN(node->value)) { //is proposition
- return fl::Op::str(node->value);
+ if (not Op::isNaN(node->value)) { //is proposition
+ return Op::str(node->value);
}
if (not node->variable.empty()) {
return node->variable;
@@ -249,8 +256,7 @@ namespace fl {
**********************************/
Function::Function(const std::string& name,
const std::string& formula, const Engine* engine)
- : Term(name), _root(fl::null), _formula(formula), _engine(engine) {
- }
+ : Term(name), _root(fl::null), _formula(formula), _engine(engine) { }
Function::Function(const Function& other) : Term(other),
_root(fl::null), _formula(other._formula), _engine(other._engine) {
@@ -271,25 +277,41 @@ namespace fl {
return *this;
}
- Function::~Function() {
- }
+ Function::~Function() { }
std::string Function::className() const {
return "Function";
}
+ Complexity Function::complexity() const {
+ Complexity result;
+ result.comparison(2 + 2); //membership(scalar) + membership(std::map)
+ if (_engine) { //insert variables in map
+ const std::size_t engineVariables = _engine->variables().size();
+ result.function(engineVariables * std::log(scalar(variables.size() + engineVariables)));
+ result.function(1 * std::log(scalar(variables.size() + engineVariables)));
+ }
+ if (_root.get()) {
+ //Node::evaluate multiplies by tree size
+ const scalar treeSize = scalar(_root->treeSize());
+ result.comparison(3 * treeSize); //if element, unary, binary
+ result.function(treeSize * std::log(treeSize)); //only operands in tree
+ }
+ return result;
+ }
+
scalar Function::membership(scalar x) const {
- if (not this->_root.get()) {
- throw fl::Exception("[function error] function <" + _formula + "> not loaded.", FL_AT);
+ if (not _root.get()) {
+ throw Exception("[function error] function <" + _formula + "> not loaded.", FL_AT);
}
- if (this->_engine) {
- for (int i = 0; i < this->_engine->numberOfInputVariables(); ++i) {
- InputVariable* input = this->_engine->getInputVariable(i);
- this->variables[input->getName()] = input->getInputValue();
+ if (_engine) {
+ for (std::size_t i = 0; i < _engine->numberOfInputVariables(); ++i) {
+ InputVariable* input = _engine->getInputVariable(i);
+ this->variables[input->getName()] = input->getValue();
}
- for (int i = 0; i < this->_engine->numberOfOutputVariables(); ++i) {
- OutputVariable* output = this->_engine->getOutputVariable(i);
- this->variables[output->getName()] = output->getOutputValue();
+ for (std::size_t i = 0; i < _engine->numberOfOutputVariables(); ++i) {
+ OutputVariable* output = _engine->getOutputVariable(i);
+ this->variables[output->getName()] = output->getValue();
}
}
this->variables["x"] = x;
@@ -297,15 +319,15 @@ namespace fl {
}
scalar Function::evaluate(const std::map<std::string, scalar>* localVariables) const {
- if (not this->_root.get())
- throw fl::Exception("[function error] evaluation failed because the function is not loaded", FL_AT);
+ if (not _root.get())
+ throw Exception("[function error] evaluation failed because the function is not loaded", FL_AT);
if (localVariables)
- return this->_root->evaluate(localVariables);
- return this->_root->evaluate(&this->variables);
+ return _root->evaluate(localVariables);
+ return _root->evaluate(&this->variables);
}
std::string Function::parameters() const {
- return _formula;
+ return getFormula();
}
void Function::configure(const std::string& parameters) {
@@ -329,18 +351,17 @@ namespace fl {
}
void Function::load() {
- load(this->_formula);
+ load(getFormula());
}
void Function::load(const std::string& formula) {
- load(formula, this->_engine);
+ load(formula, getEngine());
}
void Function::load(const std::string& formula,
const Engine* engine) {
- unload();
- this->_formula = formula;
- this->_engine = engine;
+ setFormula(formula);
+ setEngine(engine);
this->_root.reset(parse(formula));
membership(0.0); //make sure function evaluates without throwing exception.
}
@@ -373,23 +394,32 @@ namespace fl {
return new Function;
}
+ void Function::updateReference(const Engine* engine) {
+ setEngine(engine);
+ try {
+ load();
+ } catch (...) {
+ //ignore
+ }
+ }
+
std::string Function::space(const std::string& formula) const {
std::vector<std::string> chars;
chars.push_back("(");
chars.push_back(")");
chars.push_back(",");
- std::vector<std::string> operators = fl::FactoryManager::instance()->function()->availableOperators();
+ std::vector<std::string> operators = FactoryManager::instance()->function()->availableOperators();
for (std::size_t i = 0; i < operators.size(); ++i) {
- if (not (operators.at(i) == fl::Rule::andKeyword() or
- operators.at(i) == fl::Rule::orKeyword())) {
+ if (not (operators.at(i) == Rule::andKeyword() or
+ operators.at(i) == Rule::orKeyword())) {
chars.push_back(operators.at(i));
}
}
std::string result = formula;
for (std::size_t i = 0; i < chars.size(); ++i) {
- result = fl::Op::findReplace(result, chars.at(i), " " + chars.at(i) + " ");
+ result = Op::findReplace(result, chars.at(i), " " + chars.at(i) + " ");
}
return result;
}
@@ -397,7 +427,7 @@ namespace fl {
/****************************************
* The Glorious Parser
* Shunting-yard algorithm
- * TODO: Maybe change it for http://en.wikipedia.org/wiki/Operator-precedence_parser
+ * @todo: maybe change it for http://en.wikipedia.org/wiki/Operator-precedence_parser
***************************************/
std::string Function::toPostfix(const std::string& formula) const {
@@ -408,7 +438,7 @@ namespace fl {
std::stringstream tokenizer(spacedFormula);
std::string token;
- FunctionFactory* factory = fl::FactoryManager::instance()->function();
+ FunctionFactory* factory = FactoryManager::instance()->function();
while (tokenizer >> token) {
Element* element = factory->getObject(token);
bool isOperand = not element and token != "(" and token != ")" and token != ",";
@@ -427,7 +457,7 @@ namespace fl {
if (stack.empty() or stack.top() != "(") {
std::ostringstream ex;
ex << "[parsing error] mismatching parentheses in: " << formula;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
} else if (element and element->isOperator()) {
@@ -457,7 +487,7 @@ namespace fl {
if (stack.empty() or stack.top() != "(") {
std::ostringstream ex;
ex << "[parsing error] mismatching parentheses in: " << formula;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
stack.pop(); //get rid of "("
@@ -470,7 +500,7 @@ namespace fl {
} else {
std::ostringstream ex;
ex << "[parsing error] unexpected error with token <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
}
@@ -478,7 +508,7 @@ namespace fl {
if (stack.top() == "(" or stack.top() == ")") {
std::ostringstream ex;
ex << "[parsing error] mismatching parentheses in: " << formula;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
queue.push(stack.top());
stack.pop();
@@ -490,43 +520,31 @@ namespace fl {
queue.pop();
if (not queue.empty()) ssPostfix << " ";
}
- // FL_DBG("postfix=" << ssPostfix.str());
return ssPostfix.str();
}
- // bool FunctionFactory::isOperand(const std::string& name) const {
- // //An operand is not a parenthesis...
- // if (name == "(" or name == ")" or name == ",") return false;
- // //nor an operator...
- // if (isOperator(name)) return false;
- // //nor a function...
- // if (isFunction(name)) return false;
- // //...it is everything else :)
- // return true;
- // }
-
Function::Node* Function::parse(const std::string& formula) {
if (formula.empty())
- throw fl::Exception("[function error] formula is empty", FL_AT);
+ throw Exception("[function error] formula is empty", FL_AT);
std::string postfix = toPostfix(formula);
std::stack<Node*> stack;
std::istringstream tokenizer(postfix);
std::string token;
- FunctionFactory* factory = fl::FactoryManager::instance()->function();
+ FunctionFactory* factory = FactoryManager::instance()->function();
while (tokenizer >> token) {
Element* element = factory->getObject(token);
bool isOperand = not element and token != "(" and token != ")" and token != ",";
if (element) {
- if (element->arity > (int) stack.size()) {
+ if (element->arity > static_cast<int> (stack.size())) {
std::ostringstream ss;
ss << "[function error] " << (element->isOperator() ? "operator" : "function") <<
" <" << element->name << "> has arity <" << element->arity << ">, "
"but found <" << stack.size() << "> element" <<
(stack.size() == 1 ? "" : "s");
- throw fl::Exception(ss.str(), FL_AT);
+ throw Exception(ss.str(), FL_AT);
}
Node* node = new Node(element->clone());
@@ -541,10 +559,10 @@ namespace fl {
} else if (isOperand) {
Node* node;
try {
- scalar value = fl::Op::toScalar(token);
+ scalar value = Op::toScalar(token);
node = new Node(value);
} catch (std::exception& ex) {
- (void) ex;
+ FL_IUNUSED(ex);
node = new Node(token);
}
stack.push(node);
@@ -552,49 +570,9 @@ namespace fl {
}
if (stack.size() != 1)
- throw fl::Exception("[function error] ill-formed formula <" + formula + ">", FL_AT);
+ throw Exception("[function error] ill-formed formula <" + formula + ">", FL_AT);
return stack.top();
}
- void Function::main() {
- Function f;
- std::string text = "3+4*2/(1-5)^2^3";
- FL_LOG(f.toPostfix(text));
- FL_LOG("P: " << f.parse(text)->toInfix());
- FL_LOG(">" << f.parse(text)->evaluate());
- //3 4 2 * 1 5 - 2 3 ^ ^ / +
-
- f.variables["y"] = 1.0;
- text = "sin(y*x)^2/x";
- FL_LOG("pre: " << f.parse(text)->toPrefix());
- FL_LOG("in: " << f.parse(text)->toInfix());
- FL_LOG("pos: " << f.parse(text)->toPostfix());
- f.load(text);
- FL_LOG("Result: " << f.membership(1));
- //y x * sin 2 ^ x /
-
-
- text = "(Temperature is High and Oxygen is Low) or "
- "(Temperature is Low and (Oxygen is Low or Oxygen is High))";
- FL_LOG(f.toPostfix(text));
-
- f.variables["pi"] = 3.14;
- text = "-5 *4/sin(-pi/2)";
- FL_LOG(f.toPostfix(text));
- try {
- FL_LOG(f.parse(text)->evaluate());
- } catch (std::exception& e) {
- FL_LOG(e.what());
- }
- f.variables["pi"] = 3.14;
- text = "~5 *4/sin(~pi/2)";
- FL_LOG(f.toPostfix(text));
- try {
- FL_LOG(f.parse(text)->evaluate(&f.variables));
- } catch (std::exception& e) {
- FL_LOG(e.what());
- }
- }
-
}
diff --git a/fuzzylite/src/term/Gaussian.cpp b/fuzzylite/src/term/Gaussian.cpp
index 5b709f9..8413b59 100644
--- a/fuzzylite/src/term/Gaussian.cpp
+++ b/fuzzylite/src/term/Gaussian.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Gaussian.h"
@@ -28,24 +20,26 @@ namespace fl {
Gaussian::Gaussian(const std::string& name,
scalar mean, scalar standardDeviation, scalar height)
- : Term(name, height), _mean(mean), _standardDeviation(standardDeviation) {
- }
+ : Term(name, height), _mean(mean), _standardDeviation(standardDeviation) { }
- Gaussian::~Gaussian() {
- }
+ Gaussian::~Gaussian() { }
std::string Gaussian::className() const {
return "Gaussian";
}
+ Complexity Gaussian::complexity() const {
+ return Complexity().comparison(1).arithmetic(7).function(1);
+ }
+
scalar Gaussian::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- return _height * std::exp((-(x - _mean) * (x - _mean)) / (2 * _standardDeviation * _standardDeviation));
+ if (Op::isNaN(x)) return fl::nan;
+ return Term::_height * std::exp((-(x - _mean) * (x - _mean)) / (2.0 * _standardDeviation * _standardDeviation));
}
std::string Gaussian::parameters() const {
return Op::join(2, " ", _mean, _standardDeviation) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Gaussian::configure(const std::string& parameters) {
@@ -56,7 +50,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setMean(Op::toScalar(values.at(0)));
setStandardDeviation(Op::toScalar(values.at(1)));
@@ -64,16 +58,16 @@ namespace fl {
setHeight(Op::toScalar(values.at(required)));
}
- void Gaussian::setMean(scalar c) {
- this->_mean = c;
+ void Gaussian::setMean(scalar mean) {
+ this->_mean = mean;
}
scalar Gaussian::getMean() const {
return this->_mean;
}
- void Gaussian::setStandardDeviation(scalar sigma) {
- this->_standardDeviation = sigma;
+ void Gaussian::setStandardDeviation(scalar standardDeviation) {
+ this->_standardDeviation = standardDeviation;
}
scalar Gaussian::getStandardDeviation() const {
diff --git a/fuzzylite/src/term/GaussianProduct.cpp b/fuzzylite/src/term/GaussianProduct.cpp
index b9652e1..791790c 100644
--- a/fuzzylite/src/term/GaussianProduct.cpp
+++ b/fuzzylite/src/term/GaussianProduct.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/GaussianProduct.h"
@@ -30,32 +22,37 @@ namespace fl {
scalar meanA, scalar standardDeviationA, scalar meanB, scalar standardDeviationB,
scalar height)
: Term(name, height), _meanA(meanA), _standardDeviationA(standardDeviationA),
- _meanB(meanB), _standardDeviationB(standardDeviationB) {
- }
+ _meanB(meanB), _standardDeviationB(standardDeviationB) { }
- GaussianProduct::~GaussianProduct() {
- }
+ GaussianProduct::~GaussianProduct() { }
std::string GaussianProduct::className() const {
return "GaussianProduct";
}
+ Complexity GaussianProduct::complexity() const {
+ return Complexity().comparison(1 + 2).arithmetic(9 + 9 + 2).function(2);
+ }
+
scalar GaussianProduct::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- bool xLEa = fl::Op::isLE(x, _meanA);
- scalar a = (1 - xLEa) + xLEa * std::exp(
- (-(x - _meanA) * (x - _meanA)) / (2 * _standardDeviationA * _standardDeviationA)
- );
- bool xGEb = fl::Op::isGE(x, _meanB);
- scalar b = (1 - xGEb) + xGEb * std::exp(
- (-(x - _meanB) * (x - _meanB)) / (2 * _standardDeviationB * _standardDeviationB)
- );
- return _height * a * b;
+ if (Op::isNaN(x)) return fl::nan;
+
+ scalar a = 1.0, b = 1.0;
+ if (Op::isLt(x, _meanA)) {
+ a = std::exp((-(x - _meanA) * (x - _meanA)) /
+ (2.0 * _standardDeviationA * _standardDeviationA));
+ }
+ if (Op::isGt(x, _meanB)) {
+ b = std::exp((-(x - _meanB) * (x - _meanB)) /
+ (2.0 * _standardDeviationB * _standardDeviationB));
+ }
+
+ return Term::_height * a * b;
}
std::string GaussianProduct::parameters() const {
return Op::join(4, " ", _meanA, _standardDeviationA, _meanB, _standardDeviationB) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void GaussianProduct::configure(const std::string& parameters) {
@@ -66,7 +63,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setMeanA(Op::toScalar(values.at(0)));
setStandardDeviationA(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Linear.cpp b/fuzzylite/src/term/Linear.cpp
index 4111a00..e6efb43 100644
--- a/fuzzylite/src/term/Linear.cpp
+++ b/fuzzylite/src/term/Linear.cpp
@@ -1,72 +1,72 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Linear.h"
-#include "fl/Engine.h"
#include "fl/variable/InputVariable.h"
-#include <cstdarg>
-
namespace fl {
Linear::Linear(const std::string& name,
const std::vector<scalar>& coefficients,
const Engine* engine)
- : Term(name), _coefficients(coefficients), _engine(engine) {
- }
+ : Term(name), _coefficients(coefficients), _engine(engine) { }
- Linear::~Linear() {
- }
+ Linear::~Linear() { }
std::string Linear::className() const {
return "Linear";
}
+ Complexity Linear::complexity() const {
+ Complexity result;
+ result.comparison(1 + 1);
+ if (_engine) {
+ result.arithmetic(scalar(_engine->variables().size()));
+ result.comparison(scalar(_engine->variables().size())); //if (i < coefficients)
+ }
+ return result;
+ }
+
scalar Linear::membership(scalar x) const {
- (void) x;
- if (not _engine) throw fl::Exception("[linear error] term <" + getName() + "> "
+ FL_IUNUSED(x);
+ if (not _engine)
+ throw Exception("[linear error] term <" + getName() + "> "
"is missing a reference to the engine", FL_AT);
scalar result = 0.0;
- for (std::size_t i = 0; i < _engine->inputVariables().size(); ++i) {
- if (i < _coefficients.size())
- result += _coefficients.at(i) * _engine->inputVariables().at(i)->getInputValue();
+ const std::size_t numberOfInputVariables = _engine->inputVariables().size();
+ const std::size_t numberOfCoefficients = _coefficients.size();
+ for (std::size_t i = 0; i < numberOfInputVariables; ++i) {
+ if (i < numberOfCoefficients)
+ result += _coefficients.at(i) * _engine->inputVariables().at(i)->getValue();
}
- if (_coefficients.size() > _engine->inputVariables().size()) {
+ if (numberOfCoefficients > numberOfInputVariables) {
result += _coefficients.back();
}
return result;
}
- void Linear::set(const std::vector<scalar>& coeffs, const Engine* engine) {
- setCoefficients(coeffs);
+ void Linear::set(const std::vector<scalar>& coefficients, const Engine* engine) {
+ setCoefficients(coefficients);
setEngine(engine);
}
- void Linear::setCoefficients(const std::vector<scalar>& coeffs) {
- this->_coefficients = coeffs;
+ void Linear::setCoefficients(const std::vector<scalar>& coefficients) {
+ this->_coefficients = coefficients;
}
const std::vector<scalar>& Linear::coefficients() const {
@@ -90,6 +90,7 @@ namespace fl {
}
void Linear::configure(const std::string& parameters) {
+ this->_coefficients.clear();
if (parameters.empty()) return;
std::vector<std::string> strValues = Op::split(parameters, " ");
std::vector<scalar> values;
@@ -103,33 +104,12 @@ namespace fl {
return new Linear(*this);
}
- Term* Linear::constructor() {
- return new Linear;
+ void Linear::updateReference(const Engine* engine) {
+ setEngine(engine);
}
- template <typename T>
- Linear* Linear::create(const std::string& name,
- const Engine* engine, T firstCoefficient, ...) {// throw (fl::Exception) {
- if (not engine) throw fl::Exception("[linear error] cannot create term <" + name + "> "
- "without a reference to the engine", FL_AT);
- std::vector<scalar> coefficients;
- coefficients.push_back(firstCoefficient);
-
- va_list args;
- va_start(args, firstCoefficient);
- for (std::size_t i = 0; i < engine->inputVariables().size(); ++i) {
- coefficients.push_back((scalar) va_arg(args, T));
- }
- va_end(args);
-
- return new Linear(name, coefficients, engine);
+ Term* Linear::constructor() {
+ return new Linear;
}
- template FL_API Linear* Linear::create(const std::string& name,
- const Engine* engine,
- double firstCoefficient, ...);
-
- template FL_API Linear* Linear::create(const std::string& name,
- const Engine* engine,
- int firstCoefficient, ...);
}
diff --git a/fuzzylite/src/term/PiShape.cpp b/fuzzylite/src/term/PiShape.cpp
index ba3e99f..6c91f54 100644
--- a/fuzzylite/src/term/PiShape.cpp
+++ b/fuzzylite/src/term/PiShape.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/PiShape.h"
@@ -29,47 +21,45 @@ namespace fl {
PiShape::PiShape(const std::string& name, scalar bottomLeft, scalar topLeft,
scalar topRight, scalar bottomRight, scalar height)
: Term(name, height), _bottomLeft(bottomLeft), _topLeft(topLeft),
- _topRight(topRight), _bottomRight(bottomRight) {
- }
+ _topRight(topRight), _bottomRight(bottomRight) { }
- PiShape::~PiShape() {
- }
+ PiShape::~PiShape() { }
std::string PiShape::className() const {
return "PiShape";
}
- scalar PiShape::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- //from Octave smf.m
- scalar a_b_ave = (_bottomLeft + _topLeft) / 2.0;
- scalar b_minus_a = _topLeft - _bottomLeft;
- scalar c_d_ave = (_topRight + _bottomRight) / 2.0;
- scalar d_minus_c = _bottomRight - _topRight;
-
- if (Op::isLE(x, _bottomLeft)) return _height * 0.0;
-
- if (Op::isLE(x, a_b_ave))
- return _height * (2.0 * std::pow((x - _bottomLeft) / b_minus_a, 2));
-
- if (Op::isLt(x, _topLeft))
- return _height * (1.0 - 2.0 * std::pow((x - _topLeft) / b_minus_a, 2));
+ Complexity PiShape::complexity() const {
+ return Complexity().comparison(1 + 6).arithmetic(1 + 5 + 5).function(1 + 1);
+ }
+ scalar PiShape::membership(scalar x) const {
+ if (Op::isNaN(x)) return fl::nan;
+
+ scalar sshape;
+ if (Op::isLE(x, _bottomLeft))
+ sshape = 0.0;
+ else if (Op::isLE(x, 0.5 * (_bottomLeft + _topLeft)))
+ sshape = 2.0 * std::pow((x - _bottomLeft) / (_topLeft - _bottomLeft), 2);
+ else if (Op::isLt(x, _topLeft))
+ sshape = 1.0 - 2.0 * std::pow((x - _topLeft) / (_topLeft - _bottomLeft), 2);
+ else sshape = 1.0;
+
+ scalar zshape;
if (Op::isLE(x, _topRight))
- return _height * 1.0;
-
- if (Op::isLE(x, c_d_ave))
- return _height * (1.0 - 2.0 * std::pow((x - _topRight) / d_minus_c, 2));
-
- if (Op::isLt(x, _bottomRight))
- return _height * (2.0 * std::pow((x - _bottomRight) / d_minus_c, 2));
+ zshape = 1.0;
+ else if (Op::isLE(x, 0.5 * (_topRight + _bottomRight)))
+ zshape = 1.0 - 2.0 * std::pow((x - _topRight) / (_bottomRight - _topRight), 2);
+ else if (Op::isLt(x, _bottomRight))
+ zshape = 2.0 * std::pow((x - _bottomRight) / (_bottomRight - _topRight), 2);
+ else zshape = 0.0;
- return _height * 0.0;
+ return Term::_height * sshape * zshape;
}
std::string PiShape::parameters() const {
return Op::join(4, " ", _bottomLeft, _topLeft, _topRight, _bottomRight) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void PiShape::configure(const std::string& parameters) {
@@ -80,7 +70,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setBottomLeft(Op::toScalar(values.at(0)));
setTopLeft(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Ramp.cpp b/fuzzylite/src/term/Ramp.cpp
index f224045..d29233d 100644
--- a/fuzzylite/src/term/Ramp.cpp
+++ b/fuzzylite/src/term/Ramp.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Ramp.h"
@@ -27,35 +19,52 @@
namespace fl {
Ramp::Ramp(const std::string& name, scalar start, scalar end, scalar height)
- : Term(name, height), _start(start), _end(end) {
- }
+ : Term(name, height), _start(start), _end(end) { }
- Ramp::~Ramp() {
- }
+ Ramp::~Ramp() { }
std::string Ramp::className() const {
return "Ramp";
}
+ Complexity Ramp::complexity() const {
+ return Complexity().comparison(1 + 4).arithmetic(1 + 3);
+ }
+
scalar Ramp::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
+ if (Op::isNaN(x)) return fl::nan;
- if (Op::isEq(_start, _end)) return _height * 0.0;
+ if (Op::isEq(_start, _end))
+ return Term::_height * 0.0;
if (Op::isLt(_start, _end)) {
- if (Op::isLE(x, _start)) return _height * 0.0;
- if (Op::isGE(x, _end)) return _height * 1.0;
- return _height * (x - _start) / (_end - _start);
+ if (Op::isLE(x, _start))
+ return Term::_height * 0.0;
+ if (Op::isGE(x, _end))
+ return Term::_height * 1.0;
+ return Term::_height * (x - _start) / (_end - _start);
} else {
- if (Op::isGE(x, _start)) return _height * 0.0;
- if (Op::isLE(x, _end)) return _height * 1.0;
- return _height * (_start - x) / (_start - _end);
+ if (Op::isGE(x, _start))
+ return Term::_height * 0.0;
+ if (Op::isLE(x, _end))
+ return Term::_height * 1.0;
+ return Term::_height * (_start - x) / (_start - _end);
}
}
+ scalar Ramp::tsukamoto(scalar activationDegree, scalar minimum, scalar maximum) const {
+ FL_IUNUSED(minimum);
+ FL_IUNUSED(maximum);
+ return Op::scale(activationDegree, 0, 1, _start, _end);
+ }
+
+ bool Ramp::isMonotonic() const {
+ return true;
+ }
+
std::string Ramp::parameters() const {
return Op::join(2, " ", _start, _end) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Ramp::configure(const std::string& parameters) {
@@ -66,7 +75,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setStart(Op::toScalar(values.at(0)));
setEnd(Op::toScalar(values.at(1)));
@@ -92,11 +101,11 @@ namespace fl {
Ramp::Direction Ramp::direction() const {
scalar range = this->_end - this->_start;
- if (not fl::Op::isFinite(range) or fl::Op::isEq(range, 0.0)) return ZERO;
+ if (not Op::isFinite(range) or Op::isEq(range, 0.0)) return Zero;
- if (fl::Op::isGt(range, 0.0)) return POSITIVE;
+ if (Op::isGt(range, 0.0)) return Positive;
- return NEGATIVE;
+ return Negative;
}
Ramp* Ramp::clone() const {
diff --git a/fuzzylite/src/term/Rectangle.cpp b/fuzzylite/src/term/Rectangle.cpp
index 363b15d..4f975d0 100644
--- a/fuzzylite/src/term/Rectangle.cpp
+++ b/fuzzylite/src/term/Rectangle.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Rectangle.h"
@@ -27,26 +19,28 @@
namespace fl {
Rectangle::Rectangle(const std::string& name, scalar start, scalar end, scalar height)
- : Term(name, height), _start(start), _end(end) {
- }
+ : Term(name, height), _start(start), _end(end) { }
- Rectangle::~Rectangle() {
- }
+ Rectangle::~Rectangle() { }
std::string Rectangle::className() const {
return "Rectangle";
}
+ Complexity Rectangle::complexity() const {
+ return Complexity().comparison(1 + 2).arithmetic(1);
+ }
+
scalar Rectangle::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- if (fl::Op::isLt(x, _start) or fl::Op::isGt(x, _end))
- return _height * 0.0;
- return _height * 1.0;
+ if (Op::isNaN(x)) return fl::nan;
+ if (Op::isGE(x, _start) and Op::isLE(x, _end))
+ return Term::_height * 1.0;
+ return Term::_height * 0.0;
}
std::string Rectangle::parameters() const {
return Op::join(2, " ", _start, _end) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Rectangle::configure(const std::string& parameters) {
@@ -57,7 +51,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setStart(Op::toScalar(values.at(0)));
setEnd(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/SShape.cpp b/fuzzylite/src/term/SShape.cpp
index cd02be1..65dfd2b 100644
--- a/fuzzylite/src/term/SShape.cpp
+++ b/fuzzylite/src/term/SShape.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/SShape.h"
@@ -27,36 +19,58 @@
namespace fl {
SShape::SShape(const std::string& name, scalar start, scalar end, scalar height)
- : Term(name, height), _start(start), _end(end) {
- }
+ : Term(name, height), _start(start), _end(end) { }
- SShape::~SShape() {
- }
+ SShape::~SShape() { }
std::string SShape::className() const {
return "SShape";
}
+ Complexity SShape::complexity() const {
+ return Complexity().comparison(1 + 3).arithmetic(1 + 3 + 4).function(1);
+ }
+
scalar SShape::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- //from Octave smf.m
- scalar average = (_start + _end) / 2.0;
- scalar difference = _end - _start;
+ if (Op::isNaN(x)) return fl::nan;
- if (Op::isLE(x, _start)) return _height * 0.0;
+ if (Op::isLE(x, _start))
+ return Term::_height * 0.0;
- if (Op::isLE(x, average))
- return _height * (2.0 * std::pow((x - _start) / difference, 2));
+ if (Op::isLE(x, 0.5 * (_start + _end)))
+ return Term::_height * (2.0 * std::pow((x - _start) / (_end - _start), 2));
if (Op::isLt(x, _end))
- return _height * (1.0 - 2.0 * std::pow((x - _end) / difference, 2));
+ return Term::_height * (1.0 - 2.0 * std::pow((x - _end) / (_end - _start), 2));
+
+ return Term::_height * 1.0;
+ }
+
+ scalar SShape::tsukamoto(scalar activationDegree, scalar minimum, scalar maximum) const {
+ FL_IUNUSED(minimum);
+ FL_IUNUSED(maximum);
+
+ scalar w = activationDegree;
+ scalar z = fl::nan;
+
+ scalar difference = _end - _start;
+ scalar a = _start + std::sqrt(0.5 * w * difference * difference);
+ scalar b = _end + std::sqrt(-0.5 * (w - 1.0) * difference * difference);
+ if (std::abs(w - membership(a)) < std::abs(w - membership(b))) {
+ z = a;
+ } else {
+ z = b;
+ }
+ return z;
+ }
- return _height * 1.0;
+ bool SShape::isMonotonic() const {
+ return true;
}
std::string SShape::parameters() const {
return Op::join(2, " ", _start, _end) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void SShape::configure(const std::string& parameters) {
@@ -67,7 +81,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setStart(Op::toScalar(values.at(0)));
setEnd(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Sigmoid.cpp b/fuzzylite/src/term/Sigmoid.cpp
index 77d7f82..fcf165e 100644
--- a/fuzzylite/src/term/Sigmoid.cpp
+++ b/fuzzylite/src/term/Sigmoid.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Sigmoid.h"
@@ -27,24 +19,58 @@
namespace fl {
Sigmoid::Sigmoid(const std::string& name, scalar inflection, scalar slope, scalar height)
- : Term(name, height), _inflection(inflection), _slope(slope) {
- }
+ : Term(name, height), _inflection(inflection), _slope(slope) { }
- Sigmoid::~Sigmoid() {
- }
+ Sigmoid::~Sigmoid() { }
std::string Sigmoid::className() const {
return "Sigmoid";
}
+ Complexity Sigmoid::complexity() const {
+ return Complexity().comparison(1).arithmetic(1 + 4).function(1);
+ }
+
scalar Sigmoid::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- return _height * 1.0 / (1.0 + std::exp(-_slope * (x - _inflection)));
+ if (Op::isNaN(x)) return fl::nan;
+ return Term::_height * 1.0 / (1.0 + std::exp(-_slope * (x - _inflection)));
+ }
+
+ scalar Sigmoid::tsukamoto(scalar activationDegree,
+ scalar minimum, scalar maximum) const {
+
+ scalar w = activationDegree;
+ scalar z = fl::nan;
+
+ if (Op::isEq(w, 1.0)) {
+ if (Op::isGE(_slope, 0.0)) {
+ z = maximum;
+ } else {
+ z = minimum;
+ }
+
+ } else if (Op::isEq(w, 0.0)) {
+ if (Op::isGE(_slope, 0.0)) {
+ z = minimum;
+ } else {
+ z = maximum;
+ }
+ } else {
+ scalar a = _slope;
+ scalar b = _inflection;
+ z = b + (std::log(1.0 / w - 1.0) / -a);
+ }
+
+ return z;
+ }
+
+ bool Sigmoid::isMonotonic() const {
+ return true;
}
std::string Sigmoid::parameters() const {
return Op::join(2, " ", _inflection, _slope) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Sigmoid::configure(const std::string& parameters) {
@@ -55,7 +81,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setInflection(Op::toScalar(values.at(0)));
setSlope(Op::toScalar(values.at(1)));
@@ -80,11 +106,11 @@ namespace fl {
}
Sigmoid::Direction Sigmoid::direction() const {
- if (not fl::Op::isFinite(_slope) or fl::Op::isEq(_slope, 0.0)) return ZERO;
+ if (not Op::isFinite(_slope) or Op::isEq(_slope, 0.0)) return Zero;
- if (fl::Op::isGt(_slope, 0.0)) return POSITIVE;
+ if (Op::isGt(_slope, 0.0)) return Positive;
- return NEGATIVE;
+ return Negative;
}
Sigmoid* Sigmoid::clone() const {
diff --git a/fuzzylite/src/term/SigmoidDifference.cpp b/fuzzylite/src/term/SigmoidDifference.cpp
index 55a586c..8f7ee80 100644
--- a/fuzzylite/src/term/SigmoidDifference.cpp
+++ b/fuzzylite/src/term/SigmoidDifference.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/SigmoidDifference.h"
@@ -29,27 +21,29 @@ namespace fl {
SigmoidDifference::SigmoidDifference(const std::string& name,
scalar left, scalar rising,
scalar falling, scalar right, scalar height)
- : Term(name, height), _left(left), _rising(rising), _falling(falling), _right(right) {
- }
+ : Term(name, height), _left(left), _rising(rising), _falling(falling), _right(right) { }
- SigmoidDifference::~SigmoidDifference() {
- }
+ SigmoidDifference::~SigmoidDifference() { }
std::string SigmoidDifference::className() const {
return "SigmoidDifference";
}
+ Complexity SigmoidDifference::complexity() const {
+ return Complexity().comparison(1).arithmetic(2 + 4 + 4).function(2 + 1);
+ }
+
scalar SigmoidDifference::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
+ if (Op::isNaN(x)) return fl::nan;
- scalar a = 1.0 / (1 + std::exp(-_rising * (x - _left)));
- scalar b = 1.0 / (1 + std::exp(-_falling * (x - _right)));
- return _height * std::abs(a - b);
+ const scalar a = 1.0 / (1.0 + std::exp(-_rising * (x - _left)));
+ const scalar b = 1.0 / (1.0 + std::exp(-_falling * (x - _right)));
+ return Term::_height * std::abs(a - b);
}
std::string SigmoidDifference::parameters() const {
return Op::join(4, " ", _left, _rising, _falling, _right) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void SigmoidDifference::configure(const std::string& parameters) {
@@ -60,7 +54,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setLeft(Op::toScalar(values.at(0)));
setRising(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/SigmoidProduct.cpp b/fuzzylite/src/term/SigmoidProduct.cpp
index 9e43ac9..5f35750 100644
--- a/fuzzylite/src/term/SigmoidProduct.cpp
+++ b/fuzzylite/src/term/SigmoidProduct.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/SigmoidProduct.h"
@@ -29,25 +21,28 @@ namespace fl {
SigmoidProduct::SigmoidProduct(const std::string& name,
scalar left, scalar rising,
scalar falling, scalar right, scalar height)
- : Term(name, height), _left(left), _rising(rising), _falling(falling), _right(right) {
- }
+ : Term(name, height), _left(left), _rising(rising), _falling(falling), _right(right) { }
- SigmoidProduct::~SigmoidProduct() {
- }
+ SigmoidProduct::~SigmoidProduct() { }
std::string SigmoidProduct::className() const {
return "SigmoidProduct";
}
+ Complexity SigmoidProduct::complexity() const {
+ return Complexity().comparison(1).arithmetic(2 + 4 + 4).function(2);
+ }
+
scalar SigmoidProduct::membership(scalar x) const {
- scalar a = 1.0 / (1 + std::exp(-_rising * (x - _left)));
- scalar b = 1.0 / (1 + std::exp(-_falling * (x - _right)));
- return _height * a * b;
+ if (Op::isNaN(x)) return fl::nan;
+ const scalar a = 1.0 + std::exp(-_rising * (x - _left));
+ const scalar b = 1.0 + std::exp(-_falling * (x - _right));
+ return Term::_height * 1.0 / (a * b);
}
std::string SigmoidProduct::parameters() const {
return Op::join(4, " ", _left, _rising, _falling, _right) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void SigmoidProduct::configure(const std::string& parameters) {
@@ -58,7 +53,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setLeft(Op::toScalar(values.at(0)));
setRising(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Spike.cpp b/fuzzylite/src/term/Spike.cpp
index f4b73bf..a19810d 100644
--- a/fuzzylite/src/term/Spike.cpp
+++ b/fuzzylite/src/term/Spike.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Spike.h"
@@ -27,25 +19,26 @@
namespace fl {
Spike::Spike(const std::string& name, scalar center, scalar width, scalar height)
- : Term(name, height), _center(center), _width(width) {
- }
-
- Spike::~Spike() {
+ : Term(name, height), _center(center), _width(width) { }
- }
+ Spike::~Spike() { }
std::string Spike::className() const {
return "Spike";
}
+ Complexity Spike::complexity() const {
+ return Complexity().comparison(1).arithmetic(1 + 3).function(2);
+ }
+
scalar Spike::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- return _height * std::exp(-std::fabs(10.0 / _width * (x - _center)));
+ if (Op::isNaN(x)) return fl::nan;
+ return Term::_height * std::exp(-std::abs(10.0 / _width * (x - _center)));
}
std::string Spike::parameters() const {
return Op::join(2, " ", _center, _width) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Spike::configure(const std::string& parameters) {
@@ -56,7 +49,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setCenter(Op::toScalar(values.at(0)));
setWidth(Op::toScalar(values.at(1)));
@@ -87,4 +80,5 @@ namespace fl {
Term* Spike::constructor() {
return new Spike;
}
+
}
diff --git a/fuzzylite/src/term/Term.cpp b/fuzzylite/src/term/Term.cpp
index 143a98f..bf7520d 100644
--- a/fuzzylite/src/term/Term.cpp
+++ b/fuzzylite/src/term/Term.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Term.h"
@@ -30,13 +22,9 @@
namespace fl {
- Term::Term(const std::string& name, scalar height) : _name(name), _height(height) {
-
- }
-
- Term::~Term() {
+ Term::Term(const std::string& name, scalar height) : _name(name), _height(height) { }
- }
+ Term::~Term() { }
void Term::setName(const std::string& name) {
this->_name = name;
@@ -58,17 +46,20 @@ namespace fl {
return FllExporter().toString(this);
}
- void Term::updateReference(Term* term, const Engine* engine) {
- if (Linear * linear = dynamic_cast<Linear*> (term)) {
- linear->setEngine(engine);
- } else if (Function * function = dynamic_cast<Function*> (term)) {
- function->setEngine(engine);
- try {
- function->load();
- } catch (...) {
- //ignore
- }
- }
+ void Term::updateReference(const Engine* engine) {
+ FL_IUNUSED(engine);
+ //do nothing
}
+ scalar Term::tsukamoto(scalar activationDegree, scalar minimum, scalar maximum) const {
+ FL_IUNUSED(minimum);
+ FL_IUNUSED(maximum);
+ return membership(activationDegree);
+ }
+
+ bool Term::isMonotonic() const {
+ return false;
+ }
+
+
}
diff --git a/fuzzylite/src/term/Trapezoid.cpp b/fuzzylite/src/term/Trapezoid.cpp
index 60abcc4..4773dbb 100644
--- a/fuzzylite/src/term/Trapezoid.cpp
+++ b/fuzzylite/src/term/Trapezoid.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Trapezoid.h"
@@ -30,7 +22,6 @@ namespace fl {
scalar vertexA, scalar vertexB, scalar vertexC, scalar vertexD, scalar height)
: Term(name, height), _vertexA(vertexA), _vertexB(vertexB), _vertexC(vertexC), _vertexD(vertexD) {
if (Op::isNaN(vertexC) and Op::isNaN(vertexD)) {
- //TODO: Modify FLL to allow passing two parameters only.
this->_vertexD = _vertexB;
scalar range = _vertexD - _vertexA;
this->_vertexB = _vertexA + range * 1.0 / 5.0;
@@ -38,34 +29,41 @@ namespace fl {
}
}
- Trapezoid::~Trapezoid() {
- }
+ Trapezoid::~Trapezoid() { }
std::string Trapezoid::className() const {
return "Trapezoid";
}
+ Complexity Trapezoid::complexity() const {
+ return Complexity().comparison(1 + 6).arithmetic(1 + 3).function(1);
+ }
+
scalar Trapezoid::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
+ if (Op::isNaN(x)) return fl::nan;
if (Op::isLt(x, _vertexA) or Op::isGt(x, _vertexD))
- return _height * 0.0;
-
- if (Op::isLt(x, _vertexB))
- return _height * Op::min(scalar(1.0), (x - _vertexA) / (_vertexB - _vertexA));
+ return Term::_height * 0.0;
+ if (Op::isLt(x, _vertexB)) {
+ if (_vertexA == -fl::inf) return Term::_height * 1.0;
+ return Term::_height * Op::min(scalar(1.0), (x - _vertexA) / (_vertexB - _vertexA));
+ }
if (Op::isLE(x, _vertexC))
- return _height * 1.0;
+ return Term::_height * 1.0;
- if (Op::isLt(x, _vertexD))
- return _height * (_vertexD - x) / (_vertexD - _vertexC);
+ if (Op::isLt(x, _vertexD)) {
+ if (_vertexD == fl::inf) return Term::_height * 1.0;
+ return Term::_height * (_vertexD - x) / (_vertexD - _vertexC);
+ }
- return _height * 0.0;
+ if (_vertexD == fl::inf) return Term::_height * 1.0;
+ return Term::_height * 0.0;
}
std::string Trapezoid::parameters() const {
return Op::join(4, " ", _vertexA, _vertexB, _vertexC, _vertexD)+
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Trapezoid::configure(const std::string& parameters) {
@@ -76,7 +74,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setVertexA(Op::toScalar(values.at(0)));
setVertexB(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Triangle.cpp b/fuzzylite/src/term/Triangle.cpp
index 2fce1a6..9d1835c 100644
--- a/fuzzylite/src/term/Triangle.cpp
+++ b/fuzzylite/src/term/Triangle.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Triangle.h"
@@ -28,38 +20,44 @@ namespace fl {
Triangle::Triangle(const std::string& name, scalar vertexA, scalar vertexB, scalar vertexC, scalar height)
: Term(name, height), _vertexA(vertexA), _vertexB(vertexB), _vertexC(vertexC) {
- if (fl::Op::isNaN(vertexC)) {
- //TODO: Modify FLL to allow passing two parameters only.
- this->_vertexC = vertexB;
- this->_vertexB = (vertexA + vertexB) / 2.0;
+ if (Op::isNaN(vertexC)) {
+ this->_vertexC = _vertexB;
+ this->_vertexB = 0.5 * (_vertexA + _vertexB);
}
}
- Triangle::~Triangle() {
- }
+ Triangle::~Triangle() { }
std::string Triangle::className() const {
return "Triangle";
}
+ Complexity Triangle::complexity() const {
+ return Complexity().comparison(1 + 5).arithmetic(4);
+ }
+
scalar Triangle::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
+ if (Op::isNaN(x)) return fl::nan;
if (Op::isLt(x, _vertexA) or Op::isGt(x, _vertexC))
- return _height * 0.0;
+ return Term::_height * 0.0;
if (Op::isEq(x, _vertexB))
- return _height * 1.0;
-
- if (Op::isLt(x, _vertexB))
- return _height * (x - _vertexA) / (_vertexB - _vertexA);
+ return Term::_height * 1.0;
- return _height * (_vertexC - x) / (_vertexC - _vertexB);
+ if (Op::isLt(x, _vertexB)) {
+ if (_vertexA == -fl::inf)
+ return Term::_height * 1.0;
+ return Term::_height * (x - _vertexA) / (_vertexB - _vertexA);
+ }
+ if (_vertexC == fl::inf)
+ return Term::_height * 1.0;
+ return Term::_height * (_vertexC - x) / (_vertexC - _vertexB);
}
std::string Triangle::parameters() const {
return Op::join(3, " ", _vertexA, _vertexB, _vertexC) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Triangle::configure(const std::string& parameters) {
@@ -70,7 +68,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setVertexA(Op::toScalar(values.at(0)));
setVertexB(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/ZShape.cpp b/fuzzylite/src/term/ZShape.cpp
index 86668b6..9054b20 100644
--- a/fuzzylite/src/term/ZShape.cpp
+++ b/fuzzylite/src/term/ZShape.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
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.
+ the terms of the FuzzyLite License included with the software.
- 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.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/ZShape.h"
@@ -27,36 +19,58 @@
namespace fl {
ZShape::ZShape(const std::string& name, scalar start, scalar end, scalar height)
- : Term(name, height), _start(start), _end(end) {
- }
+ : Term(name, height), _start(start), _end(end) { }
- ZShape::~ZShape() {
- }
+ ZShape::~ZShape() { }
std::string ZShape::className() const {
return "ZShape";
}
+ Complexity ZShape::complexity() const {
+ return Complexity().comparison(1 + 3).arithmetic(3 + 4).function(1);
+ }
+
scalar ZShape::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- //from Octave zmf.m
- scalar average = (_start + _end) / 2;
- scalar difference = _end - _start;
+ if (Op::isNaN(x)) return fl::nan;
- if (Op::isLE(x, _start)) return _height * 1.0;
+ if (Op::isLE(x, _start))
+ return Term::_height * 1.0;
- if (Op::isLE(x, average))
- return _height * (1.0 - 2.0 * std::pow((x - _start) / difference, 2));
+ if (Op::isLE(x, 0.5 * (_start + _end)))
+ return Term::_height * (1.0 - 2.0 * std::pow((x - _start) / (_end - _start), 2));
if (Op::isLt(x, _end))
- return _height * (2.0 * std::pow((x - _end) / difference, 2));
+ return Term::_height * (2.0 * std::pow((x - _end) / (_end - _start), 2));
+
+ return Term::_height * 0.0;
+ }
+
+ scalar ZShape::tsukamoto(scalar activationDegree, scalar minimum, scalar maximum) const {
+ FL_IUNUSED(minimum);
+ FL_IUNUSED(maximum);
+
+ scalar w = activationDegree;
+ scalar z = fl::nan;
+
+ scalar difference = _end - _start;
+ scalar a = _start + std::sqrt(-0.5 * (w - 1.0) * difference * difference);
+ scalar b = _end + std::sqrt(0.5 * w * difference * difference);
+ if (std::abs(w - membership(a)) < std::abs(w - membership(b))) {
+ z = a;
+ } else {
+ z = b;
+ }
+ return z;
+ }
- return _height * 0.0;
+ bool ZShape::isMonotonic() const {
+ return true;
}
std::string ZShape::parameters() const {
return Op::join(2, " ", _start, _end) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void ZShape::configure(const std::string& parameters) {
@@ -67,7 +81,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setStart(Op::toScalar(values.at(0)));
setEnd(Op::toScalar(values.at(1)));