Extracted from [README.md](/README.md) ================================================ ### Features **Controllers** *Types* (5) Mamdani, Takagi-Sugeno, Larsen, Tsukamoto, Inverse Tsukamoto **Linguistic terms** *Basic* (4) triangle, trapezoid, rectangle, discrete. *Extended* (9) bell, cosine, gaussian, gaussian product, pi-shape, sigmoid difference, sigmoid product, spike. *Edges* (4) concave, ramp, sigmoid, s-shape, z-shape. *Functions* (3) constant, linear, function. **Conjunction and Activation** *T-Norm* (7) minimum, algebraic product, bounded difference, drastic product, einstein product, hamacher product, nilpotent minimum. **Disjunction and Accumulation** *S-Norm* (8) maximum, algebraic sum, bounded sum, normalized sum, drastic sum, einstein sum, hamacher sum, nilpotent maximum. **Defuzzifiers** *Integral* (5) centroid, bisector, smallest of maximum, largest of maximum, mean of maximum, *Weighted* (2) weighted average, weighted sum. **Hedges** *Types* (6) any, not, extremely, seldom, somewhat, very. **Import** *Types* (3) FuzzyLite Language fll, Fuzzy Inference System fis, Fuzzy Control Language fcl. **Export** *Types* (6) C++, Java, FuzzyLite Language fll, FuzzyLite Dataset fld, Fuzzy Inference System fis, Fuzzy Control Language fcl. **Examples** (30+) of Mamdani, Takagi-Sugeno and Tsukamoto controllers from fuzzylite, Octave and Matlab, each included in the following formats: C++, Java, fll, fld, fis, and fcl. *** ### Example cpp #include "fl/Headers.h" int main(int argc, char* argv[]){ using namespace fl; Engine* engine = new Engine("simple-dimmer"); InputVariable* ambient = new InputVariable; ambient->setName("Ambient"); ambient->setRange(0.000, 1.000); ambient->addTerm(new Triangle("DARK", 0.000, 0.500)); ambient->addTerm(new Triangle("MEDIUM", 0.250, 0.750)); ambient->addTerm(new Triangle("BRIGHT", 0.500, 1.000)); engine->addInputVariable(ambient); OutputVariable* power = new OutputVariable; power->setName("Power"); power->setRange(0.000, 2.000); power->setDefaultValue(fl::nan); power->addTerm(new Triangle("LOW", 0.000, 1.000)); power->addTerm(new Triangle("MEDIUM", 0.500, 1.500)); power->addTerm(new Triangle("HIGH", 1.000, 2.000)); engine->addOutputVariable(power); RuleBlock* ruleblock = new RuleBlock; ruleblock->addRule(Rule::parse("if Ambient is DARK then Power is HIGH", engine)); ruleblock->addRule(Rule::parse("if Ambient is MEDIUM then Power is MEDIUM", engine)); ruleblock->addRule(Rule::parse("if Ambient is BRIGHT then Power is LOW", engine)); engine->addRuleBlock(ruleblock); engine->configure("", "", "Minimum", "Maximum", "Centroid"); std::string status; if (not engine->isReady(&status)) throw Exception("Engine not ready. " "The following errors were encountered:\n" + status, FL_AT); for (int i = 0; i < 50; ++i){ scalar light = ambient->getMinimum() + i * (ambient->range() / 50); ambient->setInputValue(light); engine->process(); FL_LOG("Ambient.input = " << Op::str(light) << " -> " << "Power.output = " << Op::str(power->getOutputValue())); } }  *** ### What's New? The entire fuzzylite library has been thoroughly revised, refactored, validated, and significantly improved. The following sections detail the changes and enhancements of version 5.0. Users of previous versions are **strongly** encouraged to carefully read the list before migrating to version 5.0. Important changes and enhancements are marked as **(important)**, **(VERY important)** and **(EXTREMELY important)**. #### General + **(important)** fuzzylite v5.0 is dual-licensed under the [GNU LGPL v3.0](https://www.gnu.org/licenses/lgpl.html) and a paid commercial license. + Support for both C++98 and C++11 using the latest features. + Support for multiple compilers g++, Clang, MSVC. + Refactoring of many classes to improve design and performance. + **(important)** Performance improvements of Takagi-Sugeno controllers by over 55% with respect to v4.0 (estimate based on the average performance on the examples included). + Smart pointers in many classes take care of automatically deleting objects when setting new pointers (Accumulated, FactoryManager, Function, OutputVariable, Rule, and RuleBlock). * **(important)** Exceptions are thrown when any of the following RuleBlock::[conjunction|disjunction|activation], Accumulated::accumulation, and OutputVariable::defuzzifier are required but set to fl::null, thereby replacing the operations that would lead to [signal 11] Segmentation fault to operations that throw a fl::Exception instead. + Automatic build script to build fuzzylite in debug and release mode. + Binaries of debug libraries are renamed to append the letter d (e.g.,fuzzylited.dll, libfuzzylited.so). + **(important)** New file [fuzzylite/src/m/compare.m](/fuzzylite/src/m/compare.m) to compare the output values of your fuzzylite engines with the evaluation of the same engine in Octave/Matlab. + **(important)** There is practically no difference between the output values obtained with fuzzylite and those obtained with Octave/Matlab. Based on the examples, the average mean square error (MSE) between the output values is less than 7.3e-12 (or 0.0000000000073) due to negligible differences in floating-point arithmetic. The results and comparison can be found in [examples/examples.mat](/examples/examples.mat) . + **(important)** Source code of applications based on version 4.0 will most likely not compile with version 5.0. + Minor bugs and memory leaks fixed. ####Macros * **(important)** Added support for C++11 with smart pointers, method identifiers, move constructors and move operators as follows. For precise information, refer to file [fuzzylite/fl/fuzzylite.h](/fuzzylite/fl/fuzzylite.h). * **(important)** Macros for identifiers are defined as FL_IOVERRIDE override, FL_IFINAL final, FL_IDEFAULT = default, FL_IDELETE = delete, FL_INOEXCEPT noexcept, FL_DEFAULT_COPY(Class), FL_DEFAULT_MOVE(Class), and FL_DEFAULT_COPY_AND_MOVE(Class). * **(important)** Added macro FL_unique_ptr to refer to std::auto_ptr (C++98) or std::unique_ptr (C++11), and its respective FL_move_ptr(x) to move a smart pointer, albeit FL_move_ptr(x) is not used within the library as it is not needed. * **(important)** Added global variables const long fl::null = 0L to refer to the null pointer in C++98 and const std::nullptr_t null = nullptr to refer to the null pointer in C++11. * **(important)** Renamed macro FL_DEBUG to FL_DBG. * **(important)** Renamed macros FL_BEGIN_DEBUG_BLOCK and FL_END_DEBUG_BLOCK to FL_DEBUG_BEGIN and FL_DEBUG_END, respectively. * **(important)** Renamed macro FL_EXPORT to FL_API * **(EXTREMELY important)** Added macro definitions FL_EXPORT_LIBRARY and FL_IMPORT_LIBRARY. If you are building fuzzylite as a **shared library**, you need to define FL_EXPORT_LIBRARY. If you are building fuzzylite **executable** *and* it utilizes the fuzzylite **shared library**, you need to define FL_IMPORT_LIBRARY. If you are building fuzzylite as a **static library** and/or building fuzzylite **executable** using the fuzzylite **static library**, then you do not need to define either FL_[IMPORT|EXPORT]_LIBRARY. Note that the same conditions apply for your application. This is particularly important in Windows platforms, as FL_IMPORT_LIBRARY and FL_EXPORT_LIBRARY define FL_API to __declspec(dllimport) and __declspec(dllexport), respectively. If in doubt, please check [fuzzylite/CMakeLists.txt](/fuzzylite/CMakeLists.txt) #### Operation * **(important)** Added method Operation::toScalar(std::string x, scalar alternative) FL_INOEXCEPT which returns alternative if x is not a valid scalar, and never throws an exception. * **(important)** Added method Operation::toScalar(std::string x) that returns the scalar value of x or throws a fl::Exception if x is not a valid scalar. * **(VERY important)** Marked method (from v4.0) Operation::toScalar(std::string, bool, scalar) FL_IDELETE; and removed its implementation such that its usage is prevented at compile time in C++11 and at linker time in C++98. Please, use the appropriate Op::toScalar methods mentioned above. + Renamed method Op::isNan to Op::isNaN. * Added method fl::Op::isFinite(x) which returns not (isNaN(x) or isInf(x)). * Changed fl::Op::isEq(a,b) to return true if a == b == NaN. * Changed fl::Op::isEq(a,b) to return true if a == b == Inf. * Changes to fl::Op::isEq affect other comparison methods fl::Op::is[Lt|LEq|GEq|Gt]. * Added shortcuts of comparisons fl::Op::[gt,lt,ge,le,eq,neq](scalar a, scalar b), mostly to provide binary versions (without macheps) for term Function. * Deleted method Op::repeat. * Removed method fuzzylite::configuration(). * Changed default fuzzylite::_macheps = 1e-6;. * Renamed method Op::makeValidId to Op::validName, which now returns "unnamed" for empty strings. ####Engine * **(VERY important)** Moved Engine::hedges (and relevant methods) to Rule::hedges. * Added enumeration for the type of engine: enum Engine::Type{Mamdani, Larsen, TakagiSugeno, Tsukamoto, InverseTsukamoto, Hybrid, Unknown}. * Added method Type Engine::type(std::string* name, std::string* reason) to infer the type of the engine based on its configuration, additionally provides the name of the type and the inference reasons for its type. * **(important)** Changed method Engine::isReady(std::string) to satisfy the default operation of controllers. The method Engine::isReady(std::string) was initially conceived to provide information before a potential [signal 11] Segmentation fault happened due to improper configuration. However, given the improved handling of signals and exceptions mentioned in Section [General](#new-general), using method Engine::isReady(std::string) is not necessary except for providing suggestions of what could potentially cause an error. * Added methods Engine::set[Input|Output]Variables(std::vector) and Engine::setRuleBlocks(std::vector). * Added methods Engine::[input|output]Variables() and Engine::ruleBlocks() to return mutable references. * Added method Engine::variables() to retrieve a vector (copy) containing the InputVariables followed by the OutputVariables. * Added method Engine::updateReferences() to update the references to the engine in all the necessary linguistic terms (i.e., Linear and Function). * Added method Engine::clone(). * Added copy constructors, assignment operators, and default move constructor to Engine. ####Input Variables and Output Variables * **(important)** Added methods OutputVariable::[get|set]OutputValue() to [retrieve|store] value from defuzzification * **(important)** Changed return type of scalar OutputVariable::defuzzify() to void OutputVariable::defuzzify() because now it automatically stores the defuzzified output value, and also stores the previous *valid* output value regardless of locks. Like in version 4.0, if OutputVariable::lockPreviousOutputValue=true, and the defuzzified output value is not valid (i.e., [NaN|Inf]) or no rules were activated, then the defuzzified output value is replaced for the previous valid output value. * Removed method OutputVariable::defuzzifyNoLocks(). * Renamed variable OutputVariable::lastValidOutputValue to OutputVariable::previousOutputValue. * **(important)** Renamed method OutputVariable::[get|set]LastValidOutput() to OutputVariable::[get|set]PreviousOutputValue(). * Renamed variable OutputVariable::lockValidOutput to OutputVariable::lockPreviousOutputValue. * **(important)** Renamed method OutputVariable::setLockValidOutput() to OutputVariable::setLockPreviousOutputValue(). * **(important)** Renamed method OutputVariable::isLockingValidOutput() to OutputVariable::isLockedPreviousOutputValue(). * Renamed variable OutputVariable::lockOutputRange to OutputVariable::lockOutputValueInRange. * **(important)** Renamed method OutputVariable::setLockOutputRange() to OutputVariable::setLockOutputValueInRange(). * **(important)** Renamed method OutputVariable::isLockingOutputRange() to OutputVariable::isLockedOutputValueInRange(). * Added methods std::string InputVariable::fuzzyInputValue() and std::string OutputVariable::fuzzyOutputValue(). * Added method OutputVariable::clear() to clear the fuzzy output, and set OutputVariable::previousOutputValue = fl::nan and set OutputVariable::outputValue = fl::nan. * Added copy constructors, assignment operators, move constructors and move operators to [Input|Output]Variable. * Added method Variable::terms() to return mutable reference. * **(important)** Changed OutputVariable::[defuzzifier|fuzzyOutput] to smart pointers (FL_unique_ptr). #### Linguistic Terms * **(VERY important)** Added Term::[get|set]Height to define the height of *integral* terms, and multiply their respective membership functions accordingly. * Added copy constructors, assignment operators, move constructors and move operators to every Term. * **(VERY important)** Parameters of all terms are set by default to fl::nan. * **(important)** Renamed method Term::copy() to Term::clone() in every Term. * Added method Term::updateReference(Term*, Engine*) to ensure Linear and Function terms have updated pointers to the Engine (useful when cloning and copy-constructing). + **(important)** Added linguistic terms Concave, Cosine and Spike. * **(important)** Changed Accumulated to take Activated* terms instead of const Terms*. * Removed const from return type of method SNorm* Accumulated::[get|set]Accumulation(). * Changed Accumulated::accumulation to a smart pointer (FL_unique_ptr). * Added method Accumulated::terms() to return mutable reference. * **(important)** Renamed methods Triangle::[set|get][A|B|C] to ::[set|get]Vertex[A|B|C]. * **(important)** Renamed methods Trapezoid::[set|get][A|B|C|D] to ::[set|get]Vertex[A|B|C|D]. * **(important)** Renamed term Thresholded to Activated. * **(important)** Renamed methods Thresholded::[set|get]Threshold() to Activated::[set|get]Degree(). * Added enumeration [Ramp|Sigmoid]::Direction{ NEGATIVE, ZERO, POSITIVE } to refer to the slope. * Added methods Ramp::direction() and Sigmoid::direction() to retrieve direction of slope. * Removed Exception Specification from methods in Discrete, Linear and Function terms. #### Linear and Discrete Terms * **(important)** Changed Linear from having pointers to the input variables to having a pointer to the Engine. * Changed visibility of Linear::coefficients to protected. * **(important)** Added methods Linear::coefficients(), Linear::setCoefficients(). * Linear term no longer throws exception when inputVariables != |coefficients|. * **(important)** Removed public vector of variables Discrete::[x|y]. * **(important)** Added a typedef std::pair Discrete::Pair. * **(important)** Changed representation of Discrete::[x|y] from std::vector to std::vector. * Added methods Discrete::setXY() and Discrete::xy() to set and get the new representation of pairs. * Added methods Discrete::xy(int index) to retrieve Discrete::Pair at index. * **(important)** Added methods Discrete::toPairs(std::vector) which throws an exception if the vector is missing a value (i.e., std::vector.size() % 2 != 0), and Discrete::toPairs(std::vector, scalar missingValue) which adds missingValue in case std::vector.size() %2 == 1, hence never throwing an exception. * Added method Discrete::toVector(std::vector) to convert std::vector to a std::vector. * Added method Discrete::formatXY() to get pairs (x,y) nicely formatted. ####Function Term * **(important)** Merged structs Function::Operator and Function::BuiltInFunction into a single struct Function::Element. * **(EXTREMELY important)** Changed the precedence of all built-in instances of Function::Element of type Operator starting from 100 and decreasing by 10. The precedence of built-in operators is the following: (100) Logical not [!] and Negation [~]; (90) Power [^]; (80) Multiplication [*], Division [/] and Modulo [%]; (70) Addition [+] and Subtraction [-]; (60) Logical AND [and] and Logical OR [or]. If you have registered your own operators, please adjust their precedence as required. * Added to Function built-in comparison functions gt,lt,ge,le,eq and operator logical not !. * Modified typedefs Function::Unary and Function::Binary to take scalar instead of double. * Changed public Function::root to protected Function::_root and it is now a smart pointer (FL_unique_ptr). * Added method Function::root() to return pointer to Function::root. * **(EXTREMELY important)** Moved built-in functions and operators from Function to a FunctionFactory. #### [T|S]Norms and Hedges + **(important)** Fixed operation when using multiple hedges to operate from right-most to left-most, e.g. if Ambient is not very extremely bright, now evaluates as follows not(very(extremely(bright))). + Added TNorm nilpotent minimum and SNorm nilpotent maximum. * Added clone methods to every Norm. * Added clone methods to every Hedge. * **(VERY important)** Moved Engine::hedges to Rule::hedges. #### Rules * **(VERY important)** Moved Engine::hedges (and methods) to Rule::hedges. * Added method Rule::isLoaded() to determine whether a rule was properly parsed and thus can be activated. * Added method Rule::unload() to allow the existence of a rule in an inactive state (useful for invalid rules). * **(important)** Removed variable Rule::FL_ASSIGNS and method Rule::assignsKeyword(), for which the symbol = in rules is no longer valid. * Changed visibility of method Rule::setText() to public. * Added method Rule::load(const Engine*). * Changed Rule::[antecedent|consequent] to smart pointers (FL_unique_ptr). * **(important)** Renamed method Antecedent::[get|set]Root() to Antecedent::[get|set]Expression(). * Added methods [Antecedent|Consequent]::[get|set]Text(). * **(important)** Added methods [Antecedent|Consequent]::[load|unload](), with the same objective as Rule::[load|unload](). #### Rule Blocks * Added method RuleBlock::reloadRules(). * Added method RuleBlock::setRules(std::vector). * Added method RuleBlock::rules() to return mutable reference. * Removed const from TNorm and SNorm in RuleBlock::[get|set][Conjunction|Disjunction|Activation](), respectively. * Changed RuleBlock::[conjunction|disjunction|activation] to smart pointers (FL_unique_ptr). * **(VERY important)** Added basic rule chaining such that an OutputVariable can be utilized in the Antecedent of a Rule. For example, considering the rule if Power is high then InversePower is low, where Power and InversePower are both output variables, the activation degree of the Antecedent will correspond to the accumulated activation degree of the term high in the fuzzy output of Power. If Power::accumulation = none, the accumulated activation degree of the term high will be computed as the regular sum of the activation degrees of term high in the fuzzy output of Power. Otherwise, the accumulated activation degree is computed utilizing the Power::accumulation operator. #### Weighted Defuzzifiers + **(VERY important)** Performance improvements of Takagi-Sugeno controllers by over 55% (with respect to v4.0) based on the average performance on the examples included. * **(important)** Created class WeightedDefuzzifier from which classes Weighted[Average|Sum] are derived. * **(important)** Added enumeration WeightedDefuzzifier::Type{Automatic, TakagiSugeno, Tsukamoto} and respective methods WeightedDefuzzifier::[get|set]Type() and WeightedDefuzzifer::getTypeName(). * Added method WeightedDefuzzifier::inferType(Term*) to automatically determine the WeightedDefuzzifier::Type based on the class of Term. * **(important)** By default, WeightedDefuzzifier::type = Automatic, which automatically infers the type based on the WeightedDefuzzifier::inferType(). * **(important)** There is a small performance penalty when using WeightedDefuzzifier::type = Automatic because WeightedDefuzzifier::inferType() performs three dynamic_cast<>. * **(important)** Deleted class Tsukamoto. Its method static tsukamoto() was moved to virtual WeightedDefuzzifier::tsukamoto(), which allows overriding it * Added support for Tsukamoto with Concave terms. + **(EXTREMELY important)** In version 5.0, the traditional operation of Takagi-Sugeno and Tsukamoto controllers is achieved by setting OutputVariable::accumulation = none. Unlike version 4.0, the RuleBlock::activation will not have any effect on Takagi-Sugeno nor Tsukamoto controllers, for which RuleBlock::activation should also be set to none. More information about the roles of the OutputVariable::accumulation and RuleBlock::activation operators are detailed as follows. Refer to [sciweavers](http://www.sciweavers.org/free-online-latex-equation-editor) to convert LaTeX equations. + **(VERY important)** In version 5.0, the role of the RuleBlock::activation TNorm on the Weighted[Average|Sum] always performs a regular multiplication of the weights and the values (i.e., $w_i \times z_j$) regardless of the TNorm chosen. In other words, selecting any RuleBlock::activation for Weighted[Average|Sum] is irrelevant, and should be set to none as every TNorm will have the same multiplication effect. This operation is different from fuzzylite version 4.0, where the RuleBlock::activation operator was utilized to multiply the weights and values (i.e. $w_i \otimes z_j$), and therefore the traditional operation of the Weighted[Average|Sum] was achieved when RuleBlock::activation = AlgebraicProduct;. + **(VERY important)** In version 5.0, the role of the OutputVariable::accumulation = none on the Weighted[Average|Sum] results in a regular sum of the multiplied weights and values, i.e., $\dfrac{\sum_i^n w_i \times z_j}{\sum_i^n w_i}$. However, if the OutputVariable::accumulation != none, the role of the SNorm will be to accumulate the activation degrees of the *repeated* terms in the fuzzy output of the variable. For example, considering the rules if Ambient is dark then Power is high and if Ambient is medium then Power is high, for any input value of Ambient that activates both rules, the fuzzy output of Power will have the term high activated with the degree from Rule 1, and the term high activated with the degree from Rule 2. Since the term high appears twice in the fuzzy output, the role of the accumulation operator will be to accumulate the activation degree of high resulting in $\dfrac{(w_1 \oplus w_2) \times z_{high}}{(w_1 \oplus w_2)}$. If another term were activated, the result would be $\dfrac{(w_1 \oplus w_2) \times z_{high} + w_i \times z_j}{(w_1 \oplus w_2) + w_i}$. In version 4.0, the accumulation operator had no effect on the Weighted[Average|Sum]. #### Integral Defuzzifiers * **(important)** Proper handling of indefinite integral defuzzification, that is, returning fl::nan when [minimum|maximum]=[NaN|Inf]. * Default resolution of integration is defined as static int IntegralDefuzzifier::defaultResolution=200, and can be changed via static IntegralDefuzzifier::setDefaultResolution(). + **(important)** In fuzzylite, the accumulation operator has been for several versions associated with the output variables and **not** with the rule blocks, despite that the FCL format and other fuzzy logic control libraries associate the accumulation operator with the rule blocks. The argument for such a decision is that fuzzylite provides **coherent** support for multiple rule blocks operating on the same engine and on the same output variables. For example, if multiple rule blocks operate on the same output variables, it only makes sense to have a single accumulation operator associated with each output variable such that the defuzzifier can naturally operate over the accumulated fuzzy output. Differently, if the accumulation operator were associated with the rule block, the possibility of having different accumulation operators in different rule blocks questions (1) **the possibility of having multiple rule blocks operating over the same output variables**; and (2) **the usage of different accumulation operators over the accumulation and defuzzification processes**. Certainly, if (1) is not possible, i.e, different rule blocks only operate on different output variables, then (2) is not a problem because the accumulation process and defuzzification of each variable will only have a single accumulation operator. It is therefore that the association of the accumulation operator with the output variable in fuzzylite provides a **better design** and an additional feature that allows having multiple rule blocks operating over the same output variables. * Added copy constructors, assignment operators, move constructors and move operators. * Added method Defuzzifier::clone(). ####Importers and Exporters * **(EXTREMELY important)** Since terms have a new height property, [Fll|Fis|Fcl]Exporter exports terms with an additional scalar at the end, which indicates the height of the term. However, if height=1.0, the additional scalar is not exported. * **(EXTREMELY important)** In [Fll|Fis|Fcl]Importer, when importing terms, if there is an additional scalar it will be assumed as the height of the term. For example, term: high Gaussian 1.0 0.5 0.75 will create a Gaussian term with mean 1.0, standard deviation 0.5 and height 0.75. This is **extremely important** because there are some examples from Matlab in fis format that append a useless 0.0 to some terms. * **(EXTREMELY important)** In FisExporter, if the Takagi-Sugeno controller has no activation or accumulation operators (as it should generally be the case), Octave and Matlab will not be able to import the fis file. To overcome this issue, you will have to set ImpMethod="min" and AggMethod="max", where ImpMethod and AggMethod are just dummy operators that can be set to any TNorm and SNorm, respectively. + **(important)** Improved compatibility of the exported code obtained with [Fis|Fcl]Exporter by exporting the additional features of fuzzylite only when these are different from the default operation. For example, the following features will not be exported given their values: [Input|Output]Variable::enabled = true;, OutputVariable::lock-previous = false;, OutputVariable::lock-range = false;, amongst others. * **(important)** Renamed FLL property 'lock-valid' to 'lock-previous'. * **(important)** Renamed FIS property 'LockValid' to 'LockPrevious'. * **(important)** Renamed FCL property 'LOCK: VALID' to 'LOCK: PREVIOUS'. + **(important)** Export your controllers to files using [Fll|Fld|Fis|Fcl]Exporter::toFile(). + **(important)** Import your controllers from files using [Fll|Fis|Fcl]Importer::fromFile(). + **(important)** FldExporter exports the FuzzyLite Dataset of an engine utilizing the input values of another FuzzyLite Dataset. * FldExporter no longer restarts the engine when exporting. * **(important)** Renamed method FldExporter::toWriter() to FldExporter::write(). * Removed variable and methods for property int FldExporter::_maximum. * Added option in CppExporter to prepend the namespace prefix fl:: to the classes, and by default it does not prepend prefix. * Improvement accuracy of FisImporter when importing fis files whose scalar values have more than three decimal numbers. * Renamed methods in [Fis|Fcl]Importer::extract* to [Fis|Fcl]Importer::parse*. #### Factories * Created a generic CloningFactory to create clones of objects. * **(important)** Created FunctionFactory based on CloningFactory where function operators and methods are stored to be cloned as necessary by Function. Additional functions and operators can be easily registered. * **(VERY important)** Moved built-in functions and operators from Function to FunctionFactory. * Renamed methods Factory::[register|deregister]Class() to Factory::[register|deregister]Constructor(). * **(important)** Renamed Factory to ConstructionFactory. * Renamed typedef Factory::Creator to typedef Factory::Constructor. * Changed pointers of FactoryManager to smart pointers (FL_unique_ptr). #### Examples * **(important)** Added two examples for basic rule chaining: mamdani/SimpleDimmerInverse.fll and mamdani/Laundry.fll. * Included the original example files in fis format. * Added conversion of examples/original/*.fis to examples/original/*.fll. * Modified original/takagi-sugeno examples to reflect activation: none; accumulation: none;. * Updated FLD examples produced from the original examples. + **(important)** Added file [fuzzylite/src/m/compare.m](/fuzzylite/src/m/compare.m) to compare the output values of your fuzzylite engines with the evaluation of the same engine in Octave/Matlab. + **(important)** Added file [examples/examples.mat](/examples/examples.mat) containing the comparison of the output values between fuzzylite and Matlab's Fuzzy Logic Toolbox. * Added code to perform benchmarks in Linux. #### Console * **(important)** Console includes option to import custom input dataset from file an export its respective output values. * **(important)** Created the FuzzyLite Interactive Console, which can be started by specifying an input file and the output format, e.g., fuzzylite -i SimpleDimmer.fll -of fld. * Console provides more information about its usage. #### Fixes Bugs and Leaks + **(important)** Fixed operation when using multiple hedges to operate from right-most to left-most, e.g. if Ambient is not very extremely bright evaluates as follows not(very(extremely(bright))). * **(important)** Fixed membership functions of specific cases of Triangle when a=b or b=c, and Trapezoid when a=b or c=d. * Fixed minor memory leak at ~RuleBlock::[conjunction|disjunction|activation]. * Fixed minor memory leak at ~Accumulated::accumulation. * Fixed minor memory leak at ~OutputVariable::defuzzifier. * Fixed minor memory leak at ~Function::Node. * Fixed minor memory leak at ~FactoryManager::[factories]. * Fixed some rethrowing of exceptions to provide proper information about errors. Specifically, changed some rethrown exceptions from throw ex; to just throw; * Fixed building using -DFL_USE_FLOAT=ON *** For more information, visit [www.fuzzylite.com](http://www.fuzzylite.com). fuzzylite™ is a trademark of FuzzyLite Limited. Copyright © 2010-2014 FuzzyLite Limited. All rights reserved.