diff options
author | Johannes Schauer <josch@debian.org> | 2015-07-07 11:12:00 +0200 |
---|---|---|
committer | Johannes Schauer <josch@debian.org> | 2015-07-07 11:12:00 +0200 |
commit | d210b3addc8ffed7214afd8c7882e700fbcc38c5 (patch) | |
tree | ded15607f7f24f83d2d0d7c542265c0a97af577a /fuzzylite/src/term |
fuzzylite (5.1+dfsg-1) unstable; urgency=medium
* new upstream version (Closes: #777858)
* removed debian/patches/20140705-minor-improvements-on-building-script as
upstream integrated it. Adjust build options in d/rules accordingly.
* delete debian/patches/20140714-building-from-objects-just-once and
debian/patches/20141027-fix-some-spelling as they have been applied
upstream
* install usr/lib/*/pkgconfig/fuzzylite.pc in fuzzylite-dev
* SONAME bump from 5.0 to 5.1, so renaming libfuzzylite5.0 to
libfuzzylite5.1
* add debian/patches/pkgconfig_installdir to install pkgconfig file in
correct location
# imported from the archive
Diffstat (limited to 'fuzzylite/src/term')
23 files changed, 3113 insertions, 0 deletions
diff --git a/fuzzylite/src/term/Accumulated.cpp b/fuzzylite/src/term/Accumulated.cpp new file mode 100644 index 0000000..979af9f --- /dev/null +++ b/fuzzylite/src/term/Accumulated.cpp @@ -0,0 +1,211 @@ +/* + 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 new file mode 100644 index 0000000..9a27b4b --- /dev/null +++ b/fuzzylite/src/term/Activated.cpp @@ -0,0 +1,100 @@ +/* + 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/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() { + } + + std::string Activated::className() const { + return "Activated"; + } + + 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); + } + + std::string Activated::parameters() const { + FllExporter exporter; + std::ostringstream ss; + ss << Op::str(_degree) << " " << exporter.toString(_activation) << " " + << exporter.toString(_term); + return ss.str(); + } + + void Activated::configure(const std::string& parameters) { + (void) parameters; + } + + std::string Activated::toString() const { + FllExporter exporter; + std::ostringstream ss; + ss << exporter.toString(_activation) << "(" + << Op::str(_degree) << "," + << _term->getName() << ")"; + return ss.str(); + } + + void Activated::setTerm(const Term* term) { + this->_term = term; + } + + const Term* Activated::getTerm() const { + return this->_term; + } + + void Activated::setDegree(scalar degree) { + this->_degree = degree; + } + + scalar Activated::getDegree() const { + return this->_degree; + } + + void Activated::setActivation(const TNorm* activation) { + this->_activation = activation; + } + + const TNorm* Activated::getActivation() const { + return this->_activation; + } + + Activated* Activated::clone() const { + return new Activated(*this); + } + +} diff --git a/fuzzylite/src/term/Bell.cpp b/fuzzylite/src/term/Bell.cpp new file mode 100644 index 0000000..fc0b215 --- /dev/null +++ b/fuzzylite/src/term/Bell.cpp @@ -0,0 +1,99 @@ +/* + 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/Bell.h" + +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) { + } + + Bell::~Bell() { + } + + std::string Bell::className() const { + return "Bell"; + } + + 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))); + } + + std::string Bell::parameters() const { + return Op::join(3, " ", _center, _width, _slope) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void Bell::configure(const std::string& parameters) { + if (parameters.empty()) return; + std::vector<std::string> values = Op::split(parameters, " "); + std::size_t required = 3; + if (values.size() < required) { + std::ostringstream ex; + ex << "[configuration error] term <" << className() << ">" + << " requires <" << required << "> parameters"; + throw fl::Exception(ex.str(), FL_AT); + } + setCenter(Op::toScalar(values.at(0))); + setWidth(Op::toScalar(values.at(1))); + setSlope(Op::toScalar(values.at(2))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void Bell::setWidth(scalar a) { + this->_width = a; + } + + scalar Bell::getWidth() const { + return this->_width; + } + + void Bell::setSlope(scalar b) { + this->_slope = b; + } + + scalar Bell::getSlope() const { + return this->_slope; + } + + void Bell::setCenter(scalar c) { + this->_center = c; + } + + scalar Bell::getCenter() const { + return this->_center; + } + + Bell* Bell::clone() const { + return new Bell(*this); + } + + Term* Bell::constructor() { + return new Bell; + } + +} diff --git a/fuzzylite/src/term/Concave.cpp b/fuzzylite/src/term/Concave.cpp new file mode 100644 index 0000000..37679ae --- /dev/null +++ b/fuzzylite/src/term/Concave.cpp @@ -0,0 +1,107 @@ +/* + 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/Concave.h" + +namespace fl { + + Concave::Concave(const std::string& name, scalar inflection, scalar end, scalar height) + : Term(name, height), _inflection(inflection), _end(end) { + + } + + Concave::~Concave() { + + } + + std::string Concave::className() const { + return "Concave"; + } + + 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); + } + } else { //Concave decreasing + if (fl::Op::isGt(x, _end)) { + return _height * (_inflection - _end) / (_inflection - 2 * _end + x); + } + } + return _height * 1.0; + } + + std::string Concave::parameters() const { + return Op::join(2, " ", _inflection, _end) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + + } + + void Concave::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 fl::Exception(ex.str(), FL_AT); + } + setInflection(Op::toScalar(values.at(0))); + setEnd(Op::toScalar(values.at(1))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + + } + + void Concave::setInflection(scalar start) { + this->_inflection = start; + } + + scalar Concave::getInflection() const { + return this->_inflection; + } + + void Concave::setEnd(scalar end) { + this->_end = end; + } + + scalar Concave::getEnd() const { + return this->_end; + } + + Concave* Concave::clone() const { + return new Concave(*this); + } + + Term* Concave::constructor() { + return new Concave; + } + + + + + +} diff --git a/fuzzylite/src/term/Constant.cpp b/fuzzylite/src/term/Constant.cpp new file mode 100644 index 0000000..d52f8ec --- /dev/null +++ b/fuzzylite/src/term/Constant.cpp @@ -0,0 +1,70 @@ +/* + 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/Constant.h" + +namespace fl { + + Constant::Constant(const std::string& name, scalar value) + : Term(name), _value(value) { + } + + Constant::~Constant() { + } + + std::string Constant::className() const { + return "Constant"; + } + + scalar Constant::membership(scalar x) const { + (void) x; + return this->_value; + } + + std::string Constant::parameters() const { + return Op::str(_value); + } + + void Constant::configure(const std::string& parameters) { + if (parameters.empty()) return; + setValue(Op::toScalar(parameters)); + } + + void Constant::setValue(scalar value) { + this->_value = value; + } + + scalar Constant::getValue() const { + return this->_value; + } + + Constant* Constant::clone() const { + return new Constant(*this); + } + + Term* Constant::constructor() { + return new Constant; + } + +} diff --git a/fuzzylite/src/term/Cosine.cpp b/fuzzylite/src/term/Cosine.cpp new file mode 100644 index 0000000..a1402ad --- /dev/null +++ b/fuzzylite/src/term/Cosine.cpp @@ -0,0 +1,96 @@ +/* + 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/Cosine.h" + +namespace fl { + + Cosine::Cosine(const std::string& name, scalar center, scalar width, scalar height) + : Term(name, height), _center(center), _width(width) { + + } + + Cosine::~Cosine() { + + } + + std::string Cosine::className() const { + return "Cosine"; + } + + std::string Cosine::parameters() const { + return Op::join(2, " ", _center, _width) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void Cosine::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 fl::Exception(ex.str(), FL_AT); + } + setCenter(Op::toScalar(values.at(0))); + setWidth(Op::toScalar(values.at(1))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + + } + + 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; + const scalar pi = 4.0 * std::atan(1.0); + return _height * (0.5 * (1.0 + std::cos(2.0 / _width * pi * (x - _center)))); + } + + void Cosine::setCenter(scalar center) { + this->_center = center; + } + + scalar Cosine::getCenter() const { + return this->_center; + } + + void Cosine::setWidth(scalar width) { + this->_width = width; + } + + scalar Cosine::getWidth() const { + return this->_width; + } + + Cosine* Cosine::clone() const { + return new Cosine(*this); + } + + Term* Cosine::constructor() { + return new Cosine; + } +} diff --git a/fuzzylite/src/term/Discrete.cpp b/fuzzylite/src/term/Discrete.cpp new file mode 100644 index 0000000..212ada2 --- /dev/null +++ b/fuzzylite/src/term/Discrete.cpp @@ -0,0 +1,210 @@ +/* + 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/Discrete.h" + +#include <cstdarg> + +namespace fl { + + Discrete::Discrete(const std::string& name, const std::vector<Pair>& xy, scalar height) + : Term(name, height), _xy(xy) { + } + + Discrete::~Discrete() { + } + + std::string Discrete::className() const { + return "Discrete"; + } + + scalar Discrete::membership(scalar _x_) const { + if (fl::Op::isNaN(_x_)) return fl::nan; + if (_xy.empty()) + throw fl::Exception("[discrete error] term is empty", FL_AT); + + /* ______________________ + * / \ + * / \ + * ____________/ \____________ + * x[0] x[n-1] + */ + + + 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; + + 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 (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); + } + + 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); + if (i + 1 < _xy.size()) ss << " "; + } + if (not Op::isEq(_height, 1.0)) ss << " " << Op::str(_height); + return ss.str(); + } + + void Discrete::configure(const std::string& parameters) { + if (parameters.empty()) return; + std::vector<std::string> strValues = Op::split(parameters, " "); + std::vector<scalar> values(strValues.size()); + for (std::size_t i = 0; i < strValues.size(); ++i) { + values.at(i) = Op::toScalar(strValues.at(i)); + } + if (values.size() % 2 == 0) { + setHeight(1.0); + } else { + setHeight(values.back()); + values.pop_back(); + } + 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; + } + + const std::vector<Discrete::Pair>& Discrete::xy() const { + return this->_xy; + } + + std::vector<Discrete::Pair>& Discrete::xy() { + return this->_xy; + } + + const Discrete::Pair& Discrete::xy(int index) const { + return this->_xy.at(index); + } + + Discrete::Pair& Discrete::xy(int index) { + return this->_xy.at(index); + } + + 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); + } + + std::vector<Pair> result((xy.size() + 1) / 2); + for (std::size_t i = 0; i + 1 < xy.size(); i += 2) { + result.at(i / 2).first = xy.at(i); + result.at(i / 2).second = xy.at(i + 1); + } + return result; + } + + std::vector<Discrete::Pair> Discrete::toPairs(const std::vector<scalar>& xy, + scalar missingValue) FL_INOEXCEPT { + std::vector<Pair> result((xy.size() + 1) / 2); + for (std::size_t i = 0; i + 1 < xy.size(); i += 2) { + result.at(i / 2).first = xy.at(i); + result.at(i / 2).second = xy.at(i + 1); + } + if (xy.size() % 2 != 0) { + result.back().first = xy.back(); + result.back().second = missingValue; + } + return result; + } + + std::vector<scalar> Discrete::toVector(const std::vector<Pair>& xy) { + std::vector<scalar> result(xy.size() * 2); + for (std::size_t i = 0; i < xy.size(); ++i) { + result.at(2 * i) = xy.at(i).first; + result.at(2 * i + 1) = xy.at(i).second; + } + 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::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; + if (i + 1 < xy.size()) os << outerSeparator; + } + return os.str(); + } + + Discrete* Discrete::clone() const { + return new Discrete(*this); + } + + Term* Discrete::constructor() { + return new Discrete; + } + + +} diff --git a/fuzzylite/src/term/Function.cpp b/fuzzylite/src/term/Function.cpp new file mode 100644 index 0000000..c0f54b8 --- /dev/null +++ b/fuzzylite/src/term/Function.cpp @@ -0,0 +1,600 @@ +/* + 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/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 { + + /** + * Parsing elements + */ + + + 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) { + + } + + 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) { + } + + 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) { + } + + Function::Element::~Element() { + + } + + bool Function::Element::isOperator() const { + return type == OPERATOR; + } + + bool Function::Element::isFunction() const { + return type == FUNCTION; + } + + Function::Element* Function::Element::clone() const { + return new Element(*this); + } + + std::string Function::Element::toString() const { + std::ostringstream ss; + + if (type == OPERATOR) { + ss << "Operator (name=" << name << ", " + << "description=" << description << ", " + << "precedence=" << precedence << ", " + << "arity=" << arity << ", " + << "associativity=" << associativity << ", "; + if (arity == 1) ss << "pointer=" << unary; + else if (arity == 2) ss << "pointer=" << binary; + else ss << "pointer=error"; + ss << ")"; + } else if (type == FUNCTION) { + ss << "Function (name=" << name << ", " + << "description=" << description << ", " + << "arity=" << arity << ", " + << "associativity=" << associativity << ", "; + if (arity == 1) ss << "pointer=" << unary; + else if (arity == 2) ss << "pointer=" << binary; + else ss << "pointer=error"; + ss << ")"; + } + return ss.str(); + } + + /****************************** + * Tree Node Elements + ******************************/ + + Function::Node::Node(Element* element, Node* left, Node* right) + : 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) { + } + + Function::Node::Node(scalar 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) { + copyFrom(other); + } + + Function::Node& Function::Node::operator=(const Node& other) { + if (this != &other) { + element.reset(fl::null); + left.reset(fl::null); + right.reset(fl::null); + + copyFrom(other); + } + return *this; + } + + void Function::Node::copyFrom(const Node& other) { + if (other.element.get()) element.reset(other.element->clone()); + if (other.left.get()) left.reset(other.left->clone()); + if (other.right.get()) right.reset(other.right->clone()); + variable = other.variable; + value = other.value; + } + + Function::Node::~Node() { + } + + scalar Function::Node::evaluate(const std::map<std::string, scalar>* variables) const { + scalar result = fl::nan; + if (element.get()) { + if (element->unary) { + result = element->unary(left->evaluate(variables)); + } else if (element->binary) { + result = element->binary(right->evaluate(variables), left->evaluate(variables)); + } else { + std::ostringstream ex; + ex << "[function error] arity <" << element->arity << "> of " + << (element->isOperator() ? "operator" : "function") << + " <" << element->name << "> is fl::null"; + throw fl::Exception(ex.str(), FL_AT); + } + + } else if (not variable.empty()) { + if (not variables) { + throw fl::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] " + "unknown variable <" + variable + ">", FL_AT); + } else { + result = value; + } + return result; + } + + Function::Node* Function::Node::clone() const { + return new Node(*this); + } + + std::string Function::Node::toString() const { + std::ostringstream ss; + if (element.get()) ss << element->name; + else if (not variable.empty()) ss << variable; + else ss << fl::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 node->variable.empty()) { + return node->variable; + } + + std::ostringstream ss; + ss << node->toString(); + if (node->left.get()) + ss << " " << this->toPrefix(node->left.get()); + if (node->right.get()) + ss << " " << this->toPrefix(node->right.get()); + return ss.str(); + } + + 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 node->variable.empty()) { + return node->variable; + } + + std::ostringstream ss; + if (node->left.get()) + ss << this->toInfix(node->left.get()) << " "; + ss << node->toString(); + if (node->right.get()) + ss << " " << this->toInfix(node->right.get()); + return ss.str(); + } + + 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 node->variable.empty()) { + return node->variable; + } + + std::ostringstream ss; + if (node->left.get()) + ss << this->toPostfix(node->left.get()) << " "; + if (node->right.get()) + ss << this->toPostfix(node->right.get()) << " "; + ss << node->toString(); + return ss.str(); + } + + /********************************** + * Function class. + **********************************/ + Function::Function(const std::string& name, + const std::string& formula, const 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) { + if (other._root.get()) _root.reset(other._root->clone()); + variables = other.variables; + } + + Function& Function::operator=(const Function& other) { + if (this != &other) { + _root.reset(fl::null); + + Term::operator=(other); + _formula = other._formula; + _engine = other._engine; + if (other._root.get()) _root.reset(other._root->clone()); + variables = other.variables; + } + return *this; + } + + Function::~Function() { + } + + std::string Function::className() const { + return "Function"; + } + + scalar Function::membership(scalar x) const { + if (not this->_root.get()) { + throw fl::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(); + } + for (int i = 0; i < this->_engine->numberOfOutputVariables(); ++i) { + OutputVariable* output = this->_engine->getOutputVariable(i); + this->variables[output->getName()] = output->getOutputValue(); + } + } + this->variables["x"] = x; + return this->evaluate(&this->variables); + } + + 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 (localVariables) + return this->_root->evaluate(localVariables); + return this->_root->evaluate(&this->variables); + } + + std::string Function::parameters() const { + return _formula; + } + + void Function::configure(const std::string& parameters) { + load(parameters); + } + + Function* Function::create(const std::string& name, + const std::string& infix, const Engine* engine) { + FL_unique_ptr<Function> result(new Function(name)); + result->load(infix, engine); + return result.release(); + } + + bool Function::isLoaded() const { + return this->_root.get() != fl::null; + } + + void Function::unload() { + this->_root.reset(fl::null); + this->variables.clear(); + } + + void Function::load() { + load(this->_formula); + } + + void Function::load(const std::string& formula) { + load(formula, this->_engine); + } + + void Function::load(const std::string& formula, + const Engine* engine) { + unload(); + this->_formula = formula; + this->_engine = engine; + this->_root.reset(parse(formula)); + membership(0.0); //make sure function evaluates without throwing exception. + } + + void Function::setFormula(const std::string& formula) { + this->_formula = formula; + } + + std::string Function::getFormula() const { + return this->_formula; + } + + void Function::setEngine(const Engine* engine) { + this->_engine = engine; + } + + const Engine* Function::getEngine() const { + return this->_engine; + } + + Function::Node* Function::root() const { + return this->_root.get(); + } + + Function* Function::clone() const { + return new Function(*this); + } + + Term* Function::constructor() { + return new Function; + } + + 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(); + 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())) { + 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) + " "); + } + return result; + } + + /**************************************** + * The Glorious Parser + * Shunting-yard algorithm + * TODO: Maybe change it for http://en.wikipedia.org/wiki/Operator-precedence_parser + ***************************************/ + + std::string Function::toPostfix(const std::string& formula) const { + std::string spacedFormula = space(formula); + + std::queue<std::string> queue; + std::stack<std::string> stack; + + std::stringstream tokenizer(spacedFormula); + std::string token; + FunctionFactory* factory = fl::FactoryManager::instance()->function(); + while (tokenizer >> token) { + Element* element = factory->getObject(token); + bool isOperand = not element and token != "(" and token != ")" and token != ","; + + if (isOperand) { + queue.push(token); + + } else if (element and element->isFunction()) { + stack.push(token); + + } else if (token == ",") { + while (not stack.empty() and stack.top() != "(") { + queue.push(stack.top()); + stack.pop(); + } + if (stack.empty() or stack.top() != "(") { + std::ostringstream ex; + ex << "[parsing error] mismatching parentheses in: " << formula; + throw fl::Exception(ex.str(), FL_AT); + } + + } else if (element and element->isOperator()) { + Element* op1 = element; + for (;;) { + Element* op2 = fl::null; + if (not stack.empty()) op2 = factory->getObject(stack.top()); + if (not op2) break; + + if ((op1->associativity < 0 and op1->precedence == op2->precedence) + or op1->precedence < op2->precedence) { + queue.push(stack.top()); + stack.pop(); + } else + break; + } + stack.push(token); + + } else if (token == "(") { + stack.push(token); + + } else if (token == ")") { + while (not stack.empty() and stack.top() != "(") { + queue.push(stack.top()); + stack.pop(); + } + if (stack.empty() or stack.top() != "(") { + std::ostringstream ex; + ex << "[parsing error] mismatching parentheses in: " << formula; + throw fl::Exception(ex.str(), FL_AT); + } + stack.pop(); //get rid of "(" + + Element* top = fl::null; + if (not stack.empty()) top = factory->getObject(stack.top()); + if (top and top->isFunction()) { + queue.push(stack.top()); + stack.pop(); + } + } else { + std::ostringstream ex; + ex << "[parsing error] unexpected error with token <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + } + + while (not stack.empty()) { + if (stack.top() == "(" or stack.top() == ")") { + std::ostringstream ex; + ex << "[parsing error] mismatching parentheses in: " << formula; + throw fl::Exception(ex.str(), FL_AT); + } + queue.push(stack.top()); + stack.pop(); + } + + std::stringstream ssPostfix; + while (not queue.empty()) { + ssPostfix << queue.front(); + 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); + std::string postfix = toPostfix(formula); + + std::stack<Node*> stack; + + std::istringstream tokenizer(postfix); + std::string token; + FunctionFactory* factory = fl::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()) { + 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); + } + + Node* node = new Node(element->clone()); + node->left.reset(stack.top()); + stack.pop(); + if (element->arity == 2) { + node->right.reset(stack.top()); + stack.pop(); + } + stack.push(node); + + } else if (isOperand) { + Node* node; + try { + scalar value = fl::Op::toScalar(token); + node = new Node(value); + } catch (std::exception& ex) { + (void) ex; + node = new Node(token); + } + stack.push(node); + } + } + + if (stack.size() != 1) + throw fl::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 new file mode 100644 index 0000000..5b709f9 --- /dev/null +++ b/fuzzylite/src/term/Gaussian.cpp @@ -0,0 +1,92 @@ +/* + 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/Gaussian.h" + +namespace fl { + + Gaussian::Gaussian(const std::string& name, + scalar mean, scalar standardDeviation, scalar height) + : Term(name, height), _mean(mean), _standardDeviation(standardDeviation) { + } + + Gaussian::~Gaussian() { + } + + std::string Gaussian::className() const { + return "Gaussian"; + } + + 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)); + } + + std::string Gaussian::parameters() const { + return Op::join(2, " ", _mean, _standardDeviation) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void Gaussian::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 fl::Exception(ex.str(), FL_AT); + } + setMean(Op::toScalar(values.at(0))); + setStandardDeviation(Op::toScalar(values.at(1))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void Gaussian::setMean(scalar c) { + this->_mean = c; + } + + scalar Gaussian::getMean() const { + return this->_mean; + } + + void Gaussian::setStandardDeviation(scalar sigma) { + this->_standardDeviation = sigma; + } + + scalar Gaussian::getStandardDeviation() const { + return this->_standardDeviation; + } + + Gaussian* Gaussian::clone() const { + return new Gaussian(*this); + } + + Term* Gaussian::constructor() { + return new Gaussian; + } + + +} diff --git a/fuzzylite/src/term/GaussianProduct.cpp b/fuzzylite/src/term/GaussianProduct.cpp new file mode 100644 index 0000000..b9652e1 --- /dev/null +++ b/fuzzylite/src/term/GaussianProduct.cpp @@ -0,0 +1,120 @@ +/* + 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/GaussianProduct.h" + +namespace fl { + + GaussianProduct::GaussianProduct(const std::string& name, + scalar meanA, scalar standardDeviationA, scalar meanB, scalar standardDeviationB, + scalar height) + : Term(name, height), _meanA(meanA), _standardDeviationA(standardDeviationA), + _meanB(meanB), _standardDeviationB(standardDeviationB) { + } + + GaussianProduct::~GaussianProduct() { + } + + std::string GaussianProduct::className() const { + return "GaussianProduct"; + } + + 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; + } + + std::string GaussianProduct::parameters() const { + return Op::join(4, " ", _meanA, _standardDeviationA, _meanB, _standardDeviationB) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void GaussianProduct::configure(const std::string& parameters) { + if (parameters.empty()) return; + std::vector<std::string> values = Op::split(parameters, " "); + std::size_t required = 4; + if (values.size() < required) { + std::ostringstream ex; + ex << "[configuration error] term <" << className() << ">" + << " requires <" << required << "> parameters"; + throw fl::Exception(ex.str(), FL_AT); + } + setMeanA(Op::toScalar(values.at(0))); + setStandardDeviationA(Op::toScalar(values.at(1))); + setMeanB(Op::toScalar(values.at(2))); + setStandardDeviationB(Op::toScalar(values.at(3))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void GaussianProduct::setMeanA(scalar meanA) { + this->_meanA = meanA; + } + + scalar GaussianProduct::getMeanA() const { + return this->_meanA; + } + + void GaussianProduct::setStandardDeviationA(scalar sigmaA) { + this->_standardDeviationA = sigmaA; + } + + scalar GaussianProduct::getStandardDeviationA() const { + return this->_standardDeviationA; + } + + void GaussianProduct::setMeanB(scalar meanB) { + this->_meanB = meanB; + } + + scalar GaussianProduct::getMeanB() const { + return this->_meanB; + } + + void GaussianProduct::setStandardDeviationB(scalar sigmaB) { + this->_standardDeviationB = sigmaB; + } + + scalar GaussianProduct::getStandardDeviationB() const { + return this->_standardDeviationB; + } + + GaussianProduct* GaussianProduct::clone() const { + return new GaussianProduct(*this); + } + + Term* GaussianProduct::constructor() { + return new GaussianProduct; + } + + +} diff --git a/fuzzylite/src/term/Linear.cpp b/fuzzylite/src/term/Linear.cpp new file mode 100644 index 0000000..4111a00 --- /dev/null +++ b/fuzzylite/src/term/Linear.cpp @@ -0,0 +1,135 @@ +/* + 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/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) { + } + + Linear::~Linear() { + } + + std::string Linear::className() const { + return "Linear"; + } + + scalar Linear::membership(scalar x) const { + (void) x; + if (not _engine) throw fl::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(); + } + if (_coefficients.size() > _engine->inputVariables().size()) { + result += _coefficients.back(); + } + return result; + } + + void Linear::set(const std::vector<scalar>& coeffs, const Engine* engine) { + setCoefficients(coeffs); + setEngine(engine); + } + + void Linear::setCoefficients(const std::vector<scalar>& coeffs) { + this->_coefficients = coeffs; + } + + const std::vector<scalar>& Linear::coefficients() const { + return this->_coefficients; + } + + std::vector<scalar>& Linear::coefficients() { + return this->_coefficients; + } + + void Linear::setEngine(const Engine* engine) { + this->_engine = engine; + } + + const Engine* Linear::getEngine() const { + return this->_engine; + } + + std::string Linear::parameters() const { + return Op::join(this->_coefficients, " "); + } + + void Linear::configure(const std::string& parameters) { + if (parameters.empty()) return; + std::vector<std::string> strValues = Op::split(parameters, " "); + std::vector<scalar> values; + for (std::size_t i = 0; i < strValues.size(); ++i) { + values.push_back(Op::toScalar(strValues.at(i))); + } + this->_coefficients = values; + } + + Linear* Linear::clone() const { + return new Linear(*this); + } + + Term* Linear::constructor() { + return new Linear; + } + + 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); + } + + 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 new file mode 100644 index 0000000..ba3e99f --- /dev/null +++ b/fuzzylite/src/term/PiShape.cpp @@ -0,0 +1,133 @@ +/* + 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/PiShape.h" + +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) { + } + + 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)); + + 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)); + + return _height * 0.0; + } + + std::string PiShape::parameters() const { + return Op::join(4, " ", _bottomLeft, _topLeft, _topRight, _bottomRight) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void PiShape::configure(const std::string& parameters) { + if (parameters.empty()) return; + std::vector<std::string> values = Op::split(parameters, " "); + std::size_t required = 4; + if (values.size() < required) { + std::ostringstream ex; + ex << "[configuration error] term <" << className() << ">" + << " requires <" << required << "> parameters"; + throw fl::Exception(ex.str(), FL_AT); + } + setBottomLeft(Op::toScalar(values.at(0))); + setTopLeft(Op::toScalar(values.at(1))); + setTopRight(Op::toScalar(values.at(2))); + setBottomRight(Op::toScalar(values.at(3))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void PiShape::setBottomLeft(scalar a) { + this->_bottomLeft = a; + } + + scalar PiShape::getBottomLeft() const { + return this->_bottomLeft; + } + + void PiShape::setTopLeft(scalar b) { + this->_topLeft = b; + } + + scalar PiShape::getTopLeft() const { + return this->_topLeft; + } + + void PiShape::setTopRight(scalar d) { + this->_topRight = d; + } + + scalar PiShape::getTopRight() const { + return this->_topRight; + } + + void PiShape::setBottomRight(scalar c) { + this->_bottomRight = c; + } + + scalar PiShape::getBottomRight() const { + return this->_bottomRight; + } + + PiShape* PiShape::clone() const { + return new PiShape(*this); + } + + Term* PiShape::constructor() { + return new PiShape; + } + +} diff --git a/fuzzylite/src/term/Ramp.cpp b/fuzzylite/src/term/Ramp.cpp new file mode 100644 index 0000000..f224045 --- /dev/null +++ b/fuzzylite/src/term/Ramp.cpp @@ -0,0 +1,110 @@ +/* + 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/Ramp.h" + +namespace fl { + + Ramp::Ramp(const std::string& name, scalar start, scalar end, scalar height) + : Term(name, height), _start(start), _end(end) { + } + + Ramp::~Ramp() { + } + + std::string Ramp::className() const { + return "Ramp"; + } + + scalar Ramp::membership(scalar x) const { + if (fl::Op::isNaN(x)) return fl::nan; + + if (Op::isEq(_start, _end)) return _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); + } 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); + } + } + + std::string Ramp::parameters() const { + return Op::join(2, " ", _start, _end) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void Ramp::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 fl::Exception(ex.str(), FL_AT); + } + setStart(Op::toScalar(values.at(0))); + setEnd(Op::toScalar(values.at(1))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void Ramp::setStart(scalar start) { + this->_start = start; + } + + scalar Ramp::getStart() const { + return this->_start; + } + + void Ramp::setEnd(scalar end) { + this->_end = end; + } + + scalar Ramp::getEnd() const { + return this->_end; + } + + 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 (fl::Op::isGt(range, 0.0)) return POSITIVE; + + return NEGATIVE; + } + + Ramp* Ramp::clone() const { + return new Ramp(*this); + } + + Term* Ramp::constructor() { + return new Ramp; + } + +} diff --git a/fuzzylite/src/term/Rectangle.cpp b/fuzzylite/src/term/Rectangle.cpp new file mode 100644 index 0000000..363b15d --- /dev/null +++ b/fuzzylite/src/term/Rectangle.cpp @@ -0,0 +1,93 @@ +/* + 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/Rectangle.h" + +namespace fl { + + Rectangle::Rectangle(const std::string& name, scalar start, scalar end, scalar height) + : Term(name, height), _start(start), _end(end) { + } + + Rectangle::~Rectangle() { + } + + std::string Rectangle::className() const { + return "Rectangle"; + } + + 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; + } + + std::string Rectangle::parameters() const { + return Op::join(2, " ", _start, _end) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void Rectangle::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 fl::Exception(ex.str(), FL_AT); + } + setStart(Op::toScalar(values.at(0))); + setEnd(Op::toScalar(values.at(1))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void Rectangle::setStart(scalar minimum) { + this->_start = minimum; + } + + scalar Rectangle::getStart() const { + return this->_start; + } + + void Rectangle::setEnd(scalar maximum) { + this->_end = maximum; + } + + scalar Rectangle::getEnd() const { + return this->_end; + } + + Rectangle* Rectangle::clone() const { + return new Rectangle(*this); + } + + Term* Rectangle::constructor() { + return new Rectangle; + } + + +} diff --git a/fuzzylite/src/term/SShape.cpp b/fuzzylite/src/term/SShape.cpp new file mode 100644 index 0000000..cd02be1 --- /dev/null +++ b/fuzzylite/src/term/SShape.cpp @@ -0,0 +1,102 @@ +/* + 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/SShape.h" + +namespace fl { + + SShape::SShape(const std::string& name, scalar start, scalar end, scalar height) + : Term(name, height), _start(start), _end(end) { + } + + SShape::~SShape() { + } + + std::string SShape::className() const { + return "SShape"; + } + + 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::isLE(x, _start)) return _height * 0.0; + + if (Op::isLE(x, average)) + return _height * (2.0 * std::pow((x - _start) / difference, 2)); + + if (Op::isLt(x, _end)) + return _height * (1.0 - 2.0 * std::pow((x - _end) / difference, 2)); + + return _height * 1.0; + } + + std::string SShape::parameters() const { + return Op::join(2, " ", _start, _end) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void SShape::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 fl::Exception(ex.str(), FL_AT); + } + setStart(Op::toScalar(values.at(0))); + setEnd(Op::toScalar(values.at(1))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void SShape::setStart(scalar start) { + this->_start = start; + } + + scalar SShape::getStart() const { + return this->_start; + } + + void SShape::setEnd(scalar end) { + this->_end = end; + } + + scalar SShape::getEnd() const { + return this->_end; + } + + SShape* SShape::clone() const { + return new SShape(*this); + } + + Term* SShape::constructor() { + return new SShape; + } + +} diff --git a/fuzzylite/src/term/Sigmoid.cpp b/fuzzylite/src/term/Sigmoid.cpp new file mode 100644 index 0000000..77d7f82 --- /dev/null +++ b/fuzzylite/src/term/Sigmoid.cpp @@ -0,0 +1,98 @@ +/* + 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/Sigmoid.h" + +namespace fl { + + Sigmoid::Sigmoid(const std::string& name, scalar inflection, scalar slope, scalar height) + : Term(name, height), _inflection(inflection), _slope(slope) { + } + + Sigmoid::~Sigmoid() { + } + + std::string Sigmoid::className() const { + return "Sigmoid"; + } + + 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))); + } + + std::string Sigmoid::parameters() const { + return Op::join(2, " ", _inflection, _slope) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void Sigmoid::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 fl::Exception(ex.str(), FL_AT); + } + setInflection(Op::toScalar(values.at(0))); + setSlope(Op::toScalar(values.at(1))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void Sigmoid::setSlope(scalar a) { + this->_slope = a; + } + + scalar Sigmoid::getSlope() const { + return this->_slope; + } + + void Sigmoid::setInflection(scalar c) { + this->_inflection = c; + } + + scalar Sigmoid::getInflection() const { + return this->_inflection; + } + + Sigmoid::Direction Sigmoid::direction() const { + if (not fl::Op::isFinite(_slope) or fl::Op::isEq(_slope, 0.0)) return ZERO; + + if (fl::Op::isGt(_slope, 0.0)) return POSITIVE; + + return NEGATIVE; + } + + Sigmoid* Sigmoid::clone() const { + return new Sigmoid(*this); + } + + Term* Sigmoid::constructor() { + return new Sigmoid; + } + +} diff --git a/fuzzylite/src/term/SigmoidDifference.cpp b/fuzzylite/src/term/SigmoidDifference.cpp new file mode 100644 index 0000000..55a586c --- /dev/null +++ b/fuzzylite/src/term/SigmoidDifference.cpp @@ -0,0 +1,114 @@ +/* + 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/SigmoidDifference.h" + +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) { + } + + SigmoidDifference::~SigmoidDifference() { + } + + std::string SigmoidDifference::className() const { + return "SigmoidDifference"; + } + + scalar SigmoidDifference::membership(scalar x) const { + if (fl::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); + } + + std::string SigmoidDifference::parameters() const { + return Op::join(4, " ", _left, _rising, _falling, _right) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void SigmoidDifference::configure(const std::string& parameters) { + if (parameters.empty()) return; + std::vector<std::string> values = Op::split(parameters, " "); + std::size_t required = 4; + if (values.size() < required) { + std::ostringstream ex; + ex << "[configuration error] term <" << className() << ">" + << " requires <" << required << "> parameters"; + throw fl::Exception(ex.str(), FL_AT); + } + setLeft(Op::toScalar(values.at(0))); + setRising(Op::toScalar(values.at(1))); + setFalling(Op::toScalar(values.at(2))); + setRight(Op::toScalar(values.at(3))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void SigmoidDifference::setLeft(scalar leftInflection) { + this->_left = leftInflection; + } + + scalar SigmoidDifference::getLeft() const { + return this->_left; + } + + void SigmoidDifference::setRising(scalar risingSlope) { + this->_rising = risingSlope; + } + + scalar SigmoidDifference::getRising() const { + return this->_rising; + } + + void SigmoidDifference::setFalling(scalar fallingSlope) { + this->_falling = fallingSlope; + } + + scalar SigmoidDifference::getFalling() const { + return this->_falling; + } + + void SigmoidDifference::setRight(scalar rightInflection) { + this->_right = rightInflection; + } + + scalar SigmoidDifference::getRight() const { + return this->_right; + } + + SigmoidDifference* SigmoidDifference::clone() const { + return new SigmoidDifference(*this); + } + + Term* SigmoidDifference::constructor() { + return new SigmoidDifference; + } + + +} diff --git a/fuzzylite/src/term/SigmoidProduct.cpp b/fuzzylite/src/term/SigmoidProduct.cpp new file mode 100644 index 0000000..9e43ac9 --- /dev/null +++ b/fuzzylite/src/term/SigmoidProduct.cpp @@ -0,0 +1,112 @@ +/* + 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/SigmoidProduct.h" + +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) { + } + + SigmoidProduct::~SigmoidProduct() { + } + + std::string SigmoidProduct::className() const { + return "SigmoidProduct"; + } + + 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; + } + + std::string SigmoidProduct::parameters() const { + return Op::join(4, " ", _left, _rising, _falling, _right) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void SigmoidProduct::configure(const std::string& parameters) { + if (parameters.empty()) return; + std::vector<std::string> values = Op::split(parameters, " "); + std::size_t required = 4; + if (values.size() < required) { + std::ostringstream ex; + ex << "[configuration error] term <" << className() << ">" + << " requires <" << required << "> parameters"; + throw fl::Exception(ex.str(), FL_AT); + } + setLeft(Op::toScalar(values.at(0))); + setRising(Op::toScalar(values.at(1))); + setFalling(Op::toScalar(values.at(2))); + setRight(Op::toScalar(values.at(3))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + + } + + void SigmoidProduct::setRising(scalar risingSlope) { + this->_rising = risingSlope; + } + + scalar SigmoidProduct::getRising() const { + return this->_rising; + } + + void SigmoidProduct::setLeft(scalar leftInflection) { + this->_left = leftInflection; + } + + scalar SigmoidProduct::getLeft() const { + return this->_left; + } + + void SigmoidProduct::setRight(scalar rightInflection) { + this->_right = rightInflection; + } + + scalar SigmoidProduct::getRight() const { + return this->_right; + } + + void SigmoidProduct::setFalling(scalar fallingSlope) { + this->_falling = fallingSlope; + } + + scalar SigmoidProduct::getFalling() const { + return this->_falling; + } + + SigmoidProduct* SigmoidProduct::clone() const { + return new SigmoidProduct(*this); + } + + Term* SigmoidProduct::constructor() { + return new SigmoidProduct; + } + +} diff --git a/fuzzylite/src/term/Spike.cpp b/fuzzylite/src/term/Spike.cpp new file mode 100644 index 0000000..f4b73bf --- /dev/null +++ b/fuzzylite/src/term/Spike.cpp @@ -0,0 +1,90 @@ +/* + 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/Spike.h" + +namespace fl { + + Spike::Spike(const std::string& name, scalar center, scalar width, scalar height) + : Term(name, height), _center(center), _width(width) { + } + + Spike::~Spike() { + + } + + std::string Spike::className() const { + return "Spike"; + } + + 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))); + } + + std::string Spike::parameters() const { + return Op::join(2, " ", _center, _width) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void Spike::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 fl::Exception(ex.str(), FL_AT); + } + setCenter(Op::toScalar(values.at(0))); + setWidth(Op::toScalar(values.at(1))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void Spike::setCenter(scalar center) { + this->_center = center; + } + + scalar Spike::getCenter() const { + return this->_center; + } + + void Spike::setWidth(scalar width) { + this->_width = width; + } + + scalar Spike::getWidth() const { + return this->_width; + } + + Spike* Spike::clone() const { + return new Spike(*this); + } + + Term* Spike::constructor() { + return new Spike; + } +} diff --git a/fuzzylite/src/term/Term.cpp b/fuzzylite/src/term/Term.cpp new file mode 100644 index 0000000..143a98f --- /dev/null +++ b/fuzzylite/src/term/Term.cpp @@ -0,0 +1,74 @@ +/* + 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/Term.h" + +#include "fl/imex/FllExporter.h" +#include "fl/term/Linear.h" +#include "fl/term/Function.h" + +namespace fl { + + Term::Term(const std::string& name, scalar height) : _name(name), _height(height) { + + } + + Term::~Term() { + + } + + void Term::setName(const std::string& name) { + this->_name = name; + } + + std::string Term::getName() const { + return this->_name; + } + + void Term::setHeight(scalar height) { + this->_height = height; + } + + scalar Term::getHeight() const { + return this->_height; + } + + std::string Term::toString() const { + 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 + } + } + } + +} diff --git a/fuzzylite/src/term/Trapezoid.cpp b/fuzzylite/src/term/Trapezoid.cpp new file mode 100644 index 0000000..60abcc4 --- /dev/null +++ b/fuzzylite/src/term/Trapezoid.cpp @@ -0,0 +1,130 @@ +/* + 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/Trapezoid.h" + +namespace fl { + + Trapezoid::Trapezoid(const std::string& name, + 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; + this->_vertexC = _vertexA + range * 4.0 / 5.0; + } + } + + Trapezoid::~Trapezoid() { + } + + std::string Trapezoid::className() const { + return "Trapezoid"; + } + + scalar Trapezoid::membership(scalar x) const { + if (fl::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)); + + if (Op::isLE(x, _vertexC)) + return _height * 1.0; + + if (Op::isLt(x, _vertexD)) + return _height * (_vertexD - x) / (_vertexD - _vertexC); + + return _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) : ""); + } + + void Trapezoid::configure(const std::string& parameters) { + if (parameters.empty()) return; + std::vector<std::string> values = Op::split(parameters, " "); + std::size_t required = 4; + if (values.size() < required) { + std::ostringstream ex; + ex << "[configuration error] term <" << className() << ">" + << " requires <" << required << "> parameters"; + throw fl::Exception(ex.str(), FL_AT); + } + setVertexA(Op::toScalar(values.at(0))); + setVertexB(Op::toScalar(values.at(1))); + setVertexC(Op::toScalar(values.at(2))); + setVertexD(Op::toScalar(values.at(3))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void Trapezoid::setVertexA(scalar a) { + this->_vertexA = a; + } + + scalar Trapezoid::getVertexA() const { + return this->_vertexA; + } + + void Trapezoid::setVertexB(scalar b) { + this->_vertexB = b; + } + + scalar Trapezoid::getVertexB() const { + return this->_vertexB; + } + + void Trapezoid::setVertexC(scalar c) { + this->_vertexC = c; + } + + scalar Trapezoid::getVertexC() const { + return this->_vertexC; + } + + void Trapezoid::setVertexD(scalar d) { + this->_vertexD = d; + } + + scalar Trapezoid::getVertexD() const { + return this->_vertexD; + } + + Trapezoid* Trapezoid::clone() const { + return new Trapezoid(*this); + } + + Term* Trapezoid::constructor() { + return new Trapezoid; + } + + +} diff --git a/fuzzylite/src/term/Triangle.cpp b/fuzzylite/src/term/Triangle.cpp new file mode 100644 index 0000000..2fce1a6 --- /dev/null +++ b/fuzzylite/src/term/Triangle.cpp @@ -0,0 +1,115 @@ +/* + 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/Triangle.h" + +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; + } + } + + Triangle::~Triangle() { + } + + std::string Triangle::className() const { + return "Triangle"; + } + + scalar Triangle::membership(scalar x) const { + if (fl::Op::isNaN(x)) return fl::nan; + + if (Op::isLt(x, _vertexA) or Op::isGt(x, _vertexC)) + return _height * 0.0; + + if (Op::isEq(x, _vertexB)) + return _height * 1.0; + + if (Op::isLt(x, _vertexB)) + return _height * (x - _vertexA) / (_vertexB - _vertexA); + + return _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) : ""); + } + + void Triangle::configure(const std::string& parameters) { + if (parameters.empty()) return; + std::vector<std::string> values = Op::split(parameters, " "); + std::size_t required = 3; + if (values.size() < required) { + std::ostringstream ex; + ex << "[configuration error] term <" << className() << ">" + << " requires <" << required << "> parameters"; + throw fl::Exception(ex.str(), FL_AT); + } + setVertexA(Op::toScalar(values.at(0))); + setVertexB(Op::toScalar(values.at(1))); + setVertexC(Op::toScalar(values.at(2))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void Triangle::setVertexA(scalar a) { + this->_vertexA = a; + } + + scalar Triangle::getVertexA() const { + return this->_vertexA; + } + + void Triangle::setVertexB(scalar b) { + this->_vertexB = b; + } + + scalar Triangle::getVertexB() const { + return this->_vertexB; + } + + void Triangle::setVertexC(scalar c) { + this->_vertexC = c; + } + + scalar Triangle::getVertexC() const { + return this->_vertexC; + } + + Triangle* Triangle::clone() const { + return new Triangle(*this); + } + + Term* Triangle::constructor() { + return new Triangle; + } + + +} diff --git a/fuzzylite/src/term/ZShape.cpp b/fuzzylite/src/term/ZShape.cpp new file mode 100644 index 0000000..86668b6 --- /dev/null +++ b/fuzzylite/src/term/ZShape.cpp @@ -0,0 +1,102 @@ +/* + 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/ZShape.h" + +namespace fl { + + ZShape::ZShape(const std::string& name, scalar start, scalar end, scalar height) + : Term(name, height), _start(start), _end(end) { + } + + ZShape::~ZShape() { + } + + std::string ZShape::className() const { + return "ZShape"; + } + + 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::isLE(x, _start)) return _height * 1.0; + + if (Op::isLE(x, average)) + return _height * (1.0 - 2.0 * std::pow((x - _start) / difference, 2)); + + if (Op::isLt(x, _end)) + return _height * (2.0 * std::pow((x - _end) / difference, 2)); + + return _height * 0.0; + } + + std::string ZShape::parameters() const { + return Op::join(2, " ", _start, _end) + + (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : ""); + } + + void ZShape::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 fl::Exception(ex.str(), FL_AT); + } + setStart(Op::toScalar(values.at(0))); + setEnd(Op::toScalar(values.at(1))); + if (values.size() > required) + setHeight(Op::toScalar(values.at(required))); + } + + void ZShape::setStart(scalar start) { + this->_start = start; + } + + scalar ZShape::getStart() const { + return this->_start; + } + + void ZShape::setEnd(scalar end) { + this->_end = end; + } + + scalar ZShape::getEnd() const { + return this->_end; + } + + ZShape* ZShape::clone() const { + return new ZShape(*this); + } + + Term* ZShape::constructor() { + return new ZShape; + } + +} |