summaryrefslogtreecommitdiff
path: root/fuzzylite
diff options
context:
space:
mode:
Diffstat (limited to 'fuzzylite')
-rw-r--r--fuzzylite/CMakeLists.txt208
-rw-r--r--fuzzylite/FL_HEADERS92
-rw-r--r--fuzzylite/FL_SOURCES87
-rw-r--r--fuzzylite/build.bat105
-rwxr-xr-xfuzzylite/build.sh70
-rw-r--r--fuzzylite/fl/Console.h90
-rw-r--r--fuzzylite/fl/Engine.h152
-rw-r--r--fuzzylite/fl/Exception.h66
-rw-r--r--fuzzylite/fl/Headers.h131
-rw-r--r--fuzzylite/fl/Operation.h144
-rw-r--r--fuzzylite/fl/defuzzifier/Bisector.h49
-rw-r--r--fuzzylite/fl/defuzzifier/Centroid.h47
-rw-r--r--fuzzylite/fl/defuzzifier/Defuzzifier.h53
-rw-r--r--fuzzylite/fl/defuzzifier/IntegralDefuzzifier.h53
-rw-r--r--fuzzylite/fl/defuzzifier/LargestOfMaximum.h47
-rw-r--r--fuzzylite/fl/defuzzifier/MeanOfMaximum.h48
-rw-r--r--fuzzylite/fl/defuzzifier/SmallestOfMaximum.h48
-rw-r--r--fuzzylite/fl/defuzzifier/WeightedAverage.h50
-rw-r--r--fuzzylite/fl/defuzzifier/WeightedDefuzzifier.h63
-rw-r--r--fuzzylite/fl/defuzzifier/WeightedSum.h50
-rw-r--r--fuzzylite/fl/factory/CloningFactory.h62
-rw-r--r--fuzzylite/fl/factory/ConstructionFactory.h64
-rw-r--r--fuzzylite/fl/factory/DefuzzifierFactory.h51
-rw-r--r--fuzzylite/fl/factory/FactoryManager.h81
-rw-r--r--fuzzylite/fl/factory/FunctionFactory.h51
-rw-r--r--fuzzylite/fl/factory/HedgeFactory.h42
-rw-r--r--fuzzylite/fl/factory/SNormFactory.h42
-rw-r--r--fuzzylite/fl/factory/TNormFactory.h42
-rw-r--r--fuzzylite/fl/factory/TermFactory.h43
-rw-r--r--fuzzylite/fl/fuzzylite.h222
-rw-r--r--fuzzylite/fl/hedge/Any.h47
-rw-r--r--fuzzylite/fl/hedge/Extremely.h42
-rw-r--r--fuzzylite/fl/hedge/Hedge.h51
-rw-r--r--fuzzylite/fl/hedge/Not.h42
-rw-r--r--fuzzylite/fl/hedge/Seldom.h42
-rw-r--r--fuzzylite/fl/hedge/Somewhat.h42
-rw-r--r--fuzzylite/fl/hedge/Very.h42
-rw-r--r--fuzzylite/fl/imex/CppExporter.h70
-rw-r--r--fuzzylite/fl/imex/Exporter.h52
-rw-r--r--fuzzylite/fl/imex/FclExporter.h70
-rw-r--r--fuzzylite/fl/imex/FclImporter.h74
-rw-r--r--fuzzylite/fl/imex/FisExporter.h74
-rw-r--r--fuzzylite/fl/imex/FisImporter.h79
-rw-r--r--fuzzylite/fl/imex/FldExporter.h84
-rw-r--r--fuzzylite/fl/imex/FllExporter.h83
-rw-r--r--fuzzylite/fl/imex/FllImporter.h77
-rw-r--r--fuzzylite/fl/imex/Importer.h52
-rw-r--r--fuzzylite/fl/imex/JavaExporter.h68
-rw-r--r--fuzzylite/fl/norm/Norm.h55
-rw-r--r--fuzzylite/fl/norm/SNorm.h47
-rw-r--r--fuzzylite/fl/norm/TNorm.h47
-rw-r--r--fuzzylite/fl/norm/s/AlgebraicSum.h46
-rw-r--r--fuzzylite/fl/norm/s/BoundedSum.h43
-rw-r--r--fuzzylite/fl/norm/s/DrasticSum.h43
-rw-r--r--fuzzylite/fl/norm/s/EinsteinSum.h44
-rw-r--r--fuzzylite/fl/norm/s/HamacherSum.h44
-rw-r--r--fuzzylite/fl/norm/s/Maximum.h45
-rw-r--r--fuzzylite/fl/norm/s/NilpotentMaximum.h43
-rw-r--r--fuzzylite/fl/norm/s/NormalizedSum.h44
-rw-r--r--fuzzylite/fl/norm/t/AlgebraicProduct.h45
-rw-r--r--fuzzylite/fl/norm/t/BoundedDifference.h44
-rw-r--r--fuzzylite/fl/norm/t/DrasticProduct.h45
-rw-r--r--fuzzylite/fl/norm/t/EinsteinProduct.h45
-rw-r--r--fuzzylite/fl/norm/t/HamacherProduct.h44
-rw-r--r--fuzzylite/fl/norm/t/Minimum.h44
-rw-r--r--fuzzylite/fl/norm/t/NilpotentMinimum.h43
-rw-r--r--fuzzylite/fl/rule/Antecedent.h77
-rw-r--r--fuzzylite/fl/rule/Consequent.h68
-rw-r--r--fuzzylite/fl/rule/Expression.h84
-rw-r--r--fuzzylite/fl/rule/Rule.h121
-rw-r--r--fuzzylite/fl/rule/RuleBlock.h97
-rw-r--r--fuzzylite/fl/term/Accumulated.h94
-rw-r--r--fuzzylite/fl/term/Activated.h65
-rw-r--r--fuzzylite/fl/term/Bell.h68
-rw-r--r--fuzzylite/fl/term/Concave.h64
-rw-r--r--fuzzylite/fl/term/Constant.h58
-rw-r--r--fuzzylite/fl/term/Cosine.h62
-rw-r--r--fuzzylite/fl/term/Discrete.h81
-rw-r--r--fuzzylite/fl/term/Function.h171
-rw-r--r--fuzzylite/fl/term/Gaussian.h63
-rw-r--r--fuzzylite/fl/term/GaussianProduct.h73
-rw-r--r--fuzzylite/fl/term/Linear.h72
-rw-r--r--fuzzylite/fl/term/PiShape.h74
-rw-r--r--fuzzylite/fl/term/Ramp.h68
-rw-r--r--fuzzylite/fl/term/Rectangle.h62
-rw-r--r--fuzzylite/fl/term/SShape.h64
-rw-r--r--fuzzylite/fl/term/Sigmoid.h68
-rw-r--r--fuzzylite/fl/term/SigmoidDifference.h73
-rw-r--r--fuzzylite/fl/term/SigmoidProduct.h73
-rw-r--r--fuzzylite/fl/term/Spike.h62
-rw-r--r--fuzzylite/fl/term/Term.h71
-rw-r--r--fuzzylite/fl/term/Trapezoid.h69
-rw-r--r--fuzzylite/fl/term/Triangle.h68
-rw-r--r--fuzzylite/fl/term/ZShape.h63
-rw-r--r--fuzzylite/fl/variable/InputVariable.h52
-rw-r--r--fuzzylite/fl/variable/OutputVariable.h90
-rw-r--r--fuzzylite/fl/variable/Variable.h96
-rw-r--r--fuzzylite/fuzzylite.139
-rw-r--r--fuzzylite/fuzzylite.doxygen1781
-rw-r--r--fuzzylite/fuzzylite.pc.in10
-rw-r--r--fuzzylite/src/Console.cpp820
-rw-r--r--fuzzylite/src/Engine.cpp698
-rw-r--r--fuzzylite/src/Exception.cpp183
-rw-r--r--fuzzylite/src/Operation.cpp477
-rw-r--r--fuzzylite/src/defuzzifier/Bisector.cpp85
-rw-r--r--fuzzylite/src/defuzzifier/Centroid.cpp80
-rw-r--r--fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp53
-rw-r--r--fuzzylite/src/defuzzifier/LargestOfMaximum.cpp75
-rw-r--r--fuzzylite/src/defuzzifier/MeanOfMaximum.cpp88
-rw-r--r--fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp77
-rw-r--r--fuzzylite/src/defuzzifier/WeightedAverage.cpp123
-rw-r--r--fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp178
-rw-r--r--fuzzylite/src/defuzzifier/WeightedSum.cpp121
-rw-r--r--fuzzylite/src/factory/CloningFactory.cpp135
-rw-r--r--fuzzylite/src/factory/ConstructionFactory.cpp114
-rw-r--r--fuzzylite/src/factory/DefuzzifierFactory.cpp78
-rw-r--r--fuzzylite/src/factory/FactoryManager.cpp127
-rw-r--r--fuzzylite/src/factory/FunctionFactory.cpp172
-rw-r--r--fuzzylite/src/factory/HedgeFactory.cpp51
-rw-r--r--fuzzylite/src/factory/SNormFactory.cpp55
-rw-r--r--fuzzylite/src/factory/TNormFactory.cpp53
-rw-r--r--fuzzylite/src/factory/TermFactory.cpp81
-rw-r--r--fuzzylite/src/fuzzylite.cpp128
-rw-r--r--fuzzylite/src/hedge/Any.cpp52
-rw-r--r--fuzzylite/src/hedge/Extremely.cpp50
-rw-r--r--fuzzylite/src/hedge/Not.cpp46
-rw-r--r--fuzzylite/src/hedge/Seldom.cpp50
-rw-r--r--fuzzylite/src/hedge/Somewhat.cpp45
-rw-r--r--fuzzylite/src/hedge/Very.cpp45
-rw-r--r--fuzzylite/src/imex/CppExporter.cpp234
-rw-r--r--fuzzylite/src/imex/Exporter.cpp49
-rw-r--r--fuzzylite/src/imex/FclExporter.cpp256
-rw-r--r--fuzzylite/src/imex/FclImporter.cpp607
-rw-r--r--fuzzylite/src/imex/FisExporter.cpp463
-rw-r--r--fuzzylite/src/imex/FisImporter.cpp501
-rw-r--r--fuzzylite/src/imex/FldExporter.cpp246
-rw-r--r--fuzzylite/src/imex/FllExporter.cpp189
-rw-r--r--fuzzylite/src/imex/FllImporter.cpp317
-rw-r--r--fuzzylite/src/imex/Importer.cpp54
-rw-r--r--fuzzylite/src/imex/JavaExporter.cpp228
-rwxr-xr-xfuzzylite/src/m/compare.m60
-rwxr-xr-xfuzzylite/src/m/compare_examples.m45
-rw-r--r--fuzzylite/src/main.cpp71
-rw-r--r--fuzzylite/src/norm/s/AlgebraicSum.cpp45
-rw-r--r--fuzzylite/src/norm/s/BoundedSum.cpp45
-rw-r--r--fuzzylite/src/norm/s/DrasticSum.cpp48
-rw-r--r--fuzzylite/src/norm/s/EinsteinSum.cpp45
-rw-r--r--fuzzylite/src/norm/s/HamacherSum.cpp45
-rw-r--r--fuzzylite/src/norm/s/Maximum.cpp45
-rw-r--r--fuzzylite/src/norm/s/NilpotentMaximum.cpp50
-rw-r--r--fuzzylite/src/norm/s/NormalizedSum.cpp46
-rw-r--r--fuzzylite/src/norm/t/AlgebraicProduct.cpp45
-rw-r--r--fuzzylite/src/norm/t/BoundedDifference.cpp46
-rw-r--r--fuzzylite/src/norm/t/DrasticProduct.cpp48
-rw-r--r--fuzzylite/src/norm/t/EinsteinProduct.cpp45
-rw-r--r--fuzzylite/src/norm/t/HamacherProduct.cpp46
-rw-r--r--fuzzylite/src/norm/t/Minimum.cpp46
-rw-r--r--fuzzylite/src/norm/t/NilpotentMinimum.cpp50
-rw-r--r--fuzzylite/src/rule/Antecedent.cpp368
-rw-r--r--fuzzylite/src/rule/Consequent.cpp243
-rw-r--r--fuzzylite/src/rule/Expression.cpp83
-rw-r--r--fuzzylite/src/rule/Rule.cpp262
-rw-r--r--fuzzylite/src/rule/RuleBlock.cpp210
-rw-r--r--fuzzylite/src/term/Accumulated.cpp211
-rw-r--r--fuzzylite/src/term/Activated.cpp100
-rw-r--r--fuzzylite/src/term/Bell.cpp99
-rw-r--r--fuzzylite/src/term/Concave.cpp107
-rw-r--r--fuzzylite/src/term/Constant.cpp70
-rw-r--r--fuzzylite/src/term/Cosine.cpp96
-rw-r--r--fuzzylite/src/term/Discrete.cpp210
-rw-r--r--fuzzylite/src/term/Function.cpp600
-rw-r--r--fuzzylite/src/term/Gaussian.cpp92
-rw-r--r--fuzzylite/src/term/GaussianProduct.cpp120
-rw-r--r--fuzzylite/src/term/Linear.cpp135
-rw-r--r--fuzzylite/src/term/PiShape.cpp133
-rw-r--r--fuzzylite/src/term/Ramp.cpp110
-rw-r--r--fuzzylite/src/term/Rectangle.cpp93
-rw-r--r--fuzzylite/src/term/SShape.cpp102
-rw-r--r--fuzzylite/src/term/Sigmoid.cpp98
-rw-r--r--fuzzylite/src/term/SigmoidDifference.cpp114
-rw-r--r--fuzzylite/src/term/SigmoidProduct.cpp112
-rw-r--r--fuzzylite/src/term/Spike.cpp90
-rw-r--r--fuzzylite/src/term/Term.cpp74
-rw-r--r--fuzzylite/src/term/Trapezoid.cpp130
-rw-r--r--fuzzylite/src/term/Triangle.cpp115
-rw-r--r--fuzzylite/src/term/ZShape.cpp102
-rw-r--r--fuzzylite/src/variable/InputVariable.cpp54
-rw-r--r--fuzzylite/src/variable/OutputVariable.cpp195
-rw-r--r--fuzzylite/src/variable/Variable.cpp244
189 files changed, 21583 insertions, 0 deletions
diff --git a/fuzzylite/CMakeLists.txt b/fuzzylite/CMakeLists.txt
new file mode 100644
index 0000000..f00a71a
--- /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 ${FL_INSTALL_LIBDIR}/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;
+ }
+
+}
+