diff options
Diffstat (limited to 'fuzzylite/fl/term/Function.h')
-rw-r--r-- | fuzzylite/fl/term/Function.h | 312 |
1 files changed, 270 insertions, 42 deletions
diff --git a/fuzzylite/fl/term/Function.h b/fuzzylite/fl/term/Function.h index 99580b7..14e3427 100644 --- a/fuzzylite/fl/term/Function.h +++ b/fuzzylite/fl/term/Function.h @@ -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. */ #ifndef FL_FUNCTION_H @@ -34,27 +26,77 @@ namespace fl { class Engine; + /** + The Function class is a polynomial Term that represents a generic + function @f$ f : x \mapsto f(x) @f$. Every Function object has a public + key-value map, namely Function::variables, that links variable names to + fl::scalar values, which are utilized to replace the variable names for + their respective values in the given formula whenever the function + @f$f@f$ is evaluated. Specifically, when the method + Function::membership() is called, the name and value of the variable + @f$x@f$ are automatically loaded into the map. Furthermore, if an Engine + is given, the names of its InputVariable%s and OutputVariable%s will also + be automatically loaded into the map linking to their respective input + values and (previously defuzzified) output values. The + Function::variables need to be manually loaded whenever variables other + than @f$x@f$, input variables, and output variables, are expressed in the + given formula, always having in mind that (a) the map replaces existing + keys, and (b) the variable @f$x@f$, and input variables and output + variables of an engine will automatically be replaced and will also take + precedence over previously loaded variables. + + Besides the use of Function as a linguistic Term, it is also utilized to + convert the text of the Antecedent of a Rule, expressed in infix + notation, into postfix notation. + + + @author Juan Rada-Vilela, Ph.D. + @see Term + @see Variable + @see FunctionFactory + @see Antecedent::load() + @since 4.0 + */ class FL_API Function : public Term { - /**************************** - * Parsing Elements - ****************************/ - public: typedef scalar(*Unary)(scalar); typedef scalar(*Binary)(scalar, scalar); + /** + The Element class represents a single element in a formula, be that + either a function or an operator. If the Element represents a + function, the function can be Unary or Binary, that is, the function + take one or two parameters (respectively). Else, if the Element + represents an operator, the parameters to be defined are its `arity`, + its `precedence`, and its `associativity`. + */ struct FL_API Element { + /** + Determines the type of the element + */ enum Type { - OPERATOR, FUNCTION + Operator, Function }; + /**Name of the element*/ std::string name; + /**Description of the element*/ std::string description; + /**Type of the element*/ Type type; + /**Pointer to unary method*/ Unary unary; + /**Pointer to binary method*/ Binary binary; + /**Number of operands required*/ int arity; - int precedence; //Operator + /**Precedence of the element: clarifies which procedures should be + performed first in a given mathematical expression + (https://en.wikipedia.org/wiki/Order_of_operations)*/ + int precedence; + /**Associativity of the element: determines how operators of the + same precedence are grouped in the absence of parentheses + (https://en.wikipedia.org/wiki/Operator_associativity)*/ int associativity; Element(const std::string& name, const std::string& description, Type type); Element(const std::string& name, const std::string& description, @@ -64,24 +106,46 @@ namespace fl { virtual ~Element(); FL_DEFAULT_COPY_AND_MOVE(Element) + /** + Indicates whether the element is a Type::Operator + @return whether the element is a Type::Operator + */ virtual bool isOperator() const; + /** + Indicates whether the element is a Type::Function + @return whether the element is a Type::Function + */ virtual bool isFunction() const; - + /** + Clones the element + @return a clone of the element + */ virtual Element* clone() const; + /** + Returns a description of the element and its members + @return a description of the element and its members + */ virtual std::string toString() const; }; - /************************** - * Tree elements, wrap Elements into Nodes. - **************************/ - + /** + The Node class structures a binary tree by storing pointers to a left + Node and a right Node, and storing its content as a + Function::Element, the name of an InputVariable or OutputVariable, or + a constant value. + */ struct FL_API Node { + /**The node takes an operation or a function*/ FL_unique_ptr<Element> element; + /**The node can have an expression tree on the left*/ FL_unique_ptr<Node> left; + /**The node can have an expression tree on the right*/ FL_unique_ptr<Node> right; + /**The node can refer to a variable by name*/ std::string variable; + /**The node can take an arbitrary floating-point value*/ scalar value; explicit Node(Element* element, Node* left = fl::null, Node* right = fl::null); @@ -92,14 +156,79 @@ namespace fl { virtual ~Node(); FL_DEFAULT_MOVE(Node) + /** + Evaluates the node and substitutes the variables therein for the + values passed in the map. The expression tree is evaluated + recursively. + + @param variables is a map of substitutions of variable names for + fl::scalar%s + + @return a fl::scalar indicating the result of the evaluation of + the node + */ virtual scalar evaluate(const std::map<std::string, scalar>* variables = fl::null) const; + /** + Computes the size of the subtree under the given node. The complexity + of calling this method is O(n). + @param node is the root of the subtree, which is this node if + fl::null is given + @return the size of the subtree under the given node + */ + virtual std::size_t treeSize(const Node* node = fl::null) const; + + /** + Computes the size of the subtree under the given node whose elements + are of the given type. The complexity of calling this method is O(n). + @param type is the type of elements to account for + @param node is the root of the subtree, which is this node if + fl::null is given + @return + */ + virtual std::size_t treeSize(Element::Type type, + const Node* node = fl::null) const; + + /** + Creates a clone of the node. + @return a clone of the node + */ virtual Node* clone() const; + /** + Returns a string with the name of the element, the name of the + variable, or the constant value, accordingly. + @return a string with the name of the element, the name of the + variable, or the constant value, accordingly. + */ virtual std::string toString() const; + /** + Returns a prefix representation of the expression tree under the + given node + @param node is the node to start the prefix representation from. + If the node is `fl::null`, then the starting point is `this` node + @return a prefix representation of the expression tree under the + given node + */ virtual std::string toPrefix(const Node* node = fl::null) const; + /** + Returns an infix representation of the expression tree under the + given node + @param node is the node to start the infix representation from. + If the node is `fl::null`, then the starting point is `this` node + @return an infix representation of the expression tree under the + given node + */ virtual std::string toInfix(const Node* node = fl::null) const; + /** + Returns a postfix representation of the expression tree under the + given node + @param node is the node to start the postfix representation from. + If the node is `fl::null`, then the starting point is `this` node + @return a postfix representation of the expression tree under the + given node + */ virtual std::string toPostfix(const Node* node = fl::null) const; private: void copyFrom(const Node& source); @@ -112,11 +241,12 @@ namespace fl { * Term ******************************/ - protected: + private: FL_unique_ptr<Node> _root; std::string _formula; const Engine* _engine; public: + /**A map of variables and substitution values**/ mutable std::map<std::string, scalar> variables; explicit Function(const std::string& name = "", const std::string& formula = "", const Engine* engine = fl::null); @@ -125,47 +255,145 @@ namespace fl { virtual ~Function() FL_IOVERRIDE; FL_DEFAULT_MOVE(Function) + /** + Creates a Function term with the given parameters + @param name is the name of the term + @param formula is the formula defining the membership function + @param engine is the engine to which the Function can have access + @return a Function term configured with the given parameters + @throws fl::Exception if the formula has a syntax error + */ static Function* create(const std::string& name, const std::string& formula, - const Engine* engine = fl::null); // throw (fl::Exception); - + const Engine* engine = fl::null); + + virtual Complexity complexity() const FL_IOVERRIDE; + + /** + Computes the membership function value of @f$x@f$ at the root node. + If the engine has been set, the current values of the input variables + and output variables are added to the map of Function::variables. In + addition, the variable @f$x@f$ will also be added to the map. + @param x + @return the membership function value of @f$x@f$ at the root node + */ virtual scalar membership(scalar x) const FL_IOVERRIDE; - virtual scalar evaluate(const std::map<std::string, scalar>* variables) const; + /** + Computes the function value of this term using the given map of + variable substitutions. + @param variables is a map of substitution variables + @return the function value of this term using the given map of + variable substitutions. + */ + virtual scalar evaluate(const std::map<std::string, scalar>* variables = fl::null) const; virtual std::string className() const FL_IOVERRIDE; + /** + Returns the parameters of the term as `formula` + @return `formula` + */ virtual std::string parameters() const FL_IOVERRIDE; + /** + Configures the term with the parameters given as `formula` + @param parameters as `formula` + */ virtual void configure(const std::string& parameters) FL_IOVERRIDE; + /** + Sets the formula of the function + @param formula is the formula of the function + */ virtual void setFormula(const std::string& formula); + /** + Gets the formula of the function + @return the formula of the function + */ virtual std::string getFormula() const; + /** + Sets the engine to which the formula can refer + @param engine is the engine to which the formula can refer + */ virtual void setEngine(const Engine* engine); + /** + Gets the engine to which the formula can refer + @return the engine to which the formula can refer + */ virtual const Engine* getEngine() const; + /** + Gets the root node of the expression tree defining the Function. The + root is `fl::null` if the formula has not been loaded. + @return the root node of the expression tree defining the Function, + or `fl::null` if the formula has not been loaded + */ virtual Node* root() const; + /** + Indicates whether the formula is loaded + @return whether the formula is loaded + */ virtual bool isLoaded() const; + /** + Unloads the formula and resets the map of substitution variables. + */ virtual void unload(); - virtual void load(); // throw (fl::Exception); - virtual void load(const std::string& formula); // throw (fl::Exception); - virtual void load(const std::string& formula, const Engine* engine); // throw (fl::Exception); - - virtual Node* parse(const std::string& formula); // throw (fl::Exception); - - virtual std::string toPostfix(const std::string& formula) const; //throw (fl::Exception); - + /** + Loads the current formula expressed in infix notation + */ + virtual void load(); + /** + Loads the given formula expressed in infix notation + @param formula is the right-hand side of a mathematical equation + @throws fl::Exception if the formula has syntax errors + */ + virtual void load(const std::string& formula); + /** + Loads the given formula expressed in infix notation, and sets the + engine holding the variables to which the formula refers. + @param formula is the right-hand side of a mathematical equation + expressed in infix notation + @param engine is the engine to which the formula can refer + @throws fl::Exception if the formula has syntax errors + */ + virtual void load(const std::string& formula, const Engine* engine); + /** + Creates a node representing a binary expression tree from the given formula + @param formula is the right-hand side of a mathematical equation + expressed in infix notation + @return a node representing a binary expression tree from the given formula + @throws fl::Exception if the formula has syntax errors + */ + virtual Node* parse(const std::string& formula); + + /** + Translates the given formula to postfix notation + @param formula is the right-hand side of a mathematical equation + expressed in infix notation + @return the formula represented in postfix notation + @throws fl::Exception if the formula has syntax errors + */ + virtual std::string toPostfix(const std::string& formula) const; + + /** + Adds spaces to the formula to separate parentheses, commas and + function operators such that these are treated as tokens when parsing + the function. + @param formula is the right-hand side of a mathematical equation + expressed in infix notation + @return the formula with spaces before and after parentheses, commas + and function operators + */ virtual std::string space(const std::string& formula) const; + virtual void updateReference(const Engine* engine) FL_IOVERRIDE; + virtual Function* clone() const FL_IOVERRIDE; static Term* constructor(); - static void main(); - }; - } - #endif /* FL_FUNCTION_H */ |