summaryrefslogtreecommitdiff
path: root/fuzzylite/src/imex/FisExporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fuzzylite/src/imex/FisExporter.cpp')
-rw-r--r--fuzzylite/src/imex/FisExporter.cpp180
1 files changed, 70 insertions, 110 deletions
diff --git a/fuzzylite/src/imex/FisExporter.cpp b/fuzzylite/src/imex/FisExporter.cpp
index 0934b33..2daac9a 100644
--- a/fuzzylite/src/imex/FisExporter.cpp
+++ b/fuzzylite/src/imex/FisExporter.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/imex/FisExporter.h"
@@ -30,11 +22,9 @@
namespace fl {
- FisExporter::FisExporter() : Exporter() {
- }
+ FisExporter::FisExporter() : Exporter() { }
- FisExporter::~FisExporter() {
- }
+ FisExporter::~FisExporter() { }
std::string FisExporter::name() const {
return "FisExporter";
@@ -52,9 +42,10 @@ namespace fl {
return fis.str();
}
- //TODO: deal with multiple ruleblocks, merge them into one.
+
std::string FisExporter::exportSystem(const Engine* engine) const {
std::ostringstream fis;
+ fis << "#Code automatically generated with " << fuzzylite::library() << ".\n\n";
fis << "[System]\n";
fis << "Name='" << engine->getName() << "'\n";
std::string type;
@@ -66,57 +57,54 @@ namespace fl {
type = "tsukamoto";
} else if (engine->type() == Engine::InverseTsukamoto) {
type = "inverse tsukamoto";
- }else if (engine->type() == Engine::Hybrid){
+ } else if (engine->type() == Engine::Hybrid) {
type = "hybrid";
} else {
type = "unknown";
}
fis << "Type='" << type << "'\n";
- // fis << "Version=" << FL_VERSION << "\n";
+ fis << "Version=" << fuzzylite::version() << "\n";
fis << "NumInputs=" << engine->numberOfInputVariables() << "\n";
fis << "NumOutputs=" << engine->numberOfOutputVariables() << "\n";
-
- int numberOfRules = 0;
+
+ std::size_t numberOfRules = 0;
const TNorm* conjunction = fl::null;
const SNorm* disjunction = fl::null;
- const TNorm* activation = fl::null;
- for (int i = 0; i < engine->numberOfRuleBlocks(); ++i) {
+ const TNorm* implication = fl::null;
+ for (std::size_t i = 0; i < engine->numberOfRuleBlocks(); ++i) {
RuleBlock* rb = engine->getRuleBlock(i);
numberOfRules += rb->numberOfRules();
if (not conjunction) conjunction = rb->getConjunction();
if (not disjunction) disjunction = rb->getDisjunction();
- if (not activation) activation = rb->getActivation();
+ if (not implication) implication = rb->getImplication();
}
fis << "NumRules=" << numberOfRules << "\n";
- fis << "AndMethod='" << toString(conjunction) << "'\n";
- fis << "OrMethod='" << toString(disjunction) << "'\n";
- fis << "ImpMethod='" << toString(activation) << "'\n";
+ fis << "AndMethod='" << (conjunction ? toString(conjunction) : "min") << "'\n";
+ fis << "OrMethod='" << (disjunction ? toString(disjunction) : "max") << "'\n";
+ fis << "ImpMethod='" << (implication ? toString(implication) : "min") << "'\n";
- const SNorm* accumulation = fl::null;
+ const SNorm* aggregation = fl::null;
Defuzzifier* defuzzifier = fl::null;
- for (int i = 0; i < engine->numberOfOutputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfOutputVariables(); ++i) {
OutputVariable* outputVariable = engine->getOutputVariable(i);
- if (not accumulation) accumulation = outputVariable->fuzzyOutput()->getAccumulation();
+ if (not aggregation) aggregation = outputVariable->fuzzyOutput()->getAggregation();
if (not defuzzifier) defuzzifier = outputVariable->getDefuzzifier();
}
- fis << "AggMethod='" << toString(accumulation) << "'\n";
+ fis << "AggMethod='" << (aggregation ? toString(aggregation) : "max") << "'\n";
fis << "DefuzzMethod='" << toString(defuzzifier) << "'\n";
return fis.str();
}
std::string FisExporter::exportInputs(const Engine* engine) const {
std::ostringstream fis;
- for (int ixVar = 0; ixVar < engine->numberOfInputVariables(); ++ixVar) {
+ for (std::size_t ixVar = 0; ixVar < engine->numberOfInputVariables(); ++ixVar) {
InputVariable* var = engine->getInputVariable(ixVar);
fis << "[Input" << (ixVar + 1) << "]\n";
- if (not var->isEnabled()) {
- fis << "Enabled=" << var->isEnabled() << "\n";
- }
fis << "Name='" << Op::validName(var->getName()) << "'\n";
- fis << "Range=[" << fl::Op::join(2, " ", var->getMinimum(), var->getMaximum()) << "]\n";
+ fis << "Range=[" << Op::join(2, " ", var->getMinimum(), var->getMaximum()) << "]\n";
fis << "NumMFs=" << var->numberOfTerms() << "\n";
- for (int ixTerm = 0; ixTerm < var->numberOfTerms(); ++ixTerm) {
+ for (std::size_t ixTerm = 0; ixTerm < var->numberOfTerms(); ++ixTerm) {
fis << "MF" << (ixTerm + 1) << "='" << Op::validName(var->getTerm(ixTerm)->getName()) << "':"
<< toString(var->getTerm(ixTerm)) << "\n";
}
@@ -127,25 +115,13 @@ namespace fl {
std::string FisExporter::exportOutputs(const Engine* engine) const {
std::ostringstream fis;
- for (int ixVar = 0; ixVar < engine->numberOfOutputVariables(); ++ixVar) {
+ for (std::size_t ixVar = 0; ixVar < engine->numberOfOutputVariables(); ++ixVar) {
OutputVariable* var = engine->getOutputVariable(ixVar);
fis << "[Output" << (ixVar + 1) << "]\n";
- if (not var->isEnabled()) {
- fis << "Enabled=" << var->isEnabled() << "\n";
- }
fis << "Name='" << Op::validName(var->getName()) << "'\n";
- fis << "Range=[" << fl::Op::join(2, " ", var->getMinimum(), var->getMaximum()) << "]\n";
- if (not fl::Op::isNaN(var->getDefaultValue())) {
- fis << "Default=" << fl::Op::str(var->getDefaultValue()) << "\n";
- }
- if (var->isLockedPreviousOutputValue()) {
- fis << "LockPrevious=" << var->isLockedPreviousOutputValue() << "\n";
- }
- if (var->isLockedOutputValueInRange()) {
- fis << "LockRange=" << var->isLockedOutputValueInRange() << "\n";
- }
+ fis << "Range=[" << Op::join(2, " ", var->getMinimum(), var->getMaximum()) << "]\n";
fis << "NumMFs=" << var->numberOfTerms() << "\n";
- for (int ixTerm = 0; ixTerm < var->numberOfTerms(); ++ixTerm) {
+ for (std::size_t ixTerm = 0; ixTerm < var->numberOfTerms(); ++ixTerm) {
fis << "MF" << (ixTerm + 1) << "='" << Op::validName(var->getTerm(ixTerm)->getName()) << "':"
<< toString(var->getTerm(ixTerm)) << "\n";
}
@@ -157,10 +133,10 @@ namespace fl {
std::string FisExporter::exportRules(const Engine* engine) const {
std::ostringstream fis;
fis << "[Rules]\n";
- for (int ixRuleBlock = 0; ixRuleBlock < engine->numberOfRuleBlocks(); ++ixRuleBlock) {
+ for (std::size_t ixRuleBlock = 0; ixRuleBlock < engine->numberOfRuleBlocks(); ++ixRuleBlock) {
RuleBlock* rb = engine->getRuleBlock(ixRuleBlock);
if (engine->numberOfRuleBlocks() > 1) fis << "# RuleBlock " << rb->getName() << "\n";
- for (int ixRule = 0; ixRule < rb->numberOfRules(); ++ixRule) {
+ for (std::size_t ixRule = 0; ixRule < rb->numberOfRules(); ++ixRule) {
Rule* rule = rb->getRule(ixRule);
if (rule->isLoaded()) {
fis << exportRule(rule, engine) << "\n";
@@ -198,15 +174,15 @@ namespace fl {
}
}
if (not equalOperators) {
- throw fl::Exception("[exporter error] "
+ throw Exception("[exporter error] "
"fis files do not support rules with different connectors "
"(i.e. ['and', 'or']). All connectors within a rule must be the same", FL_AT);
}
std::ostringstream fis;
std::vector<Variable*> inputVariables, outputVariables;
- for (int i = 0; i < engine->numberOfInputVariables(); ++i)
+ for (std::size_t i = 0; i < engine->numberOfInputVariables(); ++i)
inputVariables.push_back(engine->getInputVariable(i));
- for (int i = 0; i < engine->numberOfOutputVariables(); ++i)
+ for (std::size_t i = 0; i < engine->numberOfOutputVariables(); ++i)
outputVariables.push_back(engine->getOutputVariable(i));
fis << translate(propositions, inputVariables) << ", ";
@@ -226,14 +202,14 @@ namespace fl {
std::ostringstream ss;
for (std::size_t ixVariable = 0; ixVariable < variables.size(); ++ixVariable) {
Variable* variable = variables.at(ixVariable);
- int termIndexPlusOne = 0;
+ std::size_t termIndexPlusOne = 0;
scalar plusHedge = 0;
int negated = 1;
for (std::size_t ixProposition = 0; ixProposition < propositions.size(); ++ixProposition) {
Proposition* proposition = propositions.at(ixProposition);
if (proposition->variable != variable) continue;
- for (int termIndex = 0; termIndex < variable->numberOfTerms(); ++termIndex) {
+ for (std::size_t termIndex = 0; termIndex < variable->numberOfTerms(); ++termIndex) {
if (variable->getTerm(termIndex) == proposition->term) {
termIndexPlusOne = termIndex + 1;
break;
@@ -259,8 +235,8 @@ namespace fl {
break;
}
if (negated < 0) ss << "-";
- if (not fl::Op::isNaN(plusHedge)) {
- ss << fl::Op::str(termIndexPlusOne + plusHedge);
+ if (not Op::isNaN(plusHedge)) {
+ ss << Op::str(termIndexPlusOne + plusHedge);
} else {
ss << termIndexPlusOne << ".?"; // Unreconized hedge combination
}
@@ -268,29 +244,6 @@ namespace fl {
}
return ss.str();
}
-
- std::string FisExporter::toString(const Norm * norm) const {
- if (not norm) return "";
- //TNorm
- if (norm->className() == Minimum().className()) return "min";
- if (norm->className() == AlgebraicProduct().className()) return "prod";
- if (norm->className() == BoundedDifference().className()) return "bounded_difference";
- if (norm->className() == DrasticProduct().className()) return "drastic_product";
- if (norm->className() == EinsteinProduct().className()) return "einstein_product";
- if (norm->className() == HamacherProduct().className()) return "hamacher_product";
- if (norm->className() == NilpotentMinimum().className()) return "nilpotent_minimum";
- //SNorm
- if (norm->className() == Maximum().className()) return "max";
- if (norm->className() == AlgebraicSum().className()) return "sum";
- if (norm->className() == BoundedSum().className()) return "bounded_sum";
- if (norm->className() == NormalizedSum().className()) return "normalized_sum";
- if (norm->className() == DrasticSum().className()) return "drastic_sum";
- if (norm->className() == EinsteinSum().className()) return "einstein_sum";
- if (norm->className() == HamacherSum().className()) return "hamacher_sum";
- if (norm->className() == NilpotentMaximum().className()) return "nilpotent_maximum";
-
- return norm->className();
- }
std::string FisExporter::toString(const TNorm * tnorm) const {
if (not tnorm) return "";
@@ -304,16 +257,17 @@ namespace fl {
return tnorm->className();
}
- std::string FisExporter::toString(const SNorm * snorm) const {
+ std::string FisExporter::toString(const SNorm* snorm) const {
if (not snorm) return "";
if (snorm->className() == Maximum().className()) return "max";
- if (snorm->className() == AlgebraicSum().className()) return "sum";
+ if (snorm->className() == AlgebraicSum().className()) return "probor";
if (snorm->className() == BoundedSum().className()) return "bounded_sum";
if (snorm->className() == NormalizedSum().className()) return "normalized_sum";
if (snorm->className() == DrasticSum().className()) return "drastic_sum";
if (snorm->className() == EinsteinSum().className()) return "einstein_sum";
if (snorm->className() == HamacherSum().className()) return "hamacher_sum";
if (snorm->className() == NilpotentMaximum().className()) return "nilpotent_maximum";
+ if (snorm->className() == UnboundedSum().className()) return "sum";
return snorm->className();
}
@@ -332,30 +286,36 @@ namespace fl {
std::string FisExporter::toString(const Term * term) const {
std::ostringstream ss;
if (const Bell * x = dynamic_cast<const Bell*> (term)) {
- ss << "'gbellmf',[" << fl::Op::join(3, " ",
+ ss << "'gbellmf',[" << Op::join(3, " ",
x->getWidth(), x->getSlope(), x->getCenter()) << "]";
return ss.str();
}
+ if (const Binary * x = dynamic_cast<const Binary*> (term)) {
+ ss << "'binarymf,[" << Op::join(2, " ",
+ x->getStart(), x->getDirection()) << "]";
+ return ss.str();
+ }
+
if (const Concave * x = dynamic_cast<const Concave*> (term)) {
- ss << "'concavemf',[" << fl::Op::join(2, " ",
+ ss << "'concavemf',[" << Op::join(2, " ",
x->getInflection(), x->getEnd()) << "]";
return ss.str();
}
if (const Constant * x = dynamic_cast<const Constant*> (term)) {
- ss << "'constant',[" << fl::Op::str(x->getValue()) << "]";
+ ss << "'constant',[" << Op::str(x->getValue()) << "]";
return ss.str();
}
if (const Cosine * x = dynamic_cast<const Cosine*> (term)) {
- ss << "'cosinemf',[" << fl::Op::join(2, " ",
+ ss << "'cosinemf',[" << Op::join(2, " ",
x->getCenter(), x->getWidth()) << "]";
return ss.str();
}
if (const Discrete * x = dynamic_cast<const Discrete*> (term)) {
- ss << "'discretemf',[" << fl::Op::join(Discrete::toVector(x->xy()), " ") << "]";
+ ss << "'discretemf',[" << Op::join(Discrete::toVector(x->xy()), " ") << "]";
return ss.str();
}
@@ -365,95 +325,95 @@ namespace fl {
}
if (const Gaussian * x = dynamic_cast<const Gaussian*> (term)) {
- ss << "'gaussmf',[" << fl::Op::join(2, " ",
+ ss << "'gaussmf',[" << Op::join(2, " ",
x->getStandardDeviation(), x->getMean()) << "]";
return ss.str();
}
if (const GaussianProduct * x = dynamic_cast<const GaussianProduct*> (term)) {
- ss << "'gauss2mf',[" << fl::Op::join(4, " ",
+ ss << "'gauss2mf',[" << Op::join(4, " ",
x->getStandardDeviationA(), x->getMeanA(),
x->getStandardDeviationB(), x->getMeanB()) << "]";
return ss.str();
}
if (const Linear * x = dynamic_cast<const Linear*> (term)) {
- ss << "'linear',[" << fl::Op::join<scalar>(x->coefficients(), " ") << "]";
+ ss << "'linear',[" << Op::join<scalar>(x->coefficients(), " ") << "]";
return ss.str();
}
if (const PiShape * x = dynamic_cast<const PiShape*> (term)) {
- ss << "'pimf',[" << fl::Op::join(4, " ",
+ ss << "'pimf',[" << Op::join(4, " ",
x->getBottomLeft(), x->getTopLeft(),
x->getTopRight(), x->getBottomRight()) << "]";
return ss.str();
}
if (const Ramp * x = dynamic_cast<const Ramp*> (term)) {
- ss << "'rampmf',[" << fl::Op::join(2, " ",
+ ss << "'rampmf',[" << Op::join(2, " ",
x->getStart(), x->getEnd()) << "]";
return ss.str();
}
if (const Rectangle * x = dynamic_cast<const Rectangle*> (term)) {
- ss << "'rectmf',[" << fl::Op::join(2, " ",
+ ss << "'rectmf',[" << Op::join(2, " ",
x->getStart(), x->getEnd()) << "]";
return ss.str();
}
if (const SigmoidDifference * x = dynamic_cast<const SigmoidDifference*> (term)) {
- ss << "'dsigmf',[" << fl::Op::join(4, " ",
+ ss << "'dsigmf',[" << Op::join(4, " ",
x->getRising(), x->getLeft(),
x->getFalling(), x->getRight()) << "]";
return ss.str();
}
if (const Sigmoid * x = dynamic_cast<const Sigmoid*> (term)) {
- ss << "'sigmf',[" << fl::Op::join(2, " ",
+ ss << "'sigmf',[" << Op::join(2, " ",
x->getSlope(), x->getInflection()) << "]";
return ss.str();
}
if (const SigmoidProduct * x = dynamic_cast<const SigmoidProduct*> (term)) {
- ss << "'psigmf',[" << fl::Op::join(4, " ",
+ ss << "'psigmf',[" << Op::join(4, " ",
x->getRising(), x->getLeft(),
x->getFalling(), x->getRight()) << "]";
return ss.str();
}
if (const SShape * x = dynamic_cast<const SShape*> (term)) {
- ss << "'smf',[" << fl::Op::join(2, " ",
+ ss << "'smf',[" << Op::join(2, " ",
x->getStart(), x->getEnd()) << "]";
return ss.str();
}
if (const Spike * x = dynamic_cast<const Spike*> (term)) {
- ss << "'spikemf',[" << fl::Op::join(2, " ",
+ ss << "'spikemf',[" << Op::join(2, " ",
x->getCenter(), x->getWidth()) << "]";
return ss.str();
}
if (const Trapezoid * x = dynamic_cast<const Trapezoid*> (term)) {
- ss << "'trapmf',[" << fl::Op::join(4, " ",
+ ss << "'trapmf',[" << Op::join(4, " ",
x->getVertexA(), x->getVertexB(), x->getVertexC(), x->getVertexD()) << "]";
return ss.str();
}
if (const Triangle * x = dynamic_cast<const Triangle*> (term)) {
- ss << "'trimf',[" << fl::Op::join(3, " ",
+ ss << "'trimf',[" << Op::join(3, " ",
x->getVertexA(), x->getVertexB(), x->getVertexC()) << "]";
return ss.str();
}
if (const ZShape * x = dynamic_cast<const ZShape*> (term)) {
- ss << "'zmf',[" << fl::Op::join(2, " ",
+ ss << "'zmf',[" << Op::join(2, " ",
x->getStart(), x->getEnd()) << "]";
return ss.str();
}
- ss << "[exporter error] term of class <" << term->className() << "> not supported";
- throw fl::Exception(ss.str(), FL_AT);
+ ss << "[exporter error] term of class <" << (term ? term->className() : "null") << "> not supported";
+ throw Exception(ss.str(), FL_AT);
}
FisExporter* FisExporter::clone() const {