diff options
author | Johannes Schauer <josch@debian.org> | 2015-07-07 10:12:00 +0100 |
---|---|---|
committer | Johannes Schauer <josch@debian.org> | 2015-07-07 10:12:00 +0100 |
commit | 0e8c1c9d31d15034b1ff1062c9bf0bfcdc849dd9 (patch) | |
tree | 840a335d9a4487d3f1909a31c8526a2e647809e7 /fuzzylite |
Import fuzzylite_5.1+dfsg.orig.tar.xz
[dgit import orig fuzzylite_5.1+dfsg.orig.tar.xz]
Diffstat (limited to 'fuzzylite')
189 files changed, 21583 insertions, 0 deletions
diff --git a/fuzzylite/CMakeLists.txt b/fuzzylite/CMakeLists.txt new file mode 100644 index 0000000..1fd21ec --- /dev/null +++ b/fuzzylite/CMakeLists.txt @@ -0,0 +1,208 @@ +cmake_minimum_required(VERSION 2.8) + +project(fuzzylite CXX) + +###DEFINES SECTION +if(NOT CMAKE_VERBOSE_MAKEFILE) + set(CMAKE_VERBOSE_MAKEFILE false) +endif() + +set(FL_VERSION 5.1) +add_definitions(-DFL_VERSION="${FL_VERSION}") + +set(FL_DATE "1507") +add_definitions(-DFL_DATE="${FL_DATE}") + +add_definitions(-DFL_BUILD_PATH="${CMAKE_SOURCE_DIR}") #used to determine FL__FILE__ + +option(FL_BUILD_SHARED "Build shared library" ON) +option(FL_BUILD_STATIC "Build static library" ON) +if(FL_BUILD_SHARED) + option(FL_BUILD_BINARY "Build fuzzylite binary" ON) +endif() + +option(FL_USE_FLOAT "Use fl::scalar as float" OFF) +option(FL_BACKTRACE "Provide backtrace information in case of errors" OFF) +option(FL_CPP11 "Builds utilizing C++11, i.e., passing -std=c++11" OFF) + +if(FL_CPP11 AND MSVC) + message("Warning: MSVC not compatible with FL_CPP11 flag") +endif() + +if(FL_USE_FLOAT) + add_definitions(-DFL_USE_FLOAT) +endif(FL_USE_FLOAT) + +if(NOT FL_BACKTRACE) + add_definitions(-DFL_BACKTRACE_OFF) +endif() + +if(FL_CPP11) + add_definitions(-DFL_CPP11) + if(NOT MSVC) + add_definitions(-std=c++11) + endif(NOT MSVC) +endif(FL_CPP11) + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY bin) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin) + +if(NOT MSVC) + set(CMAKE_CXX_FLAGS "-pedantic -Wall -Wextra ${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + + if(NOT APPLE) + set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined ${CMAKE_SHARED_LINKER_FLAGS}") #To avoid undefined methods in library + endif() +endif() + +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-non-literal-null-conversion") +endif() + +set(FL_LIBS) + +if(MSVC) + set(CMAKE_CXX_FLAGS "/W4 /EHsc") + #Wx: Treat warnings as errors. W4: All warnings + #http://msdn.microsoft.com/en-us/library/thxezb7y.aspx + #EHsc: call destructors on __try __catch, and to ignore C4530: C++ exception handler used. Note, unwind semantics are not enabled + if (FL_BACKTRACE) + set(FL_LIBS dbghelp) + endif() +endif() + +###BUILD SECTION + +include_directories(.) +if (APPLE) + cmake_policy(SET CMP0042 NEW) +endif() + +file(STRINGS FL_HEADERS fl-headers) +file(STRINGS FL_SOURCES fl-sources) + +string(REGEX REPLACE "\n" " " ${fl-headers} ${fl-headers}) +string(REGEX REPLACE "\n" " " ${fl-sources} ${fl-sources}) + +message("${exepath}") + + +set(CMAKE_DEBUG_POSTFIX d) + +if (MSVC OR CMAKE_GENERATOR STREQUAL Xcode) + if(FL_BUILD_SHARED) + add_library(fl-shared SHARED ${fl-headers} ${fl-sources}) + endif() + + if(FL_BUILD_STATIC) + add_library(fl-static STATIC ${fl-headers} ${fl-sources}) + endif() +else() + if(FL_BUILD_SHARED OR FL_BUILD_STATIC) + add_library(fl-obj OBJECT ${fl-headers} ${fl-sources}) + if(NOT MINGW) + set_target_properties(fl-obj PROPERTIES COMPILE_FLAGS "-fPIC") + endif() + endif() + + if(FL_BUILD_SHARED) + add_library(fl-shared SHARED $<TARGET_OBJECTS:fl-obj>) + endif(FL_BUILD_SHARED) + + if(FL_BUILD_STATIC) + add_library(fl-static STATIC $<TARGET_OBJECTS:fl-obj>) + endif(FL_BUILD_STATIC) +endif() + +if(FL_BUILD_SHARED) + set_target_properties(fl-shared PROPERTIES OUTPUT_NAME fuzzylite) + set_target_properties(fl-shared PROPERTIES DEBUG_POSTFIX d) + set_target_properties(fl-shared PROPERTIES COMPILE_DEFINITIONS "FL_EXPORT_LIBRARY") + set_target_properties(fl-shared PROPERTIES VERSION 5.1) + target_link_libraries(fl-shared ${FL_LIBS}) +endif() + +if(FL_BUILD_STATIC) + set_target_properties(fl-static PROPERTIES OUTPUT_NAME fuzzylite-static) + set_target_properties(fl-static PROPERTIES DEBUG_POSTFIX d) + set_target_properties(fl-static PROPERTIES VERSION 5.1) + target_link_libraries(fl-static ${FL_LIBS}) +endif() + +if(FL_BUILD_BINARY) + add_executable(fl-bin src/main.cpp) + set_target_properties(fl-bin PROPERTIES OUTPUT_NAME fuzzylite) + set_target_properties(fl-bin PROPERTIES OUTPUT_NAME fuzzylite IMPORT_PREFIX tmp-) #To prevent LNK1149 in Windows + set_target_properties(fl-bin PROPERTIES DEBUG_POSTFIX d) + + set_target_properties(fl-bin PROPERTIES COMPILE_DEFINITIONS "FL_IMPORT_LIBRARY") + target_link_libraries(fl-bin fl-shared ${FL_LIBS}) +endif(FL_BUILD_BINARY) + +###INSTALL SECTION +if(NOT FL_INSTALL_BINDIR) + set(FL_INSTALL_BINDIR bin) +endif() + +if(NOT FL_INSTALL_LIBDIR) + if(NOT CMAKE_INSTALL_LIBDIR) + set(FL_INSTALL_LIBDIR lib) + else() + set(FL_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}) + endif() +endif() + +if(FL_BUILD_BINARY) + install(TARGETS fl-bin + RUNTIME DESTINATION ${FL_INSTALL_BINDIR} + LIBRARY DESTINATION ${FL_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${FL_INSTALL_LIBDIR} + ) +endif() + +if(FL_BUILD_SHARED) + install(TARGETS fl-shared + RUNTIME DESTINATION ${FL_INSTALL_BINDIR} + LIBRARY DESTINATION ${FL_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${FL_INSTALL_LIBDIR} + ) +endif() + +if(FL_BUILD_STATIC) + install(TARGETS fl-static + RUNTIME DESTINATION ${FL_INSTALL_BINDIR} + LIBRARY DESTINATION ${FL_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${FL_INSTALL_LIBDIR} + ) +endif() + +install(DIRECTORY fl/ DESTINATION include/fl) + +#pkg-config +configure_file(${CMAKE_SOURCE_DIR}/fuzzylite.pc.in ${CMAKE_BINARY_DIR}/fuzzylite.pc @ONLY) +install(FILES ${CMAKE_BINARY_DIR}/fuzzylite.pc DESTINATION lib/pkgconfig) + +message("=====================================") +message("fuzzylite v.${FL_VERSION}b${FL_DATE}\n") +message("FL_USE_FLOAT=${FL_USE_FLOAT}") +message("FL_CPP11=${FL_CPP11}") +message("FL_BACKTRACE=${FL_BACKTRACE}") +message("FL_INSTALL_BINDIR=${FL_INSTALL_BINDIR}") +message("FL_INSTALL_LIBDIR=${FL_INSTALL_LIBDIR}") +message("Build=${CMAKE_BUILD_TYPE}") +message("=====================================\n") + +###UNINSTALL SECTION +#configure_file( + #"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" + #"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + #IMMEDIATE @ONLY) + +#add_custom_target(uninstall + #COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake) + +#unix uninstall +#xargs rm < install_manifest.txt diff --git a/fuzzylite/FL_HEADERS b/fuzzylite/FL_HEADERS new file mode 100644 index 0000000..f8b578c --- /dev/null +++ b/fuzzylite/FL_HEADERS @@ -0,0 +1,92 @@ +fl/Console.h +fl/defuzzifier/Bisector.h +fl/defuzzifier/Centroid.h +fl/defuzzifier/Defuzzifier.h +fl/defuzzifier/IntegralDefuzzifier.h +fl/defuzzifier/LargestOfMaximum.h +fl/defuzzifier/MeanOfMaximum.h +fl/defuzzifier/SmallestOfMaximum.h +fl/defuzzifier/WeightedAverage.h +fl/defuzzifier/WeightedDefuzzifier.h +fl/defuzzifier/WeightedSum.h +fl/Engine.h +fl/Exception.h +fl/factory/CloningFactory.h +fl/factory/ConstructionFactory.h +fl/factory/DefuzzifierFactory.h +fl/factory/FactoryManager.h +fl/factory/FunctionFactory.h +fl/factory/HedgeFactory.h +fl/factory/SNormFactory.h +fl/factory/TermFactory.h +fl/factory/TNormFactory.h +fl/fuzzylite.h +fl/Headers.h +fl/hedge/Any.h +fl/hedge/Extremely.h +fl/hedge/Hedge.h +fl/hedge/Not.h +fl/hedge/Seldom.h +fl/hedge/Somewhat.h +fl/hedge/Very.h +fl/imex/CppExporter.h +fl/imex/Exporter.h +fl/imex/FclExporter.h +fl/imex/FclImporter.h +fl/imex/FisExporter.h +fl/imex/FisImporter.h +fl/imex/FldExporter.h +fl/imex/FllExporter.h +fl/imex/FllImporter.h +fl/imex/Importer.h +fl/imex/JavaExporter.h +fl/norm/Norm.h +fl/norm/s/AlgebraicSum.h +fl/norm/s/BoundedSum.h +fl/norm/s/DrasticSum.h +fl/norm/s/EinsteinSum.h +fl/norm/s/HamacherSum.h +fl/norm/s/Maximum.h +fl/norm/s/NilpotentMaximum.h +fl/norm/s/NormalizedSum.h +fl/norm/SNorm.h +fl/norm/t/AlgebraicProduct.h +fl/norm/t/BoundedDifference.h +fl/norm/t/DrasticProduct.h +fl/norm/t/EinsteinProduct.h +fl/norm/t/HamacherProduct.h +fl/norm/t/Minimum.h +fl/norm/t/NilpotentMinimum.h +fl/norm/TNorm.h +fl/Operation.h +fl/rule/Antecedent.h +fl/rule/Consequent.h +fl/rule/Expression.h +fl/rule/RuleBlock.h +fl/rule/Rule.h +fl/term/Accumulated.h +fl/term/Activated.h +fl/term/Bell.h +fl/term/Concave.h +fl/term/Constant.h +fl/term/Cosine.h +fl/term/Discrete.h +fl/term/Function.h +fl/term/Gaussian.h +fl/term/GaussianProduct.h +fl/term/Linear.h +fl/term/PiShape.h +fl/term/Ramp.h +fl/term/Rectangle.h +fl/term/SigmoidDifference.h +fl/term/Sigmoid.h +fl/term/SigmoidProduct.h +fl/term/Spike.h +fl/term/SShape.h +fl/term/Term.h +fl/term/Trapezoid.h +fl/term/Triangle.h +fl/term/ZShape.h +fl/variable/InputVariable.h +fl/variable/OutputVariable.h +fl/variable/Variable.h diff --git a/fuzzylite/FL_SOURCES b/fuzzylite/FL_SOURCES new file mode 100644 index 0000000..64d07f9 --- /dev/null +++ b/fuzzylite/FL_SOURCES @@ -0,0 +1,87 @@ +src/Console.cpp +src/defuzzifier/Bisector.cpp +src/defuzzifier/Centroid.cpp +src/defuzzifier/IntegralDefuzzifier.cpp +src/defuzzifier/LargestOfMaximum.cpp +src/defuzzifier/MeanOfMaximum.cpp +src/defuzzifier/SmallestOfMaximum.cpp +src/defuzzifier/WeightedAverage.cpp +src/defuzzifier/WeightedDefuzzifier.cpp +src/defuzzifier/WeightedSum.cpp +src/Engine.cpp +src/Exception.cpp +src/factory/CloningFactory.cpp +src/factory/ConstructionFactory.cpp +src/factory/DefuzzifierFactory.cpp +src/factory/FactoryManager.cpp +src/factory/FunctionFactory.cpp +src/factory/HedgeFactory.cpp +src/factory/SNormFactory.cpp +src/factory/TermFactory.cpp +src/factory/TNormFactory.cpp +src/fuzzylite.cpp +src/hedge/Any.cpp +src/hedge/Extremely.cpp +src/hedge/Not.cpp +src/hedge/Seldom.cpp +src/hedge/Somewhat.cpp +src/hedge/Very.cpp +src/imex/CppExporter.cpp +src/imex/Exporter.cpp +src/imex/FclExporter.cpp +src/imex/FclImporter.cpp +src/imex/FisExporter.cpp +src/imex/FisImporter.cpp +src/imex/FldExporter.cpp +src/imex/FllExporter.cpp +src/imex/FllImporter.cpp +src/imex/Importer.cpp +src/imex/JavaExporter.cpp +src/main.cpp +src/norm/s/AlgebraicSum.cpp +src/norm/s/BoundedSum.cpp +src/norm/s/DrasticSum.cpp +src/norm/s/EinsteinSum.cpp +src/norm/s/HamacherSum.cpp +src/norm/s/Maximum.cpp +src/norm/s/NilpotentMaximum.cpp +src/norm/s/NormalizedSum.cpp +src/norm/t/AlgebraicProduct.cpp +src/norm/t/BoundedDifference.cpp +src/norm/t/DrasticProduct.cpp +src/norm/t/EinsteinProduct.cpp +src/norm/t/HamacherProduct.cpp +src/norm/t/Minimum.cpp +src/norm/t/NilpotentMinimum.cpp +src/Operation.cpp +src/rule/Antecedent.cpp +src/rule/Consequent.cpp +src/rule/Expression.cpp +src/rule/RuleBlock.cpp +src/rule/Rule.cpp +src/term/Accumulated.cpp +src/term/Activated.cpp +src/term/Bell.cpp +src/term/Concave.cpp +src/term/Constant.cpp +src/term/Cosine.cpp +src/term/Discrete.cpp +src/term/Function.cpp +src/term/Gaussian.cpp +src/term/GaussianProduct.cpp +src/term/Linear.cpp +src/term/PiShape.cpp +src/term/Ramp.cpp +src/term/Rectangle.cpp +src/term/Sigmoid.cpp +src/term/SigmoidDifference.cpp +src/term/SigmoidProduct.cpp +src/term/Spike.cpp +src/term/SShape.cpp +src/term/Term.cpp +src/term/Trapezoid.cpp +src/term/Triangle.cpp +src/term/ZShape.cpp +src/variable/InputVariable.cpp +src/variable/OutputVariable.cpp +src/variable/Variable.cpp diff --git a/fuzzylite/build.bat b/fuzzylite/build.bat new file mode 100644 index 0000000..17f5b6d --- /dev/null +++ b/fuzzylite/build.bat @@ -0,0 +1,105 @@ +@echo off +setlocal EnableDelayedExpansion +set argc=0 +set valid="no" + +for %%a in (%*) do ( + set /A argc+=1 + if /I "%%a"=="help" ( + call:usage + goto:eof + ) + if /I "%%a"=="all" set valid="yes" + if /I "%%a"=="release" set valid="yes" + if /I "%%a"=="debug" set valid="yes" + if /I "%%a"=="clean" set valid="yes" + + if !valid!=="no" ( + echo Invalid option: %%a + call:usage + goto:eof + ) +) + +if %argc%==0 echo Building schedule: all +if not %argc%==0 echo Building schedule: %* +echo Starting in 3 seconds... +ping 1.1.1.1 -n 1 -w 3000 > nul +rem sleep 3 ::This function makes command line DOS-esque C:\Archiv~1 + +if %argc%==0 (call:all) + +for %%a in (%*) do (call:%%a) + +goto:eof + +:debug + echo. + echo. + echo **************************************** + echo STARTING: debug + + if not exist debug mkdir debug + cd debug + cmake .. -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Debug -DFL_BACKTRACE=ON -DFL_USE_FLOAT=OFF -DFL_CPP11=OFF + nmake + cd .. + + echo. + echo FINISHED: debug + echo **************************************** + goto:eof + +:release + echo. + echo. + echo **************************************** + echo STARTING: release + + if not exist release mkdir release + cd release + cmake .. -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DFL_BACKTRACE=OFF -DFL_USE_FLOAT=OFF -DFL_CPP11=OFF + nmake + cd .. + + echo. + echo FINISHED: release + echo **************************************** + goto:eof + +:all + echo. + echo. + echo **************************************** + echo STARTING: all + call:debug + call:release + echo. + echo FINISHED: all + echo **************************************** + goto:eof + +:clean + echo. + echo. + echo **************************************** + echo STARTING: clean + if exist debug rmdir /S /Q debug + if exist release rmdir /S /Q release + if exist CMakeFiles rmdir /S /Q CMakeFiles + echo. + echo FINISHED: clean + echo **************************************** + goto:eof + +:usage + echo Usage: build.bat [options] + echo where [options] can be any of the following: + echo ^ all builds fuzzylite in debug and release mode (default) + echo ^ debug builds fuzzylite in debug mode + echo ^ release builds fuzzylite in release mode + echo ^ clean erases previous builds + echo ^ help shows this information + echo. + +ENDLOCAL
\ No newline at end of file diff --git a/fuzzylite/build.sh b/fuzzylite/build.sh new file mode 100755 index 0000000..78343c4 --- /dev/null +++ b/fuzzylite/build.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +debug(){ + mkdir -p debug + cd debug + cmake .. -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DFL_BACKTRACE=ON -DFL_USE_FLOAT=OFF -DFL_CPP11=OFF + make + cd .. +} + +release(){ + mkdir -p release + cd release + cmake .. -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFL_BACKTRACE=ON -DFL_USE_FLOAT=OFF -DFL_CPP11=OFF + make + cd .. +} + +all(){ + debug + release +} + +clean(){ + rm -rf release debug CMakeFiles +} + +usage(){ + printf 'Usage:\t[bash] ./build.sh [options]\n' + printf "where\t[options] can be any of the following:\n" + printf "\tall\t\t builds fuzzylite in debug and release mode (default)\n" + printf "\tdebug\t\t builds fuzzylite in debug mode\n" + printf "\trelease\t\t builds fuzzylite in release mode\n" + printf "\tclean\t\t erases previous builds\n" + printf "\thelp\t\t shows this information\n" + printf "\n" +} + +############################# + +OPTIONS=( "all" "debug" "release" "clean" "help") +BUILD=( ) + +for arg in "$@" +do + if [[ "$arg" == "help" ]]; then usage && exit 0; fi + + if [[ "$arg" == "all" || "$arg" == "debug" || "$arg" == "release" || "$arg" == "clean" ]]; + then BUILD+=( $arg ); else echo "Invalid option: $arg" && usage && exit 2; + fi +done + +if [ ${#BUILD[@]} -eq 0 ]; then BUILD+=( "all" ); fi + +echo "Building schedule: ${BUILD[@]}" +echo "Starting in 3 seconds..." +sleep 3 + +for option in "${BUILD[@]}" +do + printf "\n\n" + printf "******************************\n" + printf "STARTING: $option\n" + eval ${option} + printf "\nFINISHED: $option\n" + printf "******************************\n\n" +done + + + diff --git a/fuzzylite/fl/Console.h b/fuzzylite/fl/Console.h new file mode 100644 index 0000000..59e818d --- /dev/null +++ b/fuzzylite/fl/Console.h @@ -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. + + */ + +#ifndef FL_CONSOLE_H +#define FL_CONSOLE_H + +#include "fl/fuzzylite.h" + +#include <map> +#include <string> +#include <vector> + +namespace fl { + class Engine; + + class FL_API Console { + public: + + struct Option { + std::string key, value, description; + + explicit Option(const std::string& key = "", const std::string& value = "", const std::string& description = "") : + key(key), value(value), description(description) { + } + }; + + static const std::string KW_INPUT_FILE; + static const std::string KW_INPUT_FORMAT; + static const std::string KW_OUTPUT_FILE; + static const std::string KW_OUTPUT_FORMAT; + static const std::string KW_EXAMPLE; + static const std::string KW_DECIMALS; + static const std::string KW_DATA_INPUT; + static const std::string KW_DATA_MAXIMUM; + static const std::string KW_DATA_EXPORT_HEADER; + static const std::string KW_DATA_EXPORT_INPUTS; + + static Engine* mamdani(); + static Engine* takagiSugeno(); + + protected: + static std::map<std::string, std::string> parse(int argc, char** argv); + static void process(const std::map<std::string, std::string>& options); + + static void process(const std::string& input, std::ostream& writer, + const std::string& inputFormat, const std::string& outputFormat, + const std::map<std::string, std::string>& options); + + static int readCharacter(); + static void interactive(std::ostream& writer, Engine* engine); + static std::string interactiveHelp(); + + static void exportAllExamples(const std::string& from, const std::string& to); + static void exportAllExamples(const std::string& from, const std::string& to, const std::string& path); +#ifdef FL_CPP11 + static void benchmarkExamples(const std::string& path, int runs); +#endif + + public: + static std::string usage(); + static std::vector<Option> availableOptions(); + + static int main(int argc, char** argv); + }; + +} + +#endif /* FL_CONSOLE_H */ + diff --git a/fuzzylite/fl/Engine.h b/fuzzylite/fl/Engine.h new file mode 100644 index 0000000..532c5e9 --- /dev/null +++ b/fuzzylite/fl/Engine.h @@ -0,0 +1,152 @@ +/* + 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. + + */ + +#ifndef FL_ENGINE_H +#define FL_ENGINE_H + +#include "fl/fuzzylite.h" + +#include "fl/defuzzifier/IntegralDefuzzifier.h" + +#include <string> +#include <vector> + +namespace fl { + + class InputVariable; + class OutputVariable; + class Variable; + class RuleBlock; + class Hedge; + class TNorm; + class SNorm; + class Defuzzifier; + + class FL_API Engine { + private: + void copyFrom(const Engine& source); + protected: + std::string _name; + std::vector<InputVariable*> _inputVariables; + std::vector<OutputVariable*> _outputVariables; + std::vector<RuleBlock*> _ruleblocks; + + void updateReferences() const; + + public: + explicit Engine(const std::string& name = ""); + Engine(const Engine& other); + Engine& operator=(const Engine& other); + virtual ~Engine(); + FL_DEFAULT_MOVE(Engine) + + //TODO: remove int resolution in v6.0 + virtual void configure(const std::string& conjunctionT, + const std::string& disjunctionS, + const std::string& activationT, + const std::string& accumulationS, + const std::string& defuzzifier, + int resolution = IntegralDefuzzifier::defaultResolution()); + + virtual void configure(TNorm* conjunction, SNorm* disjunction, + TNorm* activation, SNorm* accumulation, + Defuzzifier* defuzzifier); + + virtual bool isReady(std::string* status = fl::null) const; + + virtual void process(); + + virtual void restart(); + + virtual void setName(const std::string& name); + virtual std::string getName() const; + + virtual void setInputValue(const std::string& name, scalar value); + virtual scalar getOutputValue(const std::string& name); + + + virtual std::string toString() const; + + enum Type { + Mamdani, Larsen, TakagiSugeno, + Tsukamoto, InverseTsukamoto, Hybrid, Unknown + }; + virtual Type type(std::string* name = fl::null, std::string* reason = fl::null) const; + + virtual Engine* clone() const; + + virtual std::vector<Variable*> variables() const; + + /** + * Operations for iterable datatype _inputVariables + */ + virtual void addInputVariable(InputVariable* inputVariable); + virtual InputVariable* setInputVariable(InputVariable* inputVariable, int index); + virtual void insertInputVariable(InputVariable* inputVariable, int index); + virtual InputVariable* getInputVariable(int index) const; + virtual InputVariable* getInputVariable(const std::string& name) const; + virtual InputVariable* removeInputVariable(int index); + virtual InputVariable* removeInputVariable(const std::string& name); + virtual bool hasInputVariable(const std::string& name) const; + virtual int numberOfInputVariables() const; + virtual const std::vector<InputVariable*>& inputVariables() const; + virtual void setInputVariables(const std::vector<InputVariable*>& inputVariables); + virtual std::vector<InputVariable*>& inputVariables(); + + /** + * Operations for iterable datatype _outputVariables + */ + virtual void addOutputVariable(OutputVariable* outputVariable); + virtual OutputVariable* setOutputVariable(OutputVariable* outputVariable, int index); + virtual void insertOutputVariable(OutputVariable* outputVariable, int index); + virtual OutputVariable* getOutputVariable(int index) const; + virtual OutputVariable* getOutputVariable(const std::string& name) const; + virtual bool hasOutputVariable(const std::string& name) const; + virtual OutputVariable* removeOutputVariable(int index); + virtual OutputVariable* removeOutputVariable(const std::string& name); + virtual int numberOfOutputVariables() const; + virtual const std::vector<OutputVariable*>& outputVariables() const; + virtual void setOutputVariables(const std::vector<OutputVariable*>& outputVariables); + virtual std::vector<OutputVariable*>& outputVariables(); + + /** + * Operations for iterable datatype _ruleblocks + */ + virtual void addRuleBlock(RuleBlock* ruleblock); + virtual RuleBlock* setRuleBlock(RuleBlock* ruleBlock, int index); + virtual void insertRuleBlock(RuleBlock* ruleblock, int index); + virtual RuleBlock* getRuleBlock(int index) const; + virtual RuleBlock* getRuleBlock(const std::string& name) const; + virtual bool hasRuleBlock(const std::string& name) const; + virtual RuleBlock* removeRuleBlock(int index); + virtual RuleBlock* removeRuleBlock(const std::string& name); + virtual int numberOfRuleBlocks() const; + virtual const std::vector<RuleBlock*>& ruleBlocks() const; + virtual void setRuleBlocks(const std::vector<RuleBlock*>& ruleBlocks); + virtual std::vector<RuleBlock*>& ruleBlocks(); + + }; + +} +#endif /* FL_ENGINE_H */ diff --git a/fuzzylite/fl/Exception.h b/fuzzylite/fl/Exception.h new file mode 100644 index 0000000..f33fb13 --- /dev/null +++ b/fuzzylite/fl/Exception.h @@ -0,0 +1,66 @@ +/* + 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. + + */ + +#ifndef FL_EXCEPTION_H +#define FL_EXCEPTION_H + +#include "fl/fuzzylite.h" + +#include <exception> +#include <string> +#include <vector> + +namespace fl { + + class FL_API Exception : public std::exception { + protected: + std::string _what; + public: + explicit Exception(const std::string& what); + Exception(const std::string& what, const std::string& file, int line, + const std::string& function); + virtual ~Exception() FL_INOEXCEPT FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Exception) + + virtual void setWhat(const std::string& what); + virtual std::string getWhat() const; + virtual const char* what() const FL_INOEXCEPT FL_IOVERRIDE; + + virtual void append(const std::string& whatElse); + virtual void append(const std::string& file, int line, const std::string& function); + virtual void append(const std::string& whatElse, + const std::string& file, int line, const std::string& function); + + static std::string btCallStack(); + + static void signalHandler(int signal); + static void convertToException(int signal); + static void terminate(); + static void catchException(const std::exception& exception); + + + }; + +} +#endif /* FL_EXCEPTION_H */ diff --git a/fuzzylite/fl/Headers.h b/fuzzylite/fl/Headers.h new file mode 100644 index 0000000..9c2299a --- /dev/null +++ b/fuzzylite/fl/Headers.h @@ -0,0 +1,131 @@ +/* + 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. + + */ + +#ifndef FL_HEADERS_H +#define FL_HEADERS_H + +#include "fl/fuzzylite.h" + +#include "fl/Console.h" +#include "fl/Engine.h" +#include "fl/Exception.h" + +#include "fl/defuzzifier/Bisector.h" +#include "fl/defuzzifier/Centroid.h" +#include "fl/defuzzifier/Defuzzifier.h" +#include "fl/defuzzifier/IntegralDefuzzifier.h" +#include "fl/defuzzifier/SmallestOfMaximum.h" +#include "fl/defuzzifier/LargestOfMaximum.h" +#include "fl/defuzzifier/MeanOfMaximum.h" +#include "fl/defuzzifier/WeightedAverage.h" +#include "fl/defuzzifier/WeightedDefuzzifier.h" +#include "fl/defuzzifier/WeightedSum.h" + +#include "fl/factory/CloningFactory.h" +#include "fl/factory/ConstructionFactory.h" +#include "fl/factory/FactoryManager.h" +#include "fl/factory/FunctionFactory.h" +#include "fl/factory/DefuzzifierFactory.h" +#include "fl/factory/HedgeFactory.h" +#include "fl/factory/SNormFactory.h" +#include "fl/factory/TNormFactory.h" +#include "fl/factory/TermFactory.h" + +#include "fl/imex/CppExporter.h" +#include "fl/imex/FclImporter.h" +#include "fl/imex/FclExporter.h" +#include "fl/imex/FisImporter.h" +#include "fl/imex/FisExporter.h" +#include "fl/imex/FldExporter.h" +#include "fl/imex/FllImporter.h" +#include "fl/imex/FllExporter.h" +#include "fl/imex/JavaExporter.h" + +#include "fl/hedge/Any.h" +#include "fl/hedge/Extremely.h" +#include "fl/hedge/Hedge.h" +#include "fl/hedge/Not.h" +#include "fl/hedge/Seldom.h" +#include "fl/hedge/Somewhat.h" +#include "fl/hedge/Very.h" + +#include "fl/Operation.h" + +#include "fl/norm/Norm.h" +#include "fl/norm/SNorm.h" +#include "fl/norm/TNorm.h" + +#include "fl/norm/s/AlgebraicSum.h" +#include "fl/norm/s/BoundedSum.h" +#include "fl/norm/s/DrasticSum.h" +#include "fl/norm/s/EinsteinSum.h" +#include "fl/norm/s/HamacherSum.h" +#include "fl/norm/s/Maximum.h" +#include "fl/norm/s/NilpotentMaximum.h" +#include "fl/norm/s/NormalizedSum.h" + +#include "fl/norm/t/AlgebraicProduct.h" +#include "fl/norm/t/BoundedDifference.h" +#include "fl/norm/t/DrasticProduct.h" +#include "fl/norm/t/EinsteinProduct.h" +#include "fl/norm/t/HamacherProduct.h" +#include "fl/norm/t/Minimum.h" +#include "fl/norm/t/NilpotentMinimum.h" + +#include "fl/rule/Antecedent.h" +#include "fl/rule/Consequent.h" +#include "fl/rule/Rule.h" +#include "fl/rule/RuleBlock.h" +#include "fl/rule/Expression.h" + +#include "fl/term/Accumulated.h" +#include "fl/term/Bell.h" +#include "fl/term/Concave.h" +#include "fl/term/Constant.h" +#include "fl/term/Cosine.h" +#include "fl/term/Discrete.h" +#include "fl/term/Function.h" +#include "fl/term/Gaussian.h" +#include "fl/term/GaussianProduct.h" +#include "fl/term/Linear.h" +#include "fl/term/PiShape.h" +#include "fl/term/Ramp.h" +#include "fl/term/Rectangle.h" +#include "fl/term/SShape.h" +#include "fl/term/Sigmoid.h" +#include "fl/term/SigmoidDifference.h" +#include "fl/term/SigmoidProduct.h" +#include "fl/term/Spike.h" +#include "fl/term/Term.h" +#include "fl/term/Activated.h" +#include "fl/term/Trapezoid.h" +#include "fl/term/Triangle.h" +#include "fl/term/ZShape.h" + +#include "fl/variable/InputVariable.h" +#include "fl/variable/OutputVariable.h" +#include "fl/variable/Variable.h" + + +#endif /* FL_HEADERS_H */ diff --git a/fuzzylite/fl/Operation.h b/fuzzylite/fl/Operation.h new file mode 100644 index 0000000..d92e66c --- /dev/null +++ b/fuzzylite/fl/Operation.h @@ -0,0 +1,144 @@ +/* + 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. + + */ + +#ifndef FL_OPERATION_H +#define FL_OPERATION_H + +#include "fl/fuzzylite.h" + +#include "fl/Exception.h" + +#include <string> +#include <vector> + +namespace fl { + + class FL_API Operation { + public: + + template <typename T> + static T min(T a, T b); + + template <typename T> + static T max(T a, T b); + + template <typename T> + static T bound(T x, T min, T max); + + template <typename T> + static bool in(T x, T min, T max, bool geq = true, bool leq = true); + + template <typename T> + static bool isInf(T x); + + template <typename T> + static bool isNaN(T x); + + template <typename T> + static bool isFinite(T x); + + //Is less than + + static bool isLt(scalar a, scalar b, scalar macheps = fl::fuzzylite::macheps()); + static bool isLE(scalar a, scalar b, scalar macheps = fl::fuzzylite::macheps()); + static bool isEq(scalar a, scalar b, scalar macheps = fl::fuzzylite::macheps()); + static bool isGt(scalar a, scalar b, scalar macheps = fl::fuzzylite::macheps()); + static bool isGE(scalar a, scalar b, scalar macheps = fl::fuzzylite::macheps()); + + static scalar scale(scalar x, scalar fromMin, scalar fromMax, + scalar toMin, scalar toMax, bool bounded = false); + + static scalar add(scalar a, scalar b); + static scalar subtract(scalar a, scalar b); + static scalar multiply(scalar a, scalar b); + static scalar divide(scalar a, scalar b); + static scalar modulo(scalar a, scalar b); + static scalar logicalAnd(scalar a, scalar b); + static scalar logicalOr(scalar a, scalar b); + static scalar logicalNot(scalar a); + static scalar negate(scalar a); + static scalar round(scalar x); + + //greater than + static scalar gt(scalar a, scalar b); + //greater than or equal to + static scalar ge(scalar a, scalar b); + //equal to + static scalar eq(scalar a, scalar b); + //not equal to + static scalar neq(scalar a, scalar b); + //less than or equal to + static scalar le(scalar a, scalar b); + //less than + static scalar lt(scalar a, scalar b); + + static bool increment(std::vector<int>& x, std::vector<int>& min, std::vector<int>& max); + static bool increment(std::vector<int>& x, int position, std::vector<int>& min, std::vector<int>& max); + + static double mean(const std::vector<scalar>& x); + static double variance(const std::vector<scalar>& x); + static double variance(const std::vector<scalar>& x, scalar mean); + static double standardDeviation(const std::vector<scalar>& x); + static double standardDeviation(const std::vector<scalar>& x, scalar mean); + + static std::string validName(const std::string& name); + + static int isValidForName(int character); + + static std::string findReplace(const std::string& str, const std::string& find, + const std::string& replace, bool replaceAll = true); + + static std::vector<std::string> split(const std::string& str, + const std::string& delimiter = " ", bool ignoreEmpty = true); + + static std::string trim(const std::string& text); + + static std::string format(const std::string& text, int matchesChar(int), + const std::string& replacement = ""); + + //Intentionally results in a compiler error in C++11, or linker error in C++98 + //in order to avoid the deprecated usage of this method from version 4.0 + static scalar toScalar(const std::string& x, bool quiet, + scalar alternative = fl::nan) FL_IDELETE; + + static scalar toScalar(const std::string& x); //throws fl::Exception + + static scalar toScalar(const std::string& x, scalar alternative) FL_INOEXCEPT; + + static bool isNumeric(const std::string& x); + + template <typename T> + static std::string str(T x, int decimals = fuzzylite::decimals()); + + template <typename T> + static std::string join(const std::vector<T>& x, const std::string& separator); + + template <typename T> + static std::string join(int items, const std::string& separator, T first, ...); + }; + + typedef Operation Op; +} +#endif /* FL_OPERATION_H */ + diff --git a/fuzzylite/fl/defuzzifier/Bisector.h b/fuzzylite/fl/defuzzifier/Bisector.h new file mode 100644 index 0000000..7ba8db2 --- /dev/null +++ b/fuzzylite/fl/defuzzifier/Bisector.h @@ -0,0 +1,49 @@ +/* + 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. + + */ + +#ifndef FL_BISECTOR_H +#define FL_BISECTOR_H + +#include "fl/defuzzifier/IntegralDefuzzifier.h" + +namespace fl { + + class FL_API Bisector : public IntegralDefuzzifier { + public: + explicit Bisector(int resolution = defaultResolution()); + virtual ~Bisector() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Bisector) + + virtual std::string className() const FL_IOVERRIDE; + virtual scalar defuzzify(const Term* term, + scalar minimum, scalar maximum) const FL_IOVERRIDE; + virtual Bisector* clone() const FL_IOVERRIDE; + + static Defuzzifier* constructor(); + }; + +} + +#endif /* FL_BISECTOR_H */ + diff --git a/fuzzylite/fl/defuzzifier/Centroid.h b/fuzzylite/fl/defuzzifier/Centroid.h new file mode 100644 index 0000000..7510673 --- /dev/null +++ b/fuzzylite/fl/defuzzifier/Centroid.h @@ -0,0 +1,47 @@ +/* + 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. + + */ + +#ifndef FL_CENTROID_H +#define FL_CENTROID_H + +#include "fl/defuzzifier/IntegralDefuzzifier.h" + +namespace fl { + + class FL_API Centroid : public IntegralDefuzzifier { + public: + explicit Centroid(int resolution = defaultResolution()); + virtual ~Centroid() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Centroid) + + virtual std::string className() const FL_IOVERRIDE; + virtual scalar defuzzify(const Term* term, + scalar minimum, scalar maximum) const FL_IOVERRIDE; + virtual Centroid* clone() const FL_IOVERRIDE; + + static Defuzzifier* constructor(); + }; + +} +#endif /* FL_CENTROID_H */ diff --git a/fuzzylite/fl/defuzzifier/Defuzzifier.h b/fuzzylite/fl/defuzzifier/Defuzzifier.h new file mode 100644 index 0000000..3598113 --- /dev/null +++ b/fuzzylite/fl/defuzzifier/Defuzzifier.h @@ -0,0 +1,53 @@ +/* + 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. + + */ + +//TODO Check http://en.wikipedia.org/wiki/Defuzzification for other defuzzifiers. + +#ifndef FL_DEFUZZIFIER_H +#define FL_DEFUZZIFIER_H + +#include "fl/fuzzylite.h" +#include <string> + +namespace fl { + class Term; + + class FL_API Defuzzifier { + public: + + Defuzzifier() { + } + + virtual ~Defuzzifier() { + } + FL_DEFAULT_COPY_AND_MOVE(Defuzzifier) + + virtual std::string className() const = 0; + virtual Defuzzifier* clone() const = 0; + virtual scalar defuzzify(const Term* term, scalar minimum, scalar maximum) const = 0; + + }; + +} +#endif /* FL_DEFUZZIFIER_H */ diff --git a/fuzzylite/fl/defuzzifier/IntegralDefuzzifier.h b/fuzzylite/fl/defuzzifier/IntegralDefuzzifier.h new file mode 100644 index 0000000..61aaf8a --- /dev/null +++ b/fuzzylite/fl/defuzzifier/IntegralDefuzzifier.h @@ -0,0 +1,53 @@ +/* + 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. + + */ + +#ifndef FL_INTEGRALDEFUZZIFIER_H +#define FL_INTEGRALDEFUZZIFIER_H + +#include "fl/defuzzifier/Defuzzifier.h" + +namespace fl { + //TODO: check http://en.wikipedia.org/wiki/Adaptive_quadrature + + class FL_API IntegralDefuzzifier : public Defuzzifier { + protected: + static int _defaultResolution; + + int _resolution; + public: + + static void setDefaultResolution(int defaultResolution); + static int defaultResolution(); + + explicit IntegralDefuzzifier(int resolution = defaultResolution()); + virtual ~IntegralDefuzzifier() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(IntegralDefuzzifier) + + virtual void setResolution(int resolution); + virtual int getResolution() const; + }; +} + +#endif /* INTEGRALDEFUZZIFIER_H */ + diff --git a/fuzzylite/fl/defuzzifier/LargestOfMaximum.h b/fuzzylite/fl/defuzzifier/LargestOfMaximum.h new file mode 100644 index 0000000..8f1d3c8 --- /dev/null +++ b/fuzzylite/fl/defuzzifier/LargestOfMaximum.h @@ -0,0 +1,47 @@ +/* + 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. + + */ + +#ifndef FL_LARGESTOFMAXIMUM_H +#define FL_LARGESTOFMAXIMUM_H + +#include "fl/defuzzifier/IntegralDefuzzifier.h" + +namespace fl { + + class FL_API LargestOfMaximum : public IntegralDefuzzifier { + public: + explicit LargestOfMaximum(int resolution = defaultResolution()); + virtual ~LargestOfMaximum() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(LargestOfMaximum) + + virtual std::string className() const FL_IOVERRIDE; + virtual scalar defuzzify(const Term* term, + scalar minimum, scalar maximum) const FL_IOVERRIDE; + virtual LargestOfMaximum* clone() const FL_IOVERRIDE; + + static Defuzzifier* constructor(); + }; +} +#endif /* FL_LARGESTOFMAXIMUM_H */ + diff --git a/fuzzylite/fl/defuzzifier/MeanOfMaximum.h b/fuzzylite/fl/defuzzifier/MeanOfMaximum.h new file mode 100644 index 0000000..2c09759 --- /dev/null +++ b/fuzzylite/fl/defuzzifier/MeanOfMaximum.h @@ -0,0 +1,48 @@ +/* + 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. + + */ + +#ifndef FL_MEANOFMAXIMUM_H +#define FL_MEANOFMAXIMUM_H + +#include "fl/defuzzifier/IntegralDefuzzifier.h" + +namespace fl { + + class FL_API MeanOfMaximum : public IntegralDefuzzifier { + public: + explicit MeanOfMaximum(int resolution = defaultResolution()); + virtual ~MeanOfMaximum() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(MeanOfMaximum) + + virtual std::string className() const FL_IOVERRIDE; + virtual scalar defuzzify(const Term* term, + scalar minimum, scalar maximum) const FL_IOVERRIDE; + virtual MeanOfMaximum* clone() const FL_IOVERRIDE; + + static Defuzzifier* constructor(); + }; +} + +#endif /* FL_MEANOFMAXIMUM_H */ + diff --git a/fuzzylite/fl/defuzzifier/SmallestOfMaximum.h b/fuzzylite/fl/defuzzifier/SmallestOfMaximum.h new file mode 100644 index 0000000..289e2a9 --- /dev/null +++ b/fuzzylite/fl/defuzzifier/SmallestOfMaximum.h @@ -0,0 +1,48 @@ +/* + 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. + + */ + +#ifndef FL_SMALLESTOFMAXIMUM_H +#define FL_SMALLESTOFMAXIMUM_H + +#include "fl/defuzzifier/IntegralDefuzzifier.h" + +namespace fl { + + class FL_API SmallestOfMaximum : public IntegralDefuzzifier { + public: + explicit SmallestOfMaximum(int resolution = defaultResolution()); + virtual ~SmallestOfMaximum() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(SmallestOfMaximum) + + virtual std::string className() const FL_IOVERRIDE; + virtual scalar defuzzify(const Term* term, + scalar minimum, scalar maximum) const FL_IOVERRIDE; + virtual SmallestOfMaximum* clone() const FL_IOVERRIDE; + + static Defuzzifier* constructor(); + }; +} + +#endif /* FL_SMALLESTOFMAXIMUM_H */ + diff --git a/fuzzylite/fl/defuzzifier/WeightedAverage.h b/fuzzylite/fl/defuzzifier/WeightedAverage.h new file mode 100644 index 0000000..3fbbd38 --- /dev/null +++ b/fuzzylite/fl/defuzzifier/WeightedAverage.h @@ -0,0 +1,50 @@ +/* + 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. + + */ + +#ifndef FL_WEIGHTEDAVERAGE_H +#define FL_WEIGHTEDAVERAGE_H + +#include "fl/defuzzifier/WeightedDefuzzifier.h" + +namespace fl { + class Activated; + + class FL_API WeightedAverage : public WeightedDefuzzifier { + public: + explicit WeightedAverage(Type type = Automatic); + explicit WeightedAverage(const std::string& type); + virtual ~WeightedAverage() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(WeightedAverage) + + virtual std::string className() const FL_IOVERRIDE; + virtual scalar defuzzify(const Term* term, + scalar minimum, scalar maximum) const FL_IOVERRIDE; + virtual WeightedAverage* clone() const FL_IOVERRIDE; + + static Defuzzifier* constructor(); + }; +} + +#endif /* FL_WEIGHTEDAVERAGE_H */ + diff --git a/fuzzylite/fl/defuzzifier/WeightedDefuzzifier.h b/fuzzylite/fl/defuzzifier/WeightedDefuzzifier.h new file mode 100644 index 0000000..2bf0495 --- /dev/null +++ b/fuzzylite/fl/defuzzifier/WeightedDefuzzifier.h @@ -0,0 +1,63 @@ +/* + 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. + + */ + +#ifndef FL_WEIGHTEDDEFUZZIFIER_H +#define FL_WEIGHTEDDEFUZZIFIER_H + +#include "fl/defuzzifier/Defuzzifier.h" + +namespace fl { + class Activated; + + class FL_API WeightedDefuzzifier : public Defuzzifier { + public: + + enum Type { + Automatic, TakagiSugeno, Tsukamoto + }; + static std::string typeName(Type); + + explicit WeightedDefuzzifier(Type type = Automatic); + explicit WeightedDefuzzifier(const std::string& type); + virtual ~WeightedDefuzzifier() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(WeightedDefuzzifier) + + virtual void setType(Type type); + virtual Type getType() const; + virtual std::string getTypeName() const; + virtual Type inferType(const Term* term) const; + virtual bool isMonotonic(const Term* term) const; + + virtual scalar tsukamoto(const Term* monotonic, scalar activationDegree, + scalar minimum, scalar maximum) const; + + protected: + Type _type; + + }; + +} + +#endif /* FL_WEIGHTEDDEFUZZIFIER_H */ + diff --git a/fuzzylite/fl/defuzzifier/WeightedSum.h b/fuzzylite/fl/defuzzifier/WeightedSum.h new file mode 100644 index 0000000..a754023 --- /dev/null +++ b/fuzzylite/fl/defuzzifier/WeightedSum.h @@ -0,0 +1,50 @@ +/* + 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. + + */ + +#ifndef FL_WEIGHTEDSUM_H +#define FL_WEIGHTEDSUM_H + + +#include "fl/defuzzifier/WeightedDefuzzifier.h" + +namespace fl { + + class FL_API WeightedSum : public WeightedDefuzzifier { + public: + explicit WeightedSum(Type type = Automatic); + explicit WeightedSum(const std::string& type); + virtual ~WeightedSum() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(WeightedSum) + + virtual std::string className() const FL_IOVERRIDE; + virtual scalar defuzzify(const Term* term, + scalar minimum, scalar maximum) const FL_IOVERRIDE; + virtual WeightedSum* clone() const FL_IOVERRIDE; + + static Defuzzifier* constructor(); + }; +} + +#endif /* FL_WEIGHTEDSUM_H */ + diff --git a/fuzzylite/fl/factory/CloningFactory.h b/fuzzylite/fl/factory/CloningFactory.h new file mode 100644 index 0000000..3262721 --- /dev/null +++ b/fuzzylite/fl/factory/CloningFactory.h @@ -0,0 +1,62 @@ +/* + 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. + + */ + +#ifndef FL_CLONINGFACTORY_H +#define FL_CLONINGFACTORY_H + +#include "fl/fuzzylite.h" + +#include <map> +#include <string> +#include <vector> + +namespace fl { + + template <typename T> + class FL_API CloningFactory { + protected: + std::string _name; + std::map<std::string, T> _objects; + + public: + explicit CloningFactory(const std::string& name = ""); + CloningFactory(const CloningFactory& other); + CloningFactory& operator=(const CloningFactory& other); + virtual ~CloningFactory(); + FL_DEFAULT_MOVE(CloningFactory) + + virtual std::string name() const; + + virtual void registerObject(const std::string& key, T object); + virtual void deregisterObject(const std::string& key); + virtual bool hasObject(const std::string& key) const; + virtual T getObject(const std::string& key) const; + virtual T cloneObject(const std::string& key) const; + virtual std::vector<std::string> available() const; + + }; +} + +#endif /* FL_CLONINGFACTORY_H */ + diff --git a/fuzzylite/fl/factory/ConstructionFactory.h b/fuzzylite/fl/factory/ConstructionFactory.h new file mode 100644 index 0000000..d01ca7d --- /dev/null +++ b/fuzzylite/fl/factory/ConstructionFactory.h @@ -0,0 +1,64 @@ +/* + 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. + + */ + +#ifndef FL_FACTORY_H +#define FL_FACTORY_H + +#include "fl/fuzzylite.h" + +#include <map> +#include <string> +#include <vector> + +namespace fl { + + template <typename T> + class FL_API ConstructionFactory { + public: + typedef T(*Constructor)(); + + protected: + std::string _name; + std::map<std::string, Constructor> _constructors; + + public: + explicit ConstructionFactory(const std::string& name); + virtual ~ConstructionFactory(); + FL_DEFAULT_COPY_AND_MOVE(ConstructionFactory) + + virtual std::string name() const; + + virtual void registerConstructor(const std::string& key, Constructor constructor); + virtual void deregisterConstructor(const std::string& key); + virtual bool hasConstructor(const std::string& key) const; + virtual Constructor getConstructor(const std::string& key) const; + virtual T constructObject(const std::string& key) const; + virtual std::vector<std::string> available() const; + + }; + +} + +#endif /* FL_FACTORY_H */ + diff --git a/fuzzylite/fl/factory/DefuzzifierFactory.h b/fuzzylite/fl/factory/DefuzzifierFactory.h new file mode 100644 index 0000000..32d3ee7 --- /dev/null +++ b/fuzzylite/fl/factory/DefuzzifierFactory.h @@ -0,0 +1,51 @@ +/* + 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. + + */ + +#ifndef FL_DEFUZZIFIERFACTORY_H +#define FL_DEFUZZIFIERFACTORY_H + +#include "fl/factory/ConstructionFactory.h" + +#include "fl/defuzzifier/Defuzzifier.h" +#include "fl/defuzzifier/IntegralDefuzzifier.h" +#include "fl/defuzzifier/WeightedDefuzzifier.h" + +namespace fl { + + class FL_API DefuzzifierFactory : public ConstructionFactory<Defuzzifier*> { + public: + DefuzzifierFactory(); + virtual ~DefuzzifierFactory() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(DefuzzifierFactory) + + virtual Defuzzifier* constructDefuzzifier(const std::string& key, + int resolution, WeightedDefuzzifier::Type) const; + + virtual Defuzzifier* constructDefuzzifier(const std::string& key, int resolution) const; + + virtual Defuzzifier* constructDefuzzifier(const std::string& key, WeightedDefuzzifier::Type type); + }; +} +#endif /* DEFUZZIFIERFACTORY_H */ + diff --git a/fuzzylite/fl/factory/FactoryManager.h b/fuzzylite/fl/factory/FactoryManager.h new file mode 100644 index 0000000..d853d93 --- /dev/null +++ b/fuzzylite/fl/factory/FactoryManager.h @@ -0,0 +1,81 @@ +/* + 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. + + */ + +#ifndef FL_FACTORYMANAGER_H +#define FL_FACTORYMANAGER_H + +#include "fl/fuzzylite.h" + +namespace fl { + class TNormFactory; + class SNormFactory; + class DefuzzifierFactory; + class TermFactory; + class HedgeFactory; + class FunctionFactory; + + class FL_API FactoryManager { + protected: + static FactoryManager _instance; + + FL_unique_ptr<TNormFactory> _tnorm; + FL_unique_ptr<SNormFactory> _snorm; + FL_unique_ptr<DefuzzifierFactory> _defuzzifier; + FL_unique_ptr<TermFactory> _term; + FL_unique_ptr<HedgeFactory> _hedge; + FL_unique_ptr<FunctionFactory> _function; + + FactoryManager(); + FactoryManager(TNormFactory* tnorm, SNormFactory* snorm, + DefuzzifierFactory* defuzzifier, TermFactory* term, + HedgeFactory* hedge, FunctionFactory* function); + FactoryManager(const FactoryManager& other); + FactoryManager& operator=(const FactoryManager& other); + FL_DEFAULT_MOVE(FactoryManager) + virtual ~FactoryManager(); + + public: + static FactoryManager* instance(); + + virtual void setTnorm(TNormFactory* tnorm); + virtual TNormFactory* tnorm() const; + + virtual void setSnorm(SNormFactory* snorm); + virtual SNormFactory* snorm() const; + + virtual void setDefuzzifier(DefuzzifierFactory* defuzzifier); + virtual DefuzzifierFactory* defuzzifier() const; + + virtual void setTerm(TermFactory* term); + virtual TermFactory* term() const; + + virtual void setHedge(HedgeFactory* hedge); + virtual HedgeFactory* hedge() const; + + virtual void setFunction(FunctionFactory* function); + virtual FunctionFactory* function() const; + }; +} +#endif /* FL_FACTORYMANAGER_H */ + diff --git a/fuzzylite/fl/factory/FunctionFactory.h b/fuzzylite/fl/factory/FunctionFactory.h new file mode 100644 index 0000000..c1ea9f1 --- /dev/null +++ b/fuzzylite/fl/factory/FunctionFactory.h @@ -0,0 +1,51 @@ +/* + 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. + + */ + +#ifndef FL_FUNCTIONFACTORY_H +#define FL_FUNCTIONFACTORY_H + +#include "fl/factory/CloningFactory.h" + +#include "fl/term/Function.h" + +namespace fl { + + class FunctionFactory : public CloningFactory<Function::Element*> { + private: + void registerOperators(); + void registerFunctions(); + public: + FunctionFactory(); + virtual ~FunctionFactory() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(FunctionFactory) + + virtual std::vector<std::string> availableOperators() const; + virtual std::vector<std::string> availableFunctions() const; + + }; + +} + +#endif /* FL_FUNCTIONFACTORY_H */ + diff --git a/fuzzylite/fl/factory/HedgeFactory.h b/fuzzylite/fl/factory/HedgeFactory.h new file mode 100644 index 0000000..aca5d3a --- /dev/null +++ b/fuzzylite/fl/factory/HedgeFactory.h @@ -0,0 +1,42 @@ +/* + 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. + + */ + +#ifndef FL_HEDGEFACTORY_H +#define FL_HEDGEFACTORY_H + +#include "fl/factory/ConstructionFactory.h" + +#include "fl/hedge/Hedge.h" + +namespace fl { + + class FL_API HedgeFactory : public ConstructionFactory<Hedge*> { + public: + HedgeFactory(); + virtual ~HedgeFactory() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(HedgeFactory) + }; +} +#endif /* FL_HEDGEFACTORY_H */ + diff --git a/fuzzylite/fl/factory/SNormFactory.h b/fuzzylite/fl/factory/SNormFactory.h new file mode 100644 index 0000000..ca8bf1a --- /dev/null +++ b/fuzzylite/fl/factory/SNormFactory.h @@ -0,0 +1,42 @@ +/* + 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. + + */ + +#ifndef FL_SNORMFACTORY_H +#define FL_SNORMFACTORY_H + +#include "fl/factory/ConstructionFactory.h" + +#include "fl/norm/SNorm.h" + +namespace fl { + + class FL_API SNormFactory : public ConstructionFactory<SNorm*> { + public: + SNormFactory(); + virtual ~SNormFactory() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(SNormFactory) + }; +} +#endif /* FL_SNORMFACTORY_H */ + diff --git a/fuzzylite/fl/factory/TNormFactory.h b/fuzzylite/fl/factory/TNormFactory.h new file mode 100644 index 0000000..6af2249 --- /dev/null +++ b/fuzzylite/fl/factory/TNormFactory.h @@ -0,0 +1,42 @@ +/* + 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. + + */ + +#ifndef FL_TNORMFACTORY_H +#define FL_TNORMFACTORY_H + +#include "fl/factory/ConstructionFactory.h" + +#include "fl/norm/TNorm.h" + +namespace fl { + + class FL_API TNormFactory : public ConstructionFactory<TNorm*> { + public: + TNormFactory(); + virtual ~TNormFactory() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(TNormFactory) + }; +} +#endif /* FL_TNORMFACTORY_H */ + diff --git a/fuzzylite/fl/factory/TermFactory.h b/fuzzylite/fl/factory/TermFactory.h new file mode 100644 index 0000000..6fd0656 --- /dev/null +++ b/fuzzylite/fl/factory/TermFactory.h @@ -0,0 +1,43 @@ +/* + 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. + + */ + +#ifndef FL_TERMFACTORY_H +#define FL_TERMFACTORY_H + + +#include "fl/factory/ConstructionFactory.h" + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API TermFactory : public ConstructionFactory<Term*> { + public: + TermFactory(); + virtual ~TermFactory() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(TermFactory) + }; +} +#endif /* FL_TERMFACTORY_H */ + diff --git a/fuzzylite/fl/fuzzylite.h b/fuzzylite/fl/fuzzylite.h new file mode 100644 index 0000000..18c8dfa --- /dev/null +++ b/fuzzylite/fl/fuzzylite.h @@ -0,0 +1,222 @@ +/* + 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. + + */ + +#ifndef FL_FUZZYLITE_H +#define FL_FUZZYLITE_H + +#include <algorithm> +#include <cmath> +#include <iostream> +#include <sstream> +#include <limits> +#include <memory> + +#ifndef FL_VERSION +#define FL_VERSION "?" +#endif + +#ifndef FL_DATE +#define FL_DATE "?" +#endif + +#ifndef FL_BUILD_PATH +#define FL_BUILD_PATH "" +#endif + +#if defined(_WIN32) || defined(WIN32) +#define FL_WINDOWS +#endif + +#if defined(unix) || defined(__unix__) || defined(__unix) +#define FL_UNIX +#endif + +#ifdef __APPLE__ +#define FL_APPLE +#endif + +#define FL__FILE__ std::string(__FILE__).substr(std::string(FL_BUILD_PATH).size()) + +#define FL_LOG_PREFIX FL__FILE__ << " [" << __LINE__ << "]:" + +#define FL_AT FL__FILE__, __LINE__, __FUNCTION__ + + +#define FL_LOG(message) {if (fl::fuzzylite::logging()){std::cout << FL_LOG_PREFIX << message << std::endl;}} +#define FL_LOGP(message) {if (fl::fuzzylite::logging()){std::cout << message << std::endl;}} + +#define FL_DEBUG_BEGIN if (fl::fuzzylite::debug()){ +#define FL_DEBUG_END } + +#define FL_DBG(message) FL_DEBUG_BEGIN\ + std::cout << FL__FILE__ << "::" << __FUNCTION__ << "[" << __LINE__ << "]:" \ + << message << std::endl;\ + FL_DEBUG_END + + +#ifdef FL_WINDOWS +#include <ciso646> //alternative operator spellings: +//#define and && +//#define or || +//#define not ! +//#define bitand & +//#define bitor | + +//TODO: Address warning 4251 by exporting members? +//http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html +#ifdef _MSC_VER +#pragma warning (disable:4251) +#endif + +//fuzzylite as a shared library is exported +//Applications linking with fuzzylite as a shared library need to import + +//fuzzylite as a static library does not export or import +//Applications linking with fuzzylite as a static library do not import + +#if defined(FL_EXPORT_LIBRARY) +#define FL_API __declspec(dllexport) +#elif defined(FL_IMPORT_LIBRARY) +#define FL_API __declspec(dllimport) +#else +#define FL_API +#endif + +#else +#define FL_API +#endif + + +namespace fl { +#ifdef FL_USE_FLOAT + typedef float scalar; +#else + typedef double scalar; +#endif + + const scalar nan = std::numeric_limits<scalar>::quiet_NaN(); + const scalar inf = std::numeric_limits<scalar>::infinity(); + +#ifdef FL_CPP11 + //C++11 defines + + //Pointers + const std::nullptr_t null = nullptr; +#define FL_unique_ptr std::unique_ptr +#define FL_move_ptr(x) std::move(x) + + //Identifiers +#define FL_IOVERRIDE override +#define FL_IFINAL final +#define FL_IDEFAULT = default +#define FL_IDELETE = delete +#define FL_INOEXCEPT noexcept + + //Constructors +#define FL_DEFAULT_COPY(Class) \ + Class(const Class&) = default; \ + Class& operator=(const Class&) = default; +#define FL_DEFAULT_MOVE(Class) \ + Class(Class&&) = default; \ + Class& operator=(Class&&) = default; +#define FL_DEFAULT_COPY_AND_MOVE(Class) \ + Class(const Class&) = default; \ + Class& operator=(const Class&) = default;\ + Class(Class&&) = default; \ + Class& operator=(Class&&) = default; + +#define FL_DISABLE_COPY(Class) \ + Class(const Class &) = delete;\ + Class &operator=(const Class &) = delete; + +#else + //C++98 defines + + //Pointers + const long null = 0L; +#define FL_unique_ptr std::auto_ptr +#define FL_move_ptr(x) x + + //Identifiers +#define FL_IOVERRIDE +#define FL_IFINAL +#define FL_IDEFAULT +#define FL_IDELETE +#define FL_INOEXCEPT throw() + + //Constructors +#define FL_DEFAULT_COPY(Class) +#define FL_DEFAULT_MOVE(Class) +#define FL_DEFAULT_COPY_AND_MOVE(Class) + +#define FL_DISABLE_COPY(Class) \ + Class(const Class &);\ + Class &operator=(const Class &); + +#endif +} + + +namespace fl { + + class FL_API fuzzylite { + protected: + static int _decimals; + static scalar _macheps; + static bool _debug; + static bool _logging; + + public: + static std::string name(); + static std::string fullname(); + static std::string version(); + static std::string longVersion(); + static std::string license(); + static std::string author(); + static std::string company(); + static std::string website(); + + static std::string date(); + static std::string platform(); + + static std::string floatingPoint(); + + static bool debug(); + static void setDebug(bool debug); + + static int decimals(); + static void setDecimals(int decimals); + + static scalar macheps(); + static void setMachEps(scalar macheps); + + static bool logging(); + static void setLogging(bool logging); + + }; +} + + +#endif /* FL_FUZZYLITE_H */ + diff --git a/fuzzylite/fl/hedge/Any.h b/fuzzylite/fl/hedge/Any.h new file mode 100644 index 0000000..c30b4c7 --- /dev/null +++ b/fuzzylite/fl/hedge/Any.h @@ -0,0 +1,47 @@ +/* + 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. + + */ + +#ifndef FL_ANY_H +#define FL_ANY_H + +#include "fl/hedge/Hedge.h" + +namespace fl { + //Only this hedge has virtual methods due to its special case use. + + class FL_API Any : public Hedge { + public: + Any(); + virtual ~Any() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Any) + + virtual std::string name() const FL_IOVERRIDE; + virtual scalar hedge(scalar x) const FL_IOVERRIDE; + virtual Any* clone() const FL_IOVERRIDE; + + static Hedge* constructor(); + }; + +} +#endif /* FL_ANY_H */ diff --git a/fuzzylite/fl/hedge/Extremely.h b/fuzzylite/fl/hedge/Extremely.h new file mode 100644 index 0000000..7ecda66 --- /dev/null +++ b/fuzzylite/fl/hedge/Extremely.h @@ -0,0 +1,42 @@ +/* + 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. + + */ + +#ifndef FL_EXTREMELY_H +#define FL_EXTREMELY_H + +#include "fl/hedge/Hedge.h" + +namespace fl { + + class FL_API Extremely : public Hedge { + public: + std::string name() const; + scalar hedge(scalar x) const; + Extremely* clone() const; + + static Hedge* constructor(); + }; + +} +#endif /* FL_EXTREMELY_H */ diff --git a/fuzzylite/fl/hedge/Hedge.h b/fuzzylite/fl/hedge/Hedge.h new file mode 100644 index 0000000..011c745 --- /dev/null +++ b/fuzzylite/fl/hedge/Hedge.h @@ -0,0 +1,51 @@ +/* + 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. + + */ + +#ifndef FL_HEDGE_H +#define FL_HEDGE_H + +#include "fl/fuzzylite.h" + +#include <string> + +namespace fl { + + class FL_API Hedge { + public: + + Hedge() { + } + + virtual ~Hedge() { + } + FL_DEFAULT_COPY_AND_MOVE(Hedge) + + virtual std::string name() const = 0; + virtual scalar hedge(scalar x) const = 0; + virtual Hedge* clone() const = 0; + + }; +} + +#endif /* FL_HEDGE_H */ diff --git a/fuzzylite/fl/hedge/Not.h b/fuzzylite/fl/hedge/Not.h new file mode 100644 index 0000000..161fefd --- /dev/null +++ b/fuzzylite/fl/hedge/Not.h @@ -0,0 +1,42 @@ +/* + 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. + + */ + +#ifndef FL_NOT_H +#define FL_NOT_H + +#include "fl/hedge/Hedge.h" + +namespace fl { + + class FL_API Not : public Hedge { + public: + std::string name() const FL_IOVERRIDE; + scalar hedge(scalar x) const FL_IOVERRIDE; + Not* clone() const FL_IOVERRIDE; + + static Hedge* constructor(); + }; + +} +#endif /* FL_NOT_H */ diff --git a/fuzzylite/fl/hedge/Seldom.h b/fuzzylite/fl/hedge/Seldom.h new file mode 100644 index 0000000..a2a96c2 --- /dev/null +++ b/fuzzylite/fl/hedge/Seldom.h @@ -0,0 +1,42 @@ +/* + 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. + + */ + +#ifndef FL_SELDOM_H +#define FL_SELDOM_H + +#include "fl/hedge/Hedge.h" + +namespace fl { + + class FL_API Seldom : public Hedge { + public: + std::string name() const FL_IOVERRIDE; + scalar hedge(scalar x) const FL_IOVERRIDE; + Seldom* clone() const FL_IOVERRIDE; + + static Hedge* constructor(); + }; + +} +#endif /* FL_SELDOM_H */ diff --git a/fuzzylite/fl/hedge/Somewhat.h b/fuzzylite/fl/hedge/Somewhat.h new file mode 100644 index 0000000..89a14a6 --- /dev/null +++ b/fuzzylite/fl/hedge/Somewhat.h @@ -0,0 +1,42 @@ +/* + 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. + + */ + +#ifndef FL_SOMEWHAT_H +#define FL_SOMEWHAT_H + +#include "fl/hedge/Hedge.h" + +namespace fl { + + class FL_API Somewhat : public Hedge { + public: + std::string name() const FL_IOVERRIDE; + scalar hedge(scalar x) const FL_IOVERRIDE; + Somewhat* clone() const FL_IOVERRIDE; + + static Hedge* constructor(); + }; + +} +#endif /* FL_SOMEWHAT_H */ diff --git a/fuzzylite/fl/hedge/Very.h b/fuzzylite/fl/hedge/Very.h new file mode 100644 index 0000000..bcfe5e4 --- /dev/null +++ b/fuzzylite/fl/hedge/Very.h @@ -0,0 +1,42 @@ +/* + 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. + + */ + +#ifndef FL_VERY_H +#define FL_VERY_H + +#include "fl/hedge/Hedge.h" + +namespace fl { + + class FL_API Very : public Hedge { + public: + std::string name() const FL_IOVERRIDE; + scalar hedge(scalar x) const FL_IOVERRIDE; + Very* clone() const FL_IOVERRIDE; + + static Hedge* constructor(); + }; + +} +#endif /* FL_VERY_H */ diff --git a/fuzzylite/fl/imex/CppExporter.h b/fuzzylite/fl/imex/CppExporter.h new file mode 100644 index 0000000..e53cf15 --- /dev/null +++ b/fuzzylite/fl/imex/CppExporter.h @@ -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. + + */ + +#ifndef FL_CPPEXPORTER_H +#define FL_CPPEXPORTER_H + +#include "fl/imex/Exporter.h" + +namespace fl { + class Engine; + class InputVariable; + class OutputVariable; + class Term; + class RuleBlock; + class Norm; + class Defuzzifier; + class Hedge; + + class FL_API CppExporter : public Exporter { + protected: + bool _prefixNamespace; + virtual std::string fl(const std::string& clazz) const; + public: + explicit CppExporter(bool prefixNamespace = false); + virtual ~CppExporter() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(CppExporter) + + virtual std::string name() const FL_IOVERRIDE; + virtual std::string toString(const Engine* engine) const FL_IOVERRIDE; + + virtual void setPrefixNamespace(bool prefixNamespace); + virtual bool isPrefixNamespace() const; + + virtual std::string toString(const InputVariable* inputVariable, const Engine* engine) const; + virtual std::string toString(const OutputVariable* outputVariable, const Engine* engine) const; + virtual std::string toString(const RuleBlock* ruleBlock, const Engine* engine) const; + virtual std::string toString(scalar value) const; + + virtual std::string toString(const Hedge* hedge) const; + virtual std::string toString(const Term* term) const; + virtual std::string toString(const Norm* op) const; + virtual std::string toString(const Defuzzifier* defuzzifier) const; + + virtual CppExporter* clone() const FL_IOVERRIDE; + + }; +} +#endif /* FL_CPPEXPORTER_H */ + diff --git a/fuzzylite/fl/imex/Exporter.h b/fuzzylite/fl/imex/Exporter.h new file mode 100644 index 0000000..8b55c21 --- /dev/null +++ b/fuzzylite/fl/imex/Exporter.h @@ -0,0 +1,52 @@ +/* + 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. + + */ + +#ifndef FL_EXPORTER_H +#define FL_EXPORTER_H + +#include "fl/fuzzylite.h" + +#include <string> + +namespace fl { + class Engine; + + class FL_API Exporter { + public: + + Exporter(); + virtual ~Exporter(); + FL_DEFAULT_COPY_AND_MOVE(Exporter) + + virtual std::string toString(const Engine* engine) const = 0; + virtual void toFile(const std::string& path, const Engine* engine) const; + + virtual std::string name() const = 0; + virtual Exporter* clone() const = 0; + }; + +} + +#endif /* FL_EXPORTER_H */ + diff --git a/fuzzylite/fl/imex/FclExporter.h b/fuzzylite/fl/imex/FclExporter.h new file mode 100644 index 0000000..9bfa3ed --- /dev/null +++ b/fuzzylite/fl/imex/FclExporter.h @@ -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. + + */ + +#ifndef FL_FCLEXPORTER_H +#define FL_FCLEXPORTER_H + +#include "fl/imex/Exporter.h" + +namespace fl { + class InputVariable; + class OutputVariable; + class RuleBlock; + class Norm; + class TNorm; + class SNorm; + class Defuzzifier; + class Term; + + class FL_API FclExporter : public Exporter { + protected: + std::string _indent; + + public: + explicit FclExporter(const std::string& indent = " "); + virtual ~FclExporter() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(FclExporter) + + virtual void setIndent(const std::string& indent); + virtual std::string getIndent() const; + + virtual std::string name() const FL_IOVERRIDE; + virtual std::string toString(const Engine* engine) const FL_IOVERRIDE; + + virtual std::string toString(const InputVariable* variable) const; + virtual std::string toString(const OutputVariable* variable) const; + virtual std::string toString(const RuleBlock* ruleBlock) const; + + virtual std::string toString(const Norm* norm) const; + + virtual std::string toString(const TNorm* tnorm) const; //TODO: Delete in v6.0 + virtual std::string toString(const SNorm* snorm) const; //TODO: Delete in v6.0 + virtual std::string toString(const Defuzzifier* defuzzifier) const; + virtual std::string toString(const Term* term) const; + + virtual FclExporter* clone() const FL_IOVERRIDE; + }; + +} +#endif /* FL_FCLEXPORTER_H */ diff --git a/fuzzylite/fl/imex/FclImporter.h b/fuzzylite/fl/imex/FclImporter.h new file mode 100644 index 0000000..b219717 --- /dev/null +++ b/fuzzylite/fl/imex/FclImporter.h @@ -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. + + */ + +#ifndef FL_FCLIMPORTER_H +#define FL_FCLIMPORTER_H + +#include "fl/imex/Importer.h" + +#include <string> +#include <utility> +#include <vector> + + +namespace fl { + class Norm; + class TNorm; + class SNorm; + class Term; + class Defuzzifier; + + class FL_API FclImporter : public Importer { + public: + FclImporter(); + virtual ~FclImporter() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(FclImporter) + + virtual std::string name() const FL_IOVERRIDE; + + virtual Engine* fromString(const std::string& fcl) const FL_IOVERRIDE; + + virtual FclImporter* clone() const FL_IOVERRIDE; + + protected: + virtual void processBlock(const std::string& tag, const std::string& block, Engine* engine) const; + virtual void processVar(const std::string& var, const std::string& block, Engine* engine)const; + virtual void processFuzzify(const std::string& block, Engine* engine)const; + virtual void processDefuzzify(const std::string& block, Engine* engine)const; + virtual void processRuleBlock(const std::string& block, Engine* engine)const; + + virtual TNorm* parseTNorm(const std::string& line) const; + virtual SNorm* parseSNorm(const std::string& line) const; + virtual Term* parseTerm(const std::string& line, const Engine* engine) const; + + virtual Defuzzifier* parseDefuzzifier(const std::string& line) const; + virtual std::pair<scalar, bool> parseDefaultValue(const std::string& line) const; + virtual std::pair<scalar, scalar> parseRange(const std::string& line) const; + virtual std::pair<bool, bool> parseLocks(const std::string& line) const; + virtual bool parseEnabled(const std::string& line) const; + + }; + +} +#endif /* FL_FCLIMPORTER_H */ diff --git a/fuzzylite/fl/imex/FisExporter.h b/fuzzylite/fl/imex/FisExporter.h new file mode 100644 index 0000000..05d6a22 --- /dev/null +++ b/fuzzylite/fl/imex/FisExporter.h @@ -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. + + */ + +#ifndef FL_FISEXPORTER_H +#define FL_FISEXPORTER_H + +#include "fl/imex/Exporter.h" + +#include <vector> + +namespace fl { + class Norm; + class TNorm; + class SNorm; + class Defuzzifier; + class Term; + class Rule; + class Proposition; + class Variable; + + class FL_API FisExporter : public Exporter { + protected: + + virtual std::string translate(const std::vector<Proposition*>& propositions, + const std::vector<Variable*> variables) const; + + public: + FisExporter(); + virtual ~FisExporter() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(FisExporter) + + virtual std::string name() const FL_IOVERRIDE; + virtual std::string toString(const Engine* engine) const FL_IOVERRIDE; + + virtual std::string toString(const Norm* norm) const; + virtual std::string toString(const TNorm* tnorm) const; //TODO: delete in v6.0 + virtual std::string toString(const SNorm* snorm) const; //TODO: delete in v6.0 + virtual std::string toString(const Defuzzifier* defuzzifier) const; + virtual std::string toString(const Term* term) const; + + virtual std::string exportSystem(const Engine* engine) const; + virtual std::string exportInputs(const Engine* engine) const; + virtual std::string exportOutputs(const Engine* engine) const; + virtual std::string exportRules(const Engine* engine) const; + virtual std::string exportRule(const Rule* rule, const Engine* engine) const; + + virtual FisExporter* clone() const FL_IOVERRIDE; + }; + +} + +#endif /* FL_FISEXPORTER_H */ + diff --git a/fuzzylite/fl/imex/FisImporter.h b/fuzzylite/fl/imex/FisImporter.h new file mode 100644 index 0000000..b631a48 --- /dev/null +++ b/fuzzylite/fl/imex/FisImporter.h @@ -0,0 +1,79 @@ +/* + 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. + + */ + +#ifndef FL_FISIMPORTER_H +#define FL_FISIMPORTER_H + +#include "fl/imex/Importer.h" + +#include <utility> +#include <vector> + + +namespace fl { + class Norm; + class TNorm; + class SNorm; + class Term; + class Defuzzifier; + class Variable; + + class FL_API FisImporter : public Importer { + public: + FisImporter(); + virtual ~FisImporter() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(FisImporter) + + virtual std::string name() const FL_IOVERRIDE; + + virtual Engine* fromString(const std::string& fcl) const FL_IOVERRIDE; + + virtual FisImporter* clone() const FL_IOVERRIDE; + + protected: + virtual void importSystem(const std::string& section, Engine* engine, + std::string& andMethod, std::string& orMethod, + std::string& impMethod, std::string& aggMethod, + std::string& defuzzMethod) const; + virtual void importInput(const std::string& section, Engine* engine) const; + virtual void importOutput(const std::string& section, Engine* engine) const; + virtual void importRules(const std::string& section, Engine* engine) const; + virtual std::string translateProposition(scalar code, Variable* variable) const; + + //TODO: rename extract to translate in v6.0 + virtual std::string extractTNorm(const std::string& tnorm) const; + virtual std::string extractSNorm(const std::string& tnorm) const; + virtual std::string extractDefuzzifier(const std::string& defuzzifier) const; + + virtual Term* parseTerm(const std::string& line, const Engine* engine) const; + virtual Term* createInstance(const std::string& termClass, const std::string& name, + const std::vector<std::string>& params, const Engine* engine) const; + //TODO: rename to parseRange in v6.0 + virtual std::pair<scalar, scalar> range(const std::string& range) const; + + }; + +} +#endif /* FL_FISIMPORTER_H */ + diff --git a/fuzzylite/fl/imex/FldExporter.h b/fuzzylite/fl/imex/FldExporter.h new file mode 100644 index 0000000..71679a6 --- /dev/null +++ b/fuzzylite/fl/imex/FldExporter.h @@ -0,0 +1,84 @@ +/* + 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. + + */ + +#ifndef FL_FLDEXPORTER_H +#define FL_FLDEXPORTER_H + +#include "fl/imex/Exporter.h" + +#include <vector> + +namespace fl { + class Engine; + class InputVariable; + class OutputVariable; + + class FL_API FldExporter : public Exporter { + protected: + std::string _separator; + bool _exportHeaders; + bool _exportInputValues; + bool _exportOutputValues; + public: + explicit FldExporter(const std::string& separator = " "); + virtual ~FldExporter() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(FldExporter) + + virtual std::string name() const FL_IOVERRIDE; + + virtual void setSeparator(const std::string& separator); + virtual std::string getSeparator() const; + + virtual void setExportHeader(bool exportHeaders); + virtual bool exportsHeader() const; + + virtual void setExportInputValues(bool exportInputValues); + virtual bool exportsInputValues() const; + + virtual void setExportOutputValues(bool exportOutputValues); + virtual bool exportsOutputValues() const; + + virtual std::string header(const Engine* engine) const; + + //WARNING: The engine will be const_casted in order to be processed! + virtual std::string toString(const Engine* engine) const FL_IOVERRIDE; + virtual std::string toString(Engine* engine, int maximumNumberOfResults) const; + virtual std::string toString(Engine* engine, const std::string& inputData) const; + + using Exporter::toFile; + virtual void toFile(const std::string& path, Engine* engine, int maximumNumberOfResults) const; + virtual void toFile(const std::string& path, Engine* engine, const std::string& inputData) const; + + virtual std::vector<scalar> parse(const std::string& x) const; + + void write(Engine* engine, std::ostream& writer, int maximumNumberOfResults) const; + void write(Engine* engine, std::ostream& writer, std::istream& reader) const; + void write(Engine* engine, std::ostream& writer, const std::vector<scalar>& inputValues) const; + + virtual FldExporter* clone() const FL_IOVERRIDE; + }; +} + +#endif /* FL_FLDEXPORTER_H */ + diff --git a/fuzzylite/fl/imex/FllExporter.h b/fuzzylite/fl/imex/FllExporter.h new file mode 100644 index 0000000..e6a89f5 --- /dev/null +++ b/fuzzylite/fl/imex/FllExporter.h @@ -0,0 +1,83 @@ +/* + 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. + + */ + +#ifndef FL_FLLEXPORTER_H +#define FL_FLLEXPORTER_H + +#include "fl/imex/Exporter.h" + +#include <vector> + +namespace fl { + class Variable; + class InputVariable; + class OutputVariable; + class RuleBlock; + class Rule; + class Norm; + class Defuzzifier; + class Term; + + class FL_API FllExporter : public Exporter { + protected: + std::string _indent; + std::string _separator; + public: + explicit FllExporter(const std::string& indent = " ", const std::string& separator = "\n"); + virtual ~FllExporter() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(FllExporter) + + virtual std::string name() const FL_IOVERRIDE; + + virtual void setIndent(const std::string& indent); + virtual std::string getIndent() const; + + virtual void setSeparator(const std::string& separator); + virtual std::string getSeparator() const; + + virtual std::string toString(const Engine* engine) const FL_IOVERRIDE; + + virtual std::string toString(const std::vector<Variable*>& variables) const; + virtual std::string toString(const std::vector<InputVariable*>& inputVariables) const; + virtual std::string toString(const std::vector<OutputVariable*>& outputVariables) const; + virtual std::string toString(const std::vector<RuleBlock*>& ruleBlocks) const; + + virtual std::string toString(const Variable* variable) const; + virtual std::string toString(const InputVariable* inputVariable) const; + virtual std::string toString(const OutputVariable* outputVariable) const; + + virtual std::string toString(const RuleBlock* ruleBlock) const; + virtual std::string toString(const Rule* rule) const; + + virtual std::string toString(const Norm* norm) const; + virtual std::string toString(const Defuzzifier* defuzzifier) const; + virtual std::string toString(const Term* term) const; + + virtual FllExporter* clone() const FL_IOVERRIDE; + }; + +} + +#endif /* FL_FLLEXPORTER_H */ + diff --git a/fuzzylite/fl/imex/FllImporter.h b/fuzzylite/fl/imex/FllImporter.h new file mode 100644 index 0000000..5be41c7 --- /dev/null +++ b/fuzzylite/fl/imex/FllImporter.h @@ -0,0 +1,77 @@ +/* + 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. + + */ + +#ifndef FL_FLLIMPORTER_H +#define FL_FLLIMPORTER_H + +#include "fl/imex/Importer.h" + +#include <utility> + +namespace fl { + class TNorm; + class SNorm; + class Term; + class Defuzzifier; + + class FL_API FllImporter : public Importer { + protected: + std::string _separator; + public: + explicit FllImporter(const std::string& separator = "\n"); + virtual ~FllImporter() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(FllImporter) + + virtual void setSeparator(const std::string& separator); + virtual std::string getSeparator() const; + + virtual std::string name() const FL_IOVERRIDE; + virtual Engine* fromString(const std::string& fll) const FL_IOVERRIDE; + + virtual FllImporter* clone() const FL_IOVERRIDE; + + protected: + virtual void process(const std::string& tag, const std::string& block, Engine* engine) const; + virtual void processInputVariable(const std::string& block, Engine* engine) const; + virtual void processOutputVariable(const std::string& block, Engine* engine) const; + virtual void processRuleBlock(const std::string& block, Engine* engine) const; + + virtual TNorm* parseTNorm(const std::string& name) const; + virtual SNorm* parseSNorm(const std::string& name) const; + + virtual Term* parseTerm(const std::string& text, Engine* engine) const; + + virtual Defuzzifier* parseDefuzzifier(const std::string& line) const; + virtual std::pair<scalar, scalar> parseRange(const std::string& line) const; + virtual bool parseBoolean(const std::string& boolean) const; + + virtual std::pair<std::string, std::string> parseKeyValue(const std::string& text, + char separator = ':') const; + virtual std::string clean(const std::string& line) const; + + }; +} + +#endif /* FL_FLLIMPORTER_H */ + diff --git a/fuzzylite/fl/imex/Importer.h b/fuzzylite/fl/imex/Importer.h new file mode 100644 index 0000000..28d2b36 --- /dev/null +++ b/fuzzylite/fl/imex/Importer.h @@ -0,0 +1,52 @@ +/* + 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. + + */ + +#ifndef FL_IMPORTER_H +#define FL_IMPORTER_H + +#include "fl/fuzzylite.h" + +#include <string> + +namespace fl { + class Engine; + + class FL_API Importer { + public: + + Importer(); + virtual ~Importer(); + FL_DEFAULT_COPY_AND_MOVE(Importer) + + virtual Engine* fromString(const std::string& s) const = 0; + virtual Engine* fromFile(const std::string& path) const; + + virtual std::string name() const = 0; + virtual Importer* clone() const = 0; + }; + +} + +#endif /* IMPORTER_H */ + diff --git a/fuzzylite/fl/imex/JavaExporter.h b/fuzzylite/fl/imex/JavaExporter.h new file mode 100644 index 0000000..e882d4a --- /dev/null +++ b/fuzzylite/fl/imex/JavaExporter.h @@ -0,0 +1,68 @@ +/* + 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. + + */ + +#ifndef FL_JAVAEXPORTER_H +#define FL_JAVAEXPORTER_H + +#include "fl/imex/Exporter.h" + +namespace fl { + + class Engine; + class InputVariable; + class OutputVariable; + class RuleBlock; + class Term; + class Defuzzifier; + class Norm; + class SNorm; + class TNorm; + + class FL_API JavaExporter : public Exporter { + public: + JavaExporter(); + virtual ~JavaExporter() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(JavaExporter) + + virtual std::string name() const FL_IOVERRIDE; + + virtual std::string toString(const Engine* engine) const FL_IOVERRIDE; + virtual std::string toString(const InputVariable* inputVariable, const Engine* engine) const; + virtual std::string toString(const OutputVariable* outputVariable, const Engine* engine) const; + virtual std::string toString(const RuleBlock* ruleBlock, const Engine* engine) const; + virtual std::string toString(const Term* term) const; + virtual std::string toString(const Defuzzifier* defuzzifier) const; + virtual std::string toString(const Norm* norm) const; + virtual std::string toString(const SNorm* norm) const;//TODO: delete in v6.0 + virtual std::string toString(const TNorm* norm) const;//TODO: delete in v6.0 + virtual std::string toString(scalar value) const; + + virtual JavaExporter* clone() const FL_IOVERRIDE; + + }; + +} + +#endif /* FL_JAVAEXPORTER_H */ + diff --git a/fuzzylite/fl/norm/Norm.h b/fuzzylite/fl/norm/Norm.h new file mode 100644 index 0000000..5f1b578 --- /dev/null +++ b/fuzzylite/fl/norm/Norm.h @@ -0,0 +1,55 @@ +/* + 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. + + */ + +#ifndef FL_NORM_H +#define FL_NORM_H + +#include "fl/fuzzylite.h" + +#include "fl/Operation.h" + +#include <string> + +namespace fl { + + class FL_API Norm { + public: + + Norm() { + } + + virtual ~Norm() { + } + + FL_DEFAULT_COPY_AND_MOVE(Norm) + + virtual std::string className() const = 0; + virtual scalar compute(scalar a, scalar b) const = 0; + + virtual Norm* clone() const = 0; + + }; +} +#endif /* FL_NORM_H */ + diff --git a/fuzzylite/fl/norm/SNorm.h b/fuzzylite/fl/norm/SNorm.h new file mode 100644 index 0000000..a281f52 --- /dev/null +++ b/fuzzylite/fl/norm/SNorm.h @@ -0,0 +1,47 @@ +/* + 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. + + */ + +#ifndef FL_SNORM_H +#define FL_SNORM_H + +#include "fl/norm/Norm.h" + +namespace fl { + + class FL_API SNorm : public Norm { + public: + + SNorm() { + } + + virtual ~SNorm() FL_IOVERRIDE { + } + + FL_DEFAULT_COPY_AND_MOVE(SNorm) + + virtual SNorm* clone() const FL_IOVERRIDE = 0; + }; +} +#endif /* FL_SNORM_H */ + diff --git a/fuzzylite/fl/norm/TNorm.h b/fuzzylite/fl/norm/TNorm.h new file mode 100644 index 0000000..8ba8538 --- /dev/null +++ b/fuzzylite/fl/norm/TNorm.h @@ -0,0 +1,47 @@ +/* + 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. + + */ + +#ifndef FL_TNORM_H +#define FL_TNORM_H + +#include "fl/norm/Norm.h" + +namespace fl { + + class FL_API TNorm : public Norm { + public: + + TNorm() { + } + + virtual ~TNorm() FL_IOVERRIDE { + } + + FL_DEFAULT_COPY_AND_MOVE(TNorm) + + virtual TNorm* clone() const FL_IOVERRIDE = 0; + }; +} +#endif /* TNORM_H */ + diff --git a/fuzzylite/fl/norm/s/AlgebraicSum.h b/fuzzylite/fl/norm/s/AlgebraicSum.h new file mode 100644 index 0000000..786bcbd --- /dev/null +++ b/fuzzylite/fl/norm/s/AlgebraicSum.h @@ -0,0 +1,46 @@ +/* + 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. + + */ + +#ifndef FL_ALGEBRAICSUM_H +#define FL_ALGEBRAICSUM_H + +#include "fl/norm/SNorm.h" + + +namespace fl { + + class FL_API AlgebraicSum : public SNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + AlgebraicSum* clone() const FL_IOVERRIDE; + + static SNorm* constructor(); + }; + + +} + +#endif /* FL_ALGEBRAICSUM_H */ + diff --git a/fuzzylite/fl/norm/s/BoundedSum.h b/fuzzylite/fl/norm/s/BoundedSum.h new file mode 100644 index 0000000..5231856 --- /dev/null +++ b/fuzzylite/fl/norm/s/BoundedSum.h @@ -0,0 +1,43 @@ +/* + 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. + + */ + +#ifndef FL_BOUNDEDSUM_H +#define FL_BOUNDEDSUM_H + +#include "fl/norm/SNorm.h" + +namespace fl { + + class FL_API BoundedSum : public SNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + BoundedSum* clone() const FL_IOVERRIDE; + + static SNorm* constructor(); + }; +} + +#endif /* FL_BOUNDEDSUM_H */ + diff --git a/fuzzylite/fl/norm/s/DrasticSum.h b/fuzzylite/fl/norm/s/DrasticSum.h new file mode 100644 index 0000000..65d4d4c --- /dev/null +++ b/fuzzylite/fl/norm/s/DrasticSum.h @@ -0,0 +1,43 @@ +/* + 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. + + */ + +#ifndef FL_DRASTICSUM_H +#define FL_DRASTICSUM_H + +#include "fl/norm/SNorm.h" +namespace fl { + + class FL_API DrasticSum : public SNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + DrasticSum* clone() const FL_IOVERRIDE; + + static SNorm* constructor(); + }; + +} + +#endif /* FL_DRASTICSUM_H */ + diff --git a/fuzzylite/fl/norm/s/EinsteinSum.h b/fuzzylite/fl/norm/s/EinsteinSum.h new file mode 100644 index 0000000..8114c68 --- /dev/null +++ b/fuzzylite/fl/norm/s/EinsteinSum.h @@ -0,0 +1,44 @@ +/* + 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. + + */ + +#ifndef FL_EINSTEINSUM_H +#define FL_EINSTEINSUM_H + +#include "fl/norm/SNorm.h" + +namespace fl { + + class FL_API EinsteinSum : public SNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + EinsteinSum* clone() const FL_IOVERRIDE; + + static SNorm* constructor(); + }; + +} + +#endif /* FL_EINSTEINSUM_H */ + diff --git a/fuzzylite/fl/norm/s/HamacherSum.h b/fuzzylite/fl/norm/s/HamacherSum.h new file mode 100644 index 0000000..3daf852 --- /dev/null +++ b/fuzzylite/fl/norm/s/HamacherSum.h @@ -0,0 +1,44 @@ +/* + 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. + + */ + +#ifndef FL_HAMACHERSUM_H +#define FL_HAMACHERSUM_H + +#include "fl/norm/SNorm.h" + +namespace fl { + + class FL_API HamacherSum : public SNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + HamacherSum* clone() const FL_IOVERRIDE; + + static SNorm* constructor(); + }; + +} + +#endif /* FL_HAMACHERSUM_H */ + diff --git a/fuzzylite/fl/norm/s/Maximum.h b/fuzzylite/fl/norm/s/Maximum.h new file mode 100644 index 0000000..28a3b6d --- /dev/null +++ b/fuzzylite/fl/norm/s/Maximum.h @@ -0,0 +1,45 @@ +/* + 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. + + */ + +#ifndef FL_MAXIMUM_H +#define FL_MAXIMUM_H + +#include "fl/norm/SNorm.h" + +namespace fl { + + class FL_API Maximum : public SNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + Maximum* clone() const FL_IOVERRIDE; + + static SNorm* constructor(); + }; + + +} + +#endif /* FL_MAXIMUM_H */ + diff --git a/fuzzylite/fl/norm/s/NilpotentMaximum.h b/fuzzylite/fl/norm/s/NilpotentMaximum.h new file mode 100644 index 0000000..151d92d --- /dev/null +++ b/fuzzylite/fl/norm/s/NilpotentMaximum.h @@ -0,0 +1,43 @@ +/* + 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. + + */ + +#ifndef FL_NILPOTENTMAXIMUM_H +#define FL_NILPOTENTMAXIMUM_H + +#include "fl/norm/SNorm.h" + +namespace fl { + + class FL_API NilpotentMaximum : public SNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + NilpotentMaximum* clone() const FL_IOVERRIDE; + + static SNorm* constructor(); + }; +} + +#endif /* FL_NILPOTENTMAXIMUM_H */ + diff --git a/fuzzylite/fl/norm/s/NormalizedSum.h b/fuzzylite/fl/norm/s/NormalizedSum.h new file mode 100644 index 0000000..59063a6 --- /dev/null +++ b/fuzzylite/fl/norm/s/NormalizedSum.h @@ -0,0 +1,44 @@ +/* + 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. + + */ + +#ifndef FL_NORMALIZEDSUM_H +#define FL_NORMALIZEDSUM_H + +#include "fl/norm/SNorm.h" + +namespace fl { + + class FL_API NormalizedSum : public SNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + NormalizedSum* clone() const FL_IOVERRIDE; + + static SNorm* constructor(); + }; + +} + +#endif /* FL_NORMALIZEDSUM_H */ + diff --git a/fuzzylite/fl/norm/t/AlgebraicProduct.h b/fuzzylite/fl/norm/t/AlgebraicProduct.h new file mode 100644 index 0000000..e4b0865 --- /dev/null +++ b/fuzzylite/fl/norm/t/AlgebraicProduct.h @@ -0,0 +1,45 @@ +/* + 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. + + */ + +#ifndef FL_ALGEBRAICPRODUCT_H +#define FL_ALGEBRAICPRODUCT_H + +#include "fl/norm/TNorm.h" + +namespace fl { + + class FL_API AlgebraicProduct : public TNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + AlgebraicProduct* clone() const FL_IOVERRIDE; + + static TNorm* constructor(); + }; + + +} + +#endif /* FL_ALGEBRAICPRODUCT_H */ + diff --git a/fuzzylite/fl/norm/t/BoundedDifference.h b/fuzzylite/fl/norm/t/BoundedDifference.h new file mode 100644 index 0000000..3dc9d3a --- /dev/null +++ b/fuzzylite/fl/norm/t/BoundedDifference.h @@ -0,0 +1,44 @@ +/* + 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. + + */ + +#ifndef FL_BOUNDEDDIFFERENCE_H +#define FL_BOUNDEDDIFFERENCE_H + +#include "fl/norm/TNorm.h" + +namespace fl { + + class FL_API BoundedDifference : public TNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + BoundedDifference* clone() const FL_IOVERRIDE; + + static TNorm* constructor(); + }; + +} + +#endif /* FL_BOUNDEDDIFFERENCE_H */ + diff --git a/fuzzylite/fl/norm/t/DrasticProduct.h b/fuzzylite/fl/norm/t/DrasticProduct.h new file mode 100644 index 0000000..efd589d --- /dev/null +++ b/fuzzylite/fl/norm/t/DrasticProduct.h @@ -0,0 +1,45 @@ +/* + 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. + + */ + +#ifndef FL_DRASTICPRODUCT_H +#define FL_DRASTICPRODUCT_H + +#include "fl/norm/TNorm.h" + +namespace fl { + + class FL_API DrasticProduct : public TNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + DrasticProduct* clone() const FL_IOVERRIDE; + + static TNorm* constructor(); + }; + + +} + +#endif /* FL_DRASTICPRODUCT_H */ + diff --git a/fuzzylite/fl/norm/t/EinsteinProduct.h b/fuzzylite/fl/norm/t/EinsteinProduct.h new file mode 100644 index 0000000..a4c1141 --- /dev/null +++ b/fuzzylite/fl/norm/t/EinsteinProduct.h @@ -0,0 +1,45 @@ +/* + 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. + + */ + +#ifndef FL_EINSTEINPRODUCT_H +#define FL_EINSTEINPRODUCT_H + +#include "fl/norm/TNorm.h" + +namespace fl { + + class FL_API EinsteinProduct : public TNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + EinsteinProduct* clone() const FL_IOVERRIDE; + + static TNorm* constructor(); + }; + + +} + +#endif /* FL_EINSTEINPRODUCT_H */ + diff --git a/fuzzylite/fl/norm/t/HamacherProduct.h b/fuzzylite/fl/norm/t/HamacherProduct.h new file mode 100644 index 0000000..9bc6b40 --- /dev/null +++ b/fuzzylite/fl/norm/t/HamacherProduct.h @@ -0,0 +1,44 @@ +/* + 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. + + */ + +#ifndef FL_HAMACHERPRODUCT_H +#define FL_HAMACHERPRODUCT_H + +#include "fl/norm/TNorm.h" + +namespace fl { + + class FL_API HamacherProduct : public TNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + HamacherProduct* clone() const FL_IOVERRIDE; + + static TNorm* constructor(); + }; + +} + +#endif /* FL_HAMACHERPRODUCT_H */ + diff --git a/fuzzylite/fl/norm/t/Minimum.h b/fuzzylite/fl/norm/t/Minimum.h new file mode 100644 index 0000000..3590e42 --- /dev/null +++ b/fuzzylite/fl/norm/t/Minimum.h @@ -0,0 +1,44 @@ +/* + 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. + + */ + +#ifndef FL_MINIMUM_H +#define FL_MINIMUM_H + +#include "fl/norm/TNorm.h" + +namespace fl { + + class FL_API Minimum : public TNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + Minimum* clone() const FL_IOVERRIDE; + + static TNorm* constructor(); + }; + +} + +#endif /* FL_MINIMUM_H */ + diff --git a/fuzzylite/fl/norm/t/NilpotentMinimum.h b/fuzzylite/fl/norm/t/NilpotentMinimum.h new file mode 100644 index 0000000..b3c11e0 --- /dev/null +++ b/fuzzylite/fl/norm/t/NilpotentMinimum.h @@ -0,0 +1,43 @@ +/* + 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. + + */ + +#ifndef FL_NILPOTENTMINIMUM_H +#define FL_NILPOTENTMINIMUM_H + +#include "fl/norm/TNorm.h" + +namespace fl { + + class FL_API NilpotentMinimum : public TNorm { + public: + std::string className() const FL_IOVERRIDE; + scalar compute(scalar a, scalar b) const FL_IOVERRIDE; + NilpotentMinimum* clone() const FL_IOVERRIDE; + + static TNorm* constructor(); + }; +} + +#endif /* FL_NILPOTENTMINIMUM_H */ + diff --git a/fuzzylite/fl/rule/Antecedent.h b/fuzzylite/fl/rule/Antecedent.h new file mode 100644 index 0000000..02724e5 --- /dev/null +++ b/fuzzylite/fl/rule/Antecedent.h @@ -0,0 +1,77 @@ +/* + 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. + + */ + +#ifndef FL_ANTECEDENT_H +#define FL_ANTECEDENT_H + +#include "fl/fuzzylite.h" + +#include <string> + +namespace fl { + class Engine; + class Rule; + class TNorm; + class SNorm; + class Expression; + + class FL_API Antecedent { + protected: + std::string _text; + Expression* _expression; + + public: + Antecedent(); + virtual ~Antecedent(); + + virtual void setText(const std::string& text); + virtual std::string getText() const; + + virtual Expression* getExpression() const; + + virtual bool isLoaded() const; + + virtual void unload(); + virtual void load(Rule* rule, const Engine* engine); + virtual void load(const std::string& antecedent, Rule* rule, const Engine* engine); + + virtual scalar activationDegree(const TNorm* conjunction, const SNorm* disjunction, + const Expression* node) const; + + virtual scalar activationDegree(const TNorm* conjunction, const SNorm* disjunction) const; + + virtual std::string toString() const; + + virtual std::string toPrefix(const Expression* node = fl::null) const; + virtual std::string toInfix(const Expression* node = fl::null) const; + virtual std::string toPostfix(const Expression* node = fl::null) const; + + + private: + FL_DISABLE_COPY(Antecedent) + }; + +} + +#endif /* FL_ANTECEDENT_H */ diff --git a/fuzzylite/fl/rule/Consequent.h b/fuzzylite/fl/rule/Consequent.h new file mode 100644 index 0000000..5394dc0 --- /dev/null +++ b/fuzzylite/fl/rule/Consequent.h @@ -0,0 +1,68 @@ +/* + 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. + + */ + +#ifndef FL_CONSEQUENT_H +#define FL_CONSEQUENT_H + +#include "fl/fuzzylite.h" + +#include <string> +#include <vector> + +namespace fl { + class Engine; + class Rule; + class Proposition; + class TNorm; + + class FL_API Consequent { + protected: + std::string _text; + std::vector<Proposition*> _conclusions; + + public: + Consequent(); + virtual ~Consequent(); + + virtual void setText(const std::string& text); + virtual std::string getText() const; + + virtual const std::vector<Proposition*>& conclusions() const; + + virtual bool isLoaded(); + virtual void unload(); + virtual void load(Rule* rule, const Engine* engine); + virtual void load(const std::string& consequent, Rule* rule, const Engine* engine); + + virtual void modify(scalar activationDegree, const TNorm* activation); + + virtual std::string toString() const; + + private: + FL_DISABLE_COPY(Consequent) + }; + +} + +#endif /* FL_CONSEQUENT_H */ diff --git a/fuzzylite/fl/rule/Expression.h b/fuzzylite/fl/rule/Expression.h new file mode 100644 index 0000000..cb48355 --- /dev/null +++ b/fuzzylite/fl/rule/Expression.h @@ -0,0 +1,84 @@ +/* + 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. + + */ + +#ifndef FL_EXPRESSION_H +#define FL_EXPRESSION_H + +#include "fl/fuzzylite.h" + +#include <string> +#include <vector> + + + +namespace fl { + class Variable; + class Hedge; + class Term; + + class FL_API Expression { + public: + + Expression(); + virtual ~Expression(); + + virtual std::string toString() const = 0; + + private: + FL_DISABLE_COPY(Expression) + }; + + class FL_API Proposition : public Expression { + public: + Variable* variable; + std::vector<Hedge*> hedges; + Term* term; + + Proposition(); + virtual ~Proposition() FL_IOVERRIDE; + + virtual std::string toString() const FL_IOVERRIDE; + + private: + FL_DISABLE_COPY(Proposition) + }; + + class FL_API Operator : public Expression { + public: + std::string name; + Expression* left; + Expression* right; + + Operator(); + virtual ~Operator() FL_IOVERRIDE; + + virtual std::string toString() const FL_IOVERRIDE; + + private: + FL_DISABLE_COPY(Operator) + + }; + +} +#endif /* FL_FUZZYEXPRESSION_H */ diff --git a/fuzzylite/fl/rule/Rule.h b/fuzzylite/fl/rule/Rule.h new file mode 100644 index 0000000..20d39fb --- /dev/null +++ b/fuzzylite/fl/rule/Rule.h @@ -0,0 +1,121 @@ +/* + 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. + + */ + +#ifndef FL_RULE_H +#define FL_RULE_H + +#include "fl/fuzzylite.h" + +#include <map> +#include <string> + + +namespace fl { + class Engine; + class Antecedent; + class Consequent; + class Hedge; + class TNorm; + class SNorm; + + class FL_API Rule { + protected: + std::string _text; + scalar _weight; + FL_unique_ptr<Antecedent> _antecedent; + FL_unique_ptr<Consequent> _consequent; + std::map<std::string, Hedge*> _hedges; + + public: + explicit Rule(const std::string& text = "", scalar weight = 1.0); + Rule(const Rule& other); + Rule& operator=(const Rule& other); + virtual ~Rule(); + FL_DEFAULT_MOVE(Rule) + + virtual void setText(const std::string& text); + virtual std::string getText() const; + + virtual void setWeight(scalar weight); + virtual scalar getWeight() const; + + virtual void setAntecedent(Antecedent* antecedent); + virtual Antecedent* getAntecedent() const; + + virtual void setConsequent(Consequent* consequent); + virtual Consequent* getConsequent() const; + + virtual void addHedge(Hedge* hedge); + virtual Hedge* getHedge(const std::string& name) const; + virtual Hedge* removeHedge(const std::string& hedge); + virtual bool hasHedge(const std::string& name) const; + virtual int numberOfHedges() const; + virtual void setHedges(const std::map<std::string, Hedge*>& hedges); + virtual const std::map<std::string, Hedge*>& hedges() const; + virtual std::map<std::string, Hedge*>& hedges(); + + virtual scalar activationDegree(const TNorm* conjunction, const SNorm* disjunction) const; + virtual void activate(scalar degree, const TNorm* activation) const; + + virtual std::string toString() const; + + virtual bool isLoaded() const; + virtual void unload(); + virtual void load(const Engine* engine); + virtual void load(const std::string& rule, const Engine* engine); + + virtual Rule* clone() const; + + static Rule* parse(const std::string& rule, const Engine* engine); + + static std::string ifKeyword() { + return "if"; + } + + static std::string isKeyword() { + return "is"; + } + + static std::string thenKeyword() { + return "then"; + } + + static std::string andKeyword() { + return "and"; + } + + static std::string orKeyword() { + return "or"; + } + + static std::string withKeyword() { + return "with"; + } + + }; + +} + + +#endif /* FL_RULE_H */ diff --git a/fuzzylite/fl/rule/RuleBlock.h b/fuzzylite/fl/rule/RuleBlock.h new file mode 100644 index 0000000..35fe62e --- /dev/null +++ b/fuzzylite/fl/rule/RuleBlock.h @@ -0,0 +1,97 @@ +/* + 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. + + */ + +#ifndef FL_RULEBLOCK_H +#define FL_RULEBLOCK_H + +#include "fl/fuzzylite.h" + +#include <string> +#include <vector> + + +namespace fl { + + class Engine; + class Rule; + class TNorm; + class SNorm; + + class FL_API RuleBlock { + private: + void copyFrom(const RuleBlock& source); + protected: + std::string _name; + std::vector<Rule*> _rules; + FL_unique_ptr<TNorm> _conjunction; + FL_unique_ptr<SNorm> _disjunction; + FL_unique_ptr<TNorm> _activation; + bool _enabled; + + public: + explicit RuleBlock(const std::string& name = ""); + RuleBlock(const RuleBlock& other); + RuleBlock& operator=(const RuleBlock& other); + virtual ~RuleBlock(); + FL_DEFAULT_MOVE(RuleBlock) + + virtual void activate(); + + virtual void setName(std::string name); + virtual std::string getName() const; + + virtual void setConjunction(TNorm* conjunction); + virtual TNorm* getConjunction() const; + + virtual void setDisjunction(SNorm* disjunction); + virtual SNorm* getDisjunction() const; + + virtual void setActivation(TNorm* activation); + virtual TNorm* getActivation() const; + + virtual void setEnabled(bool enabled); + virtual bool isEnabled() const; + + virtual void unloadRules() const; + virtual void loadRules(const Engine* engine); + virtual void reloadRules(const Engine* engine); + + virtual std::string toString() const; + + /** + * Operations for iterable datatype _rules + */ + virtual void addRule(Rule* rule); + virtual void insertRule(Rule* rule, int index); + virtual Rule* getRule(int index) const; + virtual Rule* removeRule(int index); + virtual int numberOfRules() const; + virtual void setRules(const std::vector<Rule*>& rules); + virtual const std::vector<Rule*>& rules() const; + virtual std::vector<Rule*>& rules(); + + }; + +} +#endif /* RULEBLOCK_H */ diff --git a/fuzzylite/fl/term/Accumulated.h b/fuzzylite/fl/term/Accumulated.h new file mode 100644 index 0000000..51625d0 --- /dev/null +++ b/fuzzylite/fl/term/Accumulated.h @@ -0,0 +1,94 @@ +/* + 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. + + */ + +#ifndef FL_ACCUMULATED_H +#define FL_ACCUMULATED_H + +#include "fl/term/Term.h" + +#include <vector> + +namespace fl { + + class Activated; + class SNorm; + class TNorm; + + class FL_API Accumulated : public Term { + private: + void copyFrom(const Accumulated& source); + protected: + std::vector<Activated*> _terms; + scalar _minimum, _maximum; + FL_unique_ptr<SNorm> _accumulation; + public: + explicit Accumulated(const std::string& name = "", + scalar minimum = fl::nan, + scalar maximum = fl::nan, + SNorm* accumulation = fl::null); + Accumulated(const Accumulated& other); + Accumulated& operator=(const Accumulated& other); + virtual ~Accumulated() FL_IOVERRIDE; + FL_DEFAULT_MOVE(Accumulated) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual Accumulated* clone() const FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + virtual scalar activationDegree(const Term* forTerm) const; + + virtual std::string toString() const FL_IOVERRIDE; + + + virtual void setMinimum(scalar minimum); + virtual scalar getMinimum() const; + + virtual void setMaximum(scalar maximum); + virtual scalar getMaximum() const; + + virtual void setRange(scalar minimum, scalar maximum); + virtual scalar range() const; + + virtual void setAccumulation(SNorm* accumulation); + virtual SNorm* getAccumulation() const; + + /** + * Operations for std::vector _terms + */ + virtual void addTerm(const Term* term, scalar degree, const TNorm* activation); + virtual void addTerm(Activated* term); + virtual Activated* getTerm(int index) const; + virtual Activated* removeTerm(int index); + virtual int numberOfTerms() const; + virtual const std::vector<Activated*>& terms() const; + virtual std::vector<Activated*>& terms(); + virtual bool isEmpty() const; + virtual void clear(); + }; + +} +#endif /* FL_ACCUMULATED_H */ diff --git a/fuzzylite/fl/term/Activated.h b/fuzzylite/fl/term/Activated.h new file mode 100644 index 0000000..10c1b40 --- /dev/null +++ b/fuzzylite/fl/term/Activated.h @@ -0,0 +1,65 @@ +/* + 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. + + */ + +#ifndef FL_ACTIVATED_H +#define FL_ACTIVATED_H + +#include "fl/term/Term.h" + +namespace fl { + class TNorm; + + class FL_API Activated : public Term { + protected: + const Term* _term; + scalar _degree; + const TNorm* _activation; + + public: + explicit Activated(const Term* term = fl::null, scalar degree = 1.0, + const TNorm* activationOperator = fl::null); + virtual ~Activated() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Activated) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + virtual std::string toString() const FL_IOVERRIDE; + + virtual void setTerm(const Term* term); + virtual const Term* getTerm() const; + + virtual void setDegree(scalar degree); + virtual scalar getDegree() const; + + virtual void setActivation(const TNorm* activation); + virtual const TNorm* getActivation() const; + + virtual Activated* clone() const FL_IOVERRIDE; + }; + +} +#endif /* FL_ACTIVATED_H */ diff --git a/fuzzylite/fl/term/Bell.h b/fuzzylite/fl/term/Bell.h new file mode 100644 index 0000000..115479c --- /dev/null +++ b/fuzzylite/fl/term/Bell.h @@ -0,0 +1,68 @@ +/* + 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. + + */ + +#ifndef FL_BELL_H +#define FL_BELL_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API Bell : public Term { + protected: + scalar _center; + scalar _width; + scalar _slope; + public: + explicit Bell(const std::string& name = "", + scalar center = fl::nan, + scalar width = fl::nan, + scalar slope = fl::nan, + scalar height = 1.0); + virtual ~Bell() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Bell) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setCenter(scalar center); + virtual scalar getCenter() const; + + virtual void setWidth(scalar width); + virtual scalar getWidth() const; + + virtual void setSlope(scalar slope); + virtual scalar getSlope() const; + + virtual Bell* clone() const FL_IOVERRIDE; + + static Term* constructor(); + + }; + +} +#endif /* FL_BELL_H */ diff --git a/fuzzylite/fl/term/Concave.h b/fuzzylite/fl/term/Concave.h new file mode 100644 index 0000000..b3aabe6 --- /dev/null +++ b/fuzzylite/fl/term/Concave.h @@ -0,0 +1,64 @@ +/* + 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. + + */ + +#ifndef FL_CONCAVE_H +#define FL_CONCAVE_H + +#include "fl/term/Term.h" + + +namespace fl { + + class FL_API Concave : public Term { + protected: + scalar _inflection, _end; + public: + explicit Concave(const std::string& name = "", + scalar inflection = fl::nan, + scalar end = fl::nan, + scalar height = 1.0); + virtual ~Concave() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Concave) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setInflection(scalar inflection); + virtual scalar getInflection() const; + + virtual void setEnd(scalar end); + virtual scalar getEnd() const; + + virtual Concave* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; +} + + +#endif /* FL_CONCAVE_H */ + diff --git a/fuzzylite/fl/term/Constant.h b/fuzzylite/fl/term/Constant.h new file mode 100644 index 0000000..c4ed17d --- /dev/null +++ b/fuzzylite/fl/term/Constant.h @@ -0,0 +1,58 @@ +/* + 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. + + */ + +#ifndef FL_CONSTANT_H +#define FL_CONSTANT_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API Constant : public Term { + protected: + scalar _value; + + public: + explicit Constant(const std::string& name = "", + scalar value = fl::nan); + virtual ~Constant() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Constant) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setValue(scalar value); + virtual scalar getValue() const; + + virtual Constant* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; +} + +#endif /* FL_CONSTANT_H */ + diff --git a/fuzzylite/fl/term/Cosine.h b/fuzzylite/fl/term/Cosine.h new file mode 100644 index 0000000..510669f --- /dev/null +++ b/fuzzylite/fl/term/Cosine.h @@ -0,0 +1,62 @@ +/* + 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. + + */ + +#ifndef FL_COSINE_H +#define FL_COSINE_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API Cosine : public Term { + protected: + scalar _center, _width; + public: + explicit Cosine(const std::string& name = "", + scalar center = fl::nan, + scalar width = fl::nan, + scalar height = 1.0); + virtual ~Cosine() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Cosine) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setCenter(scalar center); + virtual scalar getCenter() const; + + virtual void setWidth(scalar width); + virtual scalar getWidth() const; + + virtual Cosine* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; +} + +#endif /* FL_COSINE_H */ + diff --git a/fuzzylite/fl/term/Discrete.h b/fuzzylite/fl/term/Discrete.h new file mode 100644 index 0000000..fc554b3 --- /dev/null +++ b/fuzzylite/fl/term/Discrete.h @@ -0,0 +1,81 @@ +/* + 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. + + */ + +#ifndef FL_DISCRETE_H +#define FL_DISCRETE_H + +#include "fl/term/Term.h" + +#include <vector> +#include <utility> + +namespace fl { + + class FL_API Discrete : public Term { + public: + typedef std::pair<scalar, scalar> Pair; + protected: + std::vector<Pair> _xy; + public: + explicit Discrete(const std::string& name = "", + const std::vector<Pair>& xy = std::vector<Pair>(), + scalar height = 1.0); + virtual ~Discrete() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Discrete) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + //Warning: this method is unsafe. Make sure you use it correctly. + template <typename T> + static Discrete* create(const std::string& name, int argc, + T x1, T y1, ...); // throw (fl::Exception); + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setXY(const std::vector<Pair>& pairs); + virtual const std::vector<Pair>& xy() const; + virtual std::vector<Pair>& xy(); + virtual const Pair& xy(int index) const; + virtual Pair& xy(int index); + + + static std::vector<scalar> toVector(const std::vector<Pair>& xy); + static std::vector<Pair> toPairs(const std::vector<scalar>& xy); + static std::vector<Pair> toPairs(const std::vector<scalar>& xy, + scalar missingValue) FL_INOEXCEPT; + + static std::string formatXY(const std::vector<Pair>& xy, + const std::string& prefix = "(", const std::string& innerSeparator = ",", + const std::string& postfix = ")", const std::string& outerSeparator = " "); + + virtual Discrete* clone() const FL_IOVERRIDE; + + static Term* constructor(); + + }; + +} +#endif /* FL_DISCRETE_H */ diff --git a/fuzzylite/fl/term/Function.h b/fuzzylite/fl/term/Function.h new file mode 100644 index 0000000..99580b7 --- /dev/null +++ b/fuzzylite/fl/term/Function.h @@ -0,0 +1,171 @@ +/* + 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. + + */ + +#ifndef FL_FUNCTION_H +#define FL_FUNCTION_H + +#include "fl/term/Term.h" + +#include <map> +#include <string> + +namespace fl { + + class Engine; + + class FL_API Function : public Term { + /**************************** + * Parsing Elements + ****************************/ + + public: + typedef scalar(*Unary)(scalar); + typedef scalar(*Binary)(scalar, scalar); + + struct FL_API Element { + + enum Type { + OPERATOR, FUNCTION + }; + std::string name; + std::string description; + Type type; + Unary unary; + Binary binary; + int arity; + int precedence; //Operator + int associativity; + Element(const std::string& name, const std::string& description, Type type); + Element(const std::string& name, const std::string& description, + Type type, Unary unary, int precedence = 0, int associativity = -1); + Element(const std::string& name, const std::string& description, + Type type, Binary binary, int precedence = 0, int associativity = -1); + virtual ~Element(); + FL_DEFAULT_COPY_AND_MOVE(Element) + + virtual bool isOperator() const; + virtual bool isFunction() const; + + virtual Element* clone() const; + + virtual std::string toString() const; + + }; + + /************************** + * Tree elements, wrap Elements into Nodes. + **************************/ + + struct FL_API Node { + FL_unique_ptr<Element> element; + FL_unique_ptr<Node> left; + FL_unique_ptr<Node> right; + std::string variable; + scalar value; + + explicit Node(Element* element, Node* left = fl::null, Node* right = fl::null); + explicit Node(const std::string& variable); + explicit Node(scalar value); + Node(const Node& source); + Node& operator=(const Node& rhs); + virtual ~Node(); + FL_DEFAULT_MOVE(Node) + + virtual scalar evaluate(const std::map<std::string, scalar>* + variables = fl::null) const; + + virtual Node* clone() const; + + virtual std::string toString() const; + virtual std::string toPrefix(const Node* node = fl::null) const; + virtual std::string toInfix(const Node* node = fl::null) const; + virtual std::string toPostfix(const Node* node = fl::null) const; + private: + void copyFrom(const Node& source); + }; + + + + + /****************************** + * Term + ******************************/ + + protected: + FL_unique_ptr<Node> _root; + std::string _formula; + const Engine* _engine; + public: + mutable std::map<std::string, scalar> variables; + explicit Function(const std::string& name = "", + const std::string& formula = "", const Engine* engine = fl::null); + Function(const Function& other); + Function& operator=(const Function& other); + virtual ~Function() FL_IOVERRIDE; + FL_DEFAULT_MOVE(Function) + + static Function* create(const std::string& name, + const std::string& formula, + const Engine* engine = fl::null); // throw (fl::Exception); + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual scalar evaluate(const std::map<std::string, scalar>* variables) const; + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual void setFormula(const std::string& formula); + virtual std::string getFormula() const; + + virtual void setEngine(const Engine* engine); + virtual const Engine* getEngine() const; + + virtual Node* root() const; + + virtual bool isLoaded() const; + 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); + + virtual std::string space(const std::string& formula) const; + + virtual Function* clone() const FL_IOVERRIDE; + + static Term* constructor(); + + static void main(); + + }; + +} + +#endif /* FL_FUNCTION_H */ + diff --git a/fuzzylite/fl/term/Gaussian.h b/fuzzylite/fl/term/Gaussian.h new file mode 100644 index 0000000..a5b8055 --- /dev/null +++ b/fuzzylite/fl/term/Gaussian.h @@ -0,0 +1,63 @@ +/* + 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. + + */ + +#ifndef FL_GAUSSIAN_H +#define FL_GAUSSIAN_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API Gaussian : public Term { + protected: + scalar _mean; + scalar _standardDeviation; + + public: + explicit Gaussian(const std::string& name = "", + scalar mean = fl::nan, + scalar standardDeviation = fl::nan, + scalar height = 1.0); + virtual ~Gaussian() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Gaussian) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setMean(scalar c); + virtual scalar getMean() const; + + virtual void setStandardDeviation(scalar sigma); + virtual scalar getStandardDeviation() const; + + virtual Gaussian* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; + +} +#endif /* FL_GAUSSIAN_H */ diff --git a/fuzzylite/fl/term/GaussianProduct.h b/fuzzylite/fl/term/GaussianProduct.h new file mode 100644 index 0000000..bd1eaaa --- /dev/null +++ b/fuzzylite/fl/term/GaussianProduct.h @@ -0,0 +1,73 @@ +/* + 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. + + */ + +#ifndef FL_GAUSSIANPRODUCT_H +#define FL_GAUSSIANPRODUCT_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API GaussianProduct : public Term { + protected: + scalar _meanA; + scalar _standardDeviationA; + scalar _meanB; + scalar _standardDeviationB; + + public: + explicit GaussianProduct(const std::string& name = "", + scalar meanA = fl::nan, + scalar standardDeviationA = fl::nan, + scalar meanB = fl::nan, + scalar standardDeviationB = fl::nan, + scalar height = 1.0); + virtual ~GaussianProduct() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(GaussianProduct) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setMeanA(scalar meanA); + virtual scalar getMeanA() const; + + virtual void setStandardDeviationA(scalar sigmaA); + virtual scalar getStandardDeviationA() const; + + virtual void setMeanB(scalar meanB); + virtual scalar getMeanB() const; + + virtual void setStandardDeviationB(scalar sigmaB); + virtual scalar getStandardDeviationB() const; + + virtual GaussianProduct* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; +} +#endif /* FL_GAUSSIANPRODUCT_H */ + diff --git a/fuzzylite/fl/term/Linear.h b/fuzzylite/fl/term/Linear.h new file mode 100644 index 0000000..67ede04 --- /dev/null +++ b/fuzzylite/fl/term/Linear.h @@ -0,0 +1,72 @@ +/* + 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. + + */ + +#ifndef FL_LINEAR_H +#define FL_LINEAR_H + +#include "fl/term/Term.h" + +namespace fl { + class Engine; + + class FL_API Linear : public Term { + protected: + std::vector<scalar> _coefficients; + const Engine* _engine; + public: + explicit Linear(const std::string& name = "", + const std::vector<scalar>& coefficients = std::vector<scalar>(), + const Engine* engine = fl::null); + virtual ~Linear() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Linear) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void set(const std::vector<scalar>& coeffs, const Engine* engine); + + virtual void setCoefficients(const std::vector<scalar>& coeffs); + virtual const std::vector<scalar>& coefficients() const; + virtual std::vector<scalar>& coefficients(); + + virtual void setEngine(const Engine* engine); + virtual const Engine* getEngine() const; + + virtual Linear* clone() const FL_IOVERRIDE; + + static Term* constructor(); + + //Warning: this method is unsafe, make sure you use it correctly. + template <typename T> + static Linear* create(const std::string& name, const Engine* engine, + T firstCoefficient, ...); // throw (fl::Exception); + }; + +} + +#endif /* FL_LINEAR_H */ + diff --git a/fuzzylite/fl/term/PiShape.h b/fuzzylite/fl/term/PiShape.h new file mode 100644 index 0000000..a0c2f78 --- /dev/null +++ b/fuzzylite/fl/term/PiShape.h @@ -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. + + */ + +#ifndef FL_PISHAPE_H +#define FL_PISHAPE_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API PiShape : public Term { + protected: + scalar _bottomLeft; + scalar _topLeft; + scalar _topRight; + scalar _bottomRight; + + public: + explicit PiShape(const std::string& name = "", + scalar bottomLeft = fl::nan, + scalar topLeft = fl::nan, + scalar topRight = fl::nan, + scalar bottomRight = fl::nan, + scalar height = 1.0); + virtual ~PiShape() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(PiShape) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setBottomLeft(scalar a); + virtual scalar getBottomLeft() const; + + virtual void setTopLeft(scalar b); + virtual scalar getTopLeft() const; + + virtual void setTopRight(scalar d); + virtual scalar getTopRight() const; + + virtual void setBottomRight(scalar c); + virtual scalar getBottomRight() const; + + virtual PiShape* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; +} + +#endif /* FL_PISHAPE_H */ + diff --git a/fuzzylite/fl/term/Ramp.h b/fuzzylite/fl/term/Ramp.h new file mode 100644 index 0000000..63a683c --- /dev/null +++ b/fuzzylite/fl/term/Ramp.h @@ -0,0 +1,68 @@ +/* + 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. + + */ + +#ifndef FL_RAMP_H +#define FL_RAMP_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API Ramp : public Term { + protected: + scalar _start, _end; + + public: + + enum Direction { + POSITIVE, ZERO, NEGATIVE + }; + explicit Ramp(const std::string& name = "", + scalar start = fl::nan, + scalar end = fl::nan, + scalar height = 1.0); + virtual ~Ramp() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Ramp) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setStart(scalar start); + virtual scalar getStart() const; + + virtual void setEnd(scalar end); + virtual scalar getEnd() const; + + virtual Direction direction() const; + + virtual Ramp* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; +} +#endif /* FL_RAMP_H */ + diff --git a/fuzzylite/fl/term/Rectangle.h b/fuzzylite/fl/term/Rectangle.h new file mode 100644 index 0000000..23b5eda --- /dev/null +++ b/fuzzylite/fl/term/Rectangle.h @@ -0,0 +1,62 @@ +/* + 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. + + */ + +#ifndef FL_RECTANGLE_H +#define FL_RECTANGLE_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API Rectangle : public Term { + protected: + scalar _start, _end; + + public: + explicit Rectangle(const std::string& name = "", + scalar start = fl::nan, + scalar end = fl::nan, + scalar height = 1.0); + virtual ~Rectangle() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Rectangle) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setStart(scalar start); + virtual scalar getStart() const; + + virtual void setEnd(scalar end); + virtual scalar getEnd() const; + + virtual Rectangle* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; + +} +#endif /* FL_RECTANGLE_H */ diff --git a/fuzzylite/fl/term/SShape.h b/fuzzylite/fl/term/SShape.h new file mode 100644 index 0000000..0891357 --- /dev/null +++ b/fuzzylite/fl/term/SShape.h @@ -0,0 +1,64 @@ +/* + 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. + + */ + + +#ifndef FL_SSHAPE_H +#define FL_SSHAPE_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API SShape : public Term { + protected: + scalar _start, _end; + + public: + explicit SShape(const std::string& name = "", + scalar start = fl::nan, + scalar end = fl::nan, + scalar height = 1.0); + virtual ~SShape() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(SShape) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setStart(scalar start); + virtual scalar getStart() const; + + virtual void setEnd(scalar end); + virtual scalar getEnd() const; + + virtual SShape* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; +} + +#endif /* FL_SSHAPE_H */ + diff --git a/fuzzylite/fl/term/Sigmoid.h b/fuzzylite/fl/term/Sigmoid.h new file mode 100644 index 0000000..b37b1be --- /dev/null +++ b/fuzzylite/fl/term/Sigmoid.h @@ -0,0 +1,68 @@ +/* + 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. + + */ + +#ifndef FL_SIGMOID_H +#define FL_SIGMOID_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API Sigmoid : public Term { + protected: + scalar _inflection; + scalar _slope; + public: + + enum Direction { + POSITIVE, ZERO, NEGATIVE + }; + explicit Sigmoid(const std::string& name = "", + scalar inflection = fl::nan, + scalar slope = fl::nan, + scalar height = 1.0); + virtual ~Sigmoid() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Sigmoid) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setInflection(scalar inflection); + virtual scalar getInflection() const; + + virtual void setSlope(scalar slope); + virtual scalar getSlope() const; + + virtual Direction direction() const; + + virtual Sigmoid* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; + +} +#endif /* FL_SIGMOID_H */ diff --git a/fuzzylite/fl/term/SigmoidDifference.h b/fuzzylite/fl/term/SigmoidDifference.h new file mode 100644 index 0000000..020f164 --- /dev/null +++ b/fuzzylite/fl/term/SigmoidDifference.h @@ -0,0 +1,73 @@ +/* + 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. + + */ + +#ifndef FL_SIGMOIDDIFFERENCE_H +#define FL_SIGMOIDDIFFERENCE_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API SigmoidDifference : public Term { + protected: + scalar _left; + scalar _rising; + scalar _falling; + scalar _right; + + public: + explicit SigmoidDifference(const std::string& name = "", + scalar left = fl::nan, + scalar rising = fl::nan, + scalar falling = fl::nan, + scalar right = fl::nan, + scalar height = 1.0); + virtual ~SigmoidDifference() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(SigmoidDifference) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setLeft(scalar leftInflection); + virtual scalar getLeft() const; + + virtual void setRising(scalar risingSlope); + virtual scalar getRising() const; + + virtual void setFalling(scalar fallingSlope); + virtual scalar getFalling() const; + + virtual void setRight(scalar rightInflection); + virtual scalar getRight() const; + + virtual SigmoidDifference* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; +} +#endif /* FL_SIGMOIDDIFFERENCE_H */ + diff --git a/fuzzylite/fl/term/SigmoidProduct.h b/fuzzylite/fl/term/SigmoidProduct.h new file mode 100644 index 0000000..cb83f30 --- /dev/null +++ b/fuzzylite/fl/term/SigmoidProduct.h @@ -0,0 +1,73 @@ +/* + 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. + + */ + +#ifndef FL_SIGMOIDPRODUCT_H +#define FL_SIGMOIDPRODUCT_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API SigmoidProduct : public Term { + protected: + scalar _left; + scalar _rising; + scalar _falling; + scalar _right; + + public: + explicit SigmoidProduct(const std::string& name = "", + scalar left = fl::nan, + scalar rising = fl::nan, + scalar falling = fl::nan, + scalar right = fl::nan, + scalar height = 1.0); + virtual ~SigmoidProduct() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(SigmoidProduct) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setLeft(scalar leftInflection); + virtual scalar getLeft() const; + + virtual void setRising(scalar risingSlope); + virtual scalar getRising() const; + + virtual void setFalling(scalar fallingSlope); + virtual scalar getFalling() const; + + virtual void setRight(scalar rightInflection); + virtual scalar getRight() const; + + virtual SigmoidProduct* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; +} +#endif /* FL_SIGMOIDPRODUCT_H */ + diff --git a/fuzzylite/fl/term/Spike.h b/fuzzylite/fl/term/Spike.h new file mode 100644 index 0000000..7e520c9 --- /dev/null +++ b/fuzzylite/fl/term/Spike.h @@ -0,0 +1,62 @@ +/* + 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. + + */ + +#ifndef FL_SPIKE_H +#define FL_SPIKE_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API Spike : public Term { + protected: + scalar _center, _width; + public: + explicit Spike(const std::string& name = "", + scalar center = fl::nan, + scalar width = fl::nan, + scalar height = 1.0); + virtual ~Spike() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Spike) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setCenter(scalar center); + virtual scalar getCenter() const; + + virtual void setWidth(scalar width); + virtual scalar getWidth() const; + + virtual Spike* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; +} + +#endif /* FL_SPIKE_H */ + diff --git a/fuzzylite/fl/term/Term.h b/fuzzylite/fl/term/Term.h new file mode 100644 index 0000000..6c2b2b1 --- /dev/null +++ b/fuzzylite/fl/term/Term.h @@ -0,0 +1,71 @@ +/* + 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. + + */ + + +#ifndef FL_TERM_H +#define FL_TERM_H + +#include "fl/fuzzylite.h" + +#include "fl/Operation.h" + +#include <cmath> +#include <string> +#include <vector> + +namespace fl { + class Engine; + + class FL_API Term { + protected: + std::string _name; + scalar _height; + public: + + explicit Term(const std::string& name = "", scalar height = 1.0); + virtual ~Term(); + FL_DEFAULT_COPY_AND_MOVE(Term) + + virtual void setName(const std::string& name); + virtual std::string getName() const; + + virtual void setHeight(scalar height); + virtual scalar getHeight() const; + + virtual std::string toString() const; + + virtual std::string className() const = 0; + virtual std::string parameters() const = 0; + virtual void configure(const std::string& parameters) = 0; + + virtual scalar membership(scalar x) const = 0; + + virtual Term* clone() const = 0; + + //FIXME: This should not be static, and may not be here either. + static void updateReference(Term* term, const Engine* engine); + }; + +} +#endif /* FL_TERM_H */ diff --git a/fuzzylite/fl/term/Trapezoid.h b/fuzzylite/fl/term/Trapezoid.h new file mode 100644 index 0000000..f896997 --- /dev/null +++ b/fuzzylite/fl/term/Trapezoid.h @@ -0,0 +1,69 @@ +/* + 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. + + */ + +#ifndef FL_TRAPEZOID_H +#define FL_TRAPEZOID_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API Trapezoid : public Term { + protected: + scalar _vertexA, _vertexB, _vertexC, _vertexD; + public: + explicit Trapezoid(const std::string& name = "", + scalar vertexA = fl::nan, + scalar vertexB = fl::nan, + scalar vertexC = fl::nan, + scalar vertexD = fl::nan, + scalar height = 1.0); + virtual ~Trapezoid() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Trapezoid) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setVertexA(scalar a); + virtual scalar getVertexA() const; + + virtual void setVertexB(scalar b); + virtual scalar getVertexB() const; + + virtual void setVertexC(scalar c); + virtual scalar getVertexC() const; + + virtual void setVertexD(scalar d); + virtual scalar getVertexD() const; + + virtual Trapezoid* clone() const FL_IOVERRIDE; + + static Term* constructor(); + }; + +} +#endif /* FL_TRAPEZOID_H */ diff --git a/fuzzylite/fl/term/Triangle.h b/fuzzylite/fl/term/Triangle.h new file mode 100644 index 0000000..9311687 --- /dev/null +++ b/fuzzylite/fl/term/Triangle.h @@ -0,0 +1,68 @@ +/* + 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. + + */ + +#ifndef FL_TRIANGLE_H +#define FL_TRIANGLE_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API Triangle : public Term { + protected: + scalar _vertexA; + scalar _vertexB; + scalar _vertexC; + public: + explicit Triangle(const std::string& name = "", + scalar vertexA = fl::nan, + scalar vertexB = fl::nan, + scalar vertexC = fl::nan, + scalar height = 1.0); + virtual ~Triangle() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(Triangle) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setVertexA(scalar a); + virtual scalar getVertexA() const; + + virtual void setVertexB(scalar b); + virtual scalar getVertexB() const; + + virtual void setVertexC(scalar c); + virtual scalar getVertexC() const; + + virtual Triangle* clone() const FL_IOVERRIDE; + + static Term* constructor(); + + }; + +} +#endif /* FL_TRIANGLE_H */ diff --git a/fuzzylite/fl/term/ZShape.h b/fuzzylite/fl/term/ZShape.h new file mode 100644 index 0000000..b53906e --- /dev/null +++ b/fuzzylite/fl/term/ZShape.h @@ -0,0 +1,63 @@ +/* + 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. + + */ + +#ifndef FL_ZSHAPE_H +#define FL_ZSHAPE_H + +#include "fl/term/Term.h" + +namespace fl { + + class FL_API ZShape : public Term { + protected: + scalar _start, _end; + + public: + explicit ZShape(const std::string& name = "", + scalar _start = fl::nan, + scalar _end = fl::nan, + scalar _height = 1.0); + virtual ~ZShape() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(ZShape) + + virtual std::string className() const FL_IOVERRIDE; + virtual std::string parameters() const FL_IOVERRIDE; + virtual void configure(const std::string& parameters) FL_IOVERRIDE; + + virtual scalar membership(scalar x) const FL_IOVERRIDE; + + virtual void setStart(scalar start); + virtual scalar getStart() const; + + virtual void setEnd(scalar end); + virtual scalar getEnd() const; + + virtual ZShape* clone() const FL_IOVERRIDE; + + static Term* constructor(); + + }; +} +#endif /* ZSHAPE_H */ + diff --git a/fuzzylite/fl/variable/InputVariable.h b/fuzzylite/fl/variable/InputVariable.h new file mode 100644 index 0000000..bba3c7d --- /dev/null +++ b/fuzzylite/fl/variable/InputVariable.h @@ -0,0 +1,52 @@ +/* + 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. + + */ + +#ifndef FL_INPUTVARIABLE_H +#define FL_INPUTVARIABLE_H + +#include "fl/variable/Variable.h" + +namespace fl { + + class FL_API InputVariable : public Variable { + protected: + scalar _inputValue; + public: + explicit InputVariable(const std::string& name = "", + scalar minimum = -fl::inf, + scalar maximum = fl::inf); + virtual ~InputVariable() FL_IOVERRIDE; + FL_DEFAULT_COPY_AND_MOVE(InputVariable) + + virtual void setInputValue(scalar inputValue); + virtual scalar getInputValue() const; + + virtual std::string fuzzyInputValue() const; + + virtual std::string toString() const FL_IOVERRIDE; + + }; + +} +#endif /* FL_INPUTVARIABLE_H */ diff --git a/fuzzylite/fl/variable/OutputVariable.h b/fuzzylite/fl/variable/OutputVariable.h new file mode 100644 index 0000000..9d00aaf --- /dev/null +++ b/fuzzylite/fl/variable/OutputVariable.h @@ -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. + + */ + +#ifndef FL_OUTPUTVARIABLE_H +#define FL_OUTPUTVARIABLE_H + +#include "fl/variable/Variable.h" + +namespace fl { + class Accumulated; + class Defuzzifier; + + class FL_API OutputVariable : public Variable { + private: + void copyFrom(const OutputVariable& other); + protected: + FL_unique_ptr<Accumulated> _fuzzyOutput; + FL_unique_ptr<Defuzzifier> _defuzzifier; + scalar _outputValue; + scalar _previousOutputValue; + scalar _defaultValue; + bool _lockOutputValueInRange; + bool _lockPreviousOutputValue; + + public: + explicit OutputVariable(const std::string& name = "", + scalar minimum = -fl::inf, scalar maximum = fl::inf); + OutputVariable(const OutputVariable& other); + OutputVariable& operator=(const OutputVariable& other); + virtual ~OutputVariable() FL_IOVERRIDE; + FL_DEFAULT_MOVE(OutputVariable) + + virtual Accumulated* fuzzyOutput() const; + + virtual void setName(const std::string& name) FL_IOVERRIDE; + + virtual void setMinimum(scalar minimum) FL_IOVERRIDE; + virtual void setMaximum(scalar maximum) FL_IOVERRIDE; + + virtual void setDefuzzifier(Defuzzifier* defuzzifier); + virtual Defuzzifier* getDefuzzifier() const; + + virtual void setOutputValue(scalar outputValue); + virtual scalar getOutputValue() const; + + virtual void setPreviousOutputValue(scalar defuzzifiedValue); + virtual scalar getPreviousOutputValue() const; + + virtual void setDefaultValue(scalar defaultValue); + virtual scalar getDefaultValue() const; + + virtual void setLockOutputValueInRange(bool lockOutputValueInRange); + virtual bool isLockedOutputValueInRange() const; + + virtual void setLockPreviousOutputValue(bool lockPreviousOutputValue); + virtual bool isLockedPreviousOutputValue() const; + + virtual void defuzzify(); + + virtual std::string fuzzyOutputValue() const; + + virtual void clear(); + + virtual std::string toString() const FL_IOVERRIDE; + + }; + +} +#endif /* FL_OUTPUTVARIABLE_H */ diff --git a/fuzzylite/fl/variable/Variable.h b/fuzzylite/fl/variable/Variable.h new file mode 100644 index 0000000..61870af --- /dev/null +++ b/fuzzylite/fl/variable/Variable.h @@ -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. + + */ + +#ifndef FL_VARIABLE_H +#define FL_VARIABLE_H + +#include "fl/fuzzylite.h" +#include "fl/defuzzifier/Centroid.h" + +#include <string> +#include <vector> + +namespace fl { + + class Term; + + class FL_API Variable { + private: + void copyFrom(const Variable& source); + + protected: + std::string _name; + std::vector<Term*> _terms; + scalar _minimum, _maximum; + bool _enabled; + + public: + explicit Variable(const std::string& name = "", + scalar minimum = -fl::inf, + scalar maximum = fl::inf); + Variable(const Variable& other); + Variable& operator=(const Variable& other); + virtual ~Variable(); + FL_DEFAULT_MOVE(Variable) + + virtual void setName(const std::string& name); + virtual std::string getName() const; + + virtual void setRange(scalar minimum, scalar maximum); + virtual scalar range() const; + + virtual void setMinimum(scalar minimum); + virtual scalar getMinimum() const; + + virtual void setMaximum(scalar maximum); + virtual scalar getMaximum() const; + + virtual void setEnabled(bool enabled); + virtual bool isEnabled() const; + + virtual std::string fuzzify(scalar x) const; + virtual Term* highestMembership(scalar x, scalar* yhighest = fl::null) const; + + virtual std::string toString() const; + + /** + * Operations for iterable datatype _terms + */ + virtual void sort(); + virtual void addTerm(Term* term); + virtual void insertTerm(Term* term, int index); + virtual Term* getTerm(int index) const; + virtual Term* getTerm(const std::string& name) const; + virtual bool hasTerm(const std::string& name) const; + virtual Term* removeTerm(int index); + virtual int numberOfTerms() const; + virtual void setTerms(const std::vector<Term*>& terms); + virtual const std::vector<Term*>& terms() const; + virtual std::vector<Term*>& terms(); + + }; + +} + +#endif /* FL_VARIABLE_H */ diff --git a/fuzzylite/fuzzylite.1 b/fuzzylite/fuzzylite.1 new file mode 100644 index 0000000..22d08d0 --- /dev/null +++ b/fuzzylite/fuzzylite.1 @@ -0,0 +1,39 @@ +.TH fuzzylite 1 "October 26, 2014" "version 5.0" "USER COMMANDS" +.SH NAME +fuzzylite \- a fuzzy logic control library +.SH SYNOPSIS +.B fuzzylite +[\-i inputfile] [\-if format] [\-o outputfile] [\-of format] [\-example letter] [\-decimals number] [\-d datafile] [\-dmaximum number] [\-dheader boolean] [\-dinputs boolean] +.SH OPTIONS +.TP +\-i inputfile +file to import your engine from +.TP +\-if format +format of the file to import (fll | fis | fcl) +.TP +\-o outputfile +file to export your engine to +.TP +\-of format +format of the file to export (fll | fld | cpp | java | fis | fcl) +.TP +\-example letter +if not inputfile, built\-in example to use as engine: (m)amdani or (t)akagi\-sugeno +.TP +\-decimals number +number of decimals to write floating\-poing values +.TP +\-d datafile +if exporting to fld, file of input values to evaluate your engine on +.TP +\-dmaximum number +if exporting to fld without datafile, maximum number of results to export +.TP +\-dheader boolean +if true and exporting to fld, include headers +.TP +\-dinputs boolean +if true and exporting to fld, include input values +.SH AUTHOR +Juan Rada\-Vilela diff --git a/fuzzylite/fuzzylite.doxygen b/fuzzylite/fuzzylite.doxygen new file mode 100644 index 0000000..4ee925f --- /dev/null +++ b/fuzzylite/fuzzylite.doxygen @@ -0,0 +1,1781 @@ +# Doxyfile 1.7.6.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "fuzzylite" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 4.0 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "A Fuzzy Logic Control Library in C++" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = ../fuzzylite.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = docs + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.h *.cpp + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = bin/ CMakeFiles/ docs/ lib/ nbproject/ + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = com.fuzzylite + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = com.fuzzylite.documentation + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Juan Rada-Vilela + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> +# Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> +# Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = YES + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/fuzzylite/fuzzylite.pc.in b/fuzzylite/fuzzylite.pc.in new file mode 100644 index 0000000..421c61a --- /dev/null +++ b/fuzzylite/fuzzylite.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +includedir=${exec_prefix}/include +libdir=@CMAKE_INSTALL_LIBDIR@ + +Name: fuzzylite +Description: A fuzzy logic control library in C++ +Version: @FL_VERSION@ +Libs: -L${libdir} -lfuzzylite +Cflags: -I${includedir}/fl diff --git a/fuzzylite/src/Console.cpp b/fuzzylite/src/Console.cpp new file mode 100644 index 0000000..3a55fc5 --- /dev/null +++ b/fuzzylite/src/Console.cpp @@ -0,0 +1,820 @@ +/* + 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/Console.h" + +#include "fl/Headers.h" + +#include <algorithm> +#include <cctype> +#include <fstream> +#include <stdlib.h> +#include <utility> +#include <vector> + +#ifdef FL_UNIX +#include <termios.h> +#include <unistd.h> +#elif defined(FL_WINDOWS) +#include <conio.h> +#endif + +#ifdef FL_CPP11 +#include <chrono> +#endif + +namespace fl { + const std::string Console::KW_INPUT_FILE = "-i"; + const std::string Console::KW_INPUT_FORMAT = "-if"; + const std::string Console::KW_OUTPUT_FILE = "-o"; + const std::string Console::KW_OUTPUT_FORMAT = "-of"; + const std::string Console::KW_EXAMPLE = "-example"; + const std::string Console::KW_DECIMALS = "-decimals"; + const std::string Console::KW_DATA_INPUT = "-d"; + const std::string Console::KW_DATA_MAXIMUM = "-dmaximum"; + const std::string Console::KW_DATA_EXPORT_HEADER = "-dheader"; + const std::string Console::KW_DATA_EXPORT_INPUTS = "-dinputs"; + + std::vector<Console::Option> Console::availableOptions() { + std::vector<Console::Option> options; + options.push_back(Option(KW_INPUT_FILE, "inputfile", "file to import your engine from")); + options.push_back(Option(KW_INPUT_FORMAT, "format", "format of the file to import (fll | fis | fcl)")); + options.push_back(Option(KW_OUTPUT_FILE, "outputfile", "file to export your engine to")); + options.push_back(Option(KW_OUTPUT_FORMAT, "format", "format of the file to export (fll | fld | cpp | java | fis | fcl)")); + options.push_back(Option(KW_EXAMPLE, "letter", "if not inputfile, built-in example to use as engine: (m)amdani or (t)akagi-sugeno")); + options.push_back(Option(KW_DECIMALS, "number", "number of decimals to write floating-poing values")); + options.push_back(Option(KW_DATA_INPUT, "datafile", "if exporting to fld, file of input values to evaluate your engine on")); + options.push_back(Option(KW_DATA_MAXIMUM, "number", "if exporting to fld without datafile, maximum number of results to export")); + options.push_back(Option(KW_DATA_EXPORT_HEADER, "boolean", "if true and exporting to fld, include headers")); + options.push_back(Option(KW_DATA_EXPORT_INPUTS, "boolean", "if true and exporting to fld, include input values")); + return options; + } + + std::string Console::usage() { + std::vector<Console::Option> options = availableOptions(); + std::ostringstream ss; + + ss << "========================================\n"; + ss << "fuzzylite: a fuzzy logic control library\n"; + ss << "version: " << fuzzylite::longVersion() << "\n"; + ss << "author: " << fuzzylite::author() << "\n"; + ss << "license: " << fuzzylite::license() << "\n"; + ss << "========================================\n\n"; + ss << "usage: fuzzylite inputfile outputfile\n"; + ss << " or: fuzzylite "; + for (std::size_t i = 0; i < options.size(); ++i) { + ss << "[" << options.at(i).key << " " << options.at(i).value << "] "; + } + ss << "\n\nwhere:\n"; + for (std::size_t i = 0; i < options.size(); ++i) { + std::string spacedKey(12, ' '); + std::string key = options.at(i).key; + std::copy(key.begin(), key.end(), spacedKey.begin()); + + std::string spacedValue(13, ' '); + std::string value = options.at(i).value; + std::copy(value.begin(), value.end(), spacedValue.begin()); + + std::string description = options.at(i).description; + + ss << spacedKey << spacedValue << description << "\n"; + } + + ss << "\n"; + ss << "Visit " << fuzzylite::website() << " for more information.\n\n"; + ss << "Copyright (C) 2010-2015 FuzzyLite Limited.\n"; + ss << "All rights reserved."; + + return ss.str(); + } + + std::map<std::string, std::string> Console::parse(int argc, char** argv) { + if ((argc - 1) % 2 != 0) { + throw fl::Exception("[option error] incomplete number of parameters [key value]", FL_AT); + } + std::map<std::string, std::string> options; + for (int i = 1; i < argc - 1; i += 2) { + std::string key = std::string(argv[i]); + std::string value = std::string(argv[i + 1]); + options[key] = value; + } + if (options.size() == 1) { + std::map<std::string, std::string>::const_iterator it = options.begin(); + if (it->first.at(0) != '-') { + options[KW_INPUT_FILE] = it->first; + options[KW_OUTPUT_FILE] = it->second; + } + } else { + std::vector<Console::Option> validOptions = availableOptions(); + + for (std::map<std::string, std::string>::const_iterator it = options.begin(); + it != options.end(); ++it) { + bool isValid = false; + for (std::size_t i = 0; i < validOptions.size(); ++i) { + std::string key = validOptions.at(i).key; + if (key == it->first) { + isValid = true; + break; + } + } + if (not isValid) { + throw fl::Exception("[option error] option <" + it->first + "> not recognized", FL_AT); + } + } + } + return options; + } + + void Console::process(const std::map<std::string, std::string>& options) { + std::map<std::string, std::string>::const_iterator it; + + it = options.find(KW_DECIMALS); + if (it != options.end()) { + fl::fuzzylite::setDecimals((int) fl::Op::toScalar(it->second)); + } + + std::string example; + std::string inputFormat; + std::ostringstream textEngine; + + it = options.find(KW_EXAMPLE); + + bool isExample = (it != options.end()); + + if (isExample) { + example = it->second; + Engine* engine; + if (example == "m" or example == "mamdani") { + engine = mamdani(); + } else if (example == "t" or example == "ts" or example == "takagi-sugeno") { + engine = takagiSugeno(); + } else { + throw fl::Exception("[option error] example <" + example + "> not available", FL_AT); + } + inputFormat = "fll"; + textEngine << FllExporter().toString(engine); + delete engine; + + } else { + it = options.find(KW_INPUT_FILE); + if (it == options.end()) { + throw fl::Exception("[option error] no input file specified", FL_AT); + } + std::string inputFilename = it->second; + std::ifstream inputFile(inputFilename.c_str()); + if (not inputFile.is_open()) { + throw fl::Exception("[file error] file <" + inputFilename + "> could not be opened", FL_AT); + } + std::string line; + while (std::getline(inputFile, line)) { + textEngine << line << std::endl; + } + inputFile.close(); + + it = options.find(KW_INPUT_FORMAT); + if (it != options.end()) { + inputFormat = it->second; + } else { + std::size_t extensionIndex = inputFilename.find_last_of("."); + if (extensionIndex != std::string::npos) { + inputFormat = inputFilename.substr(extensionIndex + 1); + } else { + throw fl::Exception("[format error] unspecified format of input file", FL_AT); + } + } + } + + std::string outputFilename; + it = options.find(KW_OUTPUT_FILE); + if (it != options.end()) { + outputFilename = it->second; + } + + std::string outputFormat; + it = options.find(KW_OUTPUT_FORMAT); + if (it != options.end()) { + outputFormat = it->second; + } else { + std::size_t extensionIndex = outputFilename.find_last_of("."); + if (extensionIndex != std::string::npos) { + outputFormat = outputFilename.substr(extensionIndex + 1); + } else { + throw fl::Exception("[format error] unspecified format of output file", FL_AT); + } + } + + + if (outputFilename.empty()) { + process(textEngine.str(), std::cout, inputFormat, outputFormat, options); + } else { + std::ofstream writer(outputFilename.c_str()); + if (not writer.is_open()) { + throw fl::Exception("[file error] file <" + outputFilename + "> could not be created", FL_AT); + } + process(textEngine.str(), writer, inputFormat, outputFormat, options); + writer.flush(); + writer.close(); + } + } + + void Console::process(const std::string& input, std::ostream& writer, + const std::string& inputFormat, const std::string& outputFormat, + const std::map<std::string, std::string>& options) { + FL_unique_ptr<Importer> importer; + FL_unique_ptr<Exporter> exporter; + FL_unique_ptr<Engine> engine; + + if ("fll" == inputFormat) { + importer.reset(new FllImporter); + } else if ("fcl" == inputFormat) { + importer.reset(new FclImporter); + } else if ("fis" == inputFormat) { + importer.reset(new FisImporter); + } else { + throw fl::Exception("[import error] format <" + inputFormat + "> " + "not supported", FL_AT); + } + + engine.reset(importer->fromString(input)); + + if ("fld" == outputFormat) { + std::map<std::string, std::string>::const_iterator it; + + FldExporter fldExporter; + fldExporter.setSeparator("\t"); + bool exportHeaders = true; + if ((it = options.find(KW_DATA_EXPORT_HEADER)) != options.end()) { + exportHeaders = ("true" == it->second); + } + fldExporter.setExportHeader(exportHeaders); + bool exportInputValues = true; + if ((it = options.find(KW_DATA_EXPORT_INPUTS)) != options.end()) { + exportInputValues = ("true" == it->second); + } + fldExporter.setExportInputValues(exportInputValues); + if ((it = options.find(KW_DATA_INPUT)) != options.end()) { + std::ifstream dataFile(it->second.c_str()); + if (not dataFile.is_open()) { + throw fl::Exception("[export error] file <" + it->second + "> could not be opened", FL_AT); + } + try { + fldExporter.write(engine.get(), writer, dataFile); + } catch (std::exception& ex) { + (void) ex; + dataFile.close(); + throw; + } + + } else { + if ((it = options.find(KW_DATA_MAXIMUM)) != options.end()) { + fldExporter.write(engine.get(), writer, (int) fl::Op::toScalar(it->second)); + } else { + std::ostringstream buffer; + buffer << "#FuzzyLite Interactive Console (press H for help)\n"; + buffer << fldExporter.header(engine.get()) << "\n"; + bool showCout = &writer != &std::cout; + writer << buffer.str(); + if (showCout) std::cout << buffer.str(); + else writer.flush(); + interactive(writer, engine.get()); + } + } + } else { + if ("fll" == outputFormat) { + exporter.reset(new FllExporter); + } else if ("fcl" == outputFormat) { + exporter.reset(new FclExporter); + } else if ("fis" == outputFormat) { + exporter.reset(new FisExporter); + } else if ("cpp" == outputFormat) { + exporter.reset(new CppExporter); + } else if ("java" == outputFormat) { + exporter.reset(new JavaExporter); + } else throw fl::Exception("[export error] format <" + outputFormat + "> " + "not supported", FL_AT); + writer << exporter->toString(engine.get()); + } + } + + int Console::readCharacter() { + int ch = 0; +#ifdef FL_UNIX + struct termios oldt, newt; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + ch = getchar(); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); +#elif defined(FL_WINDOWS) + ch = _getch(); +#endif + return ch; + } + + void Console::interactive(std::ostream& writer, Engine* engine) { + std::ostringstream buffer; + buffer << ">"; + bool showCout = &writer != &std::cout; + const std::string space("\t"); + std::vector<scalar> inputValues; + std::ostringstream inputValue; + int ch = 0; + do { + writer << buffer.str(); + if (showCout) std::cout << buffer.str(); + else writer.flush(); + buffer.str(""); + + ch = readCharacter(); + + if (std::isspace(ch)) { + scalar value = engine->getInputVariable(inputValues.size())->getInputValue(); + try { + value = fl::Op::toScalar(inputValue.str()); + } catch (std::exception& ex) { + (void) ex; + buffer << "[" << fl::Op::str(value) << "]"; + } + buffer << space; + inputValue.str(""); + inputValues.push_back(value); + if (inputValues.size() == engine->inputVariables().size()) { + ch = 'P'; //fall through to process; + } else continue; + } + + if (not std::isgraph(ch)) continue; + + switch (ch) { + default: + inputValue << char(ch); + buffer << char(ch); + break; + case 'r': + case 'R': engine->restart(); + buffer << "#[Restart]"; + //fall through + case 'd': + case 'D': inputValues.clear(); + buffer << "#[Discard]\n>"; + inputValue.str(""); + break; + case 'p': + case 'P': //Process + { + inputValue.str(""); + + for (std::size_t i = 0; i < inputValues.size(); ++i) { + InputVariable* inputVariable = engine->inputVariables().at(i); + inputVariable->setInputValue(inputValues.at(i)); + } + std::vector<scalar> missingInputs; + for (std::size_t i = inputValues.size(); i < engine->inputVariables().size(); ++i) { + InputVariable* inputVariable = engine->inputVariables().at(i); + missingInputs.push_back(inputVariable->getInputValue()); + } + inputValues.clear(); + buffer << fl::Op::join(missingInputs, space); + if (not missingInputs.empty()) buffer << space; + buffer << "=" << space; + try { + engine->process(); + std::vector<scalar> outputValues; + for (std::size_t i = 0; i < engine->outputVariables().size(); ++i) { + OutputVariable* outputVariable = engine->outputVariables().at(i); + outputVariable->defuzzify(); + outputValues.push_back(outputVariable->getOutputValue()); + } + buffer << fl::Op::join(outputValues, space) << "\n>"; + + } catch (std::exception& ex) { + buffer << "#[Error: " << ex.what() << "]"; + } + break; + } + case 'q': + case 'Q': buffer << "#[Quit]\n"; + break; + case 'h': + case 'H': buffer << "\n>" << interactiveHelp() << "\n>"; + inputValue.str(""); + break; + } + } while (not (ch == 'Q' or ch == 'q')); + writer << std::endl; + } + + std::string Console::interactiveHelp() { + return + "#Special Keys\n" + "#=============\n" + "#\tR\tRestart engine and discard current inputs\n" + "#\tD\tDiscard current inputs\n" + "#\tP\tProcess engine\n" + "#\tQ\tQuit interactive console\n" + "#\tH\tShow this help\n" + "#=============\n"; + } + + Engine* Console::mamdani() { + Engine* engine = new Engine("simple-dimmer"); + + InputVariable* ambient = new InputVariable("Ambient", 0, 1); + ambient->addTerm(new Triangle("DARK", .0, .25, .5)); + ambient->addTerm(new Triangle("MEDIUM", .25, .5, .75)); + ambient->addTerm(new Triangle("BRIGHT", .5, .75, 1)); + engine->addInputVariable(ambient); + + + OutputVariable* power = new OutputVariable("Power", 0, 2); + power->setDefaultValue(fl::nan); + power->addTerm(new Triangle("LOW", 0.0, 0.5, 1)); + power->addTerm(new Triangle("MEDIUM", 0.5, 1, 1.5)); + power->addTerm(new Triangle("HIGH", 1, 1.5, 2)); + 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"); + + return engine; + } + + Engine* Console::takagiSugeno() { + Engine* engine = new Engine("approximation of sin(x)/x"); + + fl::InputVariable* inputX = new fl::InputVariable("inputX"); + inputX->setRange(0, 10); + inputX->addTerm(new fl::Triangle("NEAR_1", 0, 1, 2)); + inputX->addTerm(new fl::Triangle("NEAR_2", 1, 2, 3)); + inputX->addTerm(new fl::Triangle("NEAR_3", 2, 3, 4)); + inputX->addTerm(new fl::Triangle("NEAR_4", 3, 4, 5)); + inputX->addTerm(new fl::Triangle("NEAR_5", 4, 5, 6)); + inputX->addTerm(new fl::Triangle("NEAR_6", 5, 6, 7)); + inputX->addTerm(new fl::Triangle("NEAR_7", 6, 7, 8)); + inputX->addTerm(new fl::Triangle("NEAR_8", 7, 8, 9)); + inputX->addTerm(new fl::Triangle("NEAR_9", 8, 9, 10)); + engine->addInputVariable(inputX); + + + fl::OutputVariable* outputFx = new fl::OutputVariable("outputFx"); + outputFx->setRange(-1, 1); + outputFx->setDefaultValue(fl::nan); + outputFx->setLockPreviousOutputValue(true); //To use its value with diffFx + outputFx->addTerm(new Constant("f1", 0.84)); + outputFx->addTerm(new Constant("f2", 0.45)); + outputFx->addTerm(new Constant("f3", 0.04)); + outputFx->addTerm(new Constant("f4", -0.18)); + outputFx->addTerm(new Constant("f5", -0.19)); + outputFx->addTerm(new Constant("f6", -0.04)); + outputFx->addTerm(new Constant("f7", 0.09)); + outputFx->addTerm(new Constant("f8", 0.12)); + outputFx->addTerm(new Constant("f9", 0.04)); + engine->addOutputVariable(outputFx); + + fl::OutputVariable* trueFx = new fl::OutputVariable("trueFx"); + trueFx->setRange(fl::nan, fl::nan); + trueFx->setLockPreviousOutputValue(true); //To use its value with diffFx + trueFx->addTerm(fl::Function::create("fx", "sin(inputX)/inputX", engine)); + engine->addOutputVariable(trueFx); + + fl::OutputVariable* diffFx = new fl::OutputVariable("diffFx"); + diffFx->addTerm(fl::Function::create("diff", "fabs(outputFx-trueFx)", engine)); + diffFx->setRange(fl::nan, fl::nan); + // diffFx->setLockValidOutput(true); //To use in input diffPreviousFx + engine->addOutputVariable(diffFx); + + fl::RuleBlock* block = new fl::RuleBlock(); + block->addRule(fl::Rule::parse("if inputX is NEAR_1 then outputFx is f1", engine)); + block->addRule(fl::Rule::parse("if inputX is NEAR_2 then outputFx is f2", engine)); + block->addRule(fl::Rule::parse("if inputX is NEAR_3 then outputFx is f3", engine)); + block->addRule(fl::Rule::parse("if inputX is NEAR_4 then outputFx is f4", engine)); + block->addRule(fl::Rule::parse("if inputX is NEAR_5 then outputFx is f5", engine)); + block->addRule(fl::Rule::parse("if inputX is NEAR_6 then outputFx is f6", engine)); + block->addRule(fl::Rule::parse("if inputX is NEAR_7 then outputFx is f7", engine)); + block->addRule(fl::Rule::parse("if inputX is NEAR_8 then outputFx is f8", engine)); + block->addRule(fl::Rule::parse("if inputX is NEAR_9 then outputFx is f9", engine)); + block->addRule(fl::Rule::parse("if inputX is any then trueFx is fx and diffFx is diff", engine)); + engine->addRuleBlock(block); + + engine->configure("", "", "AlgebraicProduct", "AlgebraicSum", "WeightedAverage"); + + return engine; + } + + void Console::exportAllExamples(const std::string& from, const std::string& to) { + Console::exportAllExamples(from, to, "."); + } + + void Console::exportAllExamples(const std::string& from, const std::string& to, const std::string& path) { + std::vector<std::string> examples; + examples.push_back("/mamdani/AllTerms"); + // examples.push_back("/mamdani/Laundry"); + examples.push_back("/mamdani/SimpleDimmer"); + // examples.push_back("/mamdani/SimpleDimmerInverse"); + examples.push_back("/mamdani/matlab/mam21"); + examples.push_back("/mamdani/matlab/mam22"); + examples.push_back("/mamdani/matlab/shower"); + examples.push_back("/mamdani/matlab/tank"); + examples.push_back("/mamdani/matlab/tank2"); + examples.push_back("/mamdani/matlab/tipper"); + examples.push_back("/mamdani/matlab/tipper1"); + examples.push_back("/mamdani/octave/investment_portfolio"); + examples.push_back("/mamdani/octave/mamdani_tip_calculator"); + examples.push_back("/takagi-sugeno/approximation"); + examples.push_back("/takagi-sugeno/SimpleDimmer"); + examples.push_back("/takagi-sugeno/matlab/fpeaks"); + examples.push_back("/takagi-sugeno/matlab/invkine1"); + examples.push_back("/takagi-sugeno/matlab/invkine2"); + examples.push_back("/takagi-sugeno/matlab/juggler"); + examples.push_back("/takagi-sugeno/matlab/membrn1"); + examples.push_back("/takagi-sugeno/matlab/membrn2"); + examples.push_back("/takagi-sugeno/matlab/slbb"); + examples.push_back("/takagi-sugeno/matlab/slcp"); + examples.push_back("/takagi-sugeno/matlab/slcp1"); + examples.push_back("/takagi-sugeno/matlab/slcpp1"); + examples.push_back("/takagi-sugeno/matlab/sltbu_fl"); + examples.push_back("/takagi-sugeno/matlab/sugeno1"); + examples.push_back("/takagi-sugeno/matlab/tanksg"); + examples.push_back("/takagi-sugeno/matlab/tippersg"); + examples.push_back("/takagi-sugeno/octave/cubic_approximator"); + examples.push_back("/takagi-sugeno/octave/heart_disease_risk"); + examples.push_back("/takagi-sugeno/octave/linear_tip_calculator"); + examples.push_back("/takagi-sugeno/octave/sugeno_tip_calculator"); + examples.push_back("/tsukamoto/tsukamoto"); + + std::string sourceBase = path + "/original"; + std::string targetBase = path + "/tmp/"; + + FL_unique_ptr<Importer> importer; + if (from == "fll") importer.reset(new FllImporter); + else if (from == "fis") importer.reset(new FisImporter); + else if (from == "fcl") importer.reset(new FclImporter); + else throw fl::Exception("[examples error] unrecognized format <" + from + "> to import", FL_AT); + + FL_unique_ptr<Exporter> exporter; + if (to == "fll") exporter.reset(new FllExporter); + else if (to == "fld") exporter.reset(new FldExporter(" ")); + else if (to == "fcl") exporter.reset(new FclExporter); + else if (to == "fis") exporter.reset(new FisExporter); + else if (to == "cpp") exporter.reset(new CppExporter); + else if (to == "java") exporter.reset(new JavaExporter); + else throw fl::Exception("[examples error] unrecognized format <" + to + "> to export", FL_AT); + + std::vector<std::pair<Exporter*, Importer*> > tests; + tests.push_back(std::pair<Exporter*, Importer*>(new FllExporter, new FllImporter)); + tests.push_back(std::pair<Exporter*, Importer*>(new FisExporter, new FisImporter)); + tests.push_back(std::pair<Exporter*, Importer*>(new FclExporter, new FclImporter)); + for (std::size_t i = 0; i < examples.size(); ++i) { + FL_LOG("Processing " << (i + 1) << "/" << examples.size() << ": " << examples.at(i)); + std::ostringstream ss; + std::string input = sourceBase + examples.at(i) + "." + from; + std::ifstream source(input.c_str()); + if (source.is_open()) { + std::string line; + while (source.good()) { + std::getline(source, line); + ss << line << "\n"; + } + source.close(); + } else throw fl::Exception("[examples error] file not found: " + input, FL_AT); + + FL_unique_ptr<Engine> engine(importer->fromString(ss.str())); + + for (std::size_t t = 0; t < tests.size(); ++t) { + std::string out = tests.at(t).first->toString(engine.get()); + FL_unique_ptr<Engine> copy(tests.at(t).second->fromString(out)); + std::string out_copy = tests.at(t).first->toString(copy.get()); + + if (out != out_copy) { + std::ostringstream ss; + ss << "[imex error] different results <" + << importer->name() << "," << exporter->name() << "> " + "at " + examples.at(t) + "." + from + ":\n"; + ss << "<Engine A>\n" << out << "\n\n" << + "================================\n\n" << + "<Engine B>\n" << out_copy; + throw fl::Exception(ss.str(), FL_AT); + } + } + + std::string output = targetBase + examples.at(i) + "." + to; + std::ofstream target(output.c_str()); + if (target.is_open()) { + if (to == "cpp") { + target << "#include <fl/Headers.h>\n\n" + << "int main(int argc, char** argv){\n" + << exporter->toString(engine.get()) + << "\n}\n"; + } else if (to == "java") { + std::string className = examples.at(i).substr(examples.at(i).find_last_of('/') + 1); + target << "import com.fuzzylite.*;\n" + << "import com.fuzzylite.defuzzifier.*;\n" + << "import com.fuzzylite.factory.*;\n" + << "import com.fuzzylite.hedge.*;\n" + << "import com.fuzzylite.imex.*;\n" + << "import com.fuzzylite.norm.*;\n" + << "import com.fuzzylite.norm.s.*;\n" + << "import com.fuzzylite.norm.t.*;\n" + << "import com.fuzzylite.rule.*;\n" + << "import com.fuzzylite.term.*;\n" + << "import com.fuzzylite.variable.*;\n\n" + << "public class " << Op::validName(className) << "{\n" + << "public static void main(String[] args){\n" + << exporter->toString(engine.get()) + << "\n}\n}\n"; + } else { + target << exporter->toString(engine.get()); + } + target.close(); + } + Engine copyConstructor(*engine.get()); + (void) copyConstructor; + Engine assignmentOperator = *engine.get(); + (void) assignmentOperator; + } + for (std::size_t i = 0; i < tests.size(); ++i) { + delete tests.at(i).first; + delete tests.at(i).second; + } + } + +#ifdef FL_CPP11 + + void Console::benchmarkExamples(const std::string& path, int runs) { + std::string sourceBase = path + "/original"; + typedef std::pair<std::string, int > Example; + std::vector<Example> examples; + examples.push_back(Example("/mamdani/AllTerms", 1e4)); + examples.push_back(Example("/mamdani/SimpleDimmer", 1e5)); + examples.push_back(Example("/mamdani/matlab/mam21", 128)); + examples.push_back(Example("/mamdani/matlab/mam22", 128)); + examples.push_back(Example("/mamdani/matlab/shower", 256)); + examples.push_back(Example("/mamdani/matlab/tank", 256)); + examples.push_back(Example("/mamdani/matlab/tank2", 512)); + examples.push_back(Example("/mamdani/matlab/tipper", 256)); + examples.push_back(Example("/mamdani/matlab/tipper1", 1e5)); + examples.push_back(Example("/mamdani/octave/investment_portfolio", 256)); + examples.push_back(Example("/mamdani/octave/mamdani_tip_calculator", 256)); + examples.push_back(Example("/takagi-sugeno/approximation", 1e6)); + examples.push_back(Example("/takagi-sugeno/SimpleDimmer", 2e6)); + examples.push_back(Example("/takagi-sugeno/matlab/fpeaks", 512)); + examples.push_back(Example("/takagi-sugeno/matlab/invkine1", 256)); + examples.push_back(Example("/takagi-sugeno/matlab/invkine2", 256)); + examples.push_back(Example("/takagi-sugeno/matlab/juggler", 512)); + examples.push_back(Example("/takagi-sugeno/matlab/membrn1", 1024)); + examples.push_back(Example("/takagi-sugeno/matlab/membrn2", 512)); + examples.push_back(Example("/takagi-sugeno/matlab/slbb", 20)); + examples.push_back(Example("/takagi-sugeno/matlab/slcp", 20)); + examples.push_back(Example("/takagi-sugeno/matlab/slcp1", 15)); + examples.push_back(Example("/takagi-sugeno/matlab/slcpp1", 9)); + examples.push_back(Example("/takagi-sugeno/matlab/sltbu_fl", 128)); + examples.push_back(Example("/takagi-sugeno/matlab/sugeno1", 2e6)); + examples.push_back(Example("/takagi-sugeno/matlab/tanksg", 1024)); + examples.push_back(Example("/takagi-sugeno/matlab/tippersg", 1024)); + examples.push_back(Example("/takagi-sugeno/octave/cubic_approximator", 2e6)); + examples.push_back(Example("/takagi-sugeno/octave/heart_disease_risk", 1024)); + examples.push_back(Example("/takagi-sugeno/octave/linear_tip_calculator", 1024)); + examples.push_back(Example("/takagi-sugeno/octave/sugeno_tip_calculator", 512)); + examples.push_back(Example("/tsukamoto/tsukamoto", 1e6)); + + for (std::size_t i = 0; i < examples.size(); ++i) { + FL_LOG(examples.at(i).first << "\t" << examples.at(i).second); + } + + std::vector<std::string> runNumbers(runs); + for (int i = 0; i < runs; ++i) { + runNumbers.at(i) = std::to_string(i + 1); + } + std::string spacedPath(40, ' '); + std::copy(path.begin(), path.end(), spacedPath.begin()); + FL_LOG(spacedPath << "\t" << "mean\tstdev\n" << Op::join(runNumbers, "\t")); + + FllImporter importer; + FldExporter exporter; + exporter.setExportHeader(false); + exporter.setExportInputValues(false); + exporter.setExportOutputValues(false); + std::ostream dummy(0); + + for (std::size_t e = 0; e < examples.size(); ++e) { + FL_unique_ptr<Engine> engine(importer.fromFile(sourceBase + examples.at(e).first + ".fll")); + + std::vector<scalar> seconds; + int results = std::pow(1.0 * examples.at(e).second, engine->numberOfInputVariables()); + + for (int r = 0; r < runs; ++r) { + auto start = std::chrono::system_clock::now(); + exporter.write(engine.get(), dummy, results); + auto end = std::chrono::system_clock::now(); + + auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds> (end - start); + + seconds.push_back(elapsed.count() / 1e3); + } + scalar mean = Op::mean(seconds); + scalar stdev = Op::standardDeviation(seconds, mean); + + std::string spacedExample(40, ' '); + std::string exampleName = examples.at(e).first; + std::copy(exampleName.begin(), exampleName.end(), spacedExample.begin()); + FL_LOG(spacedExample << "\t" << fl::Op::str(mean) << "\t" << fl::Op::str(stdev) << "\n" << + Op::join(seconds, "\t")); + } + } +#endif + + int Console::main(int argc, char** argv) { + (void) argc; + (void) argv; + if (argc <= 2) { + std::cout << usage() << std::endl; + return EXIT_SUCCESS; + } + + const std::string firstArgument = std::string(argv[1]); + + if (firstArgument == "export-examples") { + std::string path = "."; + if (argc > 2) { + path = std::string(argv[2]); + } + FL_LOG("Path=" << path); + try { + fuzzylite::setDecimals(3); + FL_LOG("Processing fll->fll"); + exportAllExamples("fll", "fll", path); + FL_LOG("Processing fll->fcl"); + exportAllExamples("fll", "fcl", path); + FL_LOG("Processing fll->fis"); + exportAllExamples("fll", "fis", path); + FL_LOG("Processing fll->cpp"); + exportAllExamples("fll", "cpp", path); + FL_LOG("Processing fll->java"); + exportAllExamples("fll", "java", path); + fuzzylite::setDecimals(8); + fuzzylite::setMachEps(1e-6); + FL_LOG("Processing fll->fld"); + exportAllExamples("fll", "fld", path); + } catch (std::exception& ex) { + std::cout << ex.what() << "\nBACKTRACE:\n" << + fl::Exception::btCallStack() << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } else if (firstArgument == "benchmarks") { +#ifdef FL_CPP11 + std::string path = "."; + if (argc > 2) { + path = std::string(argv[2]); + } + int runs = 10; + if (argc > 3) { + runs = (int) Op::toScalar(argv[3]); + } + fuzzylite::setDecimals(3); + Console::benchmarkExamples(path, runs); + return EXIT_SUCCESS; +#else + throw fl::Exception("[benchmarks error] implementation available only when built with C++11 (-DFL_CPP11)", FL_AT); +#endif + } + + try { + std::map<std::string, std::string> options = parse(argc, argv); + process(options); + } catch (std::exception& ex) { + std::cout << ex.what() << "\n" << std::endl; + // std::cout << fl::Exception::btCallStack() << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } +} diff --git a/fuzzylite/src/Engine.cpp b/fuzzylite/src/Engine.cpp new file mode 100644 index 0000000..f1e23c0 --- /dev/null +++ b/fuzzylite/src/Engine.cpp @@ -0,0 +1,698 @@ +/* + 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/Engine.h" + +#include "fl/defuzzifier/WeightedAverage.h" +#include "fl/defuzzifier/WeightedSum.h" +#include "fl/factory/DefuzzifierFactory.h" +#include "fl/factory/FactoryManager.h" +#include "fl/factory/SNormFactory.h" +#include "fl/factory/TNormFactory.h" +#include "fl/hedge/Hedge.h" +#include "fl/imex/FllExporter.h" +#include "fl/norm/t/AlgebraicProduct.h" +#include "fl/rule/Consequent.h" +#include "fl/rule/Expression.h" +#include "fl/rule/Rule.h" +#include "fl/rule/RuleBlock.h" +#include "fl/term/Accumulated.h" +#include "fl/term/Constant.h" +#include "fl/term/Linear.h" +#include "fl/term/Function.h" +#include "fl/term/Ramp.h" +#include "fl/term/Sigmoid.h" +#include "fl/term/SShape.h" +#include "fl/term/ZShape.h" +#include "fl/variable/InputVariable.h" +#include "fl/variable/OutputVariable.h" + + +namespace fl { + + Engine::Engine(const std::string& name) : _name(name) { + } + + Engine::Engine(const Engine& other) : _name("") { + copyFrom(other); + } + + Engine& Engine::operator=(const Engine& other) { + if (this != &other) { + for (std::size_t i = 0; i < _ruleblocks.size(); ++i) + delete _ruleblocks.at(i); + _ruleblocks.clear(); + for (std::size_t i = 0; i < _outputVariables.size(); ++i) + delete _outputVariables.at(i); + _outputVariables.clear(); + for (std::size_t i = 0; i < _inputVariables.size(); ++i) + delete _inputVariables.at(i); + _inputVariables.clear(); + + copyFrom(other); + } + return *this; + } + + void Engine::copyFrom(const Engine& other) { + _name = other._name; + for (std::size_t i = 0; i < other._inputVariables.size(); ++i) + _inputVariables.push_back(new InputVariable(*other._inputVariables.at(i))); + for (std::size_t i = 0; i < other._outputVariables.size(); ++i) + _outputVariables.push_back(new OutputVariable(*other._outputVariables.at(i))); + + updateReferences(); + + for (std::size_t i = 0; i < other._ruleblocks.size(); ++i) { + RuleBlock* ruleBlock = new RuleBlock(*other._ruleblocks.at(i)); + try { + ruleBlock->loadRules(this); + } catch (...) { + } + _ruleblocks.push_back(ruleBlock); + } + } + + void Engine::updateReferences() const { + std::vector<Variable*> myVariables = variables(); + for (std::size_t i = 0; i < myVariables.size(); ++i) { + Variable* variable = myVariables.at(i); + for (int t = 0; t < variable->numberOfTerms(); ++t) { + Term::updateReference(variable->getTerm(t), this); + } + } + } + + Engine::~Engine() { + for (std::size_t i = 0; i < _ruleblocks.size(); ++i) delete _ruleblocks.at(i); + for (std::size_t i = 0; i < _outputVariables.size(); ++i) delete _outputVariables.at(i); + for (std::size_t i = 0; i < _inputVariables.size(); ++i) delete _inputVariables.at(i); + } + + void Engine::configure(const std::string& conjunctionT, const std::string& disjunctionS, + const std::string& activationT, const std::string& accumulationS, + const std::string& defuzzifierName, int resolution) { + TNormFactory* tnormFactory = FactoryManager::instance()->tnorm(); + SNormFactory* snormFactory = FactoryManager::instance()->snorm(); + DefuzzifierFactory* defuzzFactory = FactoryManager::instance()->defuzzifier(); + TNorm* conjunction = tnormFactory->constructObject(conjunctionT); + SNorm* disjunction = snormFactory->constructObject(disjunctionS); + TNorm* activation = tnormFactory->constructObject(activationT); + SNorm* accumulation = snormFactory->constructObject(accumulationS); + Defuzzifier* defuzzifier = defuzzFactory->constructObject(defuzzifierName); + IntegralDefuzzifier* integralDefuzzifier = dynamic_cast<IntegralDefuzzifier*> (defuzzifier); + if (integralDefuzzifier) integralDefuzzifier->setResolution(resolution); + + configure(conjunction, disjunction, activation, accumulation, defuzzifier); + } + + void Engine::configure(TNorm* conjunction, SNorm* disjunction, + TNorm* activation, SNorm* accumulation, Defuzzifier* defuzzifier) { + for (std::size_t i = 0; i < _ruleblocks.size(); ++i) { + _ruleblocks.at(i)->setConjunction(conjunction ? conjunction->clone() : fl::null); + _ruleblocks.at(i)->setDisjunction(disjunction ? disjunction->clone() : fl::null); + _ruleblocks.at(i)->setActivation(activation ? activation->clone() : fl::null); + } + + for (std::size_t i = 0; i < _outputVariables.size(); ++i) { + _outputVariables.at(i)->setDefuzzifier(defuzzifier ? defuzzifier->clone() : fl::null); + _outputVariables.at(i)->fuzzyOutput()->setAccumulation( + accumulation ? accumulation->clone() : fl::null); + } + if (defuzzifier) delete defuzzifier; + if (accumulation) delete accumulation; + if (activation) delete activation; + if (disjunction) delete disjunction; + if (conjunction) delete conjunction; + } + + bool Engine::isReady(std::string* status) const { + std::ostringstream ss; + if (_inputVariables.empty()) { + ss << "- Engine <" << _name << "> has no input variables\n"; + } + for (std::size_t i = 0; i < _inputVariables.size(); ++i) { + InputVariable* inputVariable = _inputVariables.at(i); + if (not inputVariable) { + ss << "- Engine <" << _name << "> has a fl::null input variable at index <" << i << ">\n"; + } else if (inputVariable->terms().empty()) { + //ignore because sometimes inputs can be empty: takagi-sugeno/matlab/slcpp1.fis + // ss << "- Input variable <" << _inputVariables.at(i)->getName() << ">" + // << " has no terms\n"; + } + } + + if (_outputVariables.empty()) { + ss << "- Engine <" << _name << "> has no output variables\n"; + } + for (std::size_t i = 0; i < _outputVariables.size(); ++i) { + OutputVariable* outputVariable = _outputVariables.at(i); + if (not outputVariable) { + ss << "- Engine <" << _name << "> has a fl::null output variable at index <" << i << ">\n"; + } else { + if (outputVariable->terms().empty()) { + ss << "- Output variable <" << outputVariable->getName() << ">" + << " has no terms\n"; + } + Defuzzifier* defuzzifier = outputVariable->getDefuzzifier(); + if (not defuzzifier) { + ss << "- Output variable <" << outputVariable->getName() << ">" + << " has no defuzzifier\n"; + } + SNorm* accumulation = outputVariable->fuzzyOutput()->getAccumulation(); + if (not accumulation and dynamic_cast<IntegralDefuzzifier*> (defuzzifier)) { + ss << "- Output variable <" << outputVariable->getName() << ">" + << " has no accumulation operator\n"; + } + } + } + + if (_ruleblocks.empty()) { + ss << "- Engine <" << _name << "> has no rule blocks\n"; + } + for (std::size_t i = 0; i < _ruleblocks.size(); ++i) { + RuleBlock* ruleblock = _ruleblocks.at(i); + if (not ruleblock) { + ss << "- Engine <" << _name << "> has a fl::null rule block at index <" << i << ">\n"; + } else { + if (ruleblock->rules().empty()) { + ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has no rules\n"; + } + int requiresConjunction = 0; + int requiresDisjunction = 0; + int requiresActivation = 0; + for (int r = 0; r < ruleblock->numberOfRules(); ++r) { + Rule* rule = ruleblock->getRule(r); + if (not rule) { + ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() + << "> has a fl::null rule at index <" << r << ">\n"; + } else { + std::size_t thenIndex = rule->getText().find(" " + Rule::thenKeyword() + " "); + std::size_t andIndex = rule->getText().find(" " + Rule::andKeyword() + " "); + std::size_t orIndex = rule->getText().find(" " + Rule::orKeyword() + " "); + if (andIndex != std::string::npos and andIndex < thenIndex) { + ++requiresConjunction; + } + if (orIndex != std::string::npos and orIndex < thenIndex) { + ++requiresDisjunction; + } + if (rule->isLoaded()) { + Consequent* consequent = rule->getConsequent(); + for (std::size_t c = 0; c < consequent->conclusions().size(); ++c) { + Proposition* proposition = consequent->conclusions().at(c); + const OutputVariable* outputVariable = + dynamic_cast<const OutputVariable*> (proposition->variable); + if (outputVariable and dynamic_cast<IntegralDefuzzifier*> (outputVariable->getDefuzzifier())) { + ++requiresActivation; + break; + } + } + } + } + } + const TNorm* conjunction = ruleblock->getConjunction(); + if (requiresConjunction > 0 and not conjunction) { + ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has no conjunction operator\n"; + ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has " + << requiresConjunction << " rules that require conjunction operator\n"; + } + const SNorm* disjunction = ruleblock->getDisjunction(); + if (requiresDisjunction > 0 and not disjunction) { + ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has no disjunction operator\n"; + ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has " + << requiresDisjunction << " rules that require disjunction operator\n"; + } + const TNorm* activation = ruleblock->getActivation(); + if (requiresActivation > 0 and not activation) { + ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has no activation operator\n"; + ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has " + << requiresActivation << " rules that require activation operator\n"; + } + } + } + if (status) *status = ss.str(); + return ss.str().empty(); + } + + void Engine::restart() { + for (std::size_t i = 0; i < _inputVariables.size(); ++i) { + _inputVariables.at(i)->setInputValue(fl::nan); + } + for (std::size_t i = 0; i < _outputVariables.size(); ++i) { + _outputVariables.at(i)->clear(); + } + } + + void Engine::process() { + for (std::size_t i = 0; i < _outputVariables.size(); ++i) { + _outputVariables.at(i)->fuzzyOutput()->clear(); + } + + FL_DEBUG_BEGIN; + FL_DBG("==============="); + FL_DBG("CURRENT INPUTS:"); + for (std::size_t i = 0; i < _inputVariables.size(); ++i) { + InputVariable* inputVariable = _inputVariables.at(i); + scalar inputValue = inputVariable->getInputValue(); + if (inputVariable->isEnabled()) { + FL_DBG(inputVariable->getName() << ".input = " << Op::str(inputValue)); + FL_DBG(inputVariable->getName() << ".fuzzy = " << inputVariable->fuzzify(inputValue)); + } else { + FL_DBG(inputVariable->getName() << ".enabled = false"); + } + } + FL_DEBUG_END; + + + for (std::size_t i = 0; i < _ruleblocks.size(); ++i) { + RuleBlock* ruleBlock = _ruleblocks.at(i); + if (ruleBlock->isEnabled()) { + ruleBlock->activate(); + } + } + + for (std::size_t i = 0; i < _outputVariables.size(); ++i) { + _outputVariables.at(i)->defuzzify(); + } + + FL_DEBUG_BEGIN; + FL_DBG("==============="); + FL_DBG("CURRENT OUTPUTS:"); + for (std::size_t i = 0; i < _outputVariables.size(); ++i) { + OutputVariable* outputVariable = _outputVariables.at(i); + if (outputVariable->isEnabled()) { + FL_DBG(outputVariable->getName() << ".default = " + << outputVariable->getDefaultValue()); + + FL_DBG(outputVariable->getName() << ".lockValueInRange = " + << outputVariable->isLockedOutputValueInRange()); + + FL_DBG(outputVariable->getName() << ".lockPreviousValue= " + << outputVariable->isLockedPreviousOutputValue()); + + scalar output = outputVariable->getOutputValue(); + FL_DBG(outputVariable->getName() << ".output = " << output); + FL_DBG(outputVariable->getName() << ".fuzzy = " << + outputVariable->fuzzify(output)); + FL_DBG(outputVariable->fuzzyOutput()->toString()); + } else { + FL_DBG(outputVariable->getName() << ".enabled = false"); + } + } + FL_DBG("=============="); + FL_DEBUG_END; + } + + void Engine::setName(const std::string& name) { + this->_name = name; + } + + std::string Engine::getName() const { + return this->_name; + } + + std::string Engine::toString() const { + return FllExporter().toString(this); + } + + Engine::Type Engine::type(std::string* name, std::string* reason) const { + if (_outputVariables.empty()) { + if (name) *name = "Unknown"; + if (reason) *reason = "- Engine has no output variables"; + return Engine::Unknown; + } + + //Mamdani + bool mamdani = true; + for (std::size_t i = 0; mamdani and i < _outputVariables.size(); ++i) { + OutputVariable* outputVariable = _outputVariables.at(i); + //Defuzzifier must be integral + mamdani = mamdani and dynamic_cast<IntegralDefuzzifier*> (outputVariable->getDefuzzifier()); + } + //Larsen + bool larsen = mamdani and not _ruleblocks.empty(); + //Larsen is Mamdani with AlgebraicProduct as Activation + if (mamdani) { + for (std::size_t i = 0; larsen and i < _ruleblocks.size(); ++i) { + RuleBlock* ruleBlock = _ruleblocks.at(i); + larsen = larsen and dynamic_cast<const AlgebraicProduct*> (ruleBlock->getActivation()); + } + } + if (larsen) { + if (name) *name = "Larsen"; + if (reason) *reason = "- Output variables have integral defuzzifiers\n" + "- Rule blocks activate using the algebraic product T-Norm"; + return Engine::Larsen; + } + if (mamdani) { + if (name) *name = "Mamdani"; + if (reason) *reason = "-Output variables have integral defuzzifiers"; + return Engine::Mamdani; + } + //Else, keep checking + + //TakagiSugeno + bool takagiSugeno = true; + for (std::size_t i = 0; takagiSugeno and i < _outputVariables.size(); ++i) { + OutputVariable* outputVariable = _outputVariables.at(i); + //Defuzzifier is Weighted + WeightedDefuzzifier* weightedDefuzzifier = + dynamic_cast<WeightedDefuzzifier*> (outputVariable->getDefuzzifier()); + + takagiSugeno = takagiSugeno and weightedDefuzzifier and + (weightedDefuzzifier->getType() == WeightedDefuzzifier::Automatic or + weightedDefuzzifier->getType() == WeightedDefuzzifier::TakagiSugeno); + + if (takagiSugeno) { + //Takagi-Sugeno has only Constant, Linear or Function terms + for (int t = 0; takagiSugeno and t < outputVariable->numberOfTerms(); ++t) { + Term* term = outputVariable->getTerm(t); + takagiSugeno = takagiSugeno and + weightedDefuzzifier->inferType(term) == WeightedDefuzzifier::TakagiSugeno; + } + } + } + if (takagiSugeno) { + if (name) *name = "Takagi-Sugeno"; + if (reason) *reason = "- Output variables have weighted defuzzifiers\n" + "- Output variables have constant, linear or function terms"; + return Engine::TakagiSugeno; + } + + //Tsukamoto + bool tsukamoto = true; + for (std::size_t i = 0; tsukamoto and i < _outputVariables.size(); ++i) { + OutputVariable* outputVariable = _outputVariables.at(i); + //Defuzzifier is Weighted + WeightedDefuzzifier* weightedDefuzzifier = + dynamic_cast<WeightedDefuzzifier*> (outputVariable->getDefuzzifier()); + + tsukamoto = tsukamoto and weightedDefuzzifier and + (weightedDefuzzifier->getType() == WeightedDefuzzifier::Automatic or + weightedDefuzzifier->getType() == WeightedDefuzzifier::Tsukamoto); + if (tsukamoto) { + //Tsukamoto has only monotonic terms: Concave, Ramp, Sigmoid, SShape, or ZShape + for (int t = 0; tsukamoto and t < outputVariable->numberOfTerms(); ++t) { + Term* term = outputVariable->getTerm(t); + tsukamoto = tsukamoto and weightedDefuzzifier->isMonotonic(term); + } + } + } + if (tsukamoto) { + if (name) *name = "Tsukamoto"; + if (reason) *reason = "- Output variables have weighted defuzzifiers\n" + "- Output variables only have monotonic terms"; + return Engine::Tsukamoto; + } + + //Inverse Tsukamoto + bool inverseTsukamoto = true; + for (std::size_t i = 0; inverseTsukamoto and i < _outputVariables.size(); ++i) { + OutputVariable* outputVariable = _outputVariables.at(i); + //Defuzzifier cannot be integral + WeightedDefuzzifier* weightedDefuzzifier = + dynamic_cast<WeightedDefuzzifier*> (outputVariable->getDefuzzifier()); + inverseTsukamoto = inverseTsukamoto and weightedDefuzzifier; + } + if (inverseTsukamoto) { + if (name) *name = "Inverse Tsukamoto"; + if (reason) *reason = "- Output variables have weighted defuzzifiers\n" + "- Output variables do not only have constant, linear or function terms\n" + "- Output variables do not only have monotonic terms"; + return Engine::InverseTsukamoto; + } + + bool hybrid = true; + for (std::size_t i = 0; i < _outputVariables.size(); ++i) { + OutputVariable* outputVariable = _outputVariables.at(i); + //Output variables have non-fl::null defuzzifiers + hybrid = hybrid and outputVariable->getDefuzzifier(); + } + if (hybrid) { + if (name) *name = "Hybrid"; + if (reason) *reason = "- Output variables have different defuzzifiers"; + return Engine::Hybrid; + } + + if (name) *name = "Unknown"; + if (reason) *reason = "- There are output variables without a defuzzifier"; + return Engine::Unknown; + } + + Engine* Engine::clone() const { + return new Engine(*this); + } + + std::vector<Variable*> Engine::variables() const { + std::vector<Variable*> result; + result.reserve(_inputVariables.size() + _outputVariables.size()); + result.insert(result.end(), _inputVariables.begin(), _inputVariables.end()); + result.insert(result.end(), _outputVariables.begin(), _outputVariables.end()); + return result; + } + + /** + * Operations for InputVariables + */ + void Engine::setInputValue(const std::string& name, scalar value) { + InputVariable* inputVariable = getInputVariable(name); + inputVariable->setInputValue(value); + } + + void Engine::addInputVariable(InputVariable* inputVariable) { + this->_inputVariables.push_back(inputVariable); + } + + InputVariable* Engine::setInputVariable(InputVariable* inputVariable, int index) { + InputVariable* result = this->_inputVariables.at(index); + this->_inputVariables.at(index) = inputVariable; + return result; + } + + void Engine::insertInputVariable(InputVariable* inputVariable, int index) { + this->_inputVariables.insert(this->_inputVariables.begin() + index, + inputVariable); + } + + InputVariable* Engine::getInputVariable(int index) const { + return this->_inputVariables.at(index); + } + + InputVariable* Engine::getInputVariable(const std::string& name) const { + for (std::size_t i = 0; i < _inputVariables.size(); ++i) { + if (_inputVariables.at(i)->getName() == name) + return _inputVariables.at(i); + } + throw fl::Exception("[engine error] input variable <" + name + "> not found", FL_AT); + } + + bool Engine::hasInputVariable(const std::string& name) const { + for (std::size_t i = 0; i < _inputVariables.size(); ++i) { + if (_inputVariables.at(i)->getName() == name) + return true; + } + return false; + } + + InputVariable* Engine::removeInputVariable(int index) { + InputVariable* result = this->_inputVariables.at(index); + this->_inputVariables.erase(this->_inputVariables.begin() + index); + return result; + } + + InputVariable* Engine::removeInputVariable(const std::string& name) { + for (std::size_t i = 0; i < _inputVariables.size(); ++i) { + if (_inputVariables.at(i)->getName() == name) { + InputVariable* result = this->_inputVariables.at(i); + this->_inputVariables.erase(this->_inputVariables.begin() + i); + return result; + } + } + throw fl::Exception("[engine error] input variable <" + name + "> not found", FL_AT); + } + + int Engine::numberOfInputVariables() const { + return this->_inputVariables.size(); + } + + const std::vector<InputVariable*>& Engine::inputVariables() const { + return this->_inputVariables; + } + + void Engine::setInputVariables(const std::vector<InputVariable*>& inputVariables) { + this->_inputVariables = inputVariables; + } + + std::vector<InputVariable*>& Engine::inputVariables() { + return this->_inputVariables; + } + + /** + * Operations for OutputVariables + */ + scalar Engine::getOutputValue(const std::string& name) { + OutputVariable* outputVariable = getOutputVariable(name); + return outputVariable->getOutputValue(); + } + + void Engine::addOutputVariable(OutputVariable* outputVariable) { + this->_outputVariables.push_back(outputVariable); + } + + OutputVariable* Engine::setOutputVariable(OutputVariable* outputVariable, int index) { + OutputVariable* result = this->_outputVariables.at(index); + this->_outputVariables.at(index) = outputVariable; + return result; + } + + void Engine::insertOutputVariable(OutputVariable* outputVariable, int index) { + this->_outputVariables.insert(this->_outputVariables.begin() + index, + outputVariable); + } + + OutputVariable* Engine::getOutputVariable(int index) const { + return this->_outputVariables.at(index); + } + + OutputVariable* Engine::getOutputVariable(const std::string& name) const { + for (std::size_t i = 0; i < _outputVariables.size(); ++i) { + if (_outputVariables.at(i)->getName() == name) + return _outputVariables.at(i); + } + throw fl::Exception("[engine error] output variable <" + name + "> not found", FL_AT); + } + + bool Engine::hasOutputVariable(const std::string& name) const { + for (std::size_t i = 0; i < _outputVariables.size(); ++i) { + if (_outputVariables.at(i)->getName() == name) + return true; + } + return false; + } + + OutputVariable* Engine::removeOutputVariable(int index) { + OutputVariable* result = this->_outputVariables.at(index); + this->_outputVariables.erase(this->_outputVariables.begin() + index); + return result; + } + + OutputVariable* Engine::removeOutputVariable(const std::string& name) { + for (std::size_t i = 0; i < _outputVariables.size(); ++i) { + if (_outputVariables.at(i)->getName() == name) { + OutputVariable* result = this->_outputVariables.at(i); + this->_outputVariables.erase(this->_outputVariables.begin() + i); + return result; + } + } + throw fl::Exception("[engine error] output variable <" + name + "> not found", FL_AT); + } + + int Engine::numberOfOutputVariables() const { + return this->_outputVariables.size(); + } + + const std::vector<OutputVariable*>& Engine::outputVariables() const { + return this->_outputVariables; + } + + void Engine::setOutputVariables(const std::vector<OutputVariable*>& outputVariables) { + this->_outputVariables = outputVariables; + } + + std::vector<OutputVariable*>& Engine::outputVariables() { + return this->_outputVariables; + } + + /** + * Operations for iterable datatype _ruleblocks + */ + void Engine::addRuleBlock(RuleBlock* ruleblock) { + this->_ruleblocks.push_back(ruleblock); + } + + RuleBlock* Engine::setRuleBlock(RuleBlock* ruleBlock, int index) { + RuleBlock* result = this->_ruleblocks.at(index); + this->_ruleblocks.at(index) = ruleBlock; + return result; + } + + void Engine::insertRuleBlock(RuleBlock* ruleblock, int index) { + this->_ruleblocks.insert(this->_ruleblocks.begin() + index, ruleblock); + } + + RuleBlock* Engine::getRuleBlock(int index) const { + return this->_ruleblocks.at(index); + } + + RuleBlock* Engine::getRuleBlock(const std::string& name) const { + for (std::size_t i = 0; i < _ruleblocks.size(); ++i) { + if (_ruleblocks.at(i)->getName() == name) + return _ruleblocks.at(i); + } + throw fl::Exception("[engine error] rule block <" + name + "> not found", FL_AT); + } + + bool Engine::hasRuleBlock(const std::string& name) const { + for (std::size_t i = 0; i < _ruleblocks.size(); ++i) { + if (_ruleblocks.at(i)->getName() == name) + return true; + } + return false; + } + + RuleBlock* Engine::removeRuleBlock(int index) { + RuleBlock* result = this->_ruleblocks.at(index); + this->_ruleblocks.erase(this->_ruleblocks.begin() + index); + return result; + } + + RuleBlock* Engine::removeRuleBlock(const std::string& name) { + for (std::size_t i = 0; i < _ruleblocks.size(); ++i) { + if (_ruleblocks.at(i)->getName() == name) { + RuleBlock* result = this->_ruleblocks.at(i); + this->_ruleblocks.erase(this->_ruleblocks.begin() + i); + return result; + } + } + throw fl::Exception("[engine error] rule block <" + name + "> not found", FL_AT); + } + + int Engine::numberOfRuleBlocks() const { + return this->_ruleblocks.size(); + } + + const std::vector<RuleBlock*>& Engine::ruleBlocks() const { + return this->_ruleblocks; + } + + void Engine::setRuleBlocks(const std::vector<RuleBlock*>& ruleBlocks) { + this->_ruleblocks = ruleBlocks; + } + + std::vector<RuleBlock*>& Engine::ruleBlocks() { + return this->_ruleblocks; + } + + +} diff --git a/fuzzylite/src/Exception.cpp b/fuzzylite/src/Exception.cpp new file mode 100644 index 0000000..d24adac --- /dev/null +++ b/fuzzylite/src/Exception.cpp @@ -0,0 +1,183 @@ +/* + 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/Exception.h" + + +#ifdef FL_BACKTRACE_OFF +//do nothing + +#elif defined FL_UNIX +#include <execinfo.h> + +#elif defined FL_WINDOWS +#include <windows.h> +#include <winbase.h> +#ifndef __MINGW32__ +#include <dbghelp.h> +#endif +#endif + + +#include <signal.h> +#include <stdlib.h> +#include <string.h> + +namespace fl { + + Exception::Exception(const std::string& what) + : std::exception(), _what(what) { + FL_DBG(this->what()); + } + + Exception::Exception(const std::string& what, const std::string& file, int line, + const std::string& function) + : std::exception(), _what(what) { + append(file, line, function); + FL_DBG(this->what()); + } + + Exception::~Exception() FL_INOEXCEPT { + } + + void Exception::setWhat(const std::string& what) { + this->_what = what; + } + + std::string Exception::getWhat() const { + return this->_what; + } + + const char* Exception::what() const FL_INOEXCEPT { + return this->_what.c_str(); + } + + void Exception::append(const std::string& whatElse) { + this->_what += whatElse + "\n"; + } + + void Exception::append(const std::string& file, int line, const std::string& function) { + std::ostringstream ss; + ss << "\n{at " << file << "::" << function << "() [line:" << line << "]}"; + _what += ss.str(); + } + + void Exception::append(const std::string& whatElse, + const std::string& file, int line, const std::string& function) { + append(whatElse); + append(file, line, function); + } + + std::string Exception::btCallStack() { +#ifdef FL_BACKTRACE_OFF + return "[backtrace disabled] fuzzylite was built with option -DFL_BACKTRACE_OFF"; +#elif defined FL_UNIX + std::ostringstream btStream; + const int bufferSize = 30; + void* buffer[bufferSize]; + int backtraceSize = backtrace(buffer, bufferSize); + char **btSymbols = backtrace_symbols(buffer, backtraceSize); + if (btSymbols == fl::null) { + btStream << "[backtrace error] no symbols could be retrieved"; + } else { + if (backtraceSize == 0) btStream << "[backtrace is empty]"; + for (int i = 0; i < backtraceSize; ++i) { + btStream << btSymbols[i] << "\n"; + } + } + free(btSymbols); + return btStream.str(); + + +#elif defined FL_WINDOWS && ! defined __MINGW32__ + std::ostringstream btStream; + const int bufferSize = 30; + void* buffer[bufferSize]; + SymInitialize(GetCurrentProcess(), fl::null, TRUE); + + int backtraceSize = CaptureStackBackTrace(0, bufferSize, buffer, fl::null); + SYMBOL_INFO* btSymbol = (SYMBOL_INFO *) calloc(sizeof ( SYMBOL_INFO) + 256 * sizeof ( char), 1); + if (not btSymbol) { + btStream << "[backtrace error] no symbols could be retrieved"; + } else { + btSymbol->MaxNameLen = 255; + btSymbol->SizeOfStruct = sizeof ( SYMBOL_INFO); + if (backtraceSize == 0) btStream << "[backtrace is empty]"; + for (int i = 0; i < backtraceSize; ++i) { + SymFromAddr(GetCurrentProcess(), (DWORD64) (buffer[ i ]), 0, btSymbol); + btStream << (backtraceSize - i - 1) << ": " << + btSymbol->Name << " at 0x" << btSymbol->Address << "\n"; + } + } + free(btSymbol); + return btStream.str(); +#else + return "[backtrace missing] supported only in Unix and Windows platforms"; +#endif + } + //execinfo + + void Exception::signalHandler(int signal) { + std::ostringstream ex; + ex << "[unexpected signal " << signal << "] "; +#ifdef FL_UNIX + ex << strsignal(signal); +#endif + ex << "\nBACKTRACE:\n" << btCallStack(); + fl::Exception::catchException(fl::Exception(ex.str(), FL_AT)); + exit(EXIT_FAILURE); + } + + void Exception::convertToException(int signal) { + std::string signalDescription; +#ifdef FL_UNIX + //Unblock the signal + sigset_t empty; + sigemptyset(&empty); + sigaddset(&empty, signal); + sigprocmask(SIG_UNBLOCK, &empty, fl::null); + signalDescription = strsignal(signal); +#endif + std::ostringstream ex; + ex << "[signal " << signal << "] " << signalDescription << "\n"; + ex << "BACKTRACE:\n" << btCallStack(); + throw fl::Exception(ex.str(), FL_AT); + } + + void Exception::terminate() { + fl::Exception::catchException(fl::Exception("[unexpected exception] BACKTRACE:\n" + btCallStack(), FL_AT)); + exit(EXIT_FAILURE); + } + + void Exception::catchException(const std::exception& exception) { + std::ostringstream ss; + ss << exception.what(); + std::string backtrace = btCallStack(); + if (not backtrace.empty()) { + ss << "\n\nBACKTRACE:\n" << backtrace; + } + FL_LOG(ss.str()); + } + +} diff --git a/fuzzylite/src/Operation.cpp b/fuzzylite/src/Operation.cpp new file mode 100644 index 0000000..1596ea4 --- /dev/null +++ b/fuzzylite/src/Operation.cpp @@ -0,0 +1,477 @@ +/* + 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/Operation.h" + +#include "fl/defuzzifier/Defuzzifier.h" +#include "fl/norm/Norm.h" +#include "fl/norm/SNorm.h" +#include "fl/norm/TNorm.h" + +#include <algorithm> +#include <iomanip> +#include <cstdarg> +#include <cctype> + +namespace fl { + + template <typename T> + T Operation::min(T a, T b) { + if (isNaN(a)) return b; + if (isNaN(b)) return a; + return a < b ? a : b; + } + template FL_API scalar Operation::min(scalar a, scalar b); + template FL_API int Operation::min(int a, int b); + + template <typename T> + T Operation::max(T a, T b) { + if (isNaN(a)) return b; + if (isNaN(b)) return a; + return a > b ? a : b; + } + template FL_API scalar Operation::max(scalar a, scalar b); + template FL_API int Operation::max(int a, int b); + + template <typename T> + T Operation::bound(T x, T min, T max) { + if (isGt(x, max)) return max; + if (isLt(x, min)) return min; + return x; + } + template FL_API scalar Operation::bound(scalar x, scalar min, scalar max); + template FL_API int Operation::bound(int x, int min, int max); + + template <typename T> + bool Operation::in(T x, T min, T max, bool geq, bool leq) { + bool left = geq ? isGE(x, min) : isGt(x, min); + bool right = leq ? isLE(x, max) : isLt(x, max); + return (left and right); + } + template FL_API bool Operation::in(scalar x, scalar min, scalar max, bool geq, bool leq); + template FL_API bool Operation::in(int x, int min, int max, bool geq, bool leq); + + template <typename T> + bool Operation::isInf(T x) { + return std::abs(x) == fl::inf; + } + template FL_API bool Operation::isInf(int x); + template FL_API bool Operation::isInf(scalar x); + + template <typename T> + bool Operation::isNaN(T x) { + return not (x == x); + } + template FL_API bool Operation::isNaN(int x); + template FL_API bool Operation::isNaN(scalar x); + + template<typename T> + bool Operation::isFinite(T x) { + return not (isNaN(x) or isInf(x)); + } + template FL_API bool Operation::isFinite(int x); + template FL_API bool Operation::isFinite(scalar x); + + bool Operation::isLt(scalar a, scalar b, scalar macheps) { + return not isEq(a, b, macheps) and a < b; + } + + bool Operation::isLE(scalar a, scalar b, scalar macheps) { + return isEq(a, b, macheps) or a < b; + } + + bool Operation::isEq(scalar a, scalar b, scalar macheps) { + return a == b or std::fabs(a - b) < macheps or (isNaN(a) and isNaN(b)); + } + + bool Operation::isGt(scalar a, scalar b, scalar macheps) { + return not isEq(a, b, macheps) and a > b; + } + + bool Operation::isGE(scalar a, scalar b, scalar macheps) { + return isEq(a, b, macheps) or a > b; + } + + scalar Operation::scale(scalar x, scalar fromMin, scalar fromMax, scalar toMin, scalar toMax, bool bounded) { + scalar result = (toMax - toMin) / (fromMax - fromMin) * (x - fromMin) + toMin; + return bounded ? fl::Op::bound(result, toMin, toMax) : result; + } + + scalar Operation::add(scalar a, scalar b) { + return a + b; + } + + scalar Operation::subtract(scalar a, scalar b) { + return a - b; + } + + scalar Operation::multiply(scalar a, scalar b) { + return a * b; + } + + scalar Operation::divide(scalar a, scalar b) { + return a / b; + } + + scalar Operation::modulo(scalar a, scalar b) { + return fmod(a, b); + } + + scalar Operation::logicalAnd(scalar a, scalar b) { + return (isEq(a, 1.0) and isEq(b, 1.0)) ? 1.0 : 0.0; + } + + scalar Operation::logicalOr(scalar a, scalar b) { + return (isEq(a, 1.0) or isEq(b, 1.0)) ? 1.0 : 0.0; + } + + scalar Operation::logicalNot(scalar a) { + return isEq(a, 1.0) ? 0.0 : 1.0; + } + + scalar Operation::negate(scalar a) { + return -a; + } + + scalar Operation::round(scalar x) { + return (x > 0.0) ? std::floor(x + 0.5) : std::ceil(x - 0.5); + } + + scalar Operation::gt(scalar a, scalar b) { + return isGt(a, b); + } + + scalar Operation::ge(scalar a, scalar b) { + return isGE(a, b); + } + + scalar Operation::eq(scalar a, scalar b) { + return isEq(a, b); + } + + scalar Operation::neq(scalar a, scalar b) { + return not isEq(a, b); + } + + scalar Operation::le(scalar a, scalar b) { + return isLE(a, b); + } + + scalar Operation::lt(scalar a, scalar b) { + return isLt(a, b); + } + + bool Operation::increment(std::vector<int>& x, std::vector<int>& min, std::vector<int>& max) { + return increment(x, (int) x.size() - 1, min, max); + } + + bool Operation::increment(std::vector<int>& x, int position, std::vector<int>& min, std::vector<int>& max) { + if (x.empty() or position < 0) return true; + + bool overflow = false; + if (x.at(position) < max.at(position)) { + ++x.at(position); + } else { + overflow = (position == 0); + x.at(position) = min.at(position); + --position; + if (position >= 0) { + overflow = increment(x, position, min, max); + } + } + return overflow; + } + + double Operation::mean(const std::vector<scalar>& x) { + if (x.size() == 0) return fl::nan; + scalar sum = 0.0; + for (std::size_t i = 0; i < x.size(); ++i) sum += x.at(i); + return sum / x.size(); + } + + double Operation::standardDeviation(const std::vector<scalar>& x) { + if (x.size() <= 1) return 0.0; + return standardDeviation(x, mean(x)); + } + + double Operation::standardDeviation(const std::vector<scalar>& x, scalar mean) { + if (x.size() <= 1) return 0.0; + return std::sqrt(variance(x, mean)); + } + + double Operation::variance(const std::vector<scalar>& x) { + if (x.size() <= 1) return 0.0; + return variance(x, mean(x)); + } + + double Operation::variance(const std::vector<scalar>& x, scalar mean) { + if (x.size() <= 1) return 0.0; + scalar result = 0; + for (std::size_t i = 0; i < x.size(); ++i) { + result += (x.at(i) - mean) * (x.at(i) - mean); + } + result /= -1 + x.size(); + return result; + } + + + + //Text Operations: + + std::string Operation::validName(const std::string& name) { + if (trim(name).empty()) return "unnamed"; + std::ostringstream ss; + for (std::size_t i = 0; i < name.length(); ++i) { + char c = name[i]; + if (c == '_' or c == '.' or isalnum(c)) { + ss << c; + } + } + return ss.str(); + } + + int Operation::isValidForName(int character) { + return character == '_' or character == '.' or isalnum(character); + } + + std::string Operation::findReplace(const std::string& str, const std::string& find, + const std::string& replace, bool replaceAll) { + std::ostringstream result; + std::size_t fromIndex = 0, nextIndex; + do { + nextIndex = str.find(find, fromIndex); + result << str.substr(fromIndex, nextIndex - fromIndex); + if (nextIndex != std::string::npos) + result << replace; + fromIndex = nextIndex + find.size(); + } while (replaceAll and nextIndex != std::string::npos); + return result.str(); + } + + std::vector<std::string> Operation::split(const std::string& str, + const std::string& delimiter, bool ignoreEmpty) { + std::vector<std::string> result; + if (str.empty() or delimiter.empty()) { + result.push_back(str); + return result; + } + std::string::const_iterator position = str.begin(), next = str.begin(); + while (next != str.end()) { + next = std::search(position, str.end(), delimiter.begin(), delimiter.end()); + std::string token(position, next); + if (not (token.empty() and ignoreEmpty)) { + result.push_back(token); + } + if (next != str.end()) { + position = next + delimiter.size(); + } + } + return result; + } + + std::string Operation::trim(const std::string& text) { + if (text.empty()) return text; + if (not (std::isspace(text.at(0)) or std::isspace(text.at(text.size() - 1)))) + return text; + int start = 0, end = text.size() - 1; + while (start <= end and std::isspace(text.at(start))) { + ++start; + } + while (end >= start and std::isspace(text.at(end))) { + --end; + } + int length = end - start + 1; + if (length <= 0) return ""; + return text.substr(start, length); + } + + std::string Operation::format(const std::string& text, int matchesChar(int), + const std::string& replacement) { + std::ostringstream ss; + std::string::const_iterator it = text.begin(); + while (it != text.end()) { + if (matchesChar(*it)) { + ss << *it; + } else { + ss << replacement; + } + ++it; + } + return ss.str(); + } + + scalar Operation::toScalar(const std::string& x) { + std::istringstream iss(x); + scalar result; + iss >> result; + char strict; + if (not (iss.fail() or iss.get(strict))) return result; + + std::ostringstream nan, pInf, nInf; + nan << fl::nan; + pInf << fl::inf; + nInf << (-fl::inf); + + if (x == nan.str() or x == "nan") + return fl::nan; + if (x == pInf.str() or x == "inf") + return fl::inf; + if (x == nInf.str() or x == "-inf") + return -fl::inf; + + std::ostringstream ex; + ex << "[conversion error] from <" << x << "> to scalar"; + throw fl::Exception(ex.str(), FL_AT); + } + + scalar Operation::toScalar(const std::string& x, scalar alternative) FL_INOEXCEPT { + std::istringstream iss(x); + scalar result; + iss >> result; + char strict; + if (not (iss.fail() or iss.get(strict))) return result; + + std::ostringstream nan, pInf, nInf; + nan << fl::nan; + pInf << fl::inf; + nInf << (-fl::inf); + + if (x == nan.str() or x == "nan") + return fl::nan; + if (x == pInf.str() or x == "inf") + return fl::inf; + if (x == nInf.str() or x == "-inf") + return -fl::inf; + + return alternative; + } + + bool Operation::isNumeric(const std::string& x) { + try { + fl::Op::toScalar(x); + return true; + } catch (std::exception& ex) { + (void) ex; + return false; + } + } + + template <typename T> + std::string Operation::str(T x, int decimals) { + std::ostringstream ss; + ss << std::setprecision(decimals) << std::fixed; + if (fl::Op::isNaN(x)) { + ss << "nan"; + } else if (fl::Op::isInf(x)) { + ss << (fl::Op::isLt(x, 0.0) ? "-inf" : "inf"); + } else if (fl::Op::isEq(x, 0.0)) { + ss << 0.0; + } else ss << x; + return ss.str(); + } + template FL_API std::string Operation::str(int x, int precision); + template FL_API std::string Operation::str(scalar x, int precision); + + template <> FL_API std::string Operation::str(const std::string& x, int precision) { + (void) precision; + return x; + } + + template <typename T> + std::string Operation::join(const std::vector<T>& x, + const std::string& separator) { + std::ostringstream ss; + for (std::size_t i = 0; i < x.size(); ++i) { + ss << str(x.at(i)); + if (i + 1 < x.size()) ss << separator; + } + return ss.str(); + } + template FL_API std::string Operation::join(const std::vector<int>& x, + const std::string& separator); + template FL_API std::string Operation::join(const std::vector<scalar>& x, + const std::string& separator); + + template <> FL_API + std::string Operation::join(const std::vector<std::string>& x, + const std::string& separator) { + std::ostringstream ss; + for (std::size_t i = 0; i < x.size(); ++i) { + ss << x.at(i); + if (i + 1 < x.size()) ss << separator; + } + return ss.str(); + } + + template <typename T> + std::string Operation::join(int items, const std::string& separator, T first, ...) { + std::ostringstream ss; + ss << str(first); + if (items > 1) ss << separator; + va_list args; + va_start(args, first); + for (int i = 0; i < items - 1; ++i) { + ss << str(va_arg(args, T)); + if (i + 1 < items - 1) ss << separator; + } + va_end(args); + return ss.str(); + } + + template FL_API std::string Operation::join(int items, const std::string& separator, + int first, ...); + template FL_API std::string Operation::join(int items, const std::string& separator, + double first, ...); + + template <> FL_API std::string Operation::join(int items, const std::string& separator, + float first, ...) { + std::ostringstream ss; + ss << str(first); + if (items > 1) ss << separator; + va_list args; + va_start(args, first); + for (int i = 0; i < items - 1; ++i) { + ss << str(va_arg(args, double)); //automatic promotion + if (i + 1 < items - 1) ss << separator; + } + va_end(args); + return ss.str(); + } + + template <> FL_API + std::string Operation::join(int items, const std::string& separator, const char* first, ...) { + std::ostringstream ss; + ss << first; + if (items > 1) ss << separator; + va_list args; + va_start(args, first); + for (int i = 0; i < items - 1; ++i) { + ss << va_arg(args, const char*); + if (i + 1 < items - 1) ss << separator; + } + va_end(args); + return ss.str(); + } + +} diff --git a/fuzzylite/src/defuzzifier/Bisector.cpp b/fuzzylite/src/defuzzifier/Bisector.cpp new file mode 100644 index 0000000..ee4d2fc --- /dev/null +++ b/fuzzylite/src/defuzzifier/Bisector.cpp @@ -0,0 +1,85 @@ +/* + 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/defuzzifier/Bisector.h" + +#include "fl/term/Accumulated.h" +#include "fl/term/Term.h" + +namespace fl { + + Bisector::Bisector(int resolution) + : IntegralDefuzzifier(resolution) { + } + + Bisector::~Bisector() { + + } + + std::string Bisector::className() const { + return "Bisector"; + } + + scalar Bisector::defuzzify(const Term* term, scalar minimum, scalar maximum) const { + if (not fl::Op::isFinite(minimum + maximum)) { + return fl::nan; + } + if (maximum - minimum > _resolution) { + FL_DBG("[accuracy warning] the resolution <" << _resolution << "> " + "is smaller than the range <" << minimum << ", " << maximum << ">. In order to " + "improve the accuracy, the resolution should be at least equal to the range."); + } + scalar dx = (maximum - minimum) / _resolution; + + int counter = _resolution; + int left = 0, right = 0; + scalar leftArea = 0, rightArea = 0; + scalar xLeft = minimum, xRight = maximum; + while (counter-- > 0) { + if (fl::Op::isLE(leftArea, rightArea)) { + xLeft = minimum + (left + 0.5) * dx; + leftArea += term->membership(xLeft); + left++; + } else { + xRight = maximum - (right + 0.5) * dx; + rightArea += term->membership(xRight); + right++; + } + } + + //Inverse weighted average to compensate + scalar bisector = (leftArea * xRight + rightArea * xLeft) / (leftArea + rightArea); + return bisector; + } + + Bisector* Bisector::clone() const { + return new Bisector(*this); + } + + Defuzzifier* Bisector::constructor() { + return new Bisector; + } + + +} diff --git a/fuzzylite/src/defuzzifier/Centroid.cpp b/fuzzylite/src/defuzzifier/Centroid.cpp new file mode 100644 index 0000000..01490d3 --- /dev/null +++ b/fuzzylite/src/defuzzifier/Centroid.cpp @@ -0,0 +1,80 @@ +/* + 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/defuzzifier/Centroid.h" + +#include "fl/term/Accumulated.h" +#include "fl/term/Term.h" + + +namespace fl { + + Centroid::Centroid(int resolution) + : IntegralDefuzzifier(resolution) { + } + + Centroid::~Centroid() { + + } + + std::string Centroid::className() const { + return "Centroid"; + } + + scalar Centroid::defuzzify(const Term* term, scalar minimum, scalar maximum) const { + if (not fl::Op::isFinite(minimum + maximum)) { + return fl::nan; + } + if (maximum - minimum > _resolution) { + FL_DBG("[accuracy warning] the resolution <" << _resolution << "> " + "is smaller than the range <" << minimum << ", " << maximum << ">. In order to " + "improve the accuracy, the resolution should be at least equal to the range."); + } + scalar dx = (maximum - minimum) / _resolution; + scalar x, y; + scalar area = 0, xcentroid = 0, ycentroid = 0; + for (int i = 0; i < _resolution; ++i) { + x = minimum + (i + 0.5) * dx; + y = term->membership(x); + + xcentroid += y * x; + ycentroid += y * y; + area += y; + } + xcentroid /= area; + ycentroid /= 2 * area; + area *= dx; //total area... unused, but for future reference. + return xcentroid; + } + + Centroid* Centroid::clone() const { + return new Centroid(*this); + } + + Defuzzifier* Centroid::constructor() { + return new Centroid; + } + + +} diff --git a/fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp b/fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp new file mode 100644 index 0000000..2badf14 --- /dev/null +++ b/fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp @@ -0,0 +1,53 @@ +/* + 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/defuzzifier/IntegralDefuzzifier.h" + +namespace fl { + + int IntegralDefuzzifier::_defaultResolution = 200; + + void IntegralDefuzzifier::setDefaultResolution(int defaultResolution) { + _defaultResolution = defaultResolution; + } + + int IntegralDefuzzifier::defaultResolution() { + return _defaultResolution; + } + + IntegralDefuzzifier::IntegralDefuzzifier(int resolution) + : Defuzzifier(), _resolution(resolution) { + } + + IntegralDefuzzifier::~IntegralDefuzzifier() { + } + + void IntegralDefuzzifier::setResolution(int resolution) { + this->_resolution = resolution; + } + + int IntegralDefuzzifier::getResolution() const { + return this->_resolution; + } +} diff --git a/fuzzylite/src/defuzzifier/LargestOfMaximum.cpp b/fuzzylite/src/defuzzifier/LargestOfMaximum.cpp new file mode 100644 index 0000000..470af52 --- /dev/null +++ b/fuzzylite/src/defuzzifier/LargestOfMaximum.cpp @@ -0,0 +1,75 @@ +/* + 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/defuzzifier/LargestOfMaximum.h" + +#include "fl/Exception.h" +#include "fl/term/Term.h" + +namespace fl { + + LargestOfMaximum::LargestOfMaximum(int resolution) + : IntegralDefuzzifier(resolution) { + } + + LargestOfMaximum::~LargestOfMaximum() { + } + + std::string LargestOfMaximum::className() const { + return "LargestOfMaximum"; + } + + scalar LargestOfMaximum::defuzzify(const Term* term, scalar minimum, scalar maximum) const { + if (not fl::Op::isFinite(minimum + maximum)) { + return fl::nan; + } + if (maximum - minimum > _resolution) { + FL_DBG("[accuracy warning] the resolution <" << _resolution << "> " + "is smaller than the range <" << minimum << ", " << maximum << ">. In order to " + "improve the accuracy, the resolution should be at least equal to the range."); + } + scalar dx = (maximum - minimum) / _resolution; + scalar x, y; + scalar ymax = -1.0, xlargest = maximum; + for (int i = 0; i < _resolution; ++i) { + x = minimum + (i + 0.5) * dx; + y = term->membership(x); + + if (Op::isGE(y, ymax)) { + ymax = y; + xlargest = x; + } + } + return xlargest; + } + + LargestOfMaximum* LargestOfMaximum::clone() const { + return new LargestOfMaximum(*this); + } + + Defuzzifier* LargestOfMaximum::constructor() { + return new LargestOfMaximum; + } + +} diff --git a/fuzzylite/src/defuzzifier/MeanOfMaximum.cpp b/fuzzylite/src/defuzzifier/MeanOfMaximum.cpp new file mode 100644 index 0000000..7c40527 --- /dev/null +++ b/fuzzylite/src/defuzzifier/MeanOfMaximum.cpp @@ -0,0 +1,88 @@ +/* + 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/defuzzifier/MeanOfMaximum.h" + +#include "fl/Exception.h" +#include "fl/term/Term.h" + + +namespace fl { + + MeanOfMaximum::MeanOfMaximum(int resolution) + : IntegralDefuzzifier(resolution) { + } + + MeanOfMaximum::~MeanOfMaximum() { + } + + std::string MeanOfMaximum::className() const { + return "MeanOfMaximum"; + } + + scalar MeanOfMaximum::defuzzify(const Term* term, scalar minimum, scalar maximum) const { + if (not fl::Op::isFinite(minimum + maximum)) { + return fl::nan; + } + if (maximum - minimum > _resolution) { + FL_DBG("[accuracy warning] the resolution <" << _resolution << "> " + "is smaller than the range <" << minimum << ", " << maximum << ">. In order to " + "improve the accuracy, the resolution should be at least equal to the range."); + } + scalar dx = (maximum - minimum) / _resolution; + scalar x, y; + scalar ymax = -1.0; + scalar xsmallest = minimum; + scalar xlargest = maximum; + bool samePlateau = false; + for (int i = 0; i < _resolution; ++i) { + x = minimum + (i + 0.5) * dx; + y = term->membership(x); + + if (Op::isGt(y, ymax)) { + ymax = y; + + xsmallest = x; + xlargest = x; + + samePlateau = true; + } else if (Op::isEq(y, ymax) and samePlateau) { + xlargest = x; + } else if (Op::isLt(y, ymax)) { + samePlateau = false; + } + } + + return (xlargest + xsmallest) / 2.0; + } + + MeanOfMaximum* MeanOfMaximum::clone() const { + return new MeanOfMaximum(*this); + } + + Defuzzifier* MeanOfMaximum::constructor() { + return new MeanOfMaximum; + } + +} diff --git a/fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp b/fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp new file mode 100644 index 0000000..1e67395 --- /dev/null +++ b/fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp @@ -0,0 +1,77 @@ +/* + 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/defuzzifier/SmallestOfMaximum.h" + +#include "fl/Exception.h" +#include "fl/term/Term.h" + + +namespace fl { + + SmallestOfMaximum::SmallestOfMaximum(int resolution) + : IntegralDefuzzifier(resolution) { + } + + SmallestOfMaximum::~SmallestOfMaximum() { + } + + std::string SmallestOfMaximum::className() const { + return "SmallestOfMaximum"; + } + + scalar SmallestOfMaximum::defuzzify(const Term* term, scalar minimum, scalar maximum) const { + if (not fl::Op::isFinite(minimum + maximum)) { + return fl::nan; + } + if (maximum - minimum > _resolution) { + FL_DBG("[accuracy warning] the resolution <" << _resolution << "> " + "is smaller than the range <" << minimum << ", " << maximum << ">. In order to " + "improve the accuracy, the resolution should be at least equal to the range."); + } + scalar dx = (maximum - minimum) / _resolution; + scalar x, y; + scalar ymax = -1.0, xsmallest = minimum; + for (int i = 0; i < _resolution; ++i) { + x = minimum + (i + 0.5) * dx; + y = term->membership(x); + + if (Op::isGt(y, ymax)) { + xsmallest = x; + ymax = y; + } + } + return xsmallest; + } + + SmallestOfMaximum* SmallestOfMaximum::clone() const { + return new SmallestOfMaximum(*this); + } + + Defuzzifier* SmallestOfMaximum::constructor() { + return new SmallestOfMaximum; + } + +} + diff --git a/fuzzylite/src/defuzzifier/WeightedAverage.cpp b/fuzzylite/src/defuzzifier/WeightedAverage.cpp new file mode 100644 index 0000000..105c9d4 --- /dev/null +++ b/fuzzylite/src/defuzzifier/WeightedAverage.cpp @@ -0,0 +1,123 @@ +/* + 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/defuzzifier/WeightedAverage.h" + +#include "fl/term/Accumulated.h" +#include "fl/term/Activated.h" +#include "fl/norm/Norm.h" +#include "fl/norm/SNorm.h" +#include "fl/norm/TNorm.h" + +#include <map> + +namespace fl { + + WeightedAverage::WeightedAverage(Type type) : WeightedDefuzzifier(type) { + } + + WeightedAverage::WeightedAverage(const std::string& type) : WeightedDefuzzifier(type) { + } + + WeightedAverage::~WeightedAverage() { + } + + std::string WeightedAverage::className() const { + return "WeightedAverage"; + } + + scalar WeightedAverage::defuzzify(const Term* term, + scalar minimum, scalar maximum) const { + const Accumulated* fuzzyOutput = dynamic_cast<const Accumulated*> (term); + if (not fuzzyOutput) { + std::ostringstream ss; + ss << "[defuzzification error]" + << "expected an Accumulated term instead of" + << "<" << term->toString() << ">"; + throw fl::Exception(ss.str(), FL_AT); + } + + minimum = fuzzyOutput->getMinimum(); + maximum = fuzzyOutput->getMaximum(); + + scalar sum = 0.0; + scalar weights = 0.0; + + if (not fuzzyOutput->getAccumulation()) { + Type type = _type; + for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) { + Activated* activated = fuzzyOutput->getTerm(i); + scalar w = activated->getDegree(); + + if (type == Automatic) type = inferType(activated->getTerm()); + + scalar z = (type == TakagiSugeno) + //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work. + ? activated->getTerm()->membership(w) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions + : tsukamoto(activated->getTerm(), w, minimum, maximum); + + sum += w * z; + weights += w; + } + } else { + typedef std::map<const Term*, std::vector<Activated*> > TermGroup; + TermGroup groups; + for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) { + Activated* value = fuzzyOutput->getTerm(i); + const Term* key = value->getTerm(); + groups[key].push_back(value); + } + TermGroup::const_iterator it = groups.begin(); + Type type = _type; + while (it != groups.end()) { + const Term* activatedTerm = it->first; + scalar accumulatedDegree = 0.0; + for (std::size_t i = 0; i < it->second.size(); ++i) + accumulatedDegree = fuzzyOutput->getAccumulation()->compute( + accumulatedDegree, it->second.at(i)->getDegree()); + + if (type == Automatic) type = inferType(activatedTerm); + + scalar z = (type == TakagiSugeno) + //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work. + ? activatedTerm->membership(accumulatedDegree) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions + : tsukamoto(activatedTerm, accumulatedDegree, minimum, maximum); + + sum += accumulatedDegree * z; + weights += accumulatedDegree; + + ++it; + } + } + return sum / weights; + } + + WeightedAverage* WeightedAverage::clone() const { + return new WeightedAverage(*this); + } + + Defuzzifier* WeightedAverage::constructor() { + return new WeightedAverage; + } +} diff --git a/fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp b/fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp new file mode 100644 index 0000000..760a5dc --- /dev/null +++ b/fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp @@ -0,0 +1,178 @@ +/* + 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/defuzzifier/WeightedDefuzzifier.h" + +#include "fl/term/Activated.h" +#include "fl/term/Concave.h" +#include "fl/term/Constant.h" +#include "fl/term/Function.h" +#include "fl/term/Linear.h" +#include "fl/term/Ramp.h" +#include "fl/term/Sigmoid.h" +#include "fl/term/SShape.h" +#include "fl/term/ZShape.h" + +namespace fl { + + WeightedDefuzzifier::WeightedDefuzzifier(Type type) : _type(type) { + + } + + WeightedDefuzzifier::WeightedDefuzzifier(const std::string& type) { + if (type == "Automatic") _type = Automatic; + else if (type == "TakagiSugeno") _type = TakagiSugeno; + else if (type == "Tsukamoto") _type = Tsukamoto; + else { + _type = Automatic; + FL_LOG("[warning] incorrect type <" + type + "> of WeightedDefuzzifier" + + " has been defaulted to <Automatic>"); + } + } + + WeightedDefuzzifier::~WeightedDefuzzifier() { + + } + + std::string WeightedDefuzzifier::typeName(Type type) { + switch (type) { + case Automatic: return "Automatic"; + case TakagiSugeno: return "TakagiSugeno"; + case Tsukamoto: return "Tsukamoto"; + default: return ""; + } + } + + void WeightedDefuzzifier::setType(Type type) { + this->_type = type; + } + + WeightedDefuzzifier::Type WeightedDefuzzifier::getType() const { + return this->_type; + } + + std::string WeightedDefuzzifier::getTypeName() const { + return typeName(this->_type); + } + + WeightedDefuzzifier::Type WeightedDefuzzifier::inferType(const Term* term) const { + if (dynamic_cast<const Constant*> (term) + or dynamic_cast<const Linear*> (term) + or dynamic_cast<const Function*> (term)) { + return TakagiSugeno; + } + return Tsukamoto; + } + + bool WeightedDefuzzifier::isMonotonic(const Term* term) const { + return (dynamic_cast<const Concave*> (term)) or + (dynamic_cast<const Ramp*> (term)) or + (dynamic_cast<const Sigmoid*> (term)) or + (dynamic_cast<const SShape*> (term)) or + (dynamic_cast<const ZShape*> (term)); + } + + /** + * Instead of computing y=f(x), the goal of Tsukamoto is to find x=f(w), + * where f is monotonic. + */ + scalar WeightedDefuzzifier::tsukamoto(const Term* monotonic, scalar activationDegree, + scalar minimum, scalar maximum) const { + scalar w = activationDegree; + scalar z = fl::nan; //result; + bool isTsukamoto = true; + if (const Ramp* ramp = dynamic_cast<const Ramp*> (monotonic)) { + z = Op::scale(w, 0, 1, ramp->getStart(), ramp->getEnd()); + + } else if (const Sigmoid* sigmoid = dynamic_cast<const Sigmoid*> (monotonic)) { + if (Op::isEq(w, 1.0)) { + if (Op::isGE(sigmoid->getSlope(), 0.0)) { + z = maximum; + } else { + z = minimum; + } + + } else if (Op::isEq(w, 0.0)) { + if (Op::isGE(sigmoid->getSlope(), 0.0)) { + z = minimum; + } else { + z = maximum; + } + } else { + scalar a = sigmoid->getSlope(); + scalar b = sigmoid->getInflection(); + z = b + (std::log(1.0 / w - 1.0) / -a); + } + + } else if (const SShape* sshape = dynamic_cast<const SShape*> (monotonic)) { + scalar difference = sshape->getEnd() - sshape->getStart(); + scalar a = sshape->getStart() + std::sqrt(w * difference * difference / 2.0); + scalar b = sshape->getEnd() + std::sqrt(difference * difference * (w - 1.0) / -2.0); + if (std::fabs(w - monotonic->membership(a)) < + std::fabs(w - monotonic->membership(b))) { + z = a; + } else { + z = b; + } + + } else if (const ZShape* zshape = dynamic_cast<const ZShape*> (monotonic)) { + scalar difference = zshape->getEnd() - zshape->getStart(); + scalar a = zshape->getStart() + std::sqrt(difference * difference * (w - 1.0) / -2.0); + scalar b = zshape->getEnd() + std::sqrt(w * difference * difference / 2.0); + if (std::fabs(w - monotonic->membership(a)) < + std::fabs(w - monotonic->membership(b))) { + z = a; + } else { + z = b; + } + + } else if (const Concave* concave = dynamic_cast<const Concave*> (monotonic)) { + scalar i = concave->getInflection(); + scalar e = concave->getEnd(); + z = (i - e) / concave->membership(w) + 2 * e - i; + } else { + isTsukamoto = false; + } + + if (isTsukamoto) { + //Compare difference between estimated and true value + scalar fz = monotonic->membership(z); + if (not Op::isEq(w, fz, 1e-2)) { + FL_DBG("[tsukamoto warning] difference <" << Op::str(std::abs(w - fz)) << "> " + "might suggest an inaccurate computation of z because it is " + "expected w=f(z) in " << monotonic->className() << + " term <" << monotonic->getName() << ">, but " + "w=" << w << " " + "f(z)=" << fz << " and " + "z=" << Op::str(z)); + } + } else { + // else fallback to the regular Takagi-Sugeno or inverse Tsukamoto (according to term) + z = monotonic->membership(w); + } + return z; + } + + +} diff --git a/fuzzylite/src/defuzzifier/WeightedSum.cpp b/fuzzylite/src/defuzzifier/WeightedSum.cpp new file mode 100644 index 0000000..fb3e2e3 --- /dev/null +++ b/fuzzylite/src/defuzzifier/WeightedSum.cpp @@ -0,0 +1,121 @@ +/* + 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/defuzzifier/WeightedSum.h" + +#include "fl/term/Accumulated.h" +#include "fl/term/Activated.h" +#include "fl/norm/SNorm.h" +#include "fl/norm/TNorm.h" + +#include <map> +namespace fl { + + WeightedSum::WeightedSum(Type type) : WeightedDefuzzifier(type) { + } + + WeightedSum::WeightedSum(const std::string& type) : WeightedDefuzzifier(type) { + + } + + WeightedSum::~WeightedSum() { + } + + std::string WeightedSum::className() const { + return "WeightedSum"; + } + + scalar WeightedSum::defuzzify(const Term* term, + scalar minimum, scalar maximum) const { + const Accumulated* fuzzyOutput = dynamic_cast<const Accumulated*> (term); + if (not fuzzyOutput) { + std::ostringstream ss; + ss << "[defuzzification error]" + << "expected an Accumulated term instead of" + << "<" << term->toString() << ">"; + throw fl::Exception(ss.str(), FL_AT); + } + + minimum = fuzzyOutput->getMinimum(); + maximum = fuzzyOutput->getMaximum(); + + + scalar sum = 0.0; + + if (not fuzzyOutput->getAccumulation()) { + Type type = _type; + for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) { + Activated* activated = fuzzyOutput->getTerm(i); + scalar w = activated->getDegree(); + + if (type == Automatic) type = inferType(activated->getTerm()); + + scalar z = (type == TakagiSugeno) + //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work. + ? activated->getTerm()->membership(w) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions + : tsukamoto(activated->getTerm(), w, minimum, maximum); + + sum += w * z; + } + } else { + typedef std::map<const Term*, std::vector<Activated*> > TermGroup; + TermGroup groups; + for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) { + Activated* value = fuzzyOutput->getTerm(i); + const Term* key = value->getTerm(); + groups[key].push_back(value); + } + TermGroup::const_iterator it = groups.begin(); + Type type = _type; + while (it != groups.end()) { + const Term* activatedTerm = it->first; + scalar accumulatedDegree = 0.0; + for (std::size_t i = 0; i < it->second.size(); ++i) + accumulatedDegree = fuzzyOutput->getAccumulation()->compute( + accumulatedDegree, it->second.at(i)->getDegree()); + + if (type == Automatic) type = inferType(activatedTerm); + + scalar z = (type == TakagiSugeno) + //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work. + ? activatedTerm->membership(accumulatedDegree) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions + : tsukamoto(activatedTerm, accumulatedDegree, minimum, maximum); + + sum += accumulatedDegree * z; + + ++it; + } + } + return sum; + } + + WeightedSum* WeightedSum::clone() const { + return new WeightedSum(*this); + } + + Defuzzifier* WeightedSum::constructor() { + return new WeightedSum; + } + +} diff --git a/fuzzylite/src/factory/CloningFactory.cpp b/fuzzylite/src/factory/CloningFactory.cpp new file mode 100644 index 0000000..b187171 --- /dev/null +++ b/fuzzylite/src/factory/CloningFactory.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/factory/CloningFactory.h" + +#include "fl/Exception.h" +#include "fl/term/Function.h" + +namespace fl { + + template<typename T> + CloningFactory<T>::CloningFactory(const std::string& name) : _name(name) { + + } + + template<typename T> + CloningFactory<T>::CloningFactory(const CloningFactory& other) { + typename std::map<std::string, T>::const_iterator it = other._objects.begin(); + while (it != other._objects.end()) { + T clone = fl::null; + if (it->second) clone = it->second->clone(); + this->_objects[it->first] = clone; + ++it; + } + } + + template<typename T> + CloningFactory<T>& CloningFactory<T>::operator=(const CloningFactory& other) { + if (this != &other) { + typename std::map<std::string, T>::const_iterator it = this->_objects.begin(); + while (it != this->_objects.end()) { + if (it->second) delete it->second; + ++it; + } + this->_objects.clear(); + + it = other._objects.begin(); + while (it != other._objects.end()) { + T clone = fl::null; + if (it->second) clone = it->second->clone(); + this->_objects[it->first] = clone; + ++it; + } + } + return *this; + } + + template<typename T> + CloningFactory<T>::~CloningFactory() { + typename std::map<std::string, T>::const_iterator it = this->_objects.begin(); + while (it != this->_objects.end()) { + if (it->second) delete it->second; + ++it; + } + } + + template<typename T> + std::string CloningFactory<T>::name() const { + return this->_name; + } + + template<typename T> + void CloningFactory<T>::registerObject(const std::string& key, T object) { + this->_objects[key] = object; + } + + template<typename T> + void CloningFactory<T>::deregisterObject(const std::string& key) { + typename std::map<std::string, T>::iterator it = this->_objects.find(key); + if (it != this->_objects.end()) { + this->_objects.erase(it); + delete it->second; + } + } + + template<typename T> + bool CloningFactory<T>::hasObject(const std::string& key) const { + typename std::map<std::string, T>::const_iterator it = this->_objects.find(key); + return (it != this->_objects.end()); + } + + template<typename T> + T CloningFactory<T>::getObject(const std::string& key) const { + typename std::map<std::string, T>::const_iterator it = this->_objects.find(key); + if (it != this->_objects.end()) { + if (it->second) return it->second; + } + return fl::null; + } + + template<typename T> + T CloningFactory<T>::cloneObject(const std::string& key) const { + typename std::map<std::string, T>::const_iterator it = this->_objects.find(key); + if (it != this->_objects.end()) { + if (it->second) return it->second->clone(); + return fl::null; + } + throw fl::Exception("[cloning error] " + _name + " object by name <" + key + "> not registered", FL_AT); + } + + template<typename T> + std::vector<std::string> CloningFactory<T>::available() const { + std::vector<std::string> result; + typename std::map<std::string, T>::const_iterator it = this->_objects.begin(); + while (it != this->_objects.end()) { + result.push_back(it->first); + } + return result; + } + + template class fl::CloningFactory<fl::Function::Element*>; +} + + diff --git a/fuzzylite/src/factory/ConstructionFactory.cpp b/fuzzylite/src/factory/ConstructionFactory.cpp new file mode 100644 index 0000000..b316e52 --- /dev/null +++ b/fuzzylite/src/factory/ConstructionFactory.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/factory/ConstructionFactory.h" + +#include "fl/Exception.h" +#include "fl/defuzzifier/Defuzzifier.h" +#include "fl/hedge/Hedge.h" +#include "fl/norm/SNorm.h" +#include "fl/norm/TNorm.h" +#include "fl/term/Function.h" +#include "fl/term/Term.h" + + + +namespace fl { + + template <typename T> + ConstructionFactory<T>::ConstructionFactory(const std::string& name) : _name(name) { + + } + + template <typename T> + ConstructionFactory<T>::~ConstructionFactory() { + } + + template<typename T> + std::string ConstructionFactory<T>::name() const { + return this->_name; + } + + template <typename T> + void ConstructionFactory<T>::registerConstructor(const std::string& key, Constructor constructor) { + this->_constructors[key] = constructor; + } + + template <typename T> + void ConstructionFactory<T>::deregisterConstructor(const std::string& key) { + typename std::map<std::string, Constructor>::iterator it = this->_constructors.find(key); + if (it != this->_constructors.end()) { + this->_constructors.erase(it); + } + } + + template <typename T> + bool ConstructionFactory<T>::hasConstructor(const std::string& key) const { + typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.find(key); + return (it != this->_constructors.end()); + } + + template <typename T> + typename ConstructionFactory<T>::Constructor ConstructionFactory<T>::getConstructor(const std::string& key) const { + typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.find(key); + if (it != this->_constructors.end()) { + return it->second; + } + return fl::null; + } + + template <typename T> + T ConstructionFactory<T>::constructObject(const std::string& key) const { + typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.find(key); + if (it != this->_constructors.end()) { + if (it->second) { + return it->second(); + } + return fl::null; + } + std::ostringstream ss; + ss << "[factory error] constructor of " + _name + " <" << key << "> not registered"; + throw fl::Exception(ss.str(), FL_AT); + } + + template <typename T> + std::vector<std::string> ConstructionFactory<T>::available() const { + std::vector<std::string> result; + typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.begin(); + while (it != this->_constructors.end()) { + result.push_back(it->first); + ++it; + } + return result; + } + + template class ConstructionFactory<Defuzzifier*>; + template class ConstructionFactory<Hedge*>; + template class ConstructionFactory<SNorm*>; + template class ConstructionFactory<TNorm*>; + template class ConstructionFactory<Term*>; +} + + + diff --git a/fuzzylite/src/factory/DefuzzifierFactory.cpp b/fuzzylite/src/factory/DefuzzifierFactory.cpp new file mode 100644 index 0000000..8d89c2d --- /dev/null +++ b/fuzzylite/src/factory/DefuzzifierFactory.cpp @@ -0,0 +1,78 @@ +/* + 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/factory/DefuzzifierFactory.h" + +#include "fl/defuzzifier/Bisector.h" +#include "fl/defuzzifier/Centroid.h" +#include "fl/defuzzifier/SmallestOfMaximum.h" +#include "fl/defuzzifier/LargestOfMaximum.h" +#include "fl/defuzzifier/MeanOfMaximum.h" +#include "fl/defuzzifier/WeightedAverage.h" +#include "fl/defuzzifier/WeightedSum.h" + +namespace fl { + + DefuzzifierFactory::DefuzzifierFactory() : ConstructionFactory<Defuzzifier*>("Defuzzifier") { + registerConstructor("", fl::null); + registerConstructor(Bisector().className(), &(Bisector::constructor)); + registerConstructor(Centroid().className(), &(Centroid::constructor)); + registerConstructor(LargestOfMaximum().className(), &(LargestOfMaximum::constructor)); + registerConstructor(MeanOfMaximum().className(), &(MeanOfMaximum::constructor)); + registerConstructor(SmallestOfMaximum().className(), &(SmallestOfMaximum::constructor)); + registerConstructor(WeightedAverage().className(), &(WeightedAverage::constructor)); + registerConstructor(WeightedSum().className(), &(WeightedSum::constructor)); + } + + DefuzzifierFactory::~DefuzzifierFactory() { + + } + + Defuzzifier* DefuzzifierFactory::constructDefuzzifier(const std::string& key, + int resolution, WeightedDefuzzifier::Type type) const { + Defuzzifier* result = constructObject(key); + if (IntegralDefuzzifier * integralDefuzzifier = dynamic_cast<IntegralDefuzzifier*> (result)) { + integralDefuzzifier->setResolution(resolution); + } else if (WeightedDefuzzifier * weightedDefuzzifier = dynamic_cast<WeightedDefuzzifier*> (result)) { + weightedDefuzzifier->setType(type); + } + return result; + } + + Defuzzifier* DefuzzifierFactory::constructDefuzzifier(const std::string& key, int resolution) const { + Defuzzifier* result = constructObject(key); + if (IntegralDefuzzifier * integralDefuzzifier = dynamic_cast<IntegralDefuzzifier*> (result)) { + integralDefuzzifier->setResolution(resolution); + } + return result; + } + + Defuzzifier* DefuzzifierFactory::constructDefuzzifier(const std::string& key, WeightedDefuzzifier::Type type) { + Defuzzifier* result = constructObject(key); + if (WeightedDefuzzifier * weightedDefuzzifier = dynamic_cast<WeightedDefuzzifier*> (result)) { + weightedDefuzzifier->setType(type); + } + return result; + } +} diff --git a/fuzzylite/src/factory/FactoryManager.cpp b/fuzzylite/src/factory/FactoryManager.cpp new file mode 100644 index 0000000..c2374dc --- /dev/null +++ b/fuzzylite/src/factory/FactoryManager.cpp @@ -0,0 +1,127 @@ +/* + 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/factory/FactoryManager.h" + +#include "fl/factory/DefuzzifierFactory.h" +#include "fl/factory/FunctionFactory.h" +#include "fl/factory/HedgeFactory.h" +#include "fl/factory/SNormFactory.h" +#include "fl/factory/TermFactory.h" +#include "fl/factory/TNormFactory.h" + +namespace fl { + + FactoryManager FactoryManager::_instance; + + FactoryManager* FactoryManager::instance() { + return &_instance; + } + + FactoryManager::FactoryManager() : + _tnorm(new TNormFactory), _snorm(new SNormFactory), _defuzzifier(new DefuzzifierFactory), + _term(new TermFactory), _hedge(new HedgeFactory), _function(new FunctionFactory) { + } + + FactoryManager::FactoryManager(TNormFactory* tnorm, SNormFactory* snorm, + DefuzzifierFactory* defuzzifier, TermFactory* term, + HedgeFactory* hedge, FunctionFactory* function) : + _tnorm(tnorm), _snorm(snorm), _defuzzifier(defuzzifier), _term(term), _hedge(hedge), + _function(function) { + } + + FactoryManager::FactoryManager(const FactoryManager& other) + : _tnorm(fl::null), _snorm(fl::null), _defuzzifier(fl::null), _term(fl::null), _hedge(fl::null), _function(fl::null) { + if (other._tnorm.get()) this->_tnorm.reset(new TNormFactory(*other._tnorm.get())); + if (other._snorm.get()) this->_snorm.reset(new SNormFactory(*other._snorm.get())); + if (other._defuzzifier.get()) this->_defuzzifier.reset(new DefuzzifierFactory(*other._defuzzifier.get())); + if (other._term.get()) this->_term.reset(new TermFactory(*other._term.get())); + if (other._hedge.get()) this->_hedge.reset(new HedgeFactory(*other._hedge.get())); + if (other._function.get()) this->_function.reset(new FunctionFactory(*other._function.get())); + } + + FactoryManager& FactoryManager::operator=(const FactoryManager& other) { + if (this != &other) { + if (other._tnorm.get()) this->_tnorm.reset(new TNormFactory(*other._tnorm.get())); + if (other._snorm.get()) this->_snorm.reset(new SNormFactory(*other._snorm.get())); + if (other._defuzzifier.get()) this->_defuzzifier.reset(new DefuzzifierFactory(*other._defuzzifier.get())); + if (other._term.get()) this->_term.reset(new TermFactory(*other._term.get())); + if (other._hedge.get()) this->_hedge.reset(new HedgeFactory(*other._hedge.get())); + if (other._function.get()) this->_function.reset(new FunctionFactory(*other._function.get())); + } + return *this; + } + + FactoryManager::~FactoryManager() { + } + + void FactoryManager::setTnorm(TNormFactory* tnorm) { + this->_tnorm.reset(tnorm); + } + + TNormFactory* FactoryManager::tnorm() const { + return this->_tnorm.get(); + } + + void FactoryManager::setSnorm(SNormFactory* snorm) { + this->_snorm.reset(snorm); + } + + SNormFactory* FactoryManager::snorm() const { + return this->_snorm.get(); + } + + void FactoryManager::setDefuzzifier(DefuzzifierFactory* defuzzifier) { + this->_defuzzifier.reset(defuzzifier); + } + + DefuzzifierFactory* FactoryManager::defuzzifier() const { + return this->_defuzzifier.get(); + } + + void FactoryManager::setTerm(TermFactory* term) { + this->_term.reset(term); + } + + TermFactory* FactoryManager::term() const { + return this->_term.get(); + } + + void FactoryManager::setHedge(HedgeFactory* hedge) { + this->_hedge.reset(hedge); + } + + HedgeFactory* FactoryManager::hedge() const { + return this->_hedge.get(); + } + + void FactoryManager::setFunction(FunctionFactory* function) { + this->_function.reset(function); + } + + FunctionFactory* FactoryManager::function() const { + return this->_function.get(); + } + +} diff --git a/fuzzylite/src/factory/FunctionFactory.cpp b/fuzzylite/src/factory/FunctionFactory.cpp new file mode 100644 index 0000000..3c0718d --- /dev/null +++ b/fuzzylite/src/factory/FunctionFactory.cpp @@ -0,0 +1,172 @@ +/* + 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/factory/FunctionFactory.h" + +#include "fl/rule/Rule.h" + +namespace fl { + + FunctionFactory::FunctionFactory() : CloningFactory<Function::Element*>("Function::Element") { + registerOperators(); + registerFunctions(); + } + + FunctionFactory::~FunctionFactory() { + + } + + void FunctionFactory::registerOperators() { + //OPERATORS: + int p = 100; + //First order: not, negate: + registerObject("!", new Function::Element("!", "Logical NOT", + Function::Element::OPERATOR, &(fl::Op::logicalNot), p, 1)); //logical not + registerObject("~", new Function::Element("~", "Negation", + Function::Element::OPERATOR, &(fl::Op::negate), p, 1)); // ~ negates a number + + p -= 10; + //Second order: power + registerObject("^", new Function::Element("^", "Power", + Function::Element::OPERATOR, &(std::pow), p, 1)); + + p -= 10; + //Third order: multiplication, division, modulo + registerObject("*", new Function::Element("*", "Multiplication", + Function::Element::OPERATOR, &(fl::Op::multiply), p)); + registerObject("/", new Function::Element("/", "Division", + Function::Element::OPERATOR, &(fl::Op::divide), p)); + registerObject("%", new Function::Element("%", "Modulo", + Function::Element::OPERATOR, &(fl::Op::modulo), p)); + + p -= 10; + //Fourth order: addition, subtraction + registerObject("+", new Function::Element("+", "Addition", + Function::Element::OPERATOR, &(fl::Op::add), p)); + registerObject("-", new Function::Element("-", "Subtraction", + Function::Element::OPERATOR, &(fl::Op::subtract), p)); + + //Fifth order: logical and, logical or + p -= 10; //Logical AND + registerObject(fl::Rule::andKeyword(), new Function::Element(fl::Rule::andKeyword(), "Logical AND", + Function::Element::OPERATOR, &(fl::Op::logicalAnd), p)); + p -= 10; //Logical OR + registerObject(fl::Rule::orKeyword(), new Function::Element(fl::Rule::orKeyword(), "Logical OR", + Function::Element::OPERATOR, &(fl::Op::logicalOr), p)); + } + + void FunctionFactory::registerFunctions() { + //FUNCTIONS + registerObject("gt", new Function::Element("gt", "Greater than (>)", + Function::Element::FUNCTION, &(fl::Op::gt))); + registerObject("ge", new Function::Element("ge", "Greater than or equal to (>=)", + Function::Element::FUNCTION, &(fl::Op::ge))); + registerObject("eq", new Function::Element("eq", "Equal to (==)", + Function::Element::FUNCTION, &(fl::Op::eq))); + registerObject("neq", new Function::Element("neq", "Not equal to (!=)", + Function::Element::FUNCTION, &(fl::Op::neq))); + registerObject("le", new Function::Element("le", "Less than or equal to (<=)", + Function::Element::FUNCTION, &(fl::Op::le))); + registerObject("lt", new Function::Element("lt", "Less than (<)", + Function::Element::FUNCTION, &(fl::Op::lt))); + + registerObject("acos", new Function::Element("acos", "Inverse cosine", + Function::Element::FUNCTION, &(std::acos))); + registerObject("asin", new Function::Element("asin", "Inverse sine", + Function::Element::FUNCTION, &(std::asin))); + registerObject("atan", new Function::Element("atan", "Inverse tangent", + Function::Element::FUNCTION, &(std::atan))); + + registerObject("ceil", new Function::Element("ceil", "Ceiling", + Function::Element::FUNCTION, &(std::ceil))); + registerObject("cos", new Function::Element("cos", "Cosine", + Function::Element::FUNCTION, &(std::cos))); + registerObject("cosh", new Function::Element("cosh", "Hyperbolic cosine", + Function::Element::FUNCTION, &(std::cosh))); + registerObject("exp", new Function::Element("exp", "Exponential", + Function::Element::FUNCTION, &(std::exp))); + registerObject("fabs", new Function::Element("fabs", "Absolute", + Function::Element::FUNCTION, &(std::fabs))); + registerObject("floor", new Function::Element("floor", "Floor", + Function::Element::FUNCTION, &(std::floor))); + registerObject("log", new Function::Element("log", "Natural logarithm", + Function::Element::FUNCTION, &(std::log))); + registerObject("log10", new Function::Element("log10", "Common logarithm", + Function::Element::FUNCTION, &(std::log10))); + registerObject("round", new Function::Element("round", "Round", + Function::Element::FUNCTION, &(fl::Op::round))); + registerObject("sin", new Function::Element("sin", "Sine", + Function::Element::FUNCTION, &(std::sin))); + registerObject("sinh", new Function::Element("sinh", "Hyperbolic sine", + Function::Element::FUNCTION, &(std::sinh))); + registerObject("sqrt", new Function::Element("sqrt", "Square root", + Function::Element::FUNCTION, &(std::sqrt))); + registerObject("tan", new Function::Element("tan", "Tangent", + Function::Element::FUNCTION, &(std::tan))); + registerObject("tanh", new Function::Element("tanh", "Hyperbolic tangent", + Function::Element::FUNCTION, &(std::tanh))); + +#if defined(FL_UNIX) && !defined(FL_USE_FLOAT) + //found in Unix when using double precision. not found in Windows. + registerObject("log1p", new Function::Element("log1p", "Natural logarithm plus one", + Function::Element::FUNCTION, &(log1p))); + registerObject("acosh", new Function::Element("acosh", "Inverse hyperbolic cosine", + Function::Element::FUNCTION, &(acosh))); + registerObject("asinh", new Function::Element("asinh", "Inverse hyperbolic sine", + Function::Element::FUNCTION, &(asinh))); + registerObject("atanh", new Function::Element("atanh", "Inverse hyperbolic tangent", + Function::Element::FUNCTION, &(atanh))); +#endif + + registerObject("pow", new Function::Element("pow", "Power", + Function::Element::FUNCTION, &(std::pow))); + registerObject("atan2", new Function::Element("atan2", "Inverse tangent (y,x)", + Function::Element::FUNCTION, &(std::atan2))); + registerObject("fmod", new Function::Element("fmod", "Floating-point remainder", + Function::Element::FUNCTION, &(std::fmod))); + } + + std::vector<std::string> FunctionFactory::availableOperators() const { + std::vector<std::string> result; + std::map<std::string, Function::Element*>::const_iterator it = this->_objects.begin(); + while (it != this->_objects.end()) { + if (it->second and it->second->type == Function::Element::OPERATOR) + result.push_back(it->first); + ++it; + } + return result; + } + + std::vector<std::string> FunctionFactory::availableFunctions() const { + std::vector<std::string> result; + std::map<std::string, Function::Element*>::const_iterator it = this->_objects.begin(); + while (it != this->_objects.end()) { + if (it->second and it->second->type == Function::Element::FUNCTION) + result.push_back(it->first); + ++it; + } + return result; + } + +} diff --git a/fuzzylite/src/factory/HedgeFactory.cpp b/fuzzylite/src/factory/HedgeFactory.cpp new file mode 100644 index 0000000..ea5f77a --- /dev/null +++ b/fuzzylite/src/factory/HedgeFactory.cpp @@ -0,0 +1,51 @@ +/* + 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/factory/HedgeFactory.h" + +#include "fl/hedge/Any.h" +#include "fl/hedge/Extremely.h" +#include "fl/hedge/Not.h" +#include "fl/hedge/Seldom.h" +#include "fl/hedge/Somewhat.h" +#include "fl/hedge/Very.h" + + +namespace fl { + + HedgeFactory::HedgeFactory() : ConstructionFactory<Hedge*>("Hedge") { + registerConstructor("", fl::null); + registerConstructor(Any().name(), &(Any::constructor)); + registerConstructor(Extremely().name(), &(Extremely::constructor)); + registerConstructor(Not().name(), &(Not::constructor)); + registerConstructor(Seldom().name(), &(Seldom::constructor)); + registerConstructor(Somewhat().name(), &(Somewhat::constructor)); + registerConstructor(Very().name(), &(Very::constructor)); + } + + HedgeFactory::~HedgeFactory() { + + } + +} diff --git a/fuzzylite/src/factory/SNormFactory.cpp b/fuzzylite/src/factory/SNormFactory.cpp new file mode 100644 index 0000000..6e42551 --- /dev/null +++ b/fuzzylite/src/factory/SNormFactory.cpp @@ -0,0 +1,55 @@ +/* + 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/factory/SNormFactory.h" + +#include "fl/norm/s/AlgebraicSum.h" +#include "fl/norm/s/BoundedSum.h" +#include "fl/norm/s/DrasticSum.h" +#include "fl/norm/s/EinsteinSum.h" +#include "fl/norm/s/HamacherSum.h" +#include "fl/norm/s/Maximum.h" +#include "fl/norm/s/NilpotentMaximum.h" +#include "fl/norm/s/NormalizedSum.h" + +namespace fl { + + SNormFactory::SNormFactory() : ConstructionFactory<SNorm*>("SNorm") { + registerConstructor("", fl::null); + registerConstructor(AlgebraicSum().className(), &(AlgebraicSum::constructor)); + registerConstructor(BoundedSum().className(), &(BoundedSum::constructor)); + registerConstructor(DrasticSum().className(), &(DrasticSum::constructor)); + registerConstructor(EinsteinSum().className(), &(EinsteinSum::constructor)); + registerConstructor(HamacherSum().className(), &(HamacherSum::constructor)); + registerConstructor(Maximum().className(), &(Maximum::constructor)); + registerConstructor(NilpotentMaximum().className(), &(NilpotentMaximum::constructor)); + registerConstructor(NormalizedSum().className(), &(NormalizedSum::constructor)); + } + + SNormFactory::~SNormFactory() { + + } + + +} diff --git a/fuzzylite/src/factory/TNormFactory.cpp b/fuzzylite/src/factory/TNormFactory.cpp new file mode 100644 index 0000000..95628cc --- /dev/null +++ b/fuzzylite/src/factory/TNormFactory.cpp @@ -0,0 +1,53 @@ +/* + 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/factory/TNormFactory.h" + +#include "fl/norm/t/AlgebraicProduct.h" +#include "fl/norm/t/BoundedDifference.h" +#include "fl/norm/t/DrasticProduct.h" +#include "fl/norm/t/EinsteinProduct.h" +#include "fl/norm/t/HamacherProduct.h" +#include "fl/norm/t/Minimum.h" +#include "fl/norm/t/NilpotentMinimum.h" + +namespace fl { + + TNormFactory::TNormFactory() : ConstructionFactory<TNorm*>("TNorm") { + registerConstructor("", fl::null); + registerConstructor(AlgebraicProduct().className(), &(AlgebraicProduct::constructor)); + registerConstructor(BoundedDifference().className(), &(BoundedDifference::constructor)); + registerConstructor(DrasticProduct().className(), &(DrasticProduct::constructor)); + registerConstructor(EinsteinProduct().className(), &(EinsteinProduct::constructor)); + registerConstructor(HamacherProduct().className(), &(HamacherProduct::constructor)); + registerConstructor(Minimum().className(), &(Minimum::constructor)); + registerConstructor(NilpotentMinimum().className(), &(NilpotentMinimum::constructor)); + } + + TNormFactory::~TNormFactory() { + + } + + +} diff --git a/fuzzylite/src/factory/TermFactory.cpp b/fuzzylite/src/factory/TermFactory.cpp new file mode 100644 index 0000000..10f3c15 --- /dev/null +++ b/fuzzylite/src/factory/TermFactory.cpp @@ -0,0 +1,81 @@ +/* + 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/factory/TermFactory.h" + +#include "fl/Exception.h" +#include "fl/term/Term.h" +#include "fl/term/Bell.h" +#include "fl/term/Concave.h" +#include "fl/term/Constant.h" +#include "fl/term/Cosine.h" +#include "fl/term/Discrete.h" +#include "fl/term/Function.h" +#include "fl/term/Gaussian.h" +#include "fl/term/GaussianProduct.h" +#include "fl/term/Linear.h" +#include "fl/term/PiShape.h" +#include "fl/term/Ramp.h" +#include "fl/term/Rectangle.h" +#include "fl/term/SShape.h" +#include "fl/term/Sigmoid.h" +#include "fl/term/SigmoidDifference.h" +#include "fl/term/SigmoidProduct.h" +#include "fl/term/Spike.h" +#include "fl/term/Trapezoid.h" +#include "fl/term/Triangle.h" +#include "fl/term/ZShape.h" + +namespace fl { + + TermFactory::TermFactory() : ConstructionFactory<Term*>("Term") { + registerConstructor("", fl::null); + registerConstructor(Bell().className(), &(Bell::constructor)); + registerConstructor(Concave().className(), &(Concave::constructor)); + registerConstructor(Constant().className(), &(Constant::constructor)); + registerConstructor(Cosine().className(), &(Cosine::constructor)); + registerConstructor(Discrete().className(), &(Discrete::constructor)); + registerConstructor(Function().className(), &(Function::constructor)); + registerConstructor(Gaussian().className(), &(Gaussian::constructor)); + registerConstructor(GaussianProduct().className(), &(GaussianProduct::constructor)); + registerConstructor(Linear().className(), &(Linear::constructor)); + registerConstructor(PiShape().className(), &(PiShape::constructor)); + registerConstructor(Ramp().className(), &(Ramp::constructor)); + registerConstructor(Rectangle().className(), &(Rectangle::constructor)); + registerConstructor(SShape().className(), &(SShape::constructor)); + registerConstructor(Sigmoid().className(), &(Sigmoid::constructor)); + registerConstructor(SigmoidDifference().className(), &(SigmoidDifference::constructor)); + registerConstructor(SigmoidProduct().className(), &(SigmoidProduct::constructor)); + registerConstructor(Spike().className(), &(Spike::constructor)); + registerConstructor(Trapezoid().className(), &(Trapezoid::constructor)); + registerConstructor(Triangle().className(), &(Triangle::constructor)); + registerConstructor(ZShape().className(), &(ZShape::constructor)); + } + + TermFactory::~TermFactory() { + + } + + +} diff --git a/fuzzylite/src/fuzzylite.cpp b/fuzzylite/src/fuzzylite.cpp new file mode 100644 index 0000000..06b635a --- /dev/null +++ b/fuzzylite/src/fuzzylite.cpp @@ -0,0 +1,128 @@ +/* + 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/fuzzylite.h" + +namespace fl { + + int fuzzylite::_decimals = 3; + scalar fuzzylite::_macheps = 1e-6; + bool fuzzylite::_debug = false; + bool fuzzylite::_logging = true; + + std::string fuzzylite::name() { + return "fuzzylite"; + } + + std::string fuzzylite::fullname() { + return name() + "-" + longVersion(); + } + + std::string fuzzylite::version() { + return FL_VERSION; + } + + std::string fuzzylite::longVersion() { + return FL_VERSION "b" FL_DATE; + } + + std::string fuzzylite::license() { + return "GNU Lesser General Public License v3.0"; + } + + std::string fuzzylite::author() { + return "Juan Rada-Vilela, Ph.D."; + } + + std::string fuzzylite::company() { + return "FuzzyLite Limited"; + } + + std::string fuzzylite::website() { + return "http://www.fuzzylite.com/"; + } + + std::string fuzzylite::date() { + return FL_DATE; + } + + std::string fuzzylite::platform() { +#ifdef FL_UNIX + return "Unix"; +#elif defined FL_WINDOWS + return "Windows"; +#else + return "?"; +#endif + } + + std::string fuzzylite::floatingPoint() { + scalar someScalar = 0; + (void) someScalar; + std::string type; + + std::ostringstream ss; +#ifdef FL_USE_FLOAT + type = "float"; +#else + type = "double"; +#endif + ss << "fl::scalar is defined as \'" << type << "\' using " << + sizeof (someScalar) << " bytes"; + return ss.str(); + } + + void fuzzylite::setDebug(bool debug) { + _debug = debug; + } + + bool fuzzylite::debug() { + return _debug; + } + + void fuzzylite::setDecimals(int decimals) { + _decimals = decimals; + } + + int fuzzylite::decimals() { + return _decimals; + } + + void fuzzylite::setMachEps(scalar macheps) { + _macheps = macheps; + } + + scalar fuzzylite::macheps() { + return _macheps; + } + + void fuzzylite::setLogging(bool logging) { + _logging = logging; + } + + bool fuzzylite::logging() { + return _logging; + } + +} diff --git a/fuzzylite/src/hedge/Any.cpp b/fuzzylite/src/hedge/Any.cpp new file mode 100644 index 0000000..72724f1 --- /dev/null +++ b/fuzzylite/src/hedge/Any.cpp @@ -0,0 +1,52 @@ +/* + 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/hedge/Any.h" + +namespace fl { + + Any::Any() { + } + + Any::~Any() { + } + + std::string Any::name() const { + return "any"; + } + + scalar Any::hedge(scalar x) const { + (void) x; + return 1.0; + } + + Any* Any::clone() const { + return new Any(*this); + } + + Hedge* Any::constructor() { + return new Any; + } + +} diff --git a/fuzzylite/src/hedge/Extremely.cpp b/fuzzylite/src/hedge/Extremely.cpp new file mode 100644 index 0000000..eabbb60 --- /dev/null +++ b/fuzzylite/src/hedge/Extremely.cpp @@ -0,0 +1,50 @@ +/* + 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/hedge/Extremely.h" + +#include "fl/Operation.h" + +namespace fl { + + std::string Extremely::name() const { + return "extremely"; + } + + scalar Extremely::hedge(scalar x) const { + return Op::isLE(x, 0.5) + ? 2.0 * x * x + : 1.0 - 2.0 * (1.0 - x) * (1.0 - x); + } + + Extremely* Extremely::clone() const { + return new Extremely(*this); + } + + Hedge* Extremely::constructor() { + return new Extremely; + } + + +} diff --git a/fuzzylite/src/hedge/Not.cpp b/fuzzylite/src/hedge/Not.cpp new file mode 100644 index 0000000..531213f --- /dev/null +++ b/fuzzylite/src/hedge/Not.cpp @@ -0,0 +1,46 @@ +/* + 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/hedge/Not.h" + +namespace fl { + + std::string Not::name() const { + return "not"; + } + + scalar Not::hedge(scalar x) const { + return 1.0 - x; + } + + Not* Not::clone() const { + return new Not(*this); + } + + Hedge* Not::constructor() { + return new Not; + } + + +} diff --git a/fuzzylite/src/hedge/Seldom.cpp b/fuzzylite/src/hedge/Seldom.cpp new file mode 100644 index 0000000..d87b48a --- /dev/null +++ b/fuzzylite/src/hedge/Seldom.cpp @@ -0,0 +1,50 @@ +/* + 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/hedge/Seldom.h" + +#include "fl/Operation.h" + +namespace fl { + + std::string Seldom::name() const { + return "seldom"; + } + + scalar Seldom::hedge(scalar x) const { + return Op::isLE(x, 0.5) + ? std::sqrt(x / 2.0) + : 1.0 - std::sqrt((1.0 - x) / 2.0); + } + + Seldom* Seldom::clone() const { + return new Seldom(*this); + } + + Hedge* Seldom::constructor() { + return new Seldom; + } + + +} diff --git a/fuzzylite/src/hedge/Somewhat.cpp b/fuzzylite/src/hedge/Somewhat.cpp new file mode 100644 index 0000000..16c371b --- /dev/null +++ b/fuzzylite/src/hedge/Somewhat.cpp @@ -0,0 +1,45 @@ +/* + 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/hedge/Somewhat.h" + +namespace fl { + + std::string Somewhat::name() const { + return "somewhat"; + } + + scalar Somewhat::hedge(scalar x) const { + return std::sqrt(x); + } + + Somewhat* Somewhat::clone() const { + return new Somewhat(*this); + } + + Hedge* Somewhat::constructor() { + return new Somewhat; + } + +} diff --git a/fuzzylite/src/hedge/Very.cpp b/fuzzylite/src/hedge/Very.cpp new file mode 100644 index 0000000..dc1fbec --- /dev/null +++ b/fuzzylite/src/hedge/Very.cpp @@ -0,0 +1,45 @@ +/* + 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/hedge/Very.h" + +namespace fl { + + std::string Very::name() const { + return "very"; + } + + scalar Very::hedge(scalar x) const { + return x * x; + } + + Very* Very::clone() const { + return new Very(*this); + } + + Hedge* Very::constructor() { + return new Very; + } + +} diff --git a/fuzzylite/src/imex/CppExporter.cpp b/fuzzylite/src/imex/CppExporter.cpp new file mode 100644 index 0000000..7b21087 --- /dev/null +++ b/fuzzylite/src/imex/CppExporter.cpp @@ -0,0 +1,234 @@ +/* + 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/imex/CppExporter.h" + +#include "fl/Headers.h" + +#include <algorithm> + +namespace fl { + + CppExporter::CppExporter(bool prefixNamespace) : Exporter(), + _prefixNamespace(prefixNamespace) { + } + + CppExporter::~CppExporter() { + } + + std::string CppExporter::name() const { + return "CppExporter"; + } + + std::string CppExporter::fl(const std::string& clazz) const { + return _prefixNamespace ? "fl::" + clazz : clazz; + } + + void CppExporter::setPrefixNamespace(bool prefixNamespace){ + this->_prefixNamespace = prefixNamespace; + } + + bool CppExporter::isPrefixNamespace() const{ + return this->_prefixNamespace; + } + + std::string CppExporter::toString(const Engine* engine) const { + std::ostringstream cpp; + if (not _prefixNamespace) cpp << "using namespace fl;\n\n"; + cpp << fl("Engine* ") << "engine = new " << fl("Engine;\n"); + cpp << "engine->setName(\"" << engine->getName() << "\");\n"; + + cpp << "\n"; + + for (int i = 0; i < engine->numberOfInputVariables(); ++i) { + cpp << toString(engine->getInputVariable(i), engine) << "\n"; + } + + for (int i = 0; i < engine->numberOfOutputVariables(); ++i) { + cpp << toString(engine->getOutputVariable(i), engine) << "\n"; + } + + for (int i = 0; i < engine->numberOfRuleBlocks(); ++i) { + cpp << toString(engine->getRuleBlock(i), engine) << "\n"; + } + + return cpp.str(); + } + + std::string CppExporter::toString(const InputVariable* inputVariable, const Engine* engine) const { + std::ostringstream ss; + std::string name = "inputVariable"; + if (engine->numberOfInputVariables() > 1) { + int index = std::distance(engine->inputVariables().begin(), + std::find(engine->inputVariables().begin(), + engine->inputVariables().end(), inputVariable)); + name += Op::str<int>(index + 1); + } + ss << fl("InputVariable* ") << name << " = new " << fl("InputVariable;\n"); + ss << name << "->setEnabled(" << (inputVariable->isEnabled() ? "true" : "false") << ");\n"; + ss << name << "->setName(\"" << inputVariable->getName() << "\");\n"; + ss << name << "->setRange(" << + toString(inputVariable->getMinimum()) << ", " << + toString(inputVariable->getMaximum()) << ");\n"; + for (int t = 0; t < inputVariable->numberOfTerms(); ++t) { + ss << name << "->addTerm(" << toString(inputVariable->getTerm(t)) << ");\n"; + } + ss << "engine->addInputVariable(" << name << ");\n"; + return ss.str(); + } + + std::string CppExporter::toString(const OutputVariable* outputVariable, const Engine* engine) const { + std::ostringstream ss; + std::string name = "outputVariable"; + if (engine->numberOfOutputVariables() > 1) { + int index = std::distance(engine->outputVariables().begin(), + std::find(engine->outputVariables().begin(), + engine->outputVariables().end(), outputVariable)); + name += Op::str<int>(index + 1); + } + ss << fl("OutputVariable* ") << name << " = new " << fl("OutputVariable;\n"); + ss << name << "->setEnabled(" << (outputVariable->isEnabled() ? "true" : "false") << ");\n"; + ss << name << "->setName(\"" << outputVariable->getName() << "\");\n"; + ss << name << "->setRange(" << + toString(outputVariable->getMinimum()) << ", " << + toString(outputVariable->getMaximum()) << ");\n"; + ss << name << "->fuzzyOutput()->setAccumulation(" << + toString(outputVariable->fuzzyOutput()->getAccumulation()) << ");\n"; + ss << name << "->setDefuzzifier(" << + toString(outputVariable->getDefuzzifier()) << ");\n"; + ss << name << "->setDefaultValue(" << + toString(outputVariable->getDefaultValue()) << ");\n"; + ss << name << "->setLockPreviousOutputValue(" << + (outputVariable->isLockedPreviousOutputValue() ? "true" : "false") << ");\n"; + ss << name << "->setLockOutputValueInRange(" << + (outputVariable->isLockedOutputValueInRange() ? "true" : "false") << ");\n"; + for (int t = 0; t < outputVariable->numberOfTerms(); ++t) { + ss << name << "->addTerm(" << toString(outputVariable->getTerm(t)) << ");\n"; + } + ss << "engine->addOutputVariable(" << name << ");\n"; + return ss.str(); + } + + //TODO: addRules using `new Rule` instead of `Rule::parse` in version 6.0 + std::string CppExporter::toString(const RuleBlock* ruleBlock, const Engine* engine) const { + std::ostringstream ss; + std::string name = "ruleBlock"; + if (engine->numberOfRuleBlocks() > 1) { + int index = std::distance(engine->ruleBlocks().begin(), + std::find(engine->ruleBlocks().begin(), + engine->ruleBlocks().end(), ruleBlock)); + name += Op::str<int>(index + 1); + } + ss << fl("RuleBlock* ") << name << " = new " << fl("RuleBlock;\n"); + ss << name << "->setEnabled(" << (ruleBlock->isEnabled() ? "true" : "false") << ");\n"; + ss << name << "->setName(\"" << ruleBlock->getName() << "\");\n"; + ss << name << "->setConjunction(" << + toString(ruleBlock->getConjunction()) << ");\n"; + ss << name << "->setDisjunction(" + << toString(ruleBlock->getDisjunction()) << ");\n"; + ss << name << "->setActivation(" + << toString(ruleBlock->getActivation()) << ");\n"; + for (int r = 0; r < ruleBlock->numberOfRules(); ++r) { + ss << name << "->addRule(" << "fl::Rule::parse(\"" << + ruleBlock->getRule(r)->getText() << "\", engine));\n"; + } + ss << "engine->addRuleBlock(" << name << ");\n"; + return ss.str(); + } + + std::string CppExporter::toString(scalar value) const { + if (fl::Op::isNaN(value)) + return "fl::nan"; + if (fl::Op::isInf(value)){ + return (value > 0 ? "fl::inf" : "-fl::inf"); + } + return fl::Op::str(value); + } + + std::string CppExporter::toString(const Term* term) const { + if (not term) return "fl::null"; + + if (const Discrete * discrete = dynamic_cast<const Discrete*> (term)) { + std::ostringstream ss; + ss << fl(term->className()) << "::create(\"" << term->getName() << "\", " + << discrete->xy().size() * 2 << ", " + << fl::Op::join(Discrete::toVector(discrete->xy()), ", ") << ")"; + return ss.str(); + } + + if (const Function * function = dynamic_cast<const Function*> (term)) { + std::ostringstream ss; + ss << fl(term->className()) << "::create(\"" << term->getName() << "\", " + << "\"" << function->getFormula() << "\", engine)"; + return ss.str(); + } + + if (const Linear * linear = dynamic_cast<const Linear*> (term)) { + std::ostringstream ss; + ss << fl(term->className()) << "::create(\"" << term->getName() << "\", " + << "engine, " << fl::Op::join(linear->coefficients(), ", ") << ")"; + return ss.str(); + } + + std::ostringstream ss; + ss << "new " << fl(term->className()) << "(\"" << term->getName() << "\", " + << Op::findReplace(term->parameters(), " ", ", ") << ")"; + return ss.str(); + } + + std::string CppExporter::toString(const Hedge * hedge) const { + if (hedge->name() == Any().name()) return "new " + fl("Any"); + if (hedge->name() == Extremely().name()) return "new " + fl("Extremely"); + if (hedge->name() == Not().name()) return "new " + fl("Not"); + if (hedge->name() == Seldom().name()) return "new " + fl("Seldom"); + if (hedge->name() == Somewhat().name()) return "new " + fl("Somewhat"); + if (hedge->name() == Very().name()) return "new " + fl("Very"); + return "new " + fl(hedge->name()); + } + + std::string CppExporter::toString(const Norm* op) const { + if (not op) return "fl::null"; + return "new " + fl(op->className()); + } + + std::string CppExporter::toString(const Defuzzifier* defuzzifier) const { + if (not defuzzifier) return "fl::null"; + if (const IntegralDefuzzifier * integralDefuzzifier = + dynamic_cast<const IntegralDefuzzifier*> (defuzzifier)) { + return "new " + fl(integralDefuzzifier->className()) + "(" + + fl::Op::str(integralDefuzzifier->getResolution()) + ")"; + } + if (const WeightedDefuzzifier * weightedDefuzzifier = + dynamic_cast<const WeightedDefuzzifier*> (defuzzifier)) { + return "new " + weightedDefuzzifier->className() + + "(\"" + weightedDefuzzifier->getTypeName() + "\")"; + } + return "new " + fl(defuzzifier->className()); + } + + CppExporter* CppExporter::clone() const { + return new CppExporter(*this); + } + +} diff --git a/fuzzylite/src/imex/Exporter.cpp b/fuzzylite/src/imex/Exporter.cpp new file mode 100644 index 0000000..5b0fe1b --- /dev/null +++ b/fuzzylite/src/imex/Exporter.cpp @@ -0,0 +1,49 @@ +/* + 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/imex/Exporter.h" +#include "fl/Exception.h" + +#include <fstream> + +namespace fl { + + Exporter::Exporter() { + + } + + Exporter::~Exporter() { + + } + + void Exporter::toFile(const std::string& path, const Engine* engine) const { + std::ofstream writer(path.c_str()); + if (not writer.is_open()) { + throw fl::Exception("[file error] file <" + path + "> could not be created", FL_AT); + } + writer << toString(engine) << std::endl; + writer.close(); + } + +} diff --git a/fuzzylite/src/imex/FclExporter.cpp b/fuzzylite/src/imex/FclExporter.cpp new file mode 100644 index 0000000..cf8ffb0 --- /dev/null +++ b/fuzzylite/src/imex/FclExporter.cpp @@ -0,0 +1,256 @@ +/* + 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/imex/FclExporter.h" + +#include "fl/Headers.h" + +#include <sstream> + +namespace fl { + + FclExporter::FclExporter(const std::string& indent) : Exporter(), _indent(indent) { + } + + FclExporter::~FclExporter() { + } + + void FclExporter::setIndent(const std::string& indent) { + this->_indent = indent; + } + + std::string FclExporter::getIndent() const { + return this->_indent; + } + + std::string FclExporter::name() const { + return "FclExporter"; + } + + std::string FclExporter::toString(const Engine* engine) const { + std::ostringstream fcl; + fcl << "FUNCTION_BLOCK " << engine->getName() << "\n\n"; + + fcl << "VAR_INPUT\n"; + for (int i = 0; i < engine->numberOfInputVariables(); ++i) { + fcl << _indent << Op::validName(engine->getInputVariable(i)->getName()) << ": REAL;\n"; + } + fcl << "END_VAR\n\n"; + + fcl << "VAR_OUTPUT\n"; + for (int i = 0; i < engine->numberOfOutputVariables(); ++i) { + fcl << _indent << Op::validName(engine->getOutputVariable(i)->getName()) << ": REAL;\n"; + } + fcl << "END_VAR\n\n"; + + for (int i = 0; i < engine->numberOfInputVariables(); ++i) { + InputVariable* inputVariable = engine->getInputVariable(i); + fcl << toString(inputVariable) << "\n"; + } + + for (int i = 0; i < engine->numberOfOutputVariables(); ++i) { + OutputVariable* outputVariable = engine->getOutputVariable(i); + fcl << toString(outputVariable) << "\n"; + } + + for (int i = 0; i < engine->numberOfRuleBlocks(); ++i) { + RuleBlock* ruleblock = engine->getRuleBlock(i); + fcl << toString(ruleblock) << "\n"; + } + + fcl << "END_FUNCTION_BLOCK\n"; + return fcl.str(); + } + + std::string FclExporter::toString(const InputVariable* inputVariable) const { + std::ostringstream fcl; + fcl << "FUZZIFY " << Op::validName(inputVariable->getName()) << "\n"; + if (not inputVariable->isEnabled()) { + fcl << _indent << "ENABLED : " << + (inputVariable->isEnabled() ? "TRUE" : "FALSE") << ";\n"; + } + fcl << _indent << "RANGE := (" << fl::Op::join(2, " .. ", + inputVariable->getMinimum(), inputVariable->getMaximum()) + << ");\n"; + + for (int t = 0; t < inputVariable->numberOfTerms(); ++t) { + Term* term = inputVariable->getTerm(t); + fcl << _indent << "TERM " << Op::validName(term->getName()) << " := " << toString(term) + << ";\n"; + } + fcl << "END_FUZZIFY\n"; + return fcl.str(); + } + + std::string FclExporter::toString(const OutputVariable* outputVariable) const { + std::ostringstream fcl; + fcl << "DEFUZZIFY " << Op::validName(outputVariable->getName()) << "\n"; + if (not outputVariable->isEnabled()) { + fcl << _indent << "ENABLED : " << + (outputVariable->isEnabled() ? "TRUE" : "FALSE") << ";\n"; + } + fcl << _indent << "RANGE := (" << fl::Op::join(2, " .. ", + outputVariable->getMinimum(), outputVariable->getMaximum()) + << ");\n"; + + for (int t = 0; t < outputVariable->numberOfTerms(); ++t) { + Term* term = outputVariable->getTerm(t); + fcl << _indent << "TERM " << Op::validName(term->getName()) << " := " << toString(term) + << ";\n"; + } + if (outputVariable->getDefuzzifier()) { + fcl << _indent << "METHOD : " << toString(outputVariable->getDefuzzifier()) << ";\n"; + } + if (outputVariable->fuzzyOutput()->getAccumulation()) + fcl << _indent << "ACCU : " << toString(outputVariable->fuzzyOutput()->getAccumulation()) << ";\n"; + + fcl << _indent << "DEFAULT := " << fl::Op::str(outputVariable->getDefaultValue()); + if (outputVariable->isLockedPreviousOutputValue()) { + fcl << " | NC"; + } + fcl << ";\n"; + + if (outputVariable->isLockedOutputValueInRange()) { + fcl << _indent << "LOCK : RANGE;\n"; + } + + fcl << "END_DEFUZZIFY\n"; + return fcl.str(); + } + + std::string FclExporter::toString(const RuleBlock* ruleBlock) const { + std::ostringstream fcl; + fcl << "RULEBLOCK " << ruleBlock->getName() << "\n"; + if (not ruleBlock->isEnabled()) { + fcl << _indent << "ENABLED : " << + (ruleBlock->isEnabled() ? "TRUE" : "FALSE") << ";\n"; + } + if (ruleBlock->getConjunction()) + fcl << _indent << "AND : " << toString(ruleBlock->getConjunction()) << ";\n"; + if (ruleBlock->getDisjunction()) + fcl << _indent << "OR : " << toString(ruleBlock->getDisjunction()) << ";\n"; + if (ruleBlock->getActivation()) + fcl << _indent << "ACT : " << toString(ruleBlock->getActivation()) << ";\n"; + + for (int r = 0; r < ruleBlock->numberOfRules(); ++r) { + fcl << _indent << "RULE " << (r + 1) << " : " << + ruleBlock->getRule(r)->getText() << "\n"; + } + fcl << "END_RULEBLOCK\n"; + return fcl.str(); + } + + std::string FclExporter::toString(const Norm* norm) const{ + if (not norm) return "NONE"; + + std::string name = norm->className(); + //TNorms + if (name == Minimum().className()) return "MIN"; + if (name == AlgebraicProduct().className()) return "PROD"; + if (name == BoundedDifference().className()) return "BDIF"; + if (name == DrasticProduct().className()) return "DPROD"; + if (name == EinsteinProduct().className()) return "EPROD"; + if (name == HamacherProduct().className()) return "HPROD"; + if (name == NilpotentMinimum().className()) return "NMIN"; + + //SNorms + if (name == Maximum().className()) return "MAX"; + if (name == AlgebraicSum().className()) return "ASUM"; + if (name == NormalizedSum().className()) return "NSUM"; + if (name == BoundedSum().className()) return "BSUM"; + if (name == DrasticSum().className()) return "DSUM"; + if (name == EinsteinSum().className()) return "ESUM"; + if (name == HamacherSum().className()) return "HSUM"; + if (name == NilpotentMaximum().className()) return "NMAX"; + + return norm->className(); + } + + //TODO: Delete in v6.0 + std::string FclExporter::toString(const TNorm* tnorm) const { + if (not tnorm) return "NONE"; + std::string name = tnorm->className(); + if (name == Minimum().className()) return "MIN"; + if (name == AlgebraicProduct().className()) return "PROD"; + if (name == BoundedDifference().className()) return "BDIF"; + if (name == DrasticProduct().className()) return "DPROD"; + if (name == EinsteinProduct().className()) return "EPROD"; + if (name == HamacherProduct().className()) return "HPROD"; + if (name == NilpotentMinimum().className()) return "NMIN"; + return tnorm->className(); + } + + //TODO: Delete in v6.0 + std::string FclExporter::toString(const SNorm* snorm) const { + if (not snorm) return "NONE"; + std::string name = snorm->className(); + if (name == Maximum().className()) return "MAX"; + if (name == AlgebraicSum().className()) return "ASUM"; + if (name == NormalizedSum().className()) return "NSUM"; + if (name == BoundedSum().className()) return "BSUM"; + if (name == DrasticSum().className()) return "DSUM"; + if (name == EinsteinSum().className()) return "ESUM"; + if (name == HamacherSum().className()) return "HSUM"; + if (name == NilpotentMaximum().className()) return "NMAX"; + return snorm->className(); + } + + std::string FclExporter::toString(const Defuzzifier* defuzzifier) const { + if (not defuzzifier) return "NONE"; + if (defuzzifier->className() == Centroid().className()) return "COG"; + if (defuzzifier->className() == Bisector().className()) return "COA"; + if (defuzzifier->className() == SmallestOfMaximum().className()) return "LM"; + if (defuzzifier->className() == LargestOfMaximum().className()) return "RM"; + if (defuzzifier->className() == MeanOfMaximum().className()) return "MM"; + if (defuzzifier->className() == WeightedAverage().className()) return "COGS"; + if (defuzzifier->className() == WeightedSum().className()) return "COGSS"; + return defuzzifier->className(); + } + + std::string FclExporter::toString(const Term* term) const { + if (not term) return ""; + if (const Discrete * discrete = dynamic_cast<const Discrete*> (term)) { + std::ostringstream ss; + for (std::size_t i = 0; i < discrete->xy().size(); ++i) { + ss << "(" << fl::Op::str(discrete->xy(i).first) << ", " + << fl::Op::str(discrete->xy(i).second) << ")"; + if (i + 1 < discrete->xy().size()) ss << " "; + } + return ss.str(); + } + + if (const Constant * constant = dynamic_cast<const Constant*> (term)) { + return fl::Op::str(constant->getValue()); + } + + std::ostringstream ss; + ss << term->className() << " " << term->parameters(); + return ss.str(); + } + + FclExporter* FclExporter::clone() const { + return new FclExporter(*this); + } + + +} diff --git a/fuzzylite/src/imex/FclImporter.cpp b/fuzzylite/src/imex/FclImporter.cpp new file mode 100644 index 0000000..a56a9e1 --- /dev/null +++ b/fuzzylite/src/imex/FclImporter.cpp @@ -0,0 +1,607 @@ +/* + 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/imex/FclImporter.h" + +#include "fl/Headers.h" + +#include <iostream> +#include <sstream> + +namespace fl { + + FclImporter::FclImporter() : Importer() { + } + + FclImporter::~FclImporter() { + } + + std::string FclImporter::name() const { + return "FclImporter"; + } + + Engine* FclImporter::fromString(const std::string& fcl) const { + FL_unique_ptr<Engine> engine(new Engine); + + std::map<std::string, std::string> tags; + tags["VAR_INPUT"] = "END_VAR"; + tags["VAR_OUTPUT"] = "END_VAR"; + tags["FUZZIFY"] = "END_FUZZIFY"; + tags["DEFUZZIFY"] = "END_DEFUZZIFY"; + tags["RULEBLOCK"] = "END_RULEBLOCK"; + std::map<std::string, std::string>::const_iterator tagFinder; + + std::string currentTag = "", closingTag = ""; + std::ostringstream block; + std::istringstream fclReader(fcl); + std::string line; + + int lineNumber = 0; + while (std::getline(fclReader, line)) { + ++lineNumber; + std::vector<std::string> comments; + comments = Op::split(line, "//"); + if (comments.size() > 1) { + line = comments.front(); + } + comments = Op::split(line, "#"); + if (comments.size() > 1) { + line = comments.front(); + } + line = Op::trim(line); + if (line.empty() or line.at(0) == '%' or line.at(0) == '#' + or (line.substr(0, 2) == "//")) { + continue; + } + line = fl::Op::findReplace(line, ";", ""); + std::istringstream tokenizer(line); + std::string firstToken; + tokenizer >> firstToken; + + if (firstToken == "FUNCTION_BLOCK") { + if (tokenizer.rdbuf()->in_avail() > 0) { + std::ostringstream name; + std::string token; + tokenizer >> token; + name << token; + while (tokenizer >> token) { + name << " " << token; + } + engine->setName(name.str()); + } + continue; + } + if (firstToken == "END_FUNCTION_BLOCK") { + break; + } + + if (currentTag.empty()) { + tagFinder = tags.find(firstToken); + if (tagFinder == tags.end()) { + std::ostringstream ex; + ex << "[syntax error] unknown block definition <" << firstToken + << "> " << " in line " << lineNumber << ": " << line; + throw fl::Exception(ex.str(), FL_AT); + } + currentTag = tagFinder->first; + closingTag = tagFinder->second; + block.str(""); + block.clear(); + block << line << "\n"; + continue; + } + + if (not currentTag.empty()) { + if (firstToken == closingTag) { + processBlock(currentTag, block.str(), engine.get()); + currentTag = ""; + closingTag = ""; + } else if (tags.find(firstToken) != tags.end()) { + //if opening new block without closing the previous one + std::ostringstream ex; + ex << "[syntax error] expected <" << closingTag << "> before <" + << firstToken << "> in line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } else { + block << line << "\n"; + } + continue; + } + } + + if (not currentTag.empty()) { + std::ostringstream ex; + ex << "[syntax error] "; + if (block.rdbuf()->in_avail() > 0) { + ex << "expected <" << closingTag << "> for block:\n" << block.str(); + } else { + ex << "expected <" << closingTag << ">, but not found"; + } + throw fl::Exception(ex.str(), FL_AT); + } + return engine.release(); + } + + void FclImporter::processBlock(const std::string& tag, const std::string& block, Engine* engine) const { + if (tag == "VAR_INPUT" or tag == "VAR_OUTPUT") { + processVar(tag, block, engine); + } else if (tag == "FUZZIFY") { + processFuzzify(block, engine); + } else if (tag == "DEFUZZIFY") { + processDefuzzify(block, engine); + } else if (tag == "RULEBLOCK") { + processRuleBlock(block, engine); + } else { + std::ostringstream ex; + ex << "[syntax error] unexpected tag <" << tag << "> for block:\n" << block; + throw fl::Exception(ex.str(), FL_AT); + } + } + + void FclImporter::processVar(const std::string& tag, const std::string& block, Engine* engine)const { + std::istringstream blockReader(block); + std::string line; + + std::getline(blockReader, line); //discard first line as it is VAR_INPUT + while (std::getline(blockReader, line)) { + std::vector<std::string> token = Op::split(line, ":"); + if (token.size() != 2) { + std::ostringstream ex; + ex << "[syntax error] expected property of type (key : value) in line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } + std::string name = fl::Op::validName(token.at(0)); + if (tag == "VAR_INPUT") + engine->addInputVariable(new InputVariable(name)); + else if (tag == "VAR_OUTPUT") + engine->addOutputVariable(new OutputVariable(name)); + else { + std::ostringstream ex; + ex << "[syntax error] unexpected tag <" << tag << "> in line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } + } + } + + void FclImporter::processFuzzify(const std::string& block, Engine* engine)const { + std::istringstream blockReader(block); + std::string line; + + std::getline(blockReader, line); + std::string name; + std::size_t index = line.find_first_of(' '); + if (index != std::string::npos) { + name = fl::Op::validName(line.substr(index + 1)); + } else { + std::ostringstream ex; + ex << "[syntax error] expected name of input variable in line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } + if (not engine->hasInputVariable(name)) { + std::ostringstream ex; + ex << "[syntax error] engine does not contain " + "input variable <" << name << "> from line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } + + InputVariable* inputVariable = engine->getInputVariable(name); + while (std::getline(blockReader, line)) { + std::istringstream ss(line); + std::string firstToken; + ss >> firstToken; + try { + if (firstToken == "RANGE") { + std::pair<scalar, scalar> minmax = parseRange(line); + inputVariable->setMinimum(minmax.first); + inputVariable->setMaximum(minmax.second); + } else if (firstToken == "ENABLED") { + inputVariable->setEnabled(parseEnabled(line)); + } else if (firstToken == "TERM") { + inputVariable->addTerm(parseTerm(line, engine)); + } else throw fl::Exception("[syntax error] unexpected token " + "<" + firstToken + ">" + line, FL_AT); + } catch (fl::Exception& ex) { + ex.append("At line: <" + line + ">"); + throw; + } + } + + } + + void FclImporter::processDefuzzify(const std::string& block, Engine* engine) const { + std::istringstream blockReader(block); + std::string line; + + std::getline(blockReader, line); + std::string name; + std::size_t index = line.find_first_of(' '); + if (index != std::string::npos) { + name = fl::Op::validName(line.substr(index + 1)); + } else { + std::ostringstream ex; + ex << "[syntax error] expected an output variable name in line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } + if (not engine->hasOutputVariable(name)) { + std::ostringstream ex; + ex << "[syntax error] output variable <" << name + << "> not registered in engine. " + << "Line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } + + OutputVariable* outputVariable = engine->getOutputVariable(name); + while (std::getline(blockReader, line)) { + line = fl::Op::trim(line); + std::istringstream tokenizer(line); + std::string firstToken; + tokenizer >> firstToken; + if (firstToken == "TERM") { + outputVariable->addTerm(parseTerm(line, engine)); + } else if (firstToken == "METHOD") { + outputVariable->setDefuzzifier(parseDefuzzifier(line)); + } else if (firstToken == "ACCU") { + outputVariable->fuzzyOutput()->setAccumulation(parseSNorm(line)); + } else if (firstToken == "DEFAULT") { + std::pair<scalar, bool> defaultAndLock = parseDefaultValue(line); + outputVariable->setDefaultValue(defaultAndLock.first); + outputVariable->setLockPreviousOutputValue(defaultAndLock.second or + outputVariable->isLockedPreviousOutputValue()); + } else if (firstToken == "RANGE") { + std::pair<scalar, scalar> minmax = parseRange(line); + outputVariable->setMinimum(minmax.first); + outputVariable->setMaximum(minmax.second); + } else if (firstToken == "LOCK") { + std::pair<bool, bool> output_range = parseLocks(line); + outputVariable->setLockPreviousOutputValue(output_range.first); + outputVariable->setLockOutputValueInRange(output_range.second); + } else if (firstToken == "ENABLED") { + outputVariable->setEnabled(parseEnabled(line)); + } else { + std::ostringstream ex; + ex << "[syntax error] unexpected token <" << firstToken << + "> in line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } + } + + } + + void FclImporter::processRuleBlock(const std::string& block, Engine* engine)const { + std::istringstream blockReader(block); + std::string line; + + std::string name; + std::getline(blockReader, line); + std::size_t index = line.find_last_of(' '); + if (index != std::string::npos) name = line.substr(index); + RuleBlock * ruleblock = new RuleBlock(name); + engine->addRuleBlock(ruleblock); + + while (std::getline(blockReader, line)) { + std::string firstToken = line.substr(0, line.find_first_of(' ')); + if (firstToken == "AND") { + ruleblock->setConjunction(parseTNorm(line)); + } else if (firstToken == "OR") { + ruleblock->setDisjunction(parseSNorm(line)); + } else if (firstToken == "ACT") { + ruleblock->setActivation(parseTNorm(line)); + } else if (firstToken == "ENABLED") { + ruleblock->setEnabled(parseEnabled(line)); + } else if (firstToken == "RULE") { + std::size_t ruleStart = line.find_first_of(':'); + if (ruleStart == std::string::npos) ruleStart = 4; // "RULE".size() + std::string ruleText = line.substr(ruleStart + 1); + ruleText = fl::Op::trim(ruleText); + Rule* rule = new Rule(ruleText); + try { + rule->load(engine); + } catch (...) { + //ignore + } + ruleblock->addRule(rule); + } else { + std::ostringstream ex; + ex << "[syntax error] keyword <" << firstToken + << "> not recognized in line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } + } + } + + TNorm* FclImporter::parseTNorm(const std::string& line) const { + std::vector<std::string> token = Op::split(line, ":"); + if (token.size() != 2) { + std::ostringstream ex; + ex << "[syntax error] expected property of type (key : value) in line: " + << line; + throw fl::Exception(ex.str(), FL_AT); + } + std::string name = Op::trim(token.at(1)); + std::string className = name; + if (name == "NONE") className = ""; + else if (name == "MIN") className = Minimum().className(); + else if (name == "PROD") className = AlgebraicProduct().className(); + else if (name == "BDIF") className = BoundedDifference().className(); + else if (name == "DPROD") className = DrasticProduct().className(); + else if (name == "EPROD") className = EinsteinProduct().className(); + else if (name == "HPROD") className = HamacherProduct().className(); + else if (name == "NMIN") className = NilpotentMinimum().className(); + + return FactoryManager::instance()->tnorm()->constructObject(className); + } + + SNorm* FclImporter::parseSNorm(const std::string& line) const { + std::vector<std::string> token = Op::split(line, ":"); + if (token.size() != 2) { + std::ostringstream ex; + ex << "[syntax error] expected property of type (key : value) in line: " + << line; + throw fl::Exception(ex.str(), FL_AT); + } + std::string name = Op::trim(token.at(1)); + std::string className = name; + if (name == "NONE") className = ""; + else if (name == "MAX") className = Maximum().className(); + else if (name == "ASUM") className = AlgebraicSum().className(); + else if (name == "BSUM") className = BoundedSum().className(); + else if (name == "NSUM") className = NormalizedSum().className(); + else if (name == "DSUM") className = DrasticSum().className(); + else if (name == "ESUM") className = EinsteinSum().className(); + else if (name == "HSUM") className = HamacherSum().className(); + else if (name == "NMAX") className = NilpotentMaximum().className(); + + return FactoryManager::instance()->snorm()->constructObject(className); + } + + Term* FclImporter::parseTerm(const std::string& line, const Engine* engine) const { + std::ostringstream spacer; + for (std::size_t i = 0; i < line.size(); ++i) { + if (line.at(i) == '(' or line.at(i) == ')' or line.at(i) == ',') { + spacer << " " << line.at(i) << " "; + } else if (line.at(i) == ':') { + spacer << " :"; + } else if (line.at(i) == '=') { + spacer << "= "; + } else + spacer << line.at(i); + } + std::string spacedLine = spacer.str(); + + enum FSM { + S_KWTERM, S_NAME, S_ASSIGN, S_TERMCLASS, S_PARAMETERS + }; + FSM state = S_KWTERM; + std::istringstream tokenizer(spacedLine); + std::string token; + std::string name, termClass; + std::vector<std::string> parameters; + while (tokenizer >> token) { + if (state == S_KWTERM and token == "TERM") { + state = S_NAME; + continue; + } + if (state == S_NAME) { + name = token; + state = S_ASSIGN; + continue; + } + if (state == S_ASSIGN and token == ":=") { + state = S_TERMCLASS; + continue; + } + if (state == S_TERMCLASS) { + if (fl::Op::isNumeric(token)) { + termClass = Constant().className(); + parameters.push_back(token); + } else if (token == "(") { + termClass = Discrete().className(); + } else { + termClass = token; + } + state = S_PARAMETERS; + continue; + } + if (state == S_PARAMETERS) { + if (termClass != Function().className() and + (token == "(" or token == ")" or token == ",")) { + continue; + } + if (token == ";") break; + parameters.push_back(fl::Op::trim(token)); + } + } + if (state <= S_TERMCLASS) + throw fl::Exception("[syntax error] malformed term in line: " + line, FL_AT); + + FL_unique_ptr<Term> term; + term.reset(FactoryManager::instance()->term()->constructObject(termClass)); + Term::updateReference(term.get(), engine); + term->setName(fl::Op::validName(name)); + std::string separator; + if (not dynamic_cast<Function*> (term.get())) { + separator = " "; + } + term->configure(Op::join(parameters, separator)); //remove spaces for text of function + return term.release(); + } + + Defuzzifier* FclImporter::parseDefuzzifier(const std::string& line) const { + std::vector<std::string> token = Op::split(line, ":"); + if (token.size() != 2) { + std::ostringstream ex; + ex << "[syntax error] expected property of type (key : value) in " + << "line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } + + std::string name = fl::Op::trim(token.at(1)); + std::string className = name; + if (name == "NONE") className = ""; + else if (name == "COG") className = Centroid().className(); + else if (name == "COA") className = Bisector().className(); + else if (name == "LM") className = SmallestOfMaximum().className(); + else if (name == "RM") className = LargestOfMaximum().className(); + else if (name == "MM") className = MeanOfMaximum().className(); + else if (name == "COGS") className = WeightedAverage().className(); + else if (name == "COGSS") className = WeightedSum().className(); + + return FactoryManager::instance()->defuzzifier()->constructObject(className); + } + + std::pair<scalar, bool> FclImporter::parseDefaultValue(const std::string& line) const { + std::vector<std::string> token = Op::split(line, ":="); + if (token.size() != 2) { + std::ostringstream ex; + ex << "[syntax error] expected property of type (key := value) in line: " + << line; + throw fl::Exception(ex.str(), FL_AT); + } + + std::vector<std::string> values = Op::split(token.at(1), "|"); + + std::string defaultValue = values.front(); + std::string nc; + if (values.size() == 2) nc = values.back(); + + defaultValue = fl::Op::trim(defaultValue); + nc = fl::Op::trim(nc); + + scalar value; + try { + value = fl::Op::toScalar(defaultValue); + } catch (...) { + std::ostringstream ex; + ex << "[syntax error] expected numeric value, " + << "but found <" << defaultValue << "> in line: " + << line; + throw fl::Exception(ex.str(), FL_AT); + } + + bool lockPreviousOutput = (nc == "NC"); + + if (not (lockPreviousOutput or nc.empty())) { + throw fl::Exception("[syntax error] expected keyword <NC>, " + "but found <" + nc + "> in line: " + line, FL_AT); + } + + return std::pair<scalar, bool>(value, lockPreviousOutput); + } + + std::pair<scalar, scalar> FclImporter::parseRange(const std::string& line) const { + std::vector<std::string> token = Op::split(line, ":="); + if (token.size() != 2) { + std::ostringstream ex; + ex << "[syntax error] expected property of type (key := value) in line: " + << line; + throw fl::Exception(ex.str(), FL_AT); + } + + std::string rangeToken = token.at(1); + + std::ostringstream range; + for (std::size_t i = 0; i < rangeToken.size(); ++i) { + char character = rangeToken.at(i); + if (character == '(' or character == ')' or character == ' ' or character == ';') + continue; + range << character; + } + token = Op::split(range.str(), ".."); + if (token.size() != 2) { + std::ostringstream ex; + ex << "[syntax error] expected property of type 'start .. end', " + << "but found <" << range.str() << "> in line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } + scalar minimum, maximum; + int index; + try { + minimum = Op::toScalar(token.at(index = 0)); + maximum = Op::toScalar(token.at(index = 1)); + } catch (std::exception& ex) { + (void) ex; + std::ostringstream ss; + ss << "[syntax error] expected numeric value, but found <" << token.at(index) << "> in " + << "line: " << line; + throw fl::Exception(ss.str(), FL_AT); + } + return std::pair<scalar, scalar>(minimum, maximum); + } + + std::pair<bool, bool> FclImporter::parseLocks(const std::string& line) const { + std::size_t index = line.find_first_of(":"); + if (index == std::string::npos) { + throw fl::Exception("[syntax error] expected property of type " + "'key : value' in line: " + line, FL_AT); + } + bool output, range; + std::string value = line.substr(index + 1); + std::vector<std::string> flags = fl::Op::split(value, "|"); + if (flags.size() == 1) { + std::string flag = fl::Op::trim(flags.front()); + output = (flag == "PREVIOUS"); + range = (flag == "RANGE"); + if (not (output or range)) { + throw fl::Exception("[syntax error] expected locking flags " + "<PREVIOUS|RANGE>, but found <" + flag + "> in line: " + line, FL_AT); + } + } else if (flags.size() == 2) { + std::string flagA = fl::Op::trim(flags.front()); + std::string flagB = fl::Op::trim(flags.back()); + output = (flagA == "PREVIOUS" or flagB == "PREVIOUS"); + range = (flagA == "RANGE" or flagB == "RANGE"); + if (not (output and range)) { + throw fl::Exception("[syntax error] expected locking flags " + "<PREVIOUS|RANGE>, but found " + "<" + flags.front() + "|" + flags.back() + "> in line: " + line, FL_AT); + } + } else { + throw fl::Exception("[syntax error] expected locking flags " + "<PREVIOUS|RANGE>, but found " + "<" + value + "> in line: " + line, FL_AT); + } + return std::pair<bool, bool>(output, range); + } + + bool FclImporter::parseEnabled(const std::string& line) const { + std::vector<std::string> tokens = Op::split(line, ":"); + if (tokens.size() != 2) { + std::ostringstream ex; + ex << "[syntax error] expected property of type (key : value) in " + << "line: " << line; + throw fl::Exception(ex.str(), FL_AT); + } + + std::string boolean = fl::Op::trim(tokens.at(1)); + if (boolean == "TRUE") return true; + if (boolean == "FALSE") return false; + throw fl::Exception("[syntax error] expected boolean <TRUE|FALSE>, but found <" + line + ">", FL_AT); + } + + FclImporter* FclImporter::clone() const { + return new FclImporter(*this); + } + + +} diff --git a/fuzzylite/src/imex/FisExporter.cpp b/fuzzylite/src/imex/FisExporter.cpp new file mode 100644 index 0000000..0934b33 --- /dev/null +++ b/fuzzylite/src/imex/FisExporter.cpp @@ -0,0 +1,463 @@ +/* + 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/imex/FisExporter.h" + +#include "fl/Headers.h" + +#include <queue> + +namespace fl { + + FisExporter::FisExporter() : Exporter() { + } + + FisExporter::~FisExporter() { + } + + std::string FisExporter::name() const { + return "FisExporter"; + } + + std::string FisExporter::toString(const Engine* engine) const { + std::ostringstream fis; + fis << exportSystem(engine) << "\n"; + + fis << exportInputs(engine); + + fis << exportOutputs(engine); + + fis << exportRules(engine); + + return fis.str(); + } + //TODO: deal with multiple ruleblocks, merge them into one. + std::string FisExporter::exportSystem(const Engine* engine) const { + std::ostringstream fis; + fis << "[System]\n"; + fis << "Name='" << engine->getName() << "'\n"; + std::string type; + if (engine->type() == Engine::Mamdani or engine->type() == Engine::Larsen) { + type = "mamdani"; + } else if (engine->type() == Engine::TakagiSugeno) { + type = "sugeno"; + } else if (engine->type() == Engine::Tsukamoto) { + type = "tsukamoto"; + } else if (engine->type() == Engine::InverseTsukamoto) { + type = "inverse tsukamoto"; + }else if (engine->type() == Engine::Hybrid){ + type = "hybrid"; + } else { + type = "unknown"; + } + fis << "Type='" << type << "'\n"; + // fis << "Version=" << FL_VERSION << "\n"; + fis << "NumInputs=" << engine->numberOfInputVariables() << "\n"; + fis << "NumOutputs=" << engine->numberOfOutputVariables() << "\n"; + + int 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) { + 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(); + } + fis << "NumRules=" << numberOfRules << "\n"; + fis << "AndMethod='" << toString(conjunction) << "'\n"; + fis << "OrMethod='" << toString(disjunction) << "'\n"; + fis << "ImpMethod='" << toString(activation) << "'\n"; + + const SNorm* accumulation = fl::null; + Defuzzifier* defuzzifier = fl::null; + for (int i = 0; i < engine->numberOfOutputVariables(); ++i) { + OutputVariable* outputVariable = engine->getOutputVariable(i); + if (not accumulation) accumulation = outputVariable->fuzzyOutput()->getAccumulation(); + if (not defuzzifier) defuzzifier = outputVariable->getDefuzzifier(); + } + + fis << "AggMethod='" << toString(accumulation) << "'\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) { + 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 << "NumMFs=" << var->numberOfTerms() << "\n"; + for (int ixTerm = 0; ixTerm < var->numberOfTerms(); ++ixTerm) { + fis << "MF" << (ixTerm + 1) << "='" << Op::validName(var->getTerm(ixTerm)->getName()) << "':" + << toString(var->getTerm(ixTerm)) << "\n"; + } + fis << "\n"; + } + return fis.str(); + } + + std::string FisExporter::exportOutputs(const Engine* engine) const { + std::ostringstream fis; + for (int 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 << "NumMFs=" << var->numberOfTerms() << "\n"; + for (int ixTerm = 0; ixTerm < var->numberOfTerms(); ++ixTerm) { + fis << "MF" << (ixTerm + 1) << "='" << Op::validName(var->getTerm(ixTerm)->getName()) << "':" + << toString(var->getTerm(ixTerm)) << "\n"; + } + fis << "\n"; + } + return fis.str(); + } + + std::string FisExporter::exportRules(const Engine* engine) const { + std::ostringstream fis; + fis << "[Rules]\n"; + for (int 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) { + Rule* rule = rb->getRule(ixRule); + if (rule->isLoaded()) { + fis << exportRule(rule, engine) << "\n"; + } + } + } + return fis.str(); + } + + std::string FisExporter::exportRule(const Rule* rule, const Engine* engine) const { + if (not rule) return ""; + std::vector<Proposition*> propositions; + std::vector<Operator*> operators; + + std::queue<Expression*> bfsQueue; + bfsQueue.push(rule->getAntecedent()->getExpression()); + while (not bfsQueue.empty()) { + Expression* front = bfsQueue.front(); + bfsQueue.pop(); + Operator* op = dynamic_cast<Operator*> (front); + if (op) { + bfsQueue.push(op->left); + bfsQueue.push(op->right); + operators.push_back(op); + } else { + propositions.push_back(dynamic_cast<Proposition*> (front)); + } + } + + bool equalOperators = true; + for (std::size_t i = 0; i + 1 < operators.size(); ++i) { + if (operators.at(i)->name != operators.at(i + 1)->name) { + equalOperators = false; + break; + } + } + if (not equalOperators) { + throw fl::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) + inputVariables.push_back(engine->getInputVariable(i)); + for (int i = 0; i < engine->numberOfOutputVariables(); ++i) + outputVariables.push_back(engine->getOutputVariable(i)); + + fis << translate(propositions, inputVariables) << ", "; + fis << translate(rule->getConsequent()->conclusions(), outputVariables); + fis << "(" << Op::str(rule->getWeight()) << ") : "; + if (operators.size() == 0) fis << "1"; //does not matter + else { + if (operators.at(0)->name == Rule::andKeyword()) fis << "1"; + else if (operators.at(0)->name == Rule::orKeyword()) fis << "2"; + else fis << operators.at(0)->name; + } + return fis.str(); + } + + std::string FisExporter::translate(const std::vector<Proposition*>& propositions, + const std::vector<Variable*> variables) const { + std::ostringstream ss; + for (std::size_t ixVariable = 0; ixVariable < variables.size(); ++ixVariable) { + Variable* variable = variables.at(ixVariable); + int 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) { + if (variable->getTerm(termIndex) == proposition->term) { + termIndexPlusOne = termIndex + 1; + break; + } + } + + std::vector<Hedge*> hedges = proposition->hedges; + if (hedges.size() > 1) { + FL_DBG("[exporter warning] only a few combinations of multiple " + "hedges are supported in fis files"); + } + for (std::size_t ixHedge = 0; ixHedge < hedges.size(); ++ixHedge) { + Hedge* hedge = hedges.at(ixHedge); + if (hedge->name() == Not().name()) negated *= -1; + else if (hedge->name() == Extremely().name()) plusHedge += 0.3; + else if (hedge->name() == Very().name()) plusHedge += 0.2; + else if (hedge->name() == Somewhat().name()) plusHedge += 0.05; + else if (hedge->name() == Seldom().name()) plusHedge += 0.01; + else if (hedge->name() == Any().name()) plusHedge += 0.99; + else plusHedge = fl::nan; //Unreconized hedge combination (e.g. Any) + } + + break; + } + if (negated < 0) ss << "-"; + if (not fl::Op::isNaN(plusHedge)) { + ss << fl::Op::str(termIndexPlusOne + plusHedge); + } else { + ss << termIndexPlusOne << ".?"; // Unreconized hedge combination + } + ss << " "; + } + 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 ""; + if (tnorm->className() == Minimum().className()) return "min"; + if (tnorm->className() == AlgebraicProduct().className()) return "prod"; + if (tnorm->className() == BoundedDifference().className()) return "bounded_difference"; + if (tnorm->className() == DrasticProduct().className()) return "drastic_product"; + if (tnorm->className() == EinsteinProduct().className()) return "einstein_product"; + if (tnorm->className() == HamacherProduct().className()) return "hamacher_product"; + if (tnorm->className() == NilpotentMinimum().className()) return "nilpotent_minimum"; + return tnorm->className(); + } + + 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() == 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"; + return snorm->className(); + } + + std::string FisExporter::toString(const Defuzzifier * defuzzifier) const { + if (not defuzzifier) return ""; + if (defuzzifier->className() == Centroid().className()) return "centroid"; + if (defuzzifier->className() == Bisector().className()) return "bisector"; + if (defuzzifier->className() == LargestOfMaximum().className()) return "lom"; + if (defuzzifier->className() == MeanOfMaximum().className()) return "mom"; + if (defuzzifier->className() == SmallestOfMaximum().className()) return "som"; + if (defuzzifier->className() == WeightedAverage().className()) return "wtaver"; + if (defuzzifier->className() == WeightedSum().className()) return "wtsum"; + return defuzzifier->className(); + } + + 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, " ", + x->getWidth(), x->getSlope(), x->getCenter()) << "]"; + return ss.str(); + } + + if (const Concave * x = dynamic_cast<const Concave*> (term)) { + ss << "'concavemf',[" << fl::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()) << "]"; + return ss.str(); + } + + if (const Cosine * x = dynamic_cast<const Cosine*> (term)) { + ss << "'cosinemf',[" << fl::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()), " ") << "]"; + return ss.str(); + } + + if (const Function * x = dynamic_cast<const Function*> (term)) { + ss << "'function',[" << x->getFormula() << "]"; + return ss.str(); + } + + if (const Gaussian * x = dynamic_cast<const Gaussian*> (term)) { + ss << "'gaussmf',[" << fl::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, " ", + 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(), " ") << "]"; + return ss.str(); + } + + + if (const PiShape * x = dynamic_cast<const PiShape*> (term)) { + ss << "'pimf',[" << fl::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, " ", + x->getStart(), x->getEnd()) << "]"; + return ss.str(); + } + + if (const Rectangle * x = dynamic_cast<const Rectangle*> (term)) { + ss << "'rectmf',[" << fl::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, " ", + 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, " ", + x->getSlope(), x->getInflection()) << "]"; + return ss.str(); + } + + if (const SigmoidProduct * x = dynamic_cast<const SigmoidProduct*> (term)) { + ss << "'psigmf',[" << fl::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, " ", + x->getStart(), x->getEnd()) << "]"; + return ss.str(); + } + + if (const Spike * x = dynamic_cast<const Spike*> (term)) { + ss << "'spikemf',[" << fl::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, " ", + 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, " ", + x->getVertexA(), x->getVertexB(), x->getVertexC()) << "]"; + return ss.str(); + } + + if (const ZShape * x = dynamic_cast<const ZShape*> (term)) { + ss << "'zmf',[" << fl::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); + } + + FisExporter* FisExporter::clone() const { + return new FisExporter(*this); + } + +} diff --git a/fuzzylite/src/imex/FisImporter.cpp b/fuzzylite/src/imex/FisImporter.cpp new file mode 100644 index 0000000..741719c --- /dev/null +++ b/fuzzylite/src/imex/FisImporter.cpp @@ -0,0 +1,501 @@ +/* + 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/imex/FisImporter.h" + +#include "fl/Headers.h" + +#include <sstream> +#include <iostream> +#include <cctype> + +namespace fl { + + FisImporter::FisImporter() : Importer() { + } + + FisImporter::~FisImporter() { + } + + std::string FisImporter::name() const { + return "FisImporter"; + } + + Engine* FisImporter::fromString(const std::string& fis) const { + FL_unique_ptr<Engine> engine(new Engine); + + std::istringstream fisReader(fis); + std::string line; + int lineNumber = 0; + + std::vector<std::string> sections; + while (std::getline(fisReader, line)) { + ++lineNumber; + std::vector<std::string> comments; + comments = Op::split(line, "//"); + if (comments.size() > 1) { + line = comments.front(); + } + comments = Op::split(line, "#"); + if (comments.size() > 1) { + line = comments.front(); + } + line = Op::trim(line); + if (line.empty() or line.at(0) == '%' or line.at(0) == '#' + or (line.substr(0, 2) == "//")) { + continue; + } + + line = fl::Op::findReplace(line, "'", ""); + + if ("[System]" == line.substr(0, std::string("[System]").size()) + or "[Input" == line.substr(0, std::string("[Input").size()) + or "[Output" == line.substr(0, std::string("[Output").size()) + or "[Rules]" == line.substr(0, std::string("[Rules]").size())) { + sections.push_back(line); + } else { + if (not sections.empty()) { + sections.at(sections.size() - 1) += "\n" + line; + } else { + std::ostringstream ss; + ss << "[import error] line " << lineNumber << " <" << line + "> " + "does not belong to any section"; + throw fl::Exception(ss.str(), FL_AT); + } + } + } + std::string andMethod, orMethod, impMethod, aggMethod, defuzzMethod; + for (std::size_t i = 0; i < sections.size(); ++i) { + if ("[System]" == sections.at(i).substr(0, std::string("[System]").size())) + importSystem(sections.at(i), engine.get(), + andMethod, orMethod, impMethod, aggMethod, defuzzMethod); + else if ("[Input" == sections.at(i).substr(0, std::string("[Input").size())) + importInput(sections.at(i), engine.get()); + else if ("[Output" == sections.at(i).substr(0, std::string("[Output").size())) + importOutput(sections.at(i), engine.get()); + else if ("[Rules]" == sections.at(i).substr(0, std::string("[Rules]").size())) + importRules(sections.at(i), engine.get()); + else throw fl::Exception("[import error] section <" + + sections.at(i) + "> not recognized", FL_AT); + } + engine->configure(extractTNorm(andMethod), extractSNorm(orMethod), + extractTNorm(impMethod), extractSNorm(aggMethod), + extractDefuzzifier(defuzzMethod)); + return engine.release(); + } + + void FisImporter::importSystem(const std::string& section, Engine * engine, + std::string& andMethod, std::string& orMethod, + std::string& impMethod, std::string& aggMethod, + std::string& defuzzMethod) const { + std::istringstream reader(section); + std::string line; + std::getline(reader, line); //ignore first line [System] + while (std::getline(reader, line)) { + std::vector<std::string> keyValue = fl::Op::split(line, "="); + + std::string key = fl::Op::trim(keyValue.at(0)); + std::string value; + for (std::size_t i = 1; i < keyValue.size(); ++i) { + value += keyValue.at(i); + } + value = fl::Op::trim(value); + if (key == "Name") engine->setName(value); + else if (key == "AndMethod") andMethod = value; + else if (key == "OrMethod") orMethod = value; + else if (key == "ImpMethod") impMethod = value; + else if (key == "AggMethod") aggMethod = value; + else if (key == "DefuzzMethod") defuzzMethod = value; + else if (key == "Type" or key == "Version" + or key == "NumInputs" or key == "NumOutputs" + or key == "NumRules" or key == "NumMFs") { + //ignore because are redundant. + } else throw fl::Exception("[import error] token <" + key + "> not recognized", FL_AT); + } + } + + void FisImporter::importInput(const std::string& section, Engine* engine) const { + std::istringstream reader(section); + std::string line; + std::getline(reader, line); //ignore first line [Input#] + + InputVariable* input = new InputVariable; + engine->addInputVariable(input); + + while (std::getline(reader, line)) { + std::vector<std::string> keyValue = fl::Op::split(line, "="); + if (keyValue.size() != 2) + throw fl::Exception("[syntax error] expected a property of type " + "'key=value', but found <" + line + ">", FL_AT); + std::string key = fl::Op::trim(keyValue.at(0)); + std::string value = fl::Op::trim(keyValue.at(1)); + + if (key == "Name") input->setName(fl::Op::validName(value)); + else if (key == "Enabled") { + input->setEnabled(Op::isEq(Op::toScalar(value), 1.0)); + } else if (key == "Range") { + std::pair<scalar, scalar> minmax = range(value); + input->setMinimum(minmax.first); + input->setMaximum(minmax.second); + } else if (key.substr(0, 2) == "MF") { + input->addTerm(parseTerm(value, engine)); + } else if (key == "NumMFs") { + //ignore + } else { + throw fl::Exception("[import error] token <" + key + "> not recognized", FL_AT); + } + } + } + + void FisImporter::importOutput(const std::string& section, Engine* engine) const { + std::istringstream reader(section); + std::string line; + std::getline(reader, line); //ignore first line [Output#] + + OutputVariable* output = new OutputVariable; + engine->addOutputVariable(output); + + + while (std::getline(reader, line)) { + std::vector<std::string> keyValue = fl::Op::split(line, "="); + if (keyValue.size() != 2) + throw fl::Exception("[syntax error] expected a property of type " + "'key=value', but found < " + line + ">", FL_AT); + std::string key = fl::Op::trim(keyValue.at(0)); + std::string value = fl::Op::trim(keyValue.at(1)); + + if (key == "Name") output->setName(fl::Op::validName(value)); + else if (key == "Enabled") { + output->setEnabled(Op::isEq(Op::toScalar(value), 1.0)); + } else if (key == "Range") { + std::pair<scalar, scalar> minmax = range(value); + output->setMinimum(minmax.first); + output->setMaximum(minmax.second); + } else if (key.substr(0, 2) == "MF") { + output->addTerm(parseTerm(value, engine)); + } else if (key == "Default") { + output->setDefaultValue(fl::Op::toScalar(value)); + } else if (key == "LockPrevious") { + output->setLockPreviousOutputValue(fl::Op::isEq(fl::Op::toScalar(value), 1.0)); + } else if (key == "LockRange") { + output->setLockOutputValueInRange(fl::Op::isEq(fl::Op::toScalar(value), 1.0)); + } else if (key == "NumMFs") { + //ignore + } else { + throw fl::Exception("[import error] token <" + key + "> not recognized", FL_AT); + } + } + } + + void FisImporter::importRules(const std::string& section, Engine* engine) const { + std::istringstream reader(section); + std::string line; + std::getline(reader, line); //ignore first line [Rules] + + RuleBlock* ruleblock = new RuleBlock; + engine->addRuleBlock(ruleblock); + + while (std::getline(reader, line)) { + std::vector<std::string> inputsAndRest = fl::Op::split(line, ","); + if (inputsAndRest.size() != 2) + throw fl::Exception("[syntax error] expected rule to match pattern " + "<'i '+, 'o '+ (w) : '1|2'>, but found instead <" + line + ">", FL_AT); + + std::vector <std::string> outputsAndRest = fl::Op::split(inputsAndRest.at(1), ":"); + if (outputsAndRest.size() != 2) + throw fl::Exception("[syntax error] expected rule to match pattern " + "<'i '+, 'o '+ (w) : '1|2'>, but found instead <" + line + ">", FL_AT); + + std::vector<std::string> inputs = fl::Op::split(inputsAndRest.at(0), " "); + std::vector<std::string> outputs = fl::Op::split(outputsAndRest.at(0), " "); + std::string weightInParenthesis = outputs.at(outputs.size() - 1); + outputs.erase(outputs.begin() + outputs.size() - 1); + std::string connector = fl::Op::trim(outputsAndRest.at(1)); + + if ((int) inputs.size() != engine->numberOfInputVariables()) { + std::ostringstream ss; + ss << "[syntax error] expected <" << engine->numberOfInputVariables() << ">" + " input variables, but found <" << inputs.size() << ">" + " input variables in rule <" << line << ">"; + throw fl::Exception(ss.str(), FL_AT); + } + if ((int) outputs.size() != engine->numberOfOutputVariables()) { + std::ostringstream ss; + ss << "[syntax error] expected <" << engine->numberOfOutputVariables() << ">" + " output variables, but found <" << outputs.size() << ">" + " output variables in rule <" << line << ">"; + throw fl::Exception(ss.str(), FL_AT); + } + + std::vector<std::string> antecedent, consequent; + + for (std::size_t i = 0; i < inputs.size(); ++i) { + scalar inputCode = fl::Op::toScalar(inputs.at(i)); + if (fl::Op::isEq(inputCode, 0.0)) continue; + std::ostringstream ss; + ss << engine->getInputVariable(i)->getName() << " " + << fl::Rule::isKeyword() << " " + << translateProposition(inputCode, engine->getInputVariable(i)); + antecedent.push_back(ss.str()); + } + + for (std::size_t i = 0; i < outputs.size(); ++i) { + scalar outputCode = fl::Op::toScalar(outputs.at(i)); + if (fl::Op::isEq(outputCode, 0.0)) continue; + std::ostringstream ss; + ss << engine->getOutputVariable(i)->getName() << " " + << fl::Rule::isKeyword() << " " + << translateProposition(outputCode, engine->getOutputVariable(i)); + consequent.push_back(ss.str()); + } + + std::ostringstream ruleText; + + ruleText << fl::Rule::ifKeyword() << " "; + for (std::size_t i = 0; i < antecedent.size(); ++i) { + ruleText << antecedent.at(i); + if (i + 1 < antecedent.size()) { + ruleText << " "; + if (connector == "1") ruleText << fl::Rule::andKeyword() << " "; + else if (connector == "2") ruleText << fl::Rule::orKeyword() << " "; + else throw fl::Exception("[syntax error] connector <" + + connector + "> not recognized", FL_AT); + } + } + + ruleText << " " << fl::Rule::thenKeyword() << " "; + for (std::size_t i = 0; i < consequent.size(); ++i) { + ruleText << consequent.at(i); + if (i + 1 < consequent.size()) { + ruleText << " " << fl::Rule::andKeyword() << " "; + } + } + + std::ostringstream ss; + for (std::size_t i = 0; i < weightInParenthesis.size(); ++i) { + if (weightInParenthesis.at(i) == '(' + or weightInParenthesis.at(i) == ')' + or weightInParenthesis.at(i) == ' ') continue; + ss << weightInParenthesis.at(i); + } + + scalar weight = fl::Op::toScalar(ss.str()); + if (not fl::Op::isEq(weight, 1.0)) + ruleText << " " << fl::Rule::withKeyword() << " " << Op::str(weight); + Rule* rule = new Rule(ruleText.str()); + try { + rule->load(engine); + } catch (...) { + //ignore + } + ruleblock->addRule(rule); + } + } + + std::string FisImporter::translateProposition(scalar code, Variable* variable) const { + int intPart = (int) std::floor(std::fabs(code)) - 1; + scalar fracPart = std::fmod(std::fabs(code), 1.0); + if (intPart >= variable->numberOfTerms()) { + std::ostringstream ex; + ex << "[syntax error] the code <" << code << "> refers to a term " + "out of range from variable <" << variable->getName() << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + + bool isAny = intPart < 0; + std::ostringstream ss; + if (code < 0) ss << Not().name() << " "; + if (fl::Op::isEq(fracPart, 0.01)) ss << Seldom().name() << " "; + else if (fl::Op::isEq(fracPart, 0.05)) ss << Somewhat().name() << " "; + else if (fl::Op::isEq(fracPart, 0.2)) ss << Very().name() << " "; + else if (fl::Op::isEq(fracPart, 0.3)) ss << Extremely().name() << " "; + else if (fl::Op::isEq(fracPart, 0.4)) ss << Very().name() << " " << Very().name() << " "; + else if (fl::Op::isEq(fracPart, 0.99)) ss << Any().name() << " "; + else if (not fl::Op::isEq(fracPart, 0)) + throw fl::Exception("[syntax error] no hedge defined in FIS format for <" + + fl::Op::str(fracPart) + ">", FL_AT); + if (not isAny) { + ss << variable->getTerm(intPart)->getName(); + } + return ss.str(); + } + + std::string FisImporter::extractTNorm(const std::string & name) const { + if (name.empty()) return ""; + if (name == "min") return Minimum().className(); + if (name == "prod") return AlgebraicProduct().className(); + if (name == "bounded_difference") return BoundedDifference().className(); + if (name == "drastic_product") return DrasticProduct().className(); + if (name == "einstein_product") return EinsteinProduct().className(); + if (name == "hamacher_product") return HamacherProduct().className(); + if (name == "nilpotent_minimum") return NilpotentMinimum().className(); + return name; + } + + std::string FisImporter::extractSNorm(const std::string & name) const { + if (name.empty()) return ""; + if (name == "max") return Maximum().className(); + if (name == "sum" or name == "probor") return AlgebraicSum().className(); + if (name == "bounded_sum") return BoundedSum().className(); + if (name == "normalized_sum") return NormalizedSum().className(); + if (name == "drastic_sum") return DrasticSum().className(); + if (name == "einstein_sum") return EinsteinSum().className(); + if (name == "hamacher_sum") return HamacherSum().className(); + if (name == "nilpotent_maximum") return NilpotentMaximum().className(); + return name; + } + + std::string FisImporter::extractDefuzzifier(const std::string & name) const { + if (name.empty()) return ""; + if (name == "centroid") return Centroid().className(); + if (name == "bisector") return Bisector().className(); + if (name == "lom") return LargestOfMaximum().className(); + if (name == "mom") return MeanOfMaximum().className(); + if (name == "som") return SmallestOfMaximum().className(); + if (name == "wtaver") return WeightedAverage().className(); + if (name == "wtsum") return WeightedSum().className(); + return name; + } + + std::pair<scalar, scalar> FisImporter::range(const std::string& range) const { + std::vector<std::string> parts = fl::Op::split(range, " "); + if (parts.size() != 2) + throw fl::Exception("[syntax error] expected range in format '[begin end]'," + " but found <" + range + ">", FL_AT); + std::string begin = parts.at(0), end = parts.at(1); + if (begin.at(0) != '[' or end.at(end.size() - 1) != ']') + throw fl::Exception("[syntax error] expected range in format '[begin end]'," + " but found <" + range + ">", FL_AT); + std::pair<scalar, scalar> result; + result.first = fl::Op::toScalar(begin.substr(1)); + result.second = fl::Op::toScalar(end.substr(0, end.size() - 1)); + return result; + } + + Term * FisImporter::parseTerm(const std::string & fis, const Engine* engine) const { + std::ostringstream ss; + for (std::size_t i = 0; i < fis.size(); ++i) { + if (not (fis.at(i) == '[' or fis.at(i) == ']')) { + ss << fis.at(i); + } + } + std::string line = ss.str(); + + std::vector<std::string> nameTerm = fl::Op::split(line, ":"); + if (nameTerm.size() != 2) { + throw fl::Exception("[syntax error] expected term in format 'name':'class',[params], " + "but found <" + line + ">", FL_AT); + } + std::vector<std::string> termParams = fl::Op::split(nameTerm.at(1), ","); + if (termParams.size() != 2) { + throw fl::Exception("[syntax error] expected term in format 'name':'class',[params], " + "but found " + line, FL_AT); + } + + std::vector<std::string> parameters = fl::Op::split(termParams.at(1), " "); + for (std::size_t i = 0; i < parameters.size(); ++i) { + parameters.at(i) = fl::Op::trim(parameters.at(i)); + } + return createInstance( + fl::Op::trim(termParams.at(0)), + fl::Op::trim(nameTerm.at(0)), + parameters, engine); + } + + Term * FisImporter::createInstance(const std::string& mClass, + const std::string& name, const std::vector<std::string>& params, + const Engine* engine) const { + std::map<std::string, std::string> mapping; + mapping["discretemf"] = Discrete().className(); + mapping["concavemf"] = Concave().className(); + mapping["constant"] = Constant().className(); + mapping["cosinemf"] = Cosine().className(); + mapping["function"] = Function().className(); + mapping["gbellmf"] = Bell().className(); + mapping["gaussmf"] = Gaussian().className(); + mapping["gauss2mf"] = GaussianProduct().className(); + mapping["linear"] = Linear().className(); + mapping["pimf"] = PiShape().className(); + mapping["rampmf"] = Ramp().className(); + mapping["rectmf"] = Rectangle().className(); + mapping["smf"] = SShape().className(); + mapping["sigmf"] = Sigmoid().className(); + mapping["dsigmf"] = SigmoidDifference().className(); + mapping["psigmf"] = SigmoidProduct().className(); + mapping["spikemf"] = Spike().className(); + mapping["trapmf"] = Trapezoid().className(); + mapping["trimf"] = Triangle().className(); + mapping["zmf"] = ZShape().className(); + + std::vector<std::string> sortedParams = params; + + if (mClass == "gbellmf" and params.size() >= 3) { + sortedParams.at(0) = params.at(2); + sortedParams.at(1) = params.at(0); + sortedParams.at(2) = params.at(1); + } else if (mClass == "gaussmf" and params.size() >= 2) { + sortedParams.at(0) = params.at(1); + sortedParams.at(1) = params.at(0); + } else if (mClass == "gauss2mf" and params.size() >= 4) { + sortedParams.at(0) = params.at(1); + sortedParams.at(1) = params.at(0); + sortedParams.at(2) = params.at(3); + sortedParams.at(3) = params.at(2); + } else if (mClass == "sigmf" and params.size() >= 2) { + sortedParams.at(0) = params.at(1); + sortedParams.at(1) = params.at(0); + } else if (mClass == "dsigmf" and params.size() >= 4) { + sortedParams.at(0) = params.at(1); + sortedParams.at(1) = params.at(0); + sortedParams.at(2) = params.at(2); + sortedParams.at(3) = params.at(3); + } else if (mClass == "psigmf" and params.size() >= 4) { + sortedParams.at(0) = params.at(1); + sortedParams.at(1) = params.at(0); + sortedParams.at(2) = params.at(2); + sortedParams.at(3) = params.at(3); + } + + std::string flClass; + std::map<std::string, std::string>::const_iterator it = mapping.find(mClass); + if (it != mapping.end()) flClass = it->second; + else flClass = mClass; + + FL_unique_ptr<Term> term; + term.reset(FactoryManager::instance()->term()->constructObject(flClass)); + Term::updateReference(term.get(), engine); + term->setName(Op::validName(name)); + std::string separator; + if (not dynamic_cast<Function*> (term.get())) { + separator = " "; + } + term->configure(Op::join(sortedParams, separator)); + return term.release(); + } + + FisImporter* FisImporter::clone() const { + return new FisImporter(*this); + } + +} diff --git a/fuzzylite/src/imex/FldExporter.cpp b/fuzzylite/src/imex/FldExporter.cpp new file mode 100644 index 0000000..9064250 --- /dev/null +++ b/fuzzylite/src/imex/FldExporter.cpp @@ -0,0 +1,246 @@ +/* + 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/imex/FldExporter.h" + +#include "fl/Engine.h" +#include "fl/Operation.h" +#include "fl/variable/Variable.h" +#include "fl/variable/InputVariable.h" +#include "fl/variable/OutputVariable.h" + +#include <cmath> +#include <fstream> +#include <vector> + +namespace fl { + + FldExporter::FldExporter(const std::string& separator) : Exporter(), + _separator(separator), _exportHeaders(true), + _exportInputValues(true), _exportOutputValues(true) { + + } + + FldExporter::~FldExporter() { + } + + std::string FldExporter::name() const { + return "FldExporter"; + } + + void FldExporter::setSeparator(const std::string& separator) { + this->_separator = separator; + } + + std::string FldExporter::getSeparator() const { + return this->_separator; + } + + void FldExporter::setExportHeader(bool exportHeaders) { + this->_exportHeaders = exportHeaders; + } + + bool FldExporter::exportsHeader() const { + return this->_exportHeaders; + } + + void FldExporter::setExportInputValues(bool exportInputValues) { + this->_exportInputValues = exportInputValues; + } + + bool FldExporter::exportsInputValues() const { + return this->_exportInputValues; + } + + void FldExporter::setExportOutputValues(bool exportOutputValues) { + this->_exportOutputValues = exportOutputValues; + } + + bool FldExporter::exportsOutputValues() const { + return this->_exportOutputValues; + } + + std::string FldExporter::header(const Engine* engine) const { + std::vector<std::string> result; + if (_exportInputValues) { + for (int i = 0; i < engine->numberOfInputVariables(); ++i) { + InputVariable* inputVariable = engine->getInputVariable(i); + result.push_back("@InputVariable: " + inputVariable->getName() + ";"); + } + } + if (_exportOutputValues) { + for (int i = 0; i < engine->numberOfOutputVariables(); ++i) { + OutputVariable* outputVariable = engine->getOutputVariable(i); + result.push_back("@OutputVariable: " + outputVariable->getName() + ";"); + } + } + return "#@Engine: " + engine->getName() + ";\n#" + Op::join(result, _separator); + } + + std::string FldExporter::toString(const Engine* engine) const { + return toString(const_cast<Engine*> (engine), 1024); + } + + std::string FldExporter::toString(Engine* engine, int maximumNumberOfResults) const { + std::ostringstream result; + write(engine, result, maximumNumberOfResults); + return result.str(); + } + + void FldExporter::toFile(const std::string& path, Engine* engine, int maximumNumberOfResults) const { + std::ofstream writer(path.c_str()); + if (not writer.is_open()) { + throw fl::Exception("[file error] file <" + path + "> could not be created", FL_AT); + } + write(engine, writer, maximumNumberOfResults); + writer.close(); + } + + std::string FldExporter::toString(Engine* engine, const std::string& inputData) const { + std::ostringstream writer; + if (_exportHeaders) writer << header(engine) << "\n"; + std::istringstream reader(inputData); + std::string line; + while (std::getline(reader, line)) { + line = Op::trim(line); + if (not line.empty() and line.at(0) == '#') continue; //comments are ignored, blank lines are retained + std::vector<scalar> inputValues = parse(line); + write(engine, writer, inputValues); + writer.flush(); + } + return writer.str(); + } + + void FldExporter::toFile(const std::string& path, Engine* engine, const std::string& inputData) const { + std::ofstream writer(path.c_str()); + if (not writer.is_open()) { + throw fl::Exception("[file error] file <" + path + "> could not be created", FL_AT); + } + if (_exportHeaders) writer << header(engine) << "\n"; + std::istringstream reader(inputData); + std::string line; + while (std::getline(reader, line)) { + line = Op::trim(line); + if (not line.empty() and line.at(0) == '#') continue; //comments are ignored, blank lines are retained + std::vector<scalar> inputValues = parse(line); + write(engine, writer, inputValues); + writer.flush(); + } + writer.close(); + } + + std::vector<scalar> FldExporter::parse(const std::string& x) const { + std::vector<scalar> inputValues; + if (not (x.empty() or x.at(0) == '#')) { + std::istringstream tokenizer(x); + std::string token; + while (tokenizer >> token) + inputValues.push_back(fl::Op::toScalar(token)); + } + return inputValues; + } + + void FldExporter::write(Engine* engine, std::ostream& writer, int maximum) const { + if (_exportHeaders) writer << header(engine) << "\n"; + + int resolution = -1 + (int) std::max(1.0, std::pow( + maximum, 1.0 / engine->numberOfInputVariables())); + std::vector<int> sampleValues, minSampleValues, maxSampleValues; + for (int i = 0; i < engine->numberOfInputVariables(); ++i) { + sampleValues.push_back(0); + minSampleValues.push_back(0); + maxSampleValues.push_back(resolution); + } + + engine->restart(); + + bool overflow = false; + std::vector<scalar> inputValues(engine->numberOfInputVariables()); + while (not overflow) { + for (int i = 0; i < engine->numberOfInputVariables(); ++i) { + InputVariable* inputVariable = engine->getInputVariable(i); + inputValues.at(i) = inputVariable->getMinimum() + + sampleValues.at(i) * inputVariable->range() / std::max(1, resolution); + } + write(engine, writer, inputValues); + overflow = Op::increment(sampleValues, minSampleValues, maxSampleValues); + } + } + + void FldExporter::write(Engine* engine, std::ostream& writer, std::istream& reader) const { + if (_exportHeaders) writer << header(engine) << "\n"; + + engine->restart(); + + std::string line; + int lineNumber = 0; + while (std::getline(reader, line)) { + ++lineNumber; + std::vector<scalar> inputValues = parse(Op::trim(line)); + try { + write(engine, writer, inputValues); + } catch (fl::Exception& ex) { + ex.append(" writing line <" + Op::str(lineNumber) + ">"); + throw; + } + } + } + + void FldExporter::write(Engine* engine, std::ostream& writer, const std::vector<scalar>& inputValues) const { + if (inputValues.empty()) { + writer << "\n"; + return; + } + if (int(inputValues.size()) < engine->numberOfInputVariables()) { + std::ostringstream ex; + ex << "[export error] engine has <" << engine->numberOfInputVariables() << "> " + "input variables, but input data provides <" << inputValues.size() << "> values"; + throw fl::Exception(ex.str(), FL_AT); + } + + std::vector<std::string> values; + for (int i = 0; i < engine->numberOfInputVariables(); ++i) { + InputVariable* inputVariable = engine->getInputVariable(i); + scalar inputValue = inputVariable->isEnabled() ? inputValues.at(i) : fl::nan; + inputVariable->setInputValue(inputValue); + if (_exportInputValues) values.push_back(Op::str(inputValue)); + } + + engine->process(); + + for (int i = 0; i < engine->numberOfOutputVariables(); ++i) { + OutputVariable* outputVariable = engine->getOutputVariable(i); + outputVariable->defuzzify(); + if (_exportOutputValues) + values.push_back(Op::str(outputVariable->getOutputValue())); + } + + writer << Op::join(values, _separator) << "\n"; + } + + FldExporter* FldExporter::clone() const { + return new FldExporter(*this); + } + +} diff --git a/fuzzylite/src/imex/FllExporter.cpp b/fuzzylite/src/imex/FllExporter.cpp new file mode 100644 index 0000000..0ffeb2f --- /dev/null +++ b/fuzzylite/src/imex/FllExporter.cpp @@ -0,0 +1,189 @@ +/* + 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/imex/FllExporter.h" + +#include "fl/Headers.h" + +namespace fl { + + FllExporter::FllExporter(const std::string& indent, const std::string& separator) + : Exporter(), _indent(indent), _separator(separator) { + } + + FllExporter::~FllExporter() { + } + + std::string FllExporter::name() const { + return "FllExporter"; + } + + void FllExporter::setIndent(const std::string& indent) { + this->_indent = indent; + } + + std::string FllExporter::getIndent() const { + return this->_indent; + } + + void FllExporter::setSeparator(const std::string& separator) { + this->_separator = separator; + } + + std::string FllExporter::getSeparator() const { + return this->_separator; + } + + std::string FllExporter::toString(const Engine* engine) const { + std::vector<std::string> result; + result.push_back("Engine: " + engine->getName()); + result.push_back(toString(engine->inputVariables())); + result.push_back(toString(engine->outputVariables())); + result.push_back(toString(engine->ruleBlocks())); + return Op::join(result, _separator); + } + + std::string FllExporter::toString(const std::vector<Variable*>& variables) const { + std::vector<std::string> result; + for (std::size_t i = 0; i < variables.size(); ++i) { + result.push_back(toString(variables.at(i))); + } + return Op::join(result, _separator); + } + + std::string FllExporter::toString(const std::vector<InputVariable*>& variables) const { + std::vector<std::string> result; + for (std::size_t i = 0; i < variables.size(); ++i) { + result.push_back(toString(variables.at(i))); + } + return Op::join(result, _separator); + } + + std::string FllExporter::toString(const std::vector<OutputVariable*>& variables) const { + std::vector<std::string> result; + for (std::size_t i = 0; i < variables.size(); ++i) { + result.push_back(toString(variables.at(i))); + } + return Op::join(result, _separator); + } + + std::string FllExporter::toString(const std::vector<RuleBlock*>& ruleBlocks) const { + std::vector<std::string> result; + for (std::size_t i = 0; i < ruleBlocks.size(); ++i) { + result.push_back(toString(ruleBlocks.at(i))); + } + return Op::join(result, _separator); + } + + std::string FllExporter::toString(const Variable* variable) const { + std::vector<std::string> result; + result.push_back("Variable: " + Op::validName(variable->getName())); + result.push_back(_indent + "enabled: " + (variable->isEnabled() ? "true" : "false")); + result.push_back(_indent + "range: " + Op::join(2, " ", + variable->getMinimum(), variable->getMaximum())); + for (int i = 0; i < variable->numberOfTerms(); ++i) { + result.push_back(_indent + toString(variable->getTerm(i))); + } + return Op::join(result, _separator); + } + + std::string FllExporter::toString(const InputVariable* inputVariable) const { + std::vector<std::string> result; + result.push_back("InputVariable: " + Op::validName(inputVariable->getName())); + result.push_back(_indent + "enabled: " + (inputVariable->isEnabled() ? "true" : "false")); + result.push_back(_indent + "range: " + Op::join(2, " ", + inputVariable->getMinimum(), inputVariable->getMaximum())); + for (int i = 0; i < inputVariable->numberOfTerms(); ++i) { + result.push_back(_indent + toString(inputVariable->getTerm(i))); + } + return Op::join(result, _separator); + } + + std::string FllExporter::toString(const OutputVariable* outputVariable) const { + std::vector<std::string> result; + result.push_back("OutputVariable: " + Op::validName(outputVariable->getName())); + result.push_back(_indent + "enabled: " + (outputVariable->isEnabled() ? "true" : "false")); + result.push_back(_indent + "range: " + Op::join(2, " ", + outputVariable->getMinimum(), outputVariable->getMaximum())); + result.push_back(_indent + "accumulation: " + + toString(outputVariable->fuzzyOutput()->getAccumulation())); + result.push_back(_indent + "defuzzifier: " + + toString(outputVariable->getDefuzzifier())); + result.push_back(_indent + "default: " + Op::str(outputVariable->getDefaultValue())); + result.push_back(_indent + "lock-previous: " + + (outputVariable->isLockedPreviousOutputValue() ? "true" : "false")); + result.push_back(_indent + "lock-range: " + + (outputVariable->isLockedOutputValueInRange() ? "true" : "false")); + for (int i = 0; i < outputVariable->numberOfTerms(); ++i) { + result.push_back(_indent + toString(outputVariable->getTerm(i))); + } + return Op::join(result, _separator); + } + + std::string FllExporter::toString(const RuleBlock* ruleBlock) const { + std::vector<std::string> result; + result.push_back("RuleBlock: " + ruleBlock->getName()); + result.push_back(_indent + "enabled: " + + (ruleBlock->isEnabled() ? "true" : "false")); + result.push_back(_indent + "conjunction: " + toString(ruleBlock->getConjunction())); + result.push_back(_indent + "disjunction: " + toString(ruleBlock->getDisjunction())); + result.push_back(_indent + "activation: " + toString(ruleBlock->getActivation())); + for (int i = 0; i < ruleBlock->numberOfRules(); ++i) { + result.push_back(_indent + toString(ruleBlock->getRule(i))); + } + return Op::join(result, _separator); + } + + std::string FllExporter::toString(const Rule* rule) const { + return "rule: " + rule->getText(); + } + + std::string FllExporter::toString(const Term* term) const { + return "term: " + Op::validName(term->getName()) + " " + term->className() + + " " + term->parameters(); + } + + std::string FllExporter::toString(const Norm* norm) const { + if (norm) return norm->className(); + return "none"; + } + + std::string FllExporter::toString(const Defuzzifier* defuzzifier) const { + if (not defuzzifier) return "none"; + if (const IntegralDefuzzifier * integralDefuzzifier = + dynamic_cast<const IntegralDefuzzifier*> (defuzzifier)) { + return defuzzifier->className() + " " + Op::str<int>(integralDefuzzifier->getResolution()); + + } else if (const WeightedDefuzzifier * weightedDefuzzifier = + dynamic_cast<const WeightedDefuzzifier*> (defuzzifier)) { + return weightedDefuzzifier->className() + " " + weightedDefuzzifier->getTypeName(); + } + return defuzzifier->className(); + } + + FllExporter* FllExporter::clone() const { + return new FllExporter(*this); + } + +} diff --git a/fuzzylite/src/imex/FllImporter.cpp b/fuzzylite/src/imex/FllImporter.cpp new file mode 100644 index 0000000..2443d10 --- /dev/null +++ b/fuzzylite/src/imex/FllImporter.cpp @@ -0,0 +1,317 @@ +/* + 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/imex/FllImporter.h" + +#include "fl/Headers.h" + +#include <queue> + +namespace fl { + + FllImporter::FllImporter(const std::string& separator) : Importer(), + _separator(separator) { + } + + FllImporter::~FllImporter() { + + } + + std::string FllImporter::name() const { + return "FllImporter"; + } + + void FllImporter::setSeparator(const std::string& separator) { + this->_separator = separator; + } + + std::string FllImporter::getSeparator() const { + return this->_separator; + } + + Engine* FllImporter::fromString(const std::string& fll) const { + FL_unique_ptr<Engine> engine(new Engine); + + std::string tag; + std::ostringstream block; + std::istringstream fclReader(fll); + std::string line; + std::queue<std::string> lineQueue; + + bool processPending = false; + int lineNumber = 0; + while (not lineQueue.empty() or std::getline(fclReader, line)) { + if (not lineQueue.empty()) { + line = lineQueue.front(); + lineQueue.pop(); + } else { + line = clean(line); + if (line.empty()) continue; + std::vector<std::string> split = Op::split(line, _separator); + line = clean(split.front()); + for (std::size_t i = 1; i < split.size(); ++i) { + lineQueue.push(clean(split.at(i))); + } + ++lineNumber; + } + if (line.empty()) continue; + std::size_t colon = line.find_first_of(':'); + if (colon == std::string::npos) { + throw fl::Exception("[import error] expected a colon at line " + + Op::str(lineNumber) + ": " + line, FL_AT); + } + std::string key = Op::trim(line.substr(0, colon)); + std::string value = Op::trim(line.substr(colon + 1)); + if ("Engine" == key) { + engine->setName(value); + continue; + } else { + processPending = (key == "InputVariable" + or key == "OutputVariable" + or key == "RuleBlock"); + } + if (processPending) { + process(tag, block.str(), engine.get()); + block.str(""); //clear buffer + block.clear(); //clear error flags + processPending = false; + tag = key; + } + block << key << ":" << value << "\n"; + } + process(tag, block.str(), engine.get()); + return engine.release(); + } + + void FllImporter::process(const std::string& tag, const std::string& block, Engine* engine) const { + if (tag.empty()) return; + if ("InputVariable" == tag) { + processInputVariable(block, engine); + } else if ("OutputVariable" == tag) { + processOutputVariable(block, engine); + } else if ("RuleBlock" == tag) { + processRuleBlock(block, engine); + } else { + throw fl::Exception("[import error] block tag <" + tag + "> not recognized", FL_AT); + } + } + + void FllImporter::processInputVariable(const std::string& block, Engine* engine) const { + std::istringstream reader(block); + std::string line; + InputVariable* inputVariable = new InputVariable; + engine->addInputVariable(inputVariable); + while (std::getline(reader, line)) { + std::pair<std::string, std::string> keyValue = parseKeyValue(line, ':'); + if ("InputVariable" == keyValue.first) { + inputVariable->setName(Op::validName(keyValue.second)); + } else if ("enabled" == keyValue.first) { + inputVariable->setEnabled(parseBoolean(keyValue.second)); + } else if ("range" == keyValue.first) { + std::pair<scalar, scalar> range = parseRange(keyValue.second); + inputVariable->setRange(range.first, range.second); + } else if ("term" == keyValue.first) { + inputVariable->addTerm(parseTerm(keyValue.second, engine)); + } else { + throw fl::Exception("[import error] key <" + keyValue.first + "> not " + "recognized in pair <" + keyValue.first + ":" + keyValue.second + ">", FL_AT); + } + } + } + + void FllImporter::processOutputVariable(const std::string& block, Engine* engine) const { + std::istringstream reader(block); + std::string line; + OutputVariable* outputVariable = new OutputVariable; + engine->addOutputVariable(outputVariable); + while (std::getline(reader, line)) { + std::pair<std::string, std::string> keyValue = parseKeyValue(line, ':'); + if ("OutputVariable" == keyValue.first) { + outputVariable->setName(Op::validName(keyValue.second)); + } else if ("enabled" == keyValue.first) { + outputVariable->setEnabled(parseBoolean(keyValue.second)); + } else if ("range" == keyValue.first) { + std::pair<scalar, scalar> range = parseRange(keyValue.second); + outputVariable->setRange(range.first, range.second); + } else if ("default" == keyValue.first) { + outputVariable->setDefaultValue(Op::toScalar(keyValue.second)); + } else if ("lock-previous" == keyValue.first or "lock-valid" == keyValue.first) { + outputVariable->setLockPreviousOutputValue(parseBoolean(keyValue.second)); + } else if ("lock-range" == keyValue.first) { + outputVariable->setLockOutputValueInRange(parseBoolean(keyValue.second)); + } else if ("defuzzifier" == keyValue.first) { + outputVariable->setDefuzzifier(parseDefuzzifier(keyValue.second)); + } else if ("accumulation" == keyValue.first) { + outputVariable->fuzzyOutput()->setAccumulation(parseSNorm(keyValue.second)); + } else if ("term" == keyValue.first) { + outputVariable->addTerm(parseTerm(keyValue.second, engine)); + } else { + throw fl::Exception("[import error] key <" + keyValue.first + "> not " + "recognized in pair <" + keyValue.first + ":" + keyValue.second + ">", FL_AT); + } + } + } + + void FllImporter::processRuleBlock(const std::string& block, Engine* engine) const { + std::istringstream reader(block); + std::string line; + RuleBlock* ruleBlock = new RuleBlock; + engine->addRuleBlock(ruleBlock); + while (std::getline(reader, line)) { + std::pair<std::string, std::string> keyValue = parseKeyValue(line, ':'); + if ("RuleBlock" == keyValue.first) { + ruleBlock->setName(keyValue.second); + } else if ("enabled" == keyValue.first) { + ruleBlock->setEnabled(parseBoolean(keyValue.second)); + } else if ("conjunction" == keyValue.first) { + ruleBlock->setConjunction(parseTNorm(keyValue.second)); + } else if ("disjunction" == keyValue.first) { + ruleBlock->setDisjunction(parseSNorm(keyValue.second)); + } else if ("activation" == keyValue.first) { + ruleBlock->setActivation(parseTNorm(keyValue.second)); + } else if ("rule" == keyValue.first) { + Rule* rule = new Rule; + rule->setText(keyValue.second); + try { + rule->load(engine); + } catch (std::exception& ex) { + FL_LOG(ex.what()); + } + ruleBlock->addRule(rule); + } else { + throw fl::Exception("[import error] key <" + keyValue.first + "> not " + "recognized in pair <" + keyValue.first + ":" + keyValue.second + ">", FL_AT); + } + } + } + + Term* FllImporter::parseTerm(const std::string& text, Engine* engine) const { + std::vector<std::string> tokens = Op::split(text, " "); + + //MEDIUM Triangle 0.500 1.000 1.500 + + if (tokens.size() < 2) { + throw fl::Exception("[syntax error] expected a term in format <name class parameters>, " + "but found <" + text + ">", FL_AT); + } + FL_unique_ptr<Term> term; + term.reset(FactoryManager::instance()->term()->constructObject(tokens.at(1))); + Term::updateReference(term.get(), engine); + term->setName(Op::validName(tokens.at(0))); + std::ostringstream parameters; + for (std::size_t i = 2; i < tokens.size(); ++i) { + parameters << tokens.at(i); + if (i + 1 < tokens.size()) parameters << " "; + } + term->configure(parameters.str()); + return term.release(); + } + + TNorm* FllImporter::parseTNorm(const std::string& name) const { + if (name == "none") return FactoryManager::instance()->tnorm()->constructObject(""); + return FactoryManager::instance()->tnorm()->constructObject(name); + } + + SNorm* FllImporter::parseSNorm(const std::string& name) const { + if (name == "none") return FactoryManager::instance()->snorm()->constructObject(""); + return FactoryManager::instance()->snorm()->constructObject(name); + } + + Defuzzifier* FllImporter::parseDefuzzifier(const std::string& text) const { + std::vector<std::string> parameters = Op::split(text, " "); + std::string name = parameters.at(0); + if (name == "none") return FactoryManager::instance()->defuzzifier()->constructObject(""); + Defuzzifier* defuzzifier = FactoryManager::instance()->defuzzifier()->constructObject(name); + if (parameters.size() > 1) { + std::string parameter(parameters.at(1)); + if (IntegralDefuzzifier * integralDefuzzifier = dynamic_cast<IntegralDefuzzifier*> (defuzzifier)) { + integralDefuzzifier->setResolution((int) Op::toScalar(parameter)); + } else if (WeightedDefuzzifier * weightedDefuzzifier = dynamic_cast<WeightedDefuzzifier*> (defuzzifier)) { + WeightedDefuzzifier::Type type = WeightedDefuzzifier::Automatic; + if (parameter == "Automatic") type = WeightedDefuzzifier::Automatic; + else if (parameter == "TakagiSugeno") type = WeightedDefuzzifier::TakagiSugeno; + else if (parameter == "Tsukamoto") type = WeightedDefuzzifier::Tsukamoto; + else throw fl::Exception("[syntax error] unknown parameter of WeightedDefuzzifier <" + parameter + ">", FL_AT); + weightedDefuzzifier->setType(type); + } + } + return defuzzifier; + } + + std::pair<scalar, scalar> FllImporter::parseRange(const std::string& text) const { + std::pair<std::string, std::string> range = parseKeyValue(text, ' '); + return std::pair<scalar, scalar>(Op::toScalar(range.first), Op::toScalar(range.second)); + } + + bool FllImporter::parseBoolean(const std::string& boolean) const { + if ("true" == boolean) return true; + if ("false" == boolean) return false; + throw fl::Exception("[syntax error] expected boolean <true|false>, " + "but found <" + boolean + ">", FL_AT); + } + + std::pair<std::string, std::string> FllImporter::parseKeyValue(const std::string& text, + char separator) const { + std::size_t half = text.find_first_of(separator); + if (half == std::string::npos) { + std::ostringstream ex; + ex << "[syntax error] expected pair in the form " + "<key" << separator << "value>, but found <" << text << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + std::pair<std::string, std::string> result; + result.first = text.substr(0, half); + result.second = text.substr(half + 1); + return result; + } + + std::string FllImporter::clean(const std::string& line) const { + if (line.empty()) return line; + if (line.size() == 1) return isspace(line.at(0)) ? "" : line; + int start = 0, end = line.size() - 1; + while (start <= end and isspace(line.at(start))) { + ++start; + } + int sharp = start; + while (sharp <= end) { + if (line.at(sharp) == '#') { + end = sharp - 1; + break; + } + ++sharp; + } + while (end >= start and (line.at(end) == '#' or isspace(line.at(end)))) { + --end; + } + + int length = end - start + 1; + return line.substr(start, length); + } + + FllImporter* FllImporter::clone() const { + return new FllImporter(*this); + } + + +} diff --git a/fuzzylite/src/imex/Importer.cpp b/fuzzylite/src/imex/Importer.cpp new file mode 100644 index 0000000..faef71d --- /dev/null +++ b/fuzzylite/src/imex/Importer.cpp @@ -0,0 +1,54 @@ +/* + 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/imex/Importer.h" +#include "fl/Exception.h" + +#include <fstream> +#include <ostream> + +namespace fl { + + Importer::Importer() { + } + + Importer::~Importer() { + + } + + Engine* Importer::fromFile(const std::string& path) const { + std::ifstream reader(path.c_str()); + if (not reader.is_open()) { + throw fl::Exception("[file error] file <" + path + "> could not be opened", FL_AT); + } + std::ostringstream textEngine; + std::string line; + while (std::getline(reader, line)) { + textEngine << line << std::endl; + } + reader.close(); + return fromString(textEngine.str()); + } + +} diff --git a/fuzzylite/src/imex/JavaExporter.cpp b/fuzzylite/src/imex/JavaExporter.cpp new file mode 100644 index 0000000..a4948f8 --- /dev/null +++ b/fuzzylite/src/imex/JavaExporter.cpp @@ -0,0 +1,228 @@ +/* + 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/imex/JavaExporter.h" + +#include "fl/Headers.h" + +#include <algorithm> +namespace fl { + + JavaExporter::JavaExporter() : Exporter() { + } + + JavaExporter::~JavaExporter() { + + } + + std::string JavaExporter::name() const { + return "JavaExporter"; + } + + std::string JavaExporter::toString(const Engine* engine) const { + std::ostringstream ss; + ss << "Engine engine = new Engine();\n"; + ss << "engine.setName(\"" << engine->getName() << "\");\n"; + ss << "\n"; + + for (int i = 0; i < engine->numberOfInputVariables(); ++i) { + ss << toString(engine->getInputVariable(i), engine) << "\n"; + } + + for (int i = 0; i < engine->numberOfOutputVariables(); ++i) { + ss << toString(engine->getOutputVariable(i), engine) << "\n"; + } + + for (int i = 0; i < engine->numberOfRuleBlocks(); ++i) { + ss << toString(engine->getRuleBlock(i), engine) << "\n"; + } + + return ss.str(); + } + + std::string JavaExporter::toString(const InputVariable* inputVariable, const Engine* engine) const { + std::ostringstream ss; + std::string name = "inputVariable"; + if (engine->numberOfInputVariables() > 1) { + int index = std::distance(engine->inputVariables().begin(), + std::find(engine->inputVariables().begin(), + engine->inputVariables().end(), inputVariable)); + name += Op::str<int>(index + 1); + } + ss << "InputVariable " << name << " = new InputVariable();\n"; + ss << name << ".setEnabled(" << (inputVariable->isEnabled() ? "true" : "false") << ");\n"; + ss << name << ".setName(\"" << inputVariable->getName() << "\");\n"; + ss << name << ".setRange(" + << toString(inputVariable->getMinimum()) << ", " + << toString(inputVariable->getMaximum()) << ");\n"; + + for (int i = 0; i < inputVariable->numberOfTerms(); ++i) { + ss << name << ".addTerm(" << + toString(inputVariable->getTerm(i)) << ");\n"; + } + ss << "engine.addInputVariable(" << name << ");\n"; + return ss.str(); + } + + std::string JavaExporter::toString(const OutputVariable* outputVariable, const Engine* engine) const { + std::ostringstream ss; + std::string name = "outputVariable"; + if (engine->numberOfOutputVariables() > 1) { + int index = std::distance(engine->outputVariables().begin(), + std::find(engine->outputVariables().begin(), + engine->outputVariables().end(), outputVariable)); + name += Op::str<int>(index + 1); + } + ss << "OutputVariable " << name << " = new OutputVariable();\n"; + ss << name << ".setEnabled(" << (outputVariable->isEnabled() ? "true" : "false") << ");\n"; + ss << name << ".setName(\"" << outputVariable->getName() << "\");\n"; + ss << name << ".setRange(" + << toString(outputVariable->getMinimum()) << ", " + << toString(outputVariable->getMaximum()) << ");\n"; + ss << name << ".fuzzyOutput().setAccumulation(" << + toString(outputVariable->fuzzyOutput()->getAccumulation()) << ");\n"; + ss << name << ".setDefuzzifier(" << + toString(outputVariable->getDefuzzifier()) << ");\n"; + ss << name << ".setDefaultValue(" << + toString(outputVariable->getDefaultValue()) << ");\n"; + ss << name << ".setLockPreviousOutputValue(" << + (outputVariable->isLockedPreviousOutputValue() ? "true" : "false") << ");\n"; + ss << name << ".setLockOutputValueInRange(" << + (outputVariable->isLockedOutputValueInRange() ? "true" : "false") << ");\n"; + for (int i = 0; i < outputVariable->numberOfTerms(); ++i) { + ss << name << ".addTerm(" << + toString(outputVariable->getTerm(i)) << ");\n"; + } + ss << "engine.addOutputVariable(" << name << ");\n"; + return ss.str(); + } + + std::string JavaExporter::toString(const RuleBlock* ruleBlock, const Engine* engine) const { + std::ostringstream ss; + std::string name = "ruleBlock"; + if (engine->numberOfRuleBlocks() > 1) { + int index = std::distance(engine->ruleBlocks().begin(), + std::find(engine->ruleBlocks().begin(), + engine->ruleBlocks().end(), ruleBlock)); + name += Op::str<int>(index + 1); + } + ss << "RuleBlock " << name << " = new RuleBlock();\n"; + ss << name << ".setEnabled(" << (ruleBlock->isEnabled() ? "true" : "false") << ");\n"; + ss << name << ".setName(\"" << ruleBlock->getName() << "\");\n"; + ss << name << ".setConjunction(" + << toString(ruleBlock->getConjunction()) << ");\n"; + ss << name << ".setDisjunction(" + << toString(ruleBlock->getDisjunction()) << ");\n"; + ss << name << ".setActivation(" + << toString(ruleBlock->getActivation()) << ");\n"; + for (int i = 0; i < ruleBlock->numberOfRules(); ++i) { + Rule* rule = ruleBlock->getRule(i); + ss << name << ".addRule(Rule.parse(\"" << rule->getText() << "\", engine));\n"; + } + ss << "engine.addRuleBlock(" << name << ");\n"; + return ss.str(); + } + + std::string JavaExporter::toString(const Term* term) const { + if (not term) { + return "null"; + } + + if (const Discrete * discrete = dynamic_cast<const Discrete*> (term)) { + std::ostringstream ss; + std::vector<scalar> xy; + ss << term->className() << ".create(\"" << term->getName() << "\", " + << Op::join(Discrete::toVector(discrete->xy()), ", ") << ")"; + return ss.str(); + } + + if (const Function * function = dynamic_cast<const Function*> (term)) { + std::ostringstream ss; + ss << term->className() << ".create(\"" << term->getName() << "\", " + << "\"" << function->getFormula() << "\", engine)"; + return ss.str(); + } + + if (const Linear * linear = dynamic_cast<const Linear*> (term)) { + std::ostringstream ss; + ss << term->className() << ".create(\"" << term->getName() << "\", " + << "engine, " << Op::join(linear->coefficients(), ", ") << ")"; + return ss.str(); + } + + std::ostringstream ss; + ss << "new " << term->className() << "(\"" << term->getName() << "\", " + << Op::findReplace(term->parameters(), " ", ", ") << ")"; + return ss.str(); + } + + std::string JavaExporter::toString(const Defuzzifier* defuzzifier) const { + if (not defuzzifier) return "null"; + + if (const IntegralDefuzzifier * integralDefuzzifier = + dynamic_cast<const IntegralDefuzzifier*> (defuzzifier)) { + return "new " + integralDefuzzifier->className() + "(" + + fl::Op::str(integralDefuzzifier->getResolution()) + ")"; + } + if (const WeightedDefuzzifier * weightedDefuzzifier = + dynamic_cast<const WeightedDefuzzifier*> (defuzzifier)) { + return "new " + weightedDefuzzifier->className() + + "(\"" + weightedDefuzzifier->getTypeName() + "\")"; + } + return "new " + defuzzifier->className() + "()"; + } + + std::string JavaExporter::toString(const Norm* norm) const{ + if (not norm) return "null"; + return "new " + norm->className() + "()"; + } + + std::string JavaExporter::toString(const TNorm* norm) const { + if (not norm) return "null"; + return "new " + norm->className() + "()"; + } + + std::string JavaExporter::toString(const SNorm* norm) const { + if (not norm) return "null"; + return "new " + norm->className() + "()"; + } + + std::string JavaExporter::toString(scalar value) const { + if (Op::isNaN(value)) { + return "Double.NaN"; + } else if (Op::isInf(value)) { + return (value > 0 + ? "Double.POSITIVE_INFINITY" + : "Double.NEGATIVE_INFINITY"); + } + return Op::str(value); + } + + JavaExporter* JavaExporter::clone() const { + return new JavaExporter(*this); + } + + +} + diff --git a/fuzzylite/src/m/compare.m b/fuzzylite/src/m/compare.m new file mode 100755 index 0000000..56da68d --- /dev/null +++ b/fuzzylite/src/m/compare.m @@ -0,0 +1,60 @@ +%{/* + 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 (R) is a registered trademark of FuzzyLite Limited. + */ +}% + +function [engine] = compare(fisFile, fldFile, delimiter, hasMetadata) +if (nargin < 3) + delimiter = ' '; +end +if (nargin < 4) + hasMetadata = true; +end + +engine = readfis(fisFile); +flMatrix = dlmread(fldFile, delimiter, hasMetadata ~ = 0, 0); + +if (length(engine.input) + length(engine.output) ~ = size(flMatrix, 2)) + error('fuzzylite:compare.m', 'Number of inputs and outputs in engine differ from FLD matrix'); +end + +if (isempty(engine.andMethod)) + engine.andMethod = 'min'; +end +if (isempty(engine.orMethod)) + engine.orMethod = 'max'; +end + +engine.inputValues = flMatrix(1 : end, 1 : length(engine.input)); +engine.outputValues = evalfis(engine.inputValues, engine); +engine.flOutputValues = flMatrix(1 : end, (length(engine.input) + 1) : (length(engine.input) + length(engine.output))); +engine.outputDiff = engine.outputValues - engine.flOutputValues; +engine.fld = [engine.inputValues engine.outputValues engine.flOutputValues engine.outputDiff]; +engine.nanfreeDiff = engine.outputDiff; +engine.nanfreeDiff(find(isnan(engine.nanfreeDiff))) = 0; +engine.mse = nansum(engine.outputDiff.^2) / size(engine.outputDiff, 1); +engine.quantiles = prctile(engine.nanfreeDiff, 0 : 25 : 100); + +end + + + diff --git a/fuzzylite/src/m/compare_examples.m b/fuzzylite/src/m/compare_examples.m new file mode 100755 index 0000000..1bf6818 --- /dev/null +++ b/fuzzylite/src/m/compare_examples.m @@ -0,0 +1,45 @@ +%{/*
+ 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 (R) is a registered trademark of FuzzyLite Limited.
+ */
+}%
+
+
+function [ engines ] = compare_examples(path, delimiter, hasMetadata)
+if (nargin < 2)
+ delimiter = ' ';
+end
+if (nargin < 3)
+ hasMetadata = true;
+end
+
+examples = {'\mamdani\SimpleDimmer', '\mamdani\matlab\mam21', '\mamdani\matlab\mam22', '\mamdani\matlab\shower', '\mamdani\matlab\tank', '\mamdani\matlab\tank2', '\mamdani\matlab\tipper', '\mamdani\matlab\tipper1', '\mamdani\octave\mamdani_tip_calculator', '\takagi-sugeno\SimpleDimmer', '\takagi-sugeno\matlab\fpeaks', '\takagi-sugeno\matlab\invkine1', '\takagi-sugeno\matlab\invkine2', '\takagi-sugeno\matlab\juggler', '\takagi-sugeno\matlab\membrn1', '\takagi-sugeno\matlab\membrn2', '\takagi-sugeno\matlab\slbb', '\takagi-sugeno\matlab\slcp', '\takagi-sugeno\matlab\slcp1', '\takagi-sugeno\matlab\slcpp1', '\takagi-sugeno\matlab\sltbu_fl', '\takagi-sugeno\matlab\sugeno1', '\takagi-sugeno\matlab\tanksg', '\takagi-sugeno\matlab\tippersg', '\takagi-sugeno\octave\cubic_approximator', '\takagi-sugeno\octave\heart_disease_risk', '\takagi-sugeno\octave\linear_tip_calculator'};
+pending = {'\mamdani\octave\investment_portfolio', '\takagi-sugeno\approximation', '\takagi-sugeno\octave\sugeno_tip_calculator', '\tsukamoto\tsukamoto'};
+engines = [];
+for i = 1 : length(examples)
+ fisFile = strcat(path, examples{i}, '.fis')
+ fldFile = strcat(path, examples{i}, '.fld');
+ engines = [engines compare(fisFile, fldFile, delimiter, hasMetadata)];
+ disp(strcat('Five number summary (', num2str(i), '): ', fisFile));
+ engines(i).quantiles
+end
+end
+
diff --git a/fuzzylite/src/main.cpp b/fuzzylite/src/main.cpp new file mode 100644 index 0000000..6d8d701 --- /dev/null +++ b/fuzzylite/src/main.cpp @@ -0,0 +1,71 @@ +/* + 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/Headers.h" + +#include <cstdlib> +#include <fstream> +#include <iomanip> +#include <signal.h> +#include <typeinfo> + +using namespace fl; + +/* +#ifdef FL_WINDOWS +#include <windows.h> +BOOL WINAPI flSignalHandler(DWORD dwCtrlType) +{ + FL_LOG("Signal: " << dwCtrlType); + if (CTRL_C_EVENT == dwCtrlType){ + } + //return FALSE; + return TRUE; +} +#endif + */ + +int main(int argc, char** argv) { + (void) argc; + (void) argv; + std::set_terminate(fl::Exception::terminate); + std::set_unexpected(fl::Exception::terminate); + signal(SIGSEGV, fl::Exception::signalHandler); + signal(SIGABRT, fl::Exception::signalHandler); + signal(SIGILL, fl::Exception::signalHandler); + signal(SIGSEGV, fl::Exception::signalHandler); + signal(SIGFPE, fl::Exception::signalHandler); +#ifdef FL_UNIX + signal(SIGBUS, fl::Exception::signalHandler); + signal(SIGPIPE, fl::Exception::signalHandler); +#endif +#ifdef FL_WINDOWS + //SetConsoleCtrlHandler(flSignalHandler, TRUE); +#endif + fuzzylite::setDebug(false); + return Console::main(argc, argv); +} + + + diff --git a/fuzzylite/src/norm/s/AlgebraicSum.cpp b/fuzzylite/src/norm/s/AlgebraicSum.cpp new file mode 100644 index 0000000..e96c1a7 --- /dev/null +++ b/fuzzylite/src/norm/s/AlgebraicSum.cpp @@ -0,0 +1,45 @@ +/* + 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/norm/s/AlgebraicSum.h" + +namespace fl { + + std::string AlgebraicSum::className() const { + return "AlgebraicSum"; + } + + scalar AlgebraicSum::compute(scalar a, scalar b) const { + return a + b - (a * b); + } + + AlgebraicSum* AlgebraicSum::clone() const { + return new AlgebraicSum(*this); + } + + SNorm* AlgebraicSum::constructor() { + return new AlgebraicSum; + } + +} diff --git a/fuzzylite/src/norm/s/BoundedSum.cpp b/fuzzylite/src/norm/s/BoundedSum.cpp new file mode 100644 index 0000000..9c050c8 --- /dev/null +++ b/fuzzylite/src/norm/s/BoundedSum.cpp @@ -0,0 +1,45 @@ +/* + 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/norm/s/BoundedSum.h" + +namespace fl { + + std::string BoundedSum::className() const { + return "BoundedSum"; + } + + scalar BoundedSum::compute(scalar a, scalar b) const { + return Op::min(scalar(1.0), a + b); + } + + BoundedSum* BoundedSum::clone() const { + return new BoundedSum(*this); + } + + SNorm* BoundedSum::constructor() { + return new BoundedSum; + } + +} diff --git a/fuzzylite/src/norm/s/DrasticSum.cpp b/fuzzylite/src/norm/s/DrasticSum.cpp new file mode 100644 index 0000000..c0629db --- /dev/null +++ b/fuzzylite/src/norm/s/DrasticSum.cpp @@ -0,0 +1,48 @@ +/* + 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/norm/s/DrasticSum.h" + +namespace fl { + + std::string DrasticSum::className() const { + return "DrasticSum"; + } + + scalar DrasticSum::compute(scalar a, scalar b) const { + if (Op::isEq(Op::min(a, b), 0.0)) { + return Op::max(a, b); + } + return 1.0; + } + + DrasticSum* DrasticSum::clone() const { + return new DrasticSum(*this); + } + + SNorm* DrasticSum::constructor() { + return new DrasticSum; + } + +} diff --git a/fuzzylite/src/norm/s/EinsteinSum.cpp b/fuzzylite/src/norm/s/EinsteinSum.cpp new file mode 100644 index 0000000..ec0fbd8 --- /dev/null +++ b/fuzzylite/src/norm/s/EinsteinSum.cpp @@ -0,0 +1,45 @@ +/* + 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/norm/s/EinsteinSum.h" + +namespace fl { + + std::string EinsteinSum::className() const { + return "EinsteinSum"; + } + + scalar EinsteinSum::compute(scalar a, scalar b) const { + return (a + b) / (1.0 + a * b); + } + + EinsteinSum* EinsteinSum::clone() const { + return new EinsteinSum(*this); + } + + SNorm* EinsteinSum::constructor() { + return new EinsteinSum; + } + +} diff --git a/fuzzylite/src/norm/s/HamacherSum.cpp b/fuzzylite/src/norm/s/HamacherSum.cpp new file mode 100644 index 0000000..f9c0994 --- /dev/null +++ b/fuzzylite/src/norm/s/HamacherSum.cpp @@ -0,0 +1,45 @@ +/* + 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/norm/s/HamacherSum.h" + +namespace fl { + + std::string HamacherSum::className() const { + return "HamacherSum"; + } + + scalar HamacherSum::compute(scalar a, scalar b) const { + return (a + b - 2.0 * a * b) / (1.0 - a * b); + } + + HamacherSum* HamacherSum::clone() const { + return new HamacherSum(*this); + } + + SNorm* HamacherSum::constructor() { + return new HamacherSum; + } + +} diff --git a/fuzzylite/src/norm/s/Maximum.cpp b/fuzzylite/src/norm/s/Maximum.cpp new file mode 100644 index 0000000..ed8a839 --- /dev/null +++ b/fuzzylite/src/norm/s/Maximum.cpp @@ -0,0 +1,45 @@ +/* + 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/norm/s/Maximum.h" + +namespace fl { + + std::string Maximum::className() const { + return "Maximum"; + } + + scalar Maximum::compute(scalar a, scalar b) const { + return Op::max(a, b); + } + + Maximum* Maximum::clone() const { + return new Maximum(*this); + } + + SNorm* Maximum::constructor() { + return new Maximum; + } + +} diff --git a/fuzzylite/src/norm/s/NilpotentMaximum.cpp b/fuzzylite/src/norm/s/NilpotentMaximum.cpp new file mode 100644 index 0000000..0a09136 --- /dev/null +++ b/fuzzylite/src/norm/s/NilpotentMaximum.cpp @@ -0,0 +1,50 @@ +/* + 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/norm/s/NilpotentMaximum.h" + +namespace fl { + + std::string NilpotentMaximum::className() const { + return "NilpotentMaximum"; + } + + scalar NilpotentMaximum::compute(scalar a, scalar b) const { + if (Op::isLt(a + b, 1.0)) { + return std::max(a, b); + } + return 1.0; + } + + NilpotentMaximum* NilpotentMaximum::clone() const { + return new NilpotentMaximum(*this); + } + + SNorm* NilpotentMaximum::constructor() { + return new NilpotentMaximum; + } + + +} + diff --git a/fuzzylite/src/norm/s/NormalizedSum.cpp b/fuzzylite/src/norm/s/NormalizedSum.cpp new file mode 100644 index 0000000..94ad5ea --- /dev/null +++ b/fuzzylite/src/norm/s/NormalizedSum.cpp @@ -0,0 +1,46 @@ +/* + 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/norm/s/NormalizedSum.h" + +namespace fl { + + std::string NormalizedSum::className() const { + return "NormalizedSum"; + } + + scalar NormalizedSum::compute(scalar a, scalar b) const { + return a + b / Op::max(scalar(1.0), Op::max(a, b)); + } + + NormalizedSum* NormalizedSum::clone() const { + return new NormalizedSum(*this); + } + + SNorm* NormalizedSum::constructor() { + return new NormalizedSum; + } + + +} diff --git a/fuzzylite/src/norm/t/AlgebraicProduct.cpp b/fuzzylite/src/norm/t/AlgebraicProduct.cpp new file mode 100644 index 0000000..eee1061 --- /dev/null +++ b/fuzzylite/src/norm/t/AlgebraicProduct.cpp @@ -0,0 +1,45 @@ +/* + 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/norm/t/AlgebraicProduct.h" + +namespace fl { + + std::string AlgebraicProduct::className() const { + return "AlgebraicProduct"; + } + + scalar AlgebraicProduct::compute(scalar a, scalar b) const { + return a * b; + } + + AlgebraicProduct* AlgebraicProduct::clone() const { + return new AlgebraicProduct(*this); + } + + TNorm* AlgebraicProduct::constructor() { + return new AlgebraicProduct; + } + +} diff --git a/fuzzylite/src/norm/t/BoundedDifference.cpp b/fuzzylite/src/norm/t/BoundedDifference.cpp new file mode 100644 index 0000000..aa4fead --- /dev/null +++ b/fuzzylite/src/norm/t/BoundedDifference.cpp @@ -0,0 +1,46 @@ +/* + 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/norm/t/BoundedDifference.h" + + +namespace fl { + + std::string BoundedDifference::className() const { + return "BoundedDifference"; + } + + scalar BoundedDifference::compute(scalar a, scalar b) const { + return Op::max(scalar(0.0), a + b - scalar(1.0)); + } + + BoundedDifference* BoundedDifference::clone() const { + return new BoundedDifference(*this); + } + + TNorm* BoundedDifference::constructor() { + return new BoundedDifference; + } + +} diff --git a/fuzzylite/src/norm/t/DrasticProduct.cpp b/fuzzylite/src/norm/t/DrasticProduct.cpp new file mode 100644 index 0000000..124b79d --- /dev/null +++ b/fuzzylite/src/norm/t/DrasticProduct.cpp @@ -0,0 +1,48 @@ +/* + 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/norm/t/DrasticProduct.h" + +namespace fl { + + std::string DrasticProduct::className() const { + return "DrasticProduct"; + } + + scalar DrasticProduct::compute(scalar a, scalar b) const { + if (Op::isEq(Op::max(a, b), 1.0)) { + return Op::min(a, b); + } + return 0.0; + } + + DrasticProduct* DrasticProduct::clone() const { + return new DrasticProduct(*this); + } + + TNorm* DrasticProduct::constructor() { + return new DrasticProduct; + } + +} diff --git a/fuzzylite/src/norm/t/EinsteinProduct.cpp b/fuzzylite/src/norm/t/EinsteinProduct.cpp new file mode 100644 index 0000000..ea79188 --- /dev/null +++ b/fuzzylite/src/norm/t/EinsteinProduct.cpp @@ -0,0 +1,45 @@ +/* + 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/norm/t/EinsteinProduct.h" + +namespace fl { + + std::string EinsteinProduct::className() const { + return "EinsteinProduct"; + } + + scalar EinsteinProduct::compute(scalar a, scalar b) const { + return (a * b) / (2.0 - (a + b - a * b)); + } + + EinsteinProduct* EinsteinProduct::clone() const { + return new EinsteinProduct(*this); + } + + TNorm* EinsteinProduct::constructor() { + return new EinsteinProduct; + } + +} diff --git a/fuzzylite/src/norm/t/HamacherProduct.cpp b/fuzzylite/src/norm/t/HamacherProduct.cpp new file mode 100644 index 0000000..e3f093e --- /dev/null +++ b/fuzzylite/src/norm/t/HamacherProduct.cpp @@ -0,0 +1,46 @@ +/* + 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/norm/t/HamacherProduct.h" + + +namespace fl { + + std::string HamacherProduct::className() const { + return "HamacherProduct"; + } + + scalar HamacherProduct::compute(scalar a, scalar b) const { + return (a * b) / (a + b - a * b); + } + + HamacherProduct* HamacherProduct::clone() const { + return new HamacherProduct(*this); + } + + TNorm* HamacherProduct::constructor() { + return new HamacherProduct; + } + +} diff --git a/fuzzylite/src/norm/t/Minimum.cpp b/fuzzylite/src/norm/t/Minimum.cpp new file mode 100644 index 0000000..34f348f --- /dev/null +++ b/fuzzylite/src/norm/t/Minimum.cpp @@ -0,0 +1,46 @@ +/* + 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/norm/t/Minimum.h" + +namespace fl { + + std::string Minimum::className() const { + return "Minimum"; + } + + scalar Minimum::compute(scalar a, scalar b) const { + return Op::min(a, b); + } + + Minimum* Minimum::clone() const { + return new Minimum(*this); + } + + TNorm* Minimum::constructor() { + return new Minimum; + } + + +} diff --git a/fuzzylite/src/norm/t/NilpotentMinimum.cpp b/fuzzylite/src/norm/t/NilpotentMinimum.cpp new file mode 100644 index 0000000..b52a2fc --- /dev/null +++ b/fuzzylite/src/norm/t/NilpotentMinimum.cpp @@ -0,0 +1,50 @@ +/* + 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/norm/t/NilpotentMinimum.h" + +namespace fl { + + std::string NilpotentMinimum::className() const { + return "NilpotentMinimum"; + } + + scalar NilpotentMinimum::compute(scalar a, scalar b) const { + if (Op::isGt(a + b, 1.0)) { + return Op::min(a, b); + } + return 0.0; + } + + NilpotentMinimum* NilpotentMinimum::clone() const { + return new NilpotentMinimum(*this); + } + + TNorm* NilpotentMinimum::constructor() { + return new NilpotentMinimum; + } + + +} + diff --git a/fuzzylite/src/rule/Antecedent.cpp b/fuzzylite/src/rule/Antecedent.cpp new file mode 100644 index 0000000..aa18a68 --- /dev/null +++ b/fuzzylite/src/rule/Antecedent.cpp @@ -0,0 +1,368 @@ +/* + 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/rule/Antecedent.h" + +#include "fl/Engine.h" +#include "fl/factory/HedgeFactory.h" +#include "fl/factory/FactoryManager.h" +#include "fl/hedge/Any.h" +#include "fl/hedge/Hedge.h" +#include "fl/norm/SNorm.h" +#include "fl/norm/TNorm.h" +#include "fl/rule/Expression.h" +#include "fl/rule/Rule.h" +#include "fl/term/Accumulated.h" +#include "fl/term/Function.h" +#include "fl/term/Term.h" +#include "fl/variable/InputVariable.h" +#include "fl/variable/OutputVariable.h" + +#include <algorithm> +#include <stack> + + +namespace fl { + + Antecedent::Antecedent() + : _text(""), _expression(fl::null) { + } + + Antecedent::~Antecedent() { + unload(); + } + + void Antecedent::setText(const std::string& text) { + this->_text = text; + } + + std::string Antecedent::getText() const { + return this->_text; + } + + Expression* Antecedent::getExpression() const { + return this->_expression; + } + + bool Antecedent::isLoaded() const { + return this->_expression != fl::null; + } + + scalar Antecedent::activationDegree(const TNorm* conjunction, const SNorm* disjunction) const { + return this->activationDegree(conjunction, disjunction, this->_expression); + } + + scalar Antecedent::activationDegree(const TNorm* conjunction, const SNorm* disjunction, + const Expression* node) const { + if (not isLoaded()) { + throw fl::Exception("[antecedent error] antecedent <" + _text + "> is not loaded", FL_AT); + } + const Proposition* proposition = dynamic_cast<const Proposition*> (node); + if (proposition) { + if (not proposition->variable->isEnabled()) { + return 0.0; + } + + if (not proposition->hedges.empty()) { + //if last hedge is "Any", apply hedges in reverse order and return degree + std::vector<Hedge*>::const_reverse_iterator rit = proposition->hedges.rbegin(); + if (dynamic_cast<Any*> (*rit)) { + scalar result = (*rit)->hedge(fl::nan); + while (++rit != proposition->hedges.rend()) { + result = (*rit)->hedge(result); + } + return result; + } + } + scalar result = fl::nan; + if (InputVariable * inputVariable = dynamic_cast<InputVariable*> (proposition->variable)) { + result = proposition->term->membership(inputVariable->getInputValue()); + } else if (OutputVariable * outputVariable = dynamic_cast<OutputVariable*> (proposition->variable)) { + result = outputVariable->fuzzyOutput()->activationDegree(proposition->term); + } + for (std::vector<Hedge*>::const_reverse_iterator rit = proposition->hedges.rbegin(); + rit != proposition->hedges.rend(); ++rit) { + result = (*rit)->hedge(result); + } + return result; + } + //if node is an operator + const Operator* fuzzyOperator = dynamic_cast<const Operator*> (node); + if (not (fuzzyOperator->left and fuzzyOperator->right)) { + std::ostringstream ex; + ex << "[syntax error] left and right operands must exist"; + throw fl::Exception(ex.str(), FL_AT); + } + if (fuzzyOperator->name == Rule::andKeyword()) { + if (not conjunction) throw fl::Exception("[conjunction error] " + "the following rule requires a conjunction operator:\n" + _text, FL_AT); + return conjunction->compute( + this->activationDegree(conjunction, disjunction, fuzzyOperator->left), + this->activationDegree(conjunction, disjunction, fuzzyOperator->right)); + } + + if (fuzzyOperator->name == Rule::orKeyword()) { + if (not disjunction) throw fl::Exception("[disjunction error] " + "the following rule requires a disjunction operator:\n" + _text, FL_AT); + return disjunction->compute( + this->activationDegree(conjunction, disjunction, fuzzyOperator->left), + this->activationDegree(conjunction, disjunction, fuzzyOperator->right)); + } + std::ostringstream ex; + ex << "[syntax error] operator <" << fuzzyOperator->name << "> not recognized"; + throw fl::Exception(ex.str(), FL_AT); + + } + + void Antecedent::unload() { + if (_expression) { + delete _expression; + _expression = fl::null; + } + } + + void Antecedent::load(fl::Rule* rule, const Engine* engine) { + load(_text, rule, engine); + } + + void Antecedent::load(const std::string& antecedent, fl::Rule* rule, const Engine* engine) { + FL_DBG("Antecedent: " << antecedent); + unload(); + this->_text = antecedent; + if (fl::Op::trim(antecedent).empty()) { + throw fl::Exception("[syntax error] antecedent is empty", FL_AT); + } + /* + Builds an proposition tree from the antecedent of a fuzzy rule. + The rules are: + 1) After a variable comes 'is', + 2) After 'is' comes a hedge or a term + 3) After a hedge comes a hedge or a term + 4) After a term comes a variable or an operator + */ + + Function function; + + std::string postfix = function.toPostfix(antecedent); + FL_DBG("Postfix: " << postfix); + std::stringstream tokenizer(postfix); + std::string token; + + enum FSM { + S_VARIABLE = 1, S_IS = 2, S_HEDGE = 4, S_TERM = 8, S_AND_OR = 16 + }; + int state = S_VARIABLE; + std::stack<Expression*> expressionStack; + Proposition* proposition = fl::null; + try { + while (tokenizer >> token) { + if (state bitand S_VARIABLE) { + Variable* variable = fl::null; + if (engine->hasInputVariable(token)) variable = engine->getInputVariable(token); + else if (engine->hasOutputVariable(token)) variable = engine->getOutputVariable(token); + if (variable) { + proposition = new Proposition; + proposition->variable = variable; + expressionStack.push(proposition); + + state = S_IS; + FL_DBG("Token <" << token << "> is variable"); + continue; + } + } + + if (state bitand S_IS) { + if (token == Rule::isKeyword()) { + state = S_HEDGE bitor S_TERM; + FL_DBG("Token <" << token << "> is keyword"); + continue; + } + } + + if (state bitand S_HEDGE) { + Hedge* hedge = rule->getHedge(token); + if (not hedge) { + HedgeFactory* factory = FactoryManager::instance()->hedge(); + if (factory->hasConstructor(token)) { + hedge = factory->constructObject(token); + rule->addHedge(hedge); + } + } + if (hedge) { + proposition->hedges.push_back(hedge); + if (dynamic_cast<Any*> (hedge)) { + state = S_VARIABLE bitor S_AND_OR; + } else { + state = S_HEDGE bitor S_TERM; + } + FL_DBG("Token <" << token << "> is hedge"); + continue; + } + } + + if (state bitand S_TERM) { + if (proposition->variable->hasTerm(token)) { + proposition->term = proposition->variable->getTerm(token); + state = S_VARIABLE bitor S_AND_OR; + FL_DBG("Token <" << token << "> is term"); + continue; + } + } + + if (state bitand S_AND_OR) { + if (token == Rule::andKeyword() or token == Rule::orKeyword()) { + if (expressionStack.size() < 2) { + std::ostringstream ex; + ex << "[syntax error] logical operator <" << token << "> expects two operands," + << "but found <" << expressionStack.size() << "> in antecedent"; + throw fl::Exception(ex.str(), FL_AT); + } + Operator* fuzzyOperator = new Operator; + fuzzyOperator->name = token; + fuzzyOperator->right = expressionStack.top(); + expressionStack.pop(); + fuzzyOperator->left = expressionStack.top(); + expressionStack.pop(); + expressionStack.push(fuzzyOperator); + + state = S_VARIABLE bitor S_AND_OR; + FL_DBG("Subtree: " << fuzzyOperator->toString() << + "(" << fuzzyOperator->left->toString() << ") " << + "(" << fuzzyOperator->right->toString() << ")"); + continue; + } + } + + //If reached this point, there was an error + if ((state bitand S_VARIABLE) or (state bitand S_AND_OR)) { + std::ostringstream ex; + ex << "[syntax error] antecedent expected variable or logical operator, but found <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + if (state bitand S_IS) { + std::ostringstream ex; + ex << "[syntax error] antecedent expected keyword <" << Rule::isKeyword() << ">, but found <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + if ((state bitand S_HEDGE) or (state bitand S_TERM)) { + std::ostringstream ex; + ex << "[syntax error] antecedent expected hedge or term, but found <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + std::ostringstream ex; + ex << "[syntax error] unexpected token <" << token << "> in antecedent"; + throw fl::Exception(ex.str(), FL_AT); + } + + if (not ((state bitand S_VARIABLE) or (state bitand S_AND_OR))) { //only acceptable final state + if (state bitand S_IS) { + std::ostringstream ex; + ex << "[syntax error] antecedent expected keyword <" << Rule::isKeyword() << "> after <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + if ((state bitand S_HEDGE) or (state bitand S_TERM)) { + std::ostringstream ex; + ex << "[syntax error] antecedent expected hedge or term after <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + } + + if (expressionStack.size() != 1) { + std::vector<std::string> errors; + while (expressionStack.size() > 1) { + Expression* expression = expressionStack.top(); + expressionStack.pop(); + errors.push_back(expression->toString()); + delete expression; + } + std::ostringstream ex; + ex << "[syntax error] unable to parse the following expressions in antecedent <" + << Op::join(errors, " ") << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + } catch (...) { + for (std::size_t i = 0; i < expressionStack.size(); ++i) { + delete expressionStack.top(); + expressionStack.pop(); + } + throw; + } + this->_expression = expressionStack.top(); + } + + std::string Antecedent::toString() const { + return toInfix(this->_expression); + } + + std::string Antecedent::toPrefix(const Expression* node) const { + if (not isLoaded()) { + throw fl::Exception("[antecedent error] antecedent <" + _text + "> is not loaded", FL_AT); + } + if (not node) node = this->_expression; + + if (dynamic_cast<const Proposition*> (node)) { + return node->toString(); + } + const Operator* fuzzyOperator = dynamic_cast<const Operator*> (node); + std::stringstream ss; + ss << fuzzyOperator->toString() << " " + << toPrefix(fuzzyOperator->left) << " " + << toPrefix(fuzzyOperator->right) << " "; + return ss.str(); + } + + std::string Antecedent::toInfix(const Expression* node) const { + if (not isLoaded()) { + throw fl::Exception("[antecedent error] antecedent <" + _text + "> is not loaded", FL_AT); + } + if (not node) node = this->_expression; + if (dynamic_cast<const Proposition*> (node)) { + return node->toString(); + } + const Operator* fuzzyOperator = dynamic_cast<const Operator*> (node); + std::stringstream ss; + ss << toInfix(fuzzyOperator->left) << " " + << fuzzyOperator->toString() << " " + << toInfix(fuzzyOperator->right) << " "; + return ss.str(); + } + + std::string Antecedent::toPostfix(const Expression* node) const { + if (not isLoaded()) { + throw fl::Exception("[antecedent error] antecedent <" + _text + "> is not loaded", FL_AT); + } + if (not node) node = this->_expression; + if (dynamic_cast<const Proposition*> (node)) { + return node->toString(); + } + const Operator* fuzzyOperator = dynamic_cast<const Operator*> (node); + std::stringstream ss; + ss << toPostfix(fuzzyOperator->left) << " " + << toPostfix(fuzzyOperator->right) << " " + << fuzzyOperator->toString() << " "; + return ss.str(); + } + + +} diff --git a/fuzzylite/src/rule/Consequent.cpp b/fuzzylite/src/rule/Consequent.cpp new file mode 100644 index 0000000..28d3390 --- /dev/null +++ b/fuzzylite/src/rule/Consequent.cpp @@ -0,0 +1,243 @@ +/* + 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/rule/Consequent.h" + +#include "fl/Engine.h" +#include "fl/factory/HedgeFactory.h" +#include "fl/factory/FactoryManager.h" +#include "fl/hedge/Hedge.h" +#include "fl/hedge/Any.h" +#include "fl/norm/TNorm.h" +#include "fl/rule/Expression.h" +#include "fl/rule/Rule.h" +#include "fl/term/Accumulated.h" +#include "fl/term/Activated.h" +#include "fl/variable/OutputVariable.h" + +#include <algorithm> + +namespace fl { + + Consequent::Consequent() { + } + + Consequent::~Consequent() { + unload(); + } + + std::string Consequent::getText() const { + return this->_text; + } + + void Consequent::setText(const std::string& text) { + this->_text = text; + } + + const std::vector<Proposition*>& Consequent::conclusions() const { + return this->_conclusions; + } + + void Consequent::modify(scalar activationDegree, const TNorm* activation) { + if (not isLoaded()) { + throw fl::Exception("[consequent error] consequent <" + _text + "> is not loaded", FL_AT); + } + for (std::size_t i = 0; i < _conclusions.size(); ++i) { + Proposition* proposition = _conclusions.at(i); + if (proposition->variable->isEnabled()) { + if (not proposition->hedges.empty()) { + for (std::vector<Hedge*>::const_reverse_iterator rit = proposition->hedges.rbegin(); + rit != proposition->hedges.rend(); ++rit) { + activationDegree = (*rit)->hedge(activationDegree); + } + } + Activated* term = new Activated(_conclusions.at(i)->term, activationDegree, activation); + OutputVariable* outputVariable = dynamic_cast<OutputVariable*> (proposition->variable); + outputVariable->fuzzyOutput()->addTerm(term); + FL_DBG("Accumulating " << term->toString()); + } + } + } + + bool Consequent::isLoaded() { + return not _conclusions.empty(); + } + + void Consequent::unload() { + for (std::size_t i = 0; i < _conclusions.size(); ++i) { + delete _conclusions.at(i); + } + _conclusions.clear(); + } + + void Consequent::load(Rule* rule, const Engine* engine) { + load(_text, rule, engine); + } + + void Consequent::load(const std::string& consequent, Rule* rule, const Engine* engine) { + unload(); + this->_text = consequent; + + if (fl::Op::trim(consequent).empty()) { + throw fl::Exception("[syntax error] consequent is empty", FL_AT); + } + + /** + Extracts the list of propositions from the consequent + The rules are: + 1) After a variable comes 'is' or '=', + 2) After 'is' comes a hedge or a term + 3) After a hedge comes a hedge or a term + 4) After a term comes operators 'and' or 'with' + 5) After operator 'and' comes a variable + 6) After operator 'with' comes a float + */ + enum FSM { + S_VARIABLE = 1, S_IS = 2, S_HEDGE = 4, S_TERM = 8, + S_AND = 16, S_WITH = 32 + }; + int state = S_VARIABLE; + + Proposition* proposition = fl::null; + + std::stringstream tokenizer(consequent); + std::string token; + try { + while (tokenizer >> token) { + if (state bitand S_VARIABLE) { + if (engine->hasOutputVariable(token)) { + proposition = new Proposition; + proposition->variable = engine->getOutputVariable(token); + _conclusions.push_back(proposition); + + state = S_IS; + continue; + } + } + + if (state bitand S_IS) { + if (token == Rule::isKeyword()) { + state = S_HEDGE bitor S_TERM; + continue; + } + } + + if (state bitand S_HEDGE) { + Hedge* hedge = rule->getHedge(token); + if (not hedge) { + HedgeFactory* factory = FactoryManager::instance()->hedge(); + if (factory->hasConstructor(token)){ + hedge = factory->constructObject(token); + rule->addHedge(hedge); + } + } + if (hedge) { + proposition->hedges.push_back(hedge); + state = S_HEDGE bitor S_TERM; + continue; + } + } + + if (state bitand S_TERM) { + if (proposition->variable->hasTerm(token)) { + proposition->term = proposition->variable->getTerm(token); + state = S_AND bitor S_WITH; + continue; + } + } + + if (state bitand S_AND) { + if (token == Rule::andKeyword()) { + state = S_VARIABLE; + continue; + } + } + + //if reached this point, there was an error: + if (state bitand S_VARIABLE) { + std::ostringstream ex; + ex << "[syntax error] consequent expected output variable, but found <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + if (state bitand S_IS) { + std::ostringstream ex; + ex << "[syntax error] consequent expected keyword <" << Rule::isKeyword() << ">, " + "but found <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + + if ((state bitand S_HEDGE) or (state bitand S_TERM)) { + std::ostringstream ex; + ex << "[syntax error] consequent expected hedge or term, but found <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + + if ((state bitand S_AND) or (state bitand S_WITH)) { + std::ostringstream ex; + ex << "[syntax error] consequent expected operator <" << Rule::andKeyword() << "> " + << "or keyword <" << Rule::withKeyword() << ">, " + << "but found <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + + std::ostringstream ex; + ex << "[syntax error] unexpected token <" << token << "> in consequent"; + throw fl::Exception(ex.str(), FL_AT); + } + + if (not ((state bitand S_AND) or (state bitand S_WITH))) { //only acceptable final state + if (state bitand S_VARIABLE) { + std::ostringstream ex; + ex << "[syntax error] consequent expected output variable after <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + if (state bitand S_IS) { + std::ostringstream ex; + ex << "[syntax error] consequent expected keyword <" << Rule::isKeyword() << "> " + "after <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + if ((state bitand S_HEDGE) or (state bitand S_TERM)) { + std::ostringstream ex; + ex << "[syntax error] consequent expected hedge or term after <" << token << ">"; + throw fl::Exception(ex.str(), FL_AT); + } + } + } catch (...) { + unload(); + throw; + } + } + + std::string Consequent::toString() const { + std::stringstream ss; + for (std::size_t i = 0; i < _conclusions.size(); ++i) { + ss << _conclusions.at(i)->toString(); + if (i + 1 < _conclusions.size()) + ss << " " << Rule::andKeyword() << " "; + } + return ss.str(); + } + +} diff --git a/fuzzylite/src/rule/Expression.cpp b/fuzzylite/src/rule/Expression.cpp new file mode 100644 index 0000000..ea7873e --- /dev/null +++ b/fuzzylite/src/rule/Expression.cpp @@ -0,0 +1,83 @@ +/* + 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/rule/Expression.h" + +#include "fl/hedge/Hedge.h" +#include "fl/term/Term.h" +#include "fl/rule/Rule.h" +#include "fl/variable/Variable.h" + +namespace fl { + + Expression::Expression() { + } + + Expression::~Expression() { + } + + Proposition::Proposition() + : Expression(), variable(fl::null), term(fl::null) { + } + + Proposition::~Proposition() { + + } + + std::string Proposition::toString() const { + std::ostringstream ss; + if (variable) { + ss << variable->getName(); + } else { + ss << "?"; + } + if (not hedges.empty()) { + ss << " " << Rule::isKeyword() << " "; + for (std::size_t i = 0; i < hedges.size(); ++i) { + ss << hedges.at(i)->name() << " "; + } + } + + if (term) { //term is fl::null if hedge is any + if (hedges.empty()) { + ss << " " << Rule::isKeyword() << " "; + } + ss << term->getName(); + } + return ss.str(); + } + + Operator::Operator() : Expression(), name(""), left(fl::null), right(fl::null) { + } + + Operator::~Operator() { + if (left) delete left; + if (right) delete right; + } + + std::string Operator::toString() const { + return name; + } + +} diff --git a/fuzzylite/src/rule/Rule.cpp b/fuzzylite/src/rule/Rule.cpp new file mode 100644 index 0000000..446290b --- /dev/null +++ b/fuzzylite/src/rule/Rule.cpp @@ -0,0 +1,262 @@ +/* + 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/rule/Rule.h" + +#include "fl/Exception.h" +#include "fl/hedge/Hedge.h" +#include "fl/imex/FllExporter.h" +#include "fl/norm/Norm.h" +#include "fl/rule/Antecedent.h" +#include "fl/rule/Consequent.h" + +#include <sstream> +#include <vector> + +namespace fl { + + Rule::Rule(const std::string& text, scalar weight) + : _text(text), _weight(weight), _antecedent(new Antecedent), _consequent(new Consequent) { + } + + Rule::Rule(const Rule& other) : _text(other._text), _weight(other._weight), + _antecedent(new Antecedent), _consequent(new Consequent) { + } + + Rule& Rule::operator=(const Rule& other) { + if (this != &other) { + unload(); + + _text = other._text; + _weight = other._weight; + _antecedent.reset(new Antecedent); + _consequent.reset(new Consequent); + } + return *this; + } + + Rule::~Rule() { + unload(); + } + + void Rule::setText(const std::string& text) { + this->_text = text; + } + + std::string Rule::getText() const { + return this->_text; + } + + void Rule::setWeight(scalar weight) { + this->_weight = weight; + } + + scalar Rule::getWeight() const { + return this->_weight; + } + + void Rule::setAntecedent(Antecedent* antecedent) { + this->_antecedent.reset(antecedent); + } + + Antecedent* Rule::getAntecedent() const { + return this->_antecedent.get(); + } + + void Rule::setConsequent(Consequent* consequent) { + this->_consequent.reset(consequent); + } + + Consequent* Rule::getConsequent() const { + return this->_consequent.get(); + } + + /** + * Operations for std::vector _hedges + */ + void Rule::addHedge(Hedge* hedge) { + this->_hedges[hedge->name()] = hedge; + } + + Hedge* Rule::getHedge(const std::string& name) const { + std::map<std::string, Hedge*>::const_iterator it = this->_hedges.find(name); + if (it != this->_hedges.end()) { + if (it->second) return it->second; + } + return fl::null; + } + + Hedge* Rule::removeHedge(const std::string& name) { + Hedge* result = fl::null; + std::map<std::string, Hedge*>::iterator it = this->_hedges.find(name); + if (it != this->_hedges.end()) { + result = it->second; + this->_hedges.erase(it); + } + return result; + } + + bool Rule::hasHedge(const std::string& name) const { + std::map<std::string, Hedge*>::const_iterator it = this->_hedges.find(name); + return (it != this->_hedges.end()); + } + + int Rule::numberOfHedges() const { + return this->_hedges.size(); + } + + void Rule::setHedges(const std::map<std::string, Hedge*>& hedges) { + this->_hedges = hedges; + } + + const std::map<std::string, Hedge*>& Rule::hedges() const { + return this->_hedges; + } + + std::map<std::string, Hedge*>& Rule::hedges() { + return this->_hedges; + } + + scalar Rule::activationDegree(const TNorm* conjunction, const SNorm* disjunction) const { + if (not isLoaded()) { + throw fl::Exception("[rule error] the following rule is not loaded: " + _text, FL_AT); + } + return _weight * getAntecedent()->activationDegree(conjunction, disjunction); + } + + void Rule::activate(scalar degree, const TNorm* activation) const { + if (not isLoaded()) { + throw fl::Exception("[rule error] the following rule is not loaded: " + _text, FL_AT); + } + _consequent->modify(degree, activation); + } + + bool Rule::isLoaded() const { + return _antecedent->isLoaded() and _consequent->isLoaded(); + } + + void Rule::unload() { + _antecedent->unload(); + _consequent->unload(); + + for (std::map<std::string, Hedge*>::const_iterator it = _hedges.begin(); + it != _hedges.end(); ++it) { + delete it->second; + } + _hedges.clear(); + } + + void Rule::load(const Engine* engine) { + load(_text, engine); + } + + void Rule::load(const std::string& rule, const Engine* engine) { + this->_text = rule; + std::istringstream tokenizer(rule.substr(0, rule.find_first_of('#'))); + std::string token; + std::ostringstream ossAntecedent, ossConsequent; + scalar weight = 1.0; + + enum FSM { + S_NONE, S_IF, S_THEN, S_WITH, S_END + }; + FSM state = S_NONE; + try { + while (tokenizer >> token) { + + switch (state) { + case S_NONE: + if (token == Rule::ifKeyword()) state = S_IF; + else { + std::ostringstream ex; + ex << "[syntax error] expected keyword <" << Rule::ifKeyword() << + ">, but found <" << token << "> in rule: " << rule; + throw fl::Exception(ex.str(), FL_AT); + } + break; + case S_IF: + if (token == Rule::thenKeyword()) state = S_THEN; + else ossAntecedent << token << " "; + break; + case S_THEN: + if (token == Rule::withKeyword()) state = S_WITH; + else ossConsequent << token << " "; + break; + case S_WITH: + try { + weight = fl::Op::toScalar(token); + state = S_END; + } catch (fl::Exception& e) { + std::ostringstream ex; + ex << "[syntax error] expected a numeric value as the weight of the rule: " + << rule; + e.append(ex.str(), FL_AT); + throw e; + } + break; + case S_END: + std::ostringstream ex; + ex << "[syntax error] unexpected token <" << token << "> at the end of rule"; + throw fl::Exception(ex.str(), FL_AT); + } + } + if (state == S_NONE) { + std::ostringstream ex; + ex << "[syntax error] " << (rule.empty() ? "empty rule" : "ignored rule: " + rule); + throw fl::Exception(ex.str(), FL_AT); + } else if (state == S_IF) { + std::ostringstream ex; + ex << "[syntax error] keyword <" << Rule::thenKeyword() << "> not found in rule: " << rule; + throw fl::Exception(ex.str(), FL_AT); + } else if (state == S_WITH) { + std::ostringstream ex; + ex << "[syntax error] expected a numeric value as the weight of the rule: " << rule; + throw fl::Exception(ex.str(), FL_AT); + } + + _antecedent->load(ossAntecedent.str(), this, engine); + _consequent->load(ossConsequent.str(), this, engine); + _weight = weight; + + } catch (...) { + unload(); + throw; + } + } + + std::string Rule::toString() const { + return FllExporter().toString(this); + } + + Rule* Rule::clone() const { + return new Rule(*this); + } + + Rule* Rule::parse(const std::string& rule, const Engine* engine) { + FL_unique_ptr<Rule> result(new Rule); + result->load(rule, engine); + return result.release(); + } + +} diff --git a/fuzzylite/src/rule/RuleBlock.cpp b/fuzzylite/src/rule/RuleBlock.cpp new file mode 100644 index 0000000..9ab813e --- /dev/null +++ b/fuzzylite/src/rule/RuleBlock.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/rule/RuleBlock.h" + +#include "fl/imex/FllExporter.h" +#include "fl/norm/TNorm.h" +#include "fl/norm/SNorm.h" +#include "fl/rule/Rule.h" + +#include <sstream> + +namespace fl { + + RuleBlock::RuleBlock(const std::string& name) + : _name(name), _enabled(true) { + } + + RuleBlock::RuleBlock(const RuleBlock& other) : _name(other._name), + _enabled(true) { + copyFrom(other); + } + + RuleBlock& RuleBlock::operator=(const RuleBlock& other) { + if (this != &other) { + for (std::size_t i = 0; i < _rules.size(); ++i) { + delete _rules.at(i); + } + _rules.clear(); + _conjunction.reset(fl::null); + _disjunction.reset(fl::null); + _activation.reset(fl::null); + + copyFrom(other); + } + return *this; + } + + void RuleBlock::copyFrom(const RuleBlock& source) { + _name = source._name; + _enabled = source._enabled; + if (source._activation.get()) _activation.reset(source._activation->clone()); + if (source._conjunction.get()) _conjunction.reset(source._conjunction->clone()); + if (source._disjunction.get()) _disjunction.reset(source._disjunction->clone()); + for (std::size_t i = 0; i < source._rules.size(); ++i) { + _rules.push_back(source._rules.at(i)->clone()); + } + } + + RuleBlock::~RuleBlock() { + for (std::size_t i = 0; i < _rules.size(); ++i) { + delete _rules.at(i); + } + _rules.clear(); + } + + void RuleBlock::activate() { + FL_DBG("==================="); + FL_DBG("ACTIVATING RULEBLOCK " << _name); + for (std::size_t i = 0; i < _rules.size(); ++i) { + Rule* rule = _rules.at(i); + if (rule->isLoaded()) { + scalar activationDegree = rule->activationDegree(_conjunction.get(), _disjunction.get()); + FL_DBG("[degree=" << Op::str(activationDegree) << "] " << rule->toString()); + if (Op::isGt(activationDegree, 0.0)) { + rule->activate(activationDegree, _activation.get()); + } + } else { + FL_DBG("Rule not loaded: " << rule->toString()); + } + } + } + + void RuleBlock::unloadRules() const { + for (std::size_t i = 0; i < _rules.size(); ++i) { + _rules.at(i)->unload(); + } + } + + void RuleBlock::loadRules(const Engine* engine) { + std::ostringstream exceptions; + bool throwException = false; + for (std::size_t i = 0; i < _rules.size(); ++i) { + Rule* rule = _rules.at(i); + if (rule->isLoaded()) { + rule->unload(); + } + try { + rule->load(engine); + } catch (std::exception& ex) { + throwException = true; + exceptions << ex.what() << "\n"; + } + } + if (throwException) { + fl::Exception exception("[ruleblock error] the following " + "rules could not be loaded:\n" + exceptions.str(), FL_AT); + throw exception; + } + } + + void RuleBlock::reloadRules(const Engine* engine) { + unloadRules(); + loadRules(engine); + } + + void RuleBlock::setName(std::string name) { + this->_name = name; + } + + std::string RuleBlock::getName() const { + return this->_name; + } + + void RuleBlock::setConjunction(TNorm* tnorm) { + this->_conjunction.reset(tnorm); + } + + TNorm* RuleBlock::getConjunction() const { + return this->_conjunction.get(); + } + + void RuleBlock::setDisjunction(SNorm* snorm) { + this->_disjunction.reset(snorm); + } + + SNorm* RuleBlock::getDisjunction() const { + return this->_disjunction.get(); + } + + void RuleBlock::setActivation(TNorm* activation) { + this->_activation.reset(activation); + } + + TNorm* RuleBlock::getActivation() const { + return this->_activation.get(); + } + + void RuleBlock::setEnabled(bool enabled) { + this->_enabled = enabled; + } + + bool RuleBlock::isEnabled() const { + return this->_enabled; + } + + std::string RuleBlock::toString() const { + return FllExporter().toString(this); + } + + /** + * Operations for std::vector _rules + */ + void RuleBlock::addRule(Rule* rule) { + this->_rules.push_back(rule); + } + + void RuleBlock::insertRule(Rule* rule, int index) { + this->_rules.insert(this->_rules.begin() + index, rule); + } + + Rule* RuleBlock::getRule(int index) const { + return this->_rules.at(index); + } + + Rule* RuleBlock::removeRule(int index) { + Rule* result = this->_rules.at(index); + this->_rules.erase(this->_rules.begin() + index); + return result; + } + + int RuleBlock::numberOfRules() const { + return this->_rules.size(); + } + + const std::vector<Rule*>& RuleBlock::rules() const { + return this->_rules; + } + + void RuleBlock::setRules(const std::vector<Rule*>& rules) { + this->_rules = rules; + } + + std::vector<Rule*>& RuleBlock::rules() { + return this->_rules; + } + + +} 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; + } + +} diff --git a/fuzzylite/src/variable/InputVariable.cpp b/fuzzylite/src/variable/InputVariable.cpp new file mode 100644 index 0000000..9fa2932 --- /dev/null +++ b/fuzzylite/src/variable/InputVariable.cpp @@ -0,0 +1,54 @@ +/* + 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/variable/InputVariable.h" + +#include "fl/imex/FllExporter.h" + +namespace fl { + + InputVariable::InputVariable(const std::string& name, scalar minimum, scalar maximum) + : Variable(name, minimum, maximum), _inputValue(fl::nan) { + } + + InputVariable::~InputVariable() { + } + + void InputVariable::setInputValue(scalar inputValue) { + this->_inputValue = inputValue; + } + + scalar InputVariable::getInputValue() const { + return this->_inputValue; + } + + std::string InputVariable::fuzzyInputValue() const { + return fuzzify(_inputValue); + } + + std::string InputVariable::toString() const { + return FllExporter().toString(this); + } + +} diff --git a/fuzzylite/src/variable/OutputVariable.cpp b/fuzzylite/src/variable/OutputVariable.cpp new file mode 100644 index 0000000..6e1d906 --- /dev/null +++ b/fuzzylite/src/variable/OutputVariable.cpp @@ -0,0 +1,195 @@ +/* + 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/variable/OutputVariable.h" + +#include "fl/defuzzifier/Defuzzifier.h" +#include "fl/imex/FllExporter.h" +#include "fl/norm/SNorm.h" +#include "fl/term/Accumulated.h" +#include "fl/term/Activated.h" + +namespace fl { + + OutputVariable::OutputVariable(const std::string& name, + scalar minimum, scalar maximum) + : Variable(name, minimum, maximum), + _fuzzyOutput(new Accumulated(name, minimum, maximum)), _outputValue(fl::nan), + _previousOutputValue(fl::nan), _defaultValue(fl::nan), + _lockOutputValueInRange(false), _lockPreviousOutputValue(false) { + } + + OutputVariable::OutputVariable(const OutputVariable& other) : Variable(other) { + copyFrom(other); + } + + OutputVariable& OutputVariable::operator=(const OutputVariable& other) { + if (this != &other) { + _fuzzyOutput.reset(fl::null); + _defuzzifier.reset(fl::null); + + Variable::operator=(other); + copyFrom(other); + } + return *this; + } + + OutputVariable::~OutputVariable() { + } + + void OutputVariable::copyFrom(const OutputVariable& other) { + _fuzzyOutput.reset(other._fuzzyOutput->clone()); + if (other._defuzzifier.get()) _defuzzifier.reset(other._defuzzifier->clone()); + _outputValue = other._outputValue; + _previousOutputValue = other._previousOutputValue; + _defaultValue = other._defaultValue; + _lockOutputValueInRange = other._lockOutputValueInRange; + _lockPreviousOutputValue = other._lockPreviousOutputValue; + } + + void OutputVariable::setName(const std::string& name) { + Variable::setName(name); + this->_fuzzyOutput->setName(name); + } + + Accumulated* OutputVariable::fuzzyOutput() const { + return this->_fuzzyOutput.get(); + } + + void OutputVariable::setMinimum(scalar minimum) { + Variable::setMinimum(minimum); + this->_fuzzyOutput->setMinimum(minimum); + } + + void OutputVariable::setMaximum(scalar maximum) { + Variable::setMaximum(maximum); + this->_fuzzyOutput->setMaximum(maximum); + } + + void OutputVariable::setDefuzzifier(Defuzzifier* defuzzifier) { + this->_defuzzifier.reset(defuzzifier); + } + + Defuzzifier* OutputVariable::getDefuzzifier() const { + return this->_defuzzifier.get(); + } + + void OutputVariable::setOutputValue(scalar outputValue) { + this->_outputValue = outputValue; + } + + scalar OutputVariable::getOutputValue() const { + return this->_outputValue; + } + + void OutputVariable::setPreviousOutputValue(scalar previousOutputValue) { + this->_previousOutputValue = previousOutputValue; + } + + scalar OutputVariable::getPreviousOutputValue() const { + return this->_previousOutputValue; + } + + void OutputVariable::setDefaultValue(scalar defaultValue) { + this->_defaultValue = defaultValue; + } + + scalar OutputVariable::getDefaultValue() const { + return this->_defaultValue; + } + + void OutputVariable::setLockOutputValueInRange(bool lockOutputValueInRange) { + this->_lockOutputValueInRange = lockOutputValueInRange; + } + + bool OutputVariable::isLockedOutputValueInRange() const { + return this->_lockOutputValueInRange; + } + + void OutputVariable::setLockPreviousOutputValue(bool lockPreviousOutputValue) { + this->_lockPreviousOutputValue = lockPreviousOutputValue; + } + + bool OutputVariable::isLockedPreviousOutputValue() const { + return this->_lockPreviousOutputValue; + } + + void OutputVariable::defuzzify() { + if (fl::Op::isFinite(this->_outputValue)) { + this->_previousOutputValue = this->_outputValue; + } + + scalar result = fl::nan; + bool isValid = this->_enabled and not this->_fuzzyOutput->isEmpty(); + if (isValid) { + if (not _defuzzifier.get()) { + throw fl::Exception("[defuzzifier error] " + "defuzzifier needed to defuzzify output variable <" + _name + ">", FL_AT); + } + result = this->_defuzzifier->defuzzify(this->_fuzzyOutput.get(), _minimum, _maximum); + } else { + //if a previous defuzzification was successfully performed and + //and the output value is supposed not to change when the output is empty + if (_lockPreviousOutputValue and not Op::isNaN(_previousOutputValue)) { + result = _previousOutputValue; + } else { + result = _defaultValue; + } + } + + if (_lockOutputValueInRange) { + result = fl::Op::bound(result, _minimum, _maximum); + } + + this->_outputValue = result; + } + + std::string OutputVariable::fuzzyOutputValue() const { + std::ostringstream ss; + for (std::size_t i = 0; i < _terms.size(); ++i) { + scalar degree = _fuzzyOutput->activationDegree(_terms.at(i)); + if (i == 0) { + ss << fl::Op::str(degree); + } else { + if (fl::Op::isNaN(degree) or fl::Op::isGE(degree, 0.0)) + ss << " + " << fl::Op::str(degree); + else + ss << " - " << fl::Op::str(std::fabs(degree)); + } + ss << "/" << _terms.at(i)->getName(); + } + return ss.str(); + } + + void OutputVariable::clear() { + _fuzzyOutput->clear(); + setPreviousOutputValue(fl::nan); + setOutputValue(fl::nan); + } + + std::string OutputVariable::toString() const { + return FllExporter().toString(this); + } + +} diff --git a/fuzzylite/src/variable/Variable.cpp b/fuzzylite/src/variable/Variable.cpp new file mode 100644 index 0000000..37cf25c --- /dev/null +++ b/fuzzylite/src/variable/Variable.cpp @@ -0,0 +1,244 @@ +/* + 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/variable/Variable.h" + +#include "fl/defuzzifier/Centroid.h" +#include "fl/imex/FllExporter.h" +#include "fl/norm/Norm.h" +#include "fl/term/Constant.h" +#include "fl/term/Linear.h" +#include "fl/term/Term.h" + +#include <algorithm> +#include <map> +#include <sstream> + +namespace fl { + + Variable::Variable(const std::string& name, scalar minimum, scalar maximum) + : _name(name), _minimum(minimum), _maximum(maximum), _enabled(true) { + } + + Variable::Variable(const Variable& other) { + copyFrom(other); + } + + Variable& Variable::operator=(const Variable& other) { + if (this != &other) { + for (std::size_t i = 0; i < _terms.size(); ++i) { + delete _terms.at(i); + } + _terms.clear(); + copyFrom(other); + } + return *this; + } + + void Variable::copyFrom(const Variable& other) { + _name = other._name; + _enabled = other._enabled; + _minimum = other._minimum; + _maximum = other._maximum; + for (std::size_t i = 0; i < other._terms.size(); ++i) { + _terms.push_back(other._terms.at(i)->clone()); + } + } + + Variable::~Variable() { + for (std::size_t i = 0; i < _terms.size(); ++i) { + delete _terms.at(i); + } + } + + void Variable::setName(const std::string& name) { + this->_name = name; + } + + std::string Variable::getName() const { + return this->_name; + } + + void Variable::setRange(scalar minimum, scalar maximum) { + setMinimum(minimum); + setMaximum(maximum); + } + + scalar Variable::range() const { + return this->_maximum - this->_minimum; + } + + void Variable::setMinimum(scalar minimum) { + this->_minimum = minimum; + } + + scalar Variable::getMinimum() const { + return this->_minimum; + } + + void Variable::setMaximum(scalar maximum) { + this->_maximum = maximum; + } + + scalar Variable::getMaximum() const { + return this->_maximum; + } + + void Variable::setEnabled(bool enabled) { + this->_enabled = enabled; + } + + bool Variable::isEnabled() const { + return this->_enabled; + } + + std::string Variable::fuzzify(scalar x) const { + std::ostringstream ss; + for (std::size_t i = 0; i < _terms.size(); ++i) { + scalar fx = fl::nan; + try { + fx = _terms.at(i)->membership(x); + } catch (...) { + //ignore + } + if (i == 0) { + ss << fl::Op::str(fx); + } else { + if (fl::Op::isNaN(fx) or fl::Op::isGE(fx, 0.0)) + ss << " + " << fl::Op::str(fx); + else + ss << " - " << fl::Op::str(std::fabs(fx)); + } + ss << "/" << _terms.at(i)->getName(); + } + return ss.str(); + } + + Term* Variable::highestMembership(scalar x, scalar* yhighest) const { + Term* result = fl::null; + scalar ymax = 0.0; + for (std::size_t i = 0; i < _terms.size(); ++i) { + scalar y = fl::nan; + try { + y = _terms.at(i)->membership(x); + } catch (...) { + //ignore + } + if (fl::Op::isGt(y, ymax)) { + ymax = y; + result = _terms.at(i); + } + } + if (yhighest) *yhighest = ymax; + return result; + } + + std::string Variable::toString() const { + return FllExporter().toString(this); + } + + /** + * Operations for datatype _terms + */ + + struct SortByCoG { + std::map<const Term*, scalar> centroids; + + bool operator()(const Term* a, const Term * b) { + return fl::Op::isLt( + centroids.find(a)->second, + centroids.find(b)->second); + } + }; + + void Variable::sort() { + Centroid defuzzifier; + std::map<const Term*, scalar> centroids; + for (std::size_t i = 0; i < _terms.size(); ++i) { + Term* term = _terms.at(i); + try { + if (dynamic_cast<const Constant*> (term) or dynamic_cast<const Linear*> (term)) { + centroids[term] = term->membership(0); + } else { + centroids[term] = defuzzifier.defuzzify(term, _minimum, _maximum); + } + } catch (...) { //ignore error possibly due to Function not loaded + centroids[term] = fl::inf; + } + } + SortByCoG criterion; + criterion.centroids = centroids; + std::sort(_terms.begin(), _terms.end(), criterion); + } + + void Variable::addTerm(Term* term) { + this->_terms.push_back(term); + } + + void Variable::insertTerm(Term* term, int index) { + this->_terms.insert(this->_terms.begin() + index, term); + } + + Term* Variable::getTerm(int index) const { + return this->_terms.at(index); + } + + Term* Variable::getTerm(const std::string& name) const { + for (std::size_t i = 0; i < _terms.size(); ++i) { + if (_terms.at(i)->getName() == name) { + return _terms.at(i); + } + } + throw fl::Exception("[variable error] term <" + name + "> " + "not found in variable <" + this->_name + ">", FL_AT); + } + + bool Variable::hasTerm(const std::string& name) const { + return getTerm(name) != fl::null; + } + + Term* Variable::removeTerm(int index) { + Term* result = this->_terms.at(index); + this->_terms.erase(this->_terms.begin() + index); + return result; + } + + int Variable::numberOfTerms() const { + return this->_terms.size(); + } + + const std::vector<Term*>& Variable::terms() const { + return this->_terms; + } + + void Variable::setTerms(const std::vector<Term*>& terms) { + this->_terms = terms; + } + + std::vector<Term*>& Variable::terms() { + return this->_terms; + } + +} + |