diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5000d66 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +CMakeCache.txt +Makefile +cmake_install.cmake +CMakeFiles +*.so +*.out +sml/common/include/config.h +sml/sml.pc +install_manifest.txt +bin/ +gen/ +obj/ +local.properties +gdb.setup +gdbserver +docs/Doxyfile +soletta_module/machine_learning.json diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..14001bc --- /dev/null +++ b/AUTHORS @@ -0,0 +1,3 @@ +Bruno Dilly +Guilherme Iscaro de Godoy +Otavio Pontes diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..63ea7f6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,111 @@ +cmake_minimum_required(VERSION 2.8) + +project(machine-learning) + +option(MAINLOOP "Build support to mainloop using glib" ON) +option(FUZZY_ENGINE "Build with fuzzy logic support" ON) +option(ANN_ENGINE "Build with neural network support" ON) +option(NAIVE_ENGINE "Build with naive engine support" ON) +option(BUILD_SOLETTA_MODULE "Build machine learning module for Soletta" ON) +option(BUILD_EXAMPLES "Build examples" ON) +option(BUILD_SIMULATOR "Build simulator" ON) +option(BUILD_DOCS "Build the documentation" ON) + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug) +endif() +include(CheckCXXCompilerFlag) +include(CheckCCompilerFlag) + +CHECK_CXX_COMPILER_FLAG("-Wall" CXX_COMPILER_HAS_WALL) +CHECK_CXX_COMPILER_FLAG("-Wextra" CXX_COMPILER_WALL_HAS_WEXTRA) +CHECK_CXX_COMPILER_FLAG("-fvisibility=hidden" CXX_COMPILER_HAS_FVISIBILITY) + +CHECK_C_COMPILER_FLAG("-std=gnu99" C_COMPILER_HAS_C99) +CHECK_C_COMPILER_FLAG("-Wall" C_COMPILER_HAS_WALL) +CHECK_C_COMPILER_FLAG("-Wextra" C_COMPILER_HAS_WEXTRA) +CHECK_C_COMPILER_FLAG("-Wno-unused-parameter" C_COMPILER_HAS_WNO_UNUSED_PARAMETER) +CHECK_C_COMPILER_FLAG("-Wno-missing-field-initializers" C_COMPILER_HAS_WNO_MISSING_FIELD_INITIALIZERS) +CHECK_C_COMPILER_FLAG("-fvisibility=hidden" C_COMPILER_HAS_FVISIBILITY) + +if (CXX_COMPILER_HAS_WALL) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +endif() + +if (CXX_COMPILER_WALL_HAS_WEXTRA) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") +endif() + +if (CXX_COMPILER_HAS_FVISIBILITY) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") +endif() + +if (C_COMPILER_HAS_FVISIBILITY) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") +endif() + +if (C_COMPILER_HAS_WEXTRA) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra") +endif() + +if (C_COMPILER_HAS_WALL) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") +endif() + +if (C_COMPILER_HAS_C99) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") +else() + message(FATAL_ERROR "No gnu99 support. Bye.") +endif() + +if (C_COMPILER_HAS_WNO_UNUSED_PARAMETER) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter") +endif() + +if (C_COMPILER_HAS_WNO_MISSING_FIELD_INITIALIZERS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers") +endif() + +if (NOT ANN_ENGINE AND NOT FUZZY_ENGINE AND NOT NAIVE_ENGINE) + message(FATAL_ERROR "At least on engine must be enabled in order to build SML.") +endif() + +message("Fuzzy support:" ${FUZZY_ENGINE}) +message("ANN support:" ${ANN_ENGINE}) +message("Naive support: " ${NAIVE_ENGINE}) +message("Soletta module:" ${BUILD_SOLETTA_MODULE}) + +set(SML_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sml/include) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(SOLETTA REQUIRED soletta) + +if (ANN_ENGINE) + pkg_check_modules(FANN REQUIRED fann) +endif() + +if (FUZZY_ENGINE) + pkg_check_modules(FUZZY_LITE REQUIRED fuzzylite) +endif() + +if (MAINLOOP) + pkg_check_modules(GLIB REQUIRED glib-2.0) +endif() + +add_subdirectory(sml) + +if (BUILD_EXAMPLES) + add_subdirectory(examples) +endif() + +if (BUILD_SIMULATOR) + add_subdirectory(simulator) +endif() + +if (BUILD_SOLETTA_MODULE) + add_subdirectory(soletta_module) +endif() + +if (BUILD_DOCS) + add_subdirectory(docs) +endif() diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..f517403 --- /dev/null +++ b/COPYING @@ -0,0 +1,29 @@ +This file is part of the Soletta Project + +Copyright (C) 2015 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README b/README new file mode 100644 index 0000000..b5bcd7d --- /dev/null +++ b/README @@ -0,0 +1,88 @@ += Soletta Machine Learning = + +Soletta Machine Learning is an open source machine learning library +for development of IoT devices. +It provides APIs to handle with client side AI and an easy to use flow-based +Soletta module. + +Initially supporting neural networks and fuzzy logic learning, +using well established open source libraries, it could be easily +extended to support others. + += Building = + +== Dependencies == + +This project depends on: + +fuzzylite: + Desc: A fuzzy logic control library written in C++. + Site: http://www.fuzzylite.com/ + Source: https://github.com/fuzzylite/fuzzylite.git + +FANN (Fast Artificial Neural Network Library): + Desc: An open source neural network library. + Site: http://leenissen.dk/fann/wp/ + Source: https://github.com/libfann/fann + +Soletta: + Desc: Soletta Project is a framework for making IoT devices. + Site: https://solettaproject.org/ + Source: https://github.com/solettaproject/soletta + +Some distros (like Fedora, Ubuntu), has packaged FANN and fuzzylite. + +== Linux == + + * Build and install all dependencies + * At the moment, it's required to do a minor fix on fuzzylite/fuzzylite.pc.in: + Replace + + Cflags: -I${includedir}/fl + + by + + Cflags: -I${includedir} + + Alternativelly it's possible to provide a cmake with extra cflags: + $ cmake -DCMAKE_C_FLAGS="-I/path/to/proper/header/dir/" + + + * After dependencies setup and installation, build machine-learning running: + ** Using both engines + + $ cmake -DFUZZY_ENGINE=ON -DANN_ENGINE=ON . + + or + + $ cmake . + $ make + + ** Using only the neural networks engine + $ cmake -DFUZZY_ENGINE=OFF . + $ make + + + ** Using only the Fuzzy engine + $ cmake -DANN_ENGINE=OFF . + $ make + +== Docs == +* To build docs run: + $ make doc + +== Galileo == + * Install proper toolchain to build for galileo board. + * Edit soletta_module/i586-poky-linux-uclibc.cmake and update + CMAKE_FIND_ROOT_PATH variable to point the toolchain's sysdir with any + necessary dependencies to build sml. + * Create temporary directory to install sml and its dependencies. It is + called in this instruction {TMP_DESTDIR_PATH} + * To use soletta_module/i586-poky-linux-uclibc.cmake to build fann and + fuzzylite and install them to the toolchain's ROOT_PATH. Run: + $ cmake .. -DCMAKE_TOOLCHAIN_FILE={PATH_TO_SML}soletta_module/i586-poky-linux-uclibc.cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr + $ make && make install DESTDIR={TMP_DESTDIR_PATH} + * Copy all files in {TMP_DESTDIR_PATH} to toolchain's sysdir. + * Use same command to build sml and to install it to {TMP_DESTDIR_PATH} + * Copy all files in {TMP_DESTDIR_PATH} to root of image to be used in galileo + board. diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 0000000..145bb65 --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 2.8) + +project(docs) + +find_package(Doxygen REQUIRED) + +set(DOXY_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) +set(DOXY ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + +set(HEAD_FILE ${CMAKE_CURRENT_SOURCE_DIR}/head.html) +set(FOOT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/foot.html) +set(STYLE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/style.css) +set(EXAMPLES_PATH ${CMAKE_SOURCE_DIR}/examples) +set(INPUT_FILES "${CMAKE_CURRENT_SOURCE_DIR}/examples.dox ${CMAKE_SOURCE_DIR}/sml/include") + +set(OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/html) + +configure_file(${DOXY_IN} ${DOXY} @ONLY) + +add_custom_target(doc + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXY} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" + VERBATIM) diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in new file mode 100644 index 0000000..4259f0c --- /dev/null +++ b/docs/Doxyfile.in @@ -0,0 +1,314 @@ +# Doxyfile 1.8.9.1 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "Soletta machine learning" +PROJECT_NUMBER = +PROJECT_BRIEF = "Machine learning for IoT devices" +PROJECT_LOGO = +OUTPUT_DIRECTORY = @OUTPUT_DIR@ +CREATE_SUBDIRS = NO +ALLOW_UNICODE_NAMES = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 4 +ALIASES = +TCL_SUBST = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +MARKDOWN_SUPPORT = YES +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +LOOKUP_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_PACKAGE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +HIDE_COMPOUND_REFERENCE= NO +SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = YES +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = YES +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = @INPUT_FILES@ +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = @EXAMPLES_PATH@ +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +USE_MDFILE_AS_MAINPAGE = +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = @HEAD_FILE@ +HTML_FOOTER = @FOOT_FILE@ +HTML_STYLESHEET = @STYLE_FILE@ +HTML_EXTRA_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = NO +HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.solettaproject.ml +DOCSET_PUBLISHER_ID = org.solettaproject.ml +DOCSET_PUBLISHER_NAME = Intel Corporation +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.solettaproject.ml +QHP_VIRTUAL_FOLDER = @OUTPUT_DIR@ +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.solettaproject.ml +DISABLE_INDEX = YES +GENERATE_TREEVIEW = NO +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_FORMAT = HTML-CSS +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +MATHJAX_EXTENSIONS = +MATHJAX_CODEFILE = +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO +SEARCHENGINE_URL = +SEARCHDATA_FILE = searchdata.xml +EXTERNAL_SEARCH_ID = +EXTRA_SEARCH_MAPPINGS = +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +LATEX_EXTRA_STYLESHEET = +LATEX_EXTRA_FILES = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +RTF_SOURCE_CODE = NO +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = YES +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_SUBDIR = +MAN_LINKS = YES +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- +GENERATE_DOCBOOK = NO +DOCBOOK_OUTPUT = docbook +DOCBOOK_PROGRAMLISTING = NO +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = __attribute__((x))= +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +DIA_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +UML_LIMIT_NUM_FIELDS = 10 +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO +DOT_PATH = +DOTFILE_DIRS = +MSCFILE_DIRS = +DIAFILE_DIRS = +PLANTUML_JAR_PATH = +PLANTUML_INCLUDE_PATH = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/docs/examples.dox b/docs/examples.dox new file mode 100644 index 0000000..fa8ce50 --- /dev/null +++ b/docs/examples.dox @@ -0,0 +1,6 @@ +/** + * @page Examples Examples + * + * Here is a page with examples. + * + */ diff --git a/docs/foot.html b/docs/foot.html new file mode 100644 index 0000000..3e7e4f4 --- /dev/null +++ b/docs/foot.html @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/docs/head.html b/docs/head.html new file mode 100644 index 0000000..7160b77 --- /dev/null +++ b/docs/head.html @@ -0,0 +1,55 @@ + + + + + + + +$projectname: $title +$title + + + +$treeview +$search +$mathjax + +$extrastylesheet + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + +
+
$projectname +  $projectnumber +
+
$projectbrief
+
+
$projectbrief
+
$searchbox
+
+ + diff --git a/docs/style.css b/docs/style.css new file mode 100644 index 0000000..fc41901 --- /dev/null +++ b/docs/style.css @@ -0,0 +1,1448 @@ +/* The standard CSS for doxygen 1.8.9.1 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 4px 6px; + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah, span.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.classindex ul { + list-style: none; + padding-left: 0; +} + +div.classindex span.ai { + display: inline-block; +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #9CAFD4; + border-bottom: 1px solid #9CAFD4; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +.arrow { + color: #9CAFD4; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} + +.icon { + font-family: Arial, Helvetica; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: #728DC1; + color: white; + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfopen { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderopen.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.iconfclosed { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderclosed.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.icondoc { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('doc.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +table.directory { + font: 400 14px Roboto,sans-serif; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..e549868 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 2.8) + +project(examples) + +include_directories(${SML_INCLUDE_DIR} ${GLIB_INCLUDE_DIRS} ${FUZZY_LITE_INCLUDE_DIRS}) +link_directories(${GLIB_LIBRARY_DIRS} ${FUZZY_LITE_LIBRARY_DIRS} ${FANN_LIBRARY_DIRS} ${SOLETTA_LIBRARY_DIRS}) + +message("SML include dir:" ${SML_INCLUDE_DIR}) + +if (FUZZY_ENGINE) + add_executable(fuzzy_test.out fuzzy_test.cpp) + target_link_libraries(fuzzy_test.out ${GLIB_LIBRARIES} sml_libs) +endif() + +if (MAINLOOP) + add_executable(example_air_conditioner.out example_air_conditioner.c) + target_link_libraries(example_air_conditioner.out ${GLIB_LIBRARIES} sml_libs m) +endif() + +add_executable(example_sensor_file.out example_sensor_file) +add_executable(test_memory.out test_memory) +add_executable(foosball_example.out foosball_example) +add_executable(example_doc.out example_doc.c) +target_link_libraries(example_sensor_file.out ${GLIB_LIBRARIES} sml_libs) +target_link_libraries(test_memory.out ${GLIB_LIBRARIES} sml_libs) +target_link_libraries(foosball_example.out ${GLIB_LIBRARIES} sml_libs) +target_link_libraries(example_doc.out sml_libs) diff --git a/examples/data/example_foosball.sample1.conf b/examples/data/example_foosball.sample1.conf new file mode 100644 index 0000000..ca2dcbb --- /dev/null +++ b/examples/data/example_foosball.sample1.conf @@ -0,0 +1,65 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# File structure: +# First line with the number of players. Following lines with the names of players. One name per line +32 +Abel +Miguel +Sophia +Davi +Alice +Arthur +Manuela +Gabriel +Isabella +Pedro +Lucas +Laura +Matheus +Maria +Eduarda +Bernardo +Giovanna +Rafael +Beatriz +Enzo +Luiza +Felipe +Helena +Rafaelna +Nicolas +Isadora +Heitor +Mariana +Samuel +Gabriela +Rafaela +Henrique diff --git a/examples/data/example_foosball.sample1.data b/examples/data/example_foosball.sample1.data new file mode 100644 index 0000000..f93417f --- /dev/null +++ b/examples/data/example_foosball.sample1.data @@ -0,0 +1,123 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# File structure: +# Each line contains information about a single game. +# + +# Championship 1 +Abel Felipe Isabella Davi 5 10 +Abel Felipe Pedro Lucas 1 10 +Abel Felipe Manuela Gabriel 3 10 +Abel Felipe Rafael Beatriz 6 10 +Abel Felipe Maria Eduarda 4 10 +Abel Felipe Enzo Luiza 6 10 +Abel Felipe Bernardo Giovanna 10 6 +Abel Felipe Laura Matheus 6 10 +Abel Felipe Arthur Miguel 0 10 +Isabella Davi Pedro Lucas 6 10 +Isabella Davi Manuela Gabriel 10 8 +Isabella Davi Rafael Beatriz 10 5 +Isabella Davi Maria Eduarda 9 10 +Isabella Davi Enzo Luiza 10 2 +Isabella Davi Bernardo Giovanna 10 2 +Isabella Davi Laura Matheus 10 6 +Isabella Davi Arthur Miguel 1 10 +Pedro Lucas Manuela Gabriel 2 10 +Pedro Lucas Rafael Beatriz 10 9 +Pedro Lucas Maria Eduarda 7 10 +Pedro Lucas Enzo Luiza 10 3 +Pedro Lucas Bernardo Giovanna 5 10 +Pedro Lucas Laura Matheus 10 5 +Pedro Lucas Arthur Miguel 9 10 +Manuela Gabriel Rafael Beatriz 10 4 +Manuela Gabriel Maria Eduarda 10 3 +Manuela Gabriel Enzo Luiza 10 3 +Manuela Gabriel Bernardo Giovanna 10 5 +Manuela Gabriel Laura Matheus 10 9 +Manuela Gabriel Arthur Miguel 9 10 +Rafael Beatriz Maria Eduarda 10 7 +Rafael Beatriz Enzo Luiza 10 8 +Rafael Beatriz Bernardo Giovanna 4 10 +Rafael Beatriz Laura Matheus 2 10 +Rafael Beatriz Arthur Miguel 2 10 +Maria Eduarda Enzo Luiza 10 5 +Maria Eduarda Bernardo Giovanna 10 8 +Maria Eduarda Laura Matheus 8 10 +Maria Eduarda Arthur Miguel 3 10 +Enzo Luiza Bernardo Giovanna 2 10 +Enzo Luiza Laura Matheus 4 10 +Enzo Luiza Arthur Miguel 5 10 +Bernardo Giovanna Laura Matheus 8 10 +Bernardo Giovanna Arthur Miguel 2 10 +Laura Matheus Arthur Miguel 1 10 + +#Championship 2 +Isabella Lucas Maria Alice 10 7 +Isadora Laura Isabella Lucas 9 10 +Maria Alice Abel Giovanna 10 5 +Isabella Lucas Abel Giovanna 10 0 +Maria Alice Isadora Laura 10 9 +Maria Alice Isabella Lucas 6 10 +Abel Giovanna Maria Alice 2 10 +Abel Giovanna Maria Alice 2 10 +Abel Giovanna Isabella Lucas 3 10 +Isadora Laura Maria Alice 9 10 +Heitor Mariana Samuel Enzo 10 8 +Luiza Felipe Matheus Rafael 10 6 +Samuel Enzo Luiza Felipe 10 2 +Matheus Rafael Luiza Felipe 7 10 +Matheus Rafael Samuel Enzo 1 10 +Eduarda Manuela Bernardo Pedro 3 10 +Beatriz Davi Sophia Arthur 10 6 +Eduarda Manuela Rafaelna Miguel 3 10 +Bernardo Pedro Beatriz Davi 5 10 +Sophia Arthur Eduarda Manuela 10 2 +Bernardo Pedro Rafaelna Miguel 10 2 +Rafaelna Miguel Beatriz Davi 10 4 +Sophia Arthur Bernardo Pedro 7 10 +Bernardo Pedro Eduarda Manuela 10 2 +Beatriz Davi Bernardo Pedro 7 10 +Eduarda Manuela Sophia Arthur 0 10 +Rafaelna Miguel Bernardo Pedro 7 10 +Beatriz Davi Rafaelna Miguel 9 10 + +#Championship 3 +Pedro Gabriela Alice Beatriz 4 10 +Gabriel Matheus Manuela Laura 10 6 +Lucas Helena Nicolas Rafaela 10 8 +Alice Beatriz Eduarda Miguel 10 6 +Davi Maria Giovanna Luiza 10 1 +Gabriel Matheus Enzo Henrique 10 3 +Lucas Helena Rafaelna Bernardo 10 6 +Alice Beatriz Davi Maria 10 9 +Gabriel Matheus Lucas Helena 9 10 +Alice Beatriz Lucas Helena 8 10 +Gabriel Matheus Davi Maria 10 3 diff --git a/examples/data/example_foosball.simple.conf b/examples/data/example_foosball.simple.conf new file mode 100644 index 0000000..c676d02 --- /dev/null +++ b/examples/data/example_foosball.simple.conf @@ -0,0 +1,37 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# File structure: +# First line with the number of players. Following lines with the names of players. One name per line +4 +player1 +player2 +player3 +player4 diff --git a/examples/data/example_foosball.simple.data b/examples/data/example_foosball.simple.data new file mode 100644 index 0000000..5f0e834 --- /dev/null +++ b/examples/data/example_foosball.simple.data @@ -0,0 +1,42 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# File structure: +# Each line contains information about a single game. +# +player1 player2 player3 player4 10 1 +player1 player2 player3 player4 10 1 +player1 player2 player3 player4 10 1 +player1 player2 player3 player4 10 1 +player1 player2 player3 player4 10 1 +player1 player2 player3 player4 10 1 +player1 player2 player3 player4 10 1 +player1 player2 player3 player4 10 1 +player3 player4 player1 player2 7 10 diff --git a/examples/data/example_sensor_file1.data b/examples/data/example_sensor_file1.data new file mode 100644 index 0000000..55ff4f8 --- /dev/null +++ b/examples/data/example_sensor_file1.data @@ -0,0 +1,81 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# To be used alongside example_sensor_file1.fll +# Each line of this file represents a SML sensor/output read, followed by +# expected output value. In this case, we have: +# +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +0 1 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +1 0 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 +1 1 1 diff --git a/examples/data/example_sensor_file1.fll b/examples/data/example_sensor_file1.fll new file mode 100644 index 0000000..77d84dc --- /dev/null +++ b/examples/data/example_sensor_file1.fll @@ -0,0 +1,49 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Engine: example_in_out +InputVariable: in + enabled: true + range: 0.000 1.000 + term: off Ramp 0.1 0.0 + term: on Ramp 0.9 1.0 +OutputVariable: out + enabled: true + range: 0.000 1.000 + default: 0.000 + defuzzifier: MeanOfMaximum 500 + accumulation: Maximum + term: off Ramp 0.1 0.0 + term: on Ramp 0.9 1.0 +RuleBlock: + enabled: true + conjunction: Minimum + disjunction: Maximum + activation: Minimum diff --git a/examples/data/fuzzy_test_1.fll b/examples/data/fuzzy_test_1.fll new file mode 100644 index 0000000..dbb6624 --- /dev/null +++ b/examples/data/fuzzy_test_1.fll @@ -0,0 +1,62 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Engine: fuzzy_test_1 +InputVariable: in + enabled: true + range: 0.000 1.000 + term: off Discrete 0.000 1.000 1.000 0.000 + term: on Discrete 0.000 0.000 1.000 1.000 +InputVariable: useless + enabled: true + range: 0 9 + term: A Triangle 0 1 2 + term: B Triangle 1 2 3 + term: C Triangle 2 3 4 + term: D Triangle 3 4 5 + term: E Triangle 4 5 6 + term: F Triangle 5 6 7 + term: G Triangle 6 7 8 + term: H Triangle 7 8 9 +OutputVariable: out + enabled: true + range: 0.000 1.000 + default: nan + defuzzifier: MeanOfMaximum 500 + accumulation: Maximum + term: off Discrete 0.000 1.000 1.000 0.000 + term: on Discrete 0.000 0.000 1.000 1.000 +RuleBlock: + enabled: true + conjunction: Minimum + disjunction: Maximum + activation: Minimum + rule: if in is on then out is on + rule: if in is off then out is off diff --git a/examples/data/fuzzy_test_2.fll b/examples/data/fuzzy_test_2.fll new file mode 100644 index 0000000..518978b --- /dev/null +++ b/examples/data/fuzzy_test_2.fll @@ -0,0 +1,83 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Engine: fuzzy_test_2 +InputVariable: sensor1 + enabled: true + range: 0 1 + term: t0 Ramp 0.1375 0.0 + term: t1 Triangle 0.1125 0.25 0.3875 + term: t2 Triangle 0.3625 0.5 0.6375 + term: t3 Triangle 0.6125 0.75 0.8875 + term: t4 Ramp 0.8625 1.0 + +InputVariable: sensor2 + enabled: true + range: 0 1 + term: t0 Ramp 0.275 0.0 + term: t1 Triangle 0.225 0.5 0.775 + term: t2 Ramp 0.725 1.0 + +OutputVariable: out + enabled: true + range: 0.000 1.000 + default: 0.0 + defuzzifier: MeanOfMaximum 500 + accumulation: Maximum + term: t0 Ramp 0.06875 0.0 + term: t1 Triangle 0.05625 0.125 0.19375 + term: t2 Triangle 0.18125 0.25 0.31875 + term: t3 Triangle 0.30625 0.375 0.44375 + term: t4 Triangle 0.43125 0.5 0.56875 + term: t5 Triangle 0.55625 0.625 0.69375 + term: t6 Triangle 0.68125 0.75 0.81875 + term: t7 Triangle 0.80625 0.875 0.94375 + term: t8 Ramp 0.93125 1.0 + +RuleBlock: + enabled: true + conjunction: Minimum + disjunction: Maximum + activation: Minimum + rule: if sensor1 is t0 and sensor2 is t0 then out is t0 + rule: if sensor1 is t0 and sensor2 is t1 then out is t0 + rule: if sensor1 is t0 and sensor2 is t2 then out is t4 + rule: if sensor1 is t1 and sensor2 is t0 then out is t0 + rule: if sensor1 is t1 and sensor2 is t1 then out is t0 + rule: if sensor1 is t1 and sensor2 is t2 then out is t2 + rule: if sensor1 is t2 and sensor2 is t0 then out is t0 + rule: if sensor1 is t2 and sensor2 is t1 then out is t1 + rule: if sensor1 is t2 and sensor2 is t2 then out is t1 + rule: if sensor1 is t3 and sensor2 is t0 then out is t1 + rule: if sensor1 is t3 and sensor2 is t1 then out is t6 + rule: if sensor1 is t3 and sensor2 is t2 then out is t6 + rule: if sensor1 is t4 and sensor2 is t0 then out is t0 + rule: if sensor1 is t4 and sensor2 is t1 then out is t7 + rule: if sensor1 is t4 and sensor2 is t2 then out is t0 diff --git a/examples/example_air_conditioner.c b/examples/example_air_conditioner.c new file mode 100644 index 0000000..b921b4e --- /dev/null +++ b/examples/example_air_conditioner.c @@ -0,0 +1,296 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VAR_TEMPERATURE (0) +#define VAR_PRESENCE (1) +#define VAR_POWER (0) +#define ERROR_START (20) +#define ERROR_FREQUENCY (10) +#define READ_TIMEOUT (10) +#define STABILIZATION_HITS (0) +#define INITIAL_REQUIRED_OBS (10) +#define FUZZY_ENGINE 0 +#define ANN_ENGINE 1 + +/* + * Air Conditioner controller simulator code. + * Controller that simulates an air conditioner operated by a regular user. + * In some cases user forgets to set the air conditioner power and SML is expect + * to set it for her. + */ + +typedef enum { + COLD = 0, + WARM, + HOT +} Temperature; + +typedef struct { + int presence; + int power; + Temperature temp; + int reads; +} Air_Conditioner_Controller; + +static void +_initialize_acc(Air_Conditioner_Controller *acc) +{ + srand(time(NULL)); + memset(acc, 0, sizeof(Air_Conditioner_Controller)); +} + +static float +_generate_temperature(Temperature t) +{ + float min, max; + + if (t == COLD) { + min = 0.0; + max = 15.0; + } else if (t == WARM) { + min = 15.0; + max = 23.0; + } else { + min = 23.0; + max = 50.0; + } + + return ((float)rand() / (float)RAND_MAX) * (max - min) + min; +} + +static float +_calculate_power(Air_Conditioner_Controller *acc) +{ + switch (acc->temp) { + case HOT: + return 3; + case WARM: + return 2; + default: + return 1; + } +} + +static bool +_read_sensor_values(Air_Conditioner_Controller *acc, float *temp, + float *presence, float *power) +{ + bool error; + char *temps[3] = { "COLD", "WARM", "HOT" }; + char *presences[2] = { "ABSENT", "PRESENT" }; + char *temperature_str, *user_str, *status_str; + float t; + + acc->temp = (acc->temp + 1) % 3; + t = _generate_temperature(acc->temp); + acc->presence = rand() % 2; + + if (acc->reads > ERROR_START) { + error = (rand() % ERROR_FREQUENCY) == 0; + } else + error = false; + acc->reads++; + + if (acc->presence) { + if (error) + status_str = "User didn't change the air conditioner power " + " - current at "; + else { + status_str = "User changed the air conditioner power to "; + acc->power = _calculate_power(acc); + } + } else { + if (error) + status_str = "User left the room and let the air conditioner power" + " at "; + else { + status_str = "User changed the air conditioner power to "; + acc->power = 0; //Turn off if user is absent + } + } + + temperature_str = temps[acc->temp]; + user_str = presences[acc->presence]; + printf("Temperature is %2.0f (%s) and User is %s. [%s %d]\n", t, + temperature_str, user_str, status_str, acc->power); + + *temp = t; + *presence = acc->presence; + *power = acc->power; + + fflush(stdout); + return true; +} + +static void +_update_air_conditioner_power(Air_Conditioner_Controller *acc, float new_value) +{ + int new_power; + + if (isnan(new_value)) + return; + + new_power = roundf(new_value); + + if (new_power != acc->power) { + printf("SML fixed air conditioner power to %d\n", new_power); + acc->power = new_power; + } +} + +/* + * Air conditioner system controlled by SML code + */ + +static void +_output_state_changed_cb(struct sml_object *sml, + struct sml_variables_list *changed, void *data) +{ + struct sml_variable *sml_var = sml_variables_list_index(sml, changed, 0); + float new_value = sml_variable_get_value(sml, sml_var); + + _update_air_conditioner_power(data, new_value); +} + +static bool +_read_state_cb(struct sml_object *sml, void *data) +{ + struct sml_variable *temperature_var, *presence_var, *power_var; + struct sml_variables_list *input_list, *output_list; + Air_Conditioner_Controller *acc = data; + float temp, presence, power; + + input_list = sml_get_input_list(sml); + output_list = sml_get_output_list(sml); + + temperature_var = sml_variables_list_index(sml, input_list, + VAR_TEMPERATURE); + presence_var = sml_variables_list_index(sml, input_list, VAR_PRESENCE); + power_var = sml_variables_list_index(sml, output_list, VAR_POWER); + + if (!_read_sensor_values(acc, &temp, &presence, &power)) + return false; + + sml_variable_set_value(sml, temperature_var, temp); + sml_variable_set_value(sml, presence_var, presence); + sml_variable_set_value(sml, power_var, power); + + sml_print_debug(sml, false); + return true; +} + +static struct sml_object * +_sml_new(int id) +{ + switch (id) { + case FUZZY_ENGINE: + return sml_fuzzy_new(); + case ANN_ENGINE: + return sml_ann_new(); + } + return NULL; +} + +int +main(int argc, char **argv) +{ + Air_Conditioner_Controller acc; + struct sml_variable *temp, *presence, *power; + struct sml_object *sml; + + _initialize_acc(&acc); + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + fprintf(stderr, "Fuzzy Test: %s 0\n", argv[0]); + fprintf(stderr, "Ann Test: %s 1\n", argv[0]); + return -1; + } + + sml = _sml_new(atoi(argv[1])); + if (!sml) { + sml_critical("Failed to create sml"); + return -1; + } + + sml_main_loop_init(); + + //Set stabilization hits and initial required obs to a low value because + //this is a simulation and we don't want to wait for a long time before + //getting interesting results + sml_set_stabilization_hits(sml, STABILIZATION_HITS); + sml_ann_set_initial_required_observations(sml, INITIAL_REQUIRED_OBS); + + //Create temperature input + temp = sml_new_input(sml, "Temperature"); + sml_variable_set_range(sml, temp, 0, 50); + sml_fuzzy_variable_add_term_ramp(sml, temp, "COLD", 16, 0, 1); + sml_fuzzy_variable_add_term_triangle(sml, temp, "WARM", 15, 19, 23, 1); + sml_fuzzy_variable_add_term_ramp(sml, temp, "HOT", 22, 50, 1); + + //Create presence input + presence = sml_new_input(sml, "Presence"); + sml_variable_set_range(sml, presence, 0, 1); + sml_fuzzy_variable_add_term_ramp(sml, presence, "ABSENT", 0.6, 0, 1); + sml_fuzzy_variable_add_term_ramp(sml, presence, "PRESET", 0.4, 1, 1); + + //Create power output + power = sml_new_output(sml, "Power"); + sml_variable_set_range(sml, power, 0, 3); + sml_fuzzy_variable_add_term_ramp(sml, power, "OFF", 0.6, 0, 1); + sml_fuzzy_variable_add_term_triangle(sml, power, "LOW", 0.4, 1, 1.6, 1); + sml_fuzzy_variable_add_term_triangle(sml, power, "MEDIUM", 1.4, 2, 2.6, 1); + sml_fuzzy_variable_add_term_ramp(sml, power, "HIGH", 2.4, 3, 1); + + //set SML callbacks + sml_set_read_state_callback(sml, _read_state_cb, &acc); + sml_main_loop_schedule_sml_process(sml, READ_TIMEOUT); + sml_set_output_state_changed_callback(sml, _output_state_changed_cb, &acc); + + sml_main_loop_run(); + + sml_free(sml); + sml_main_loop_shutdown(); + return 0; +} diff --git a/examples/example_doc.c b/examples/example_doc.c new file mode 100644 index 0000000..e420025 --- /dev/null +++ b/examples/example_doc.c @@ -0,0 +1,156 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Very basic sample to introduce people to SML. + * It simulates a scenario with a presence sensor and a light bulb + * controlled by the user, that eventually forgets to turn lights off. + */ + +/* WARNING: when this sample breaks, it means "Getting Started on SML" + * wiki page must to be updated. + * All patches applied here should be applied there as well. + * + * https://github.com/solettaproject/soletta/wiki/Getting-Started-on-SML + */ + +#include +#include +#include +#include + + +static int switch_state = 0; + +static bool +read_state_cb(struct sml_object *sml, void *data) +{ + struct sml_variables_list *inputs, *outputs; + struct sml_variable *sensor, *light; + + static int sensor_state = 0; + static int off_count = 0; + static unsigned int count = 0; + + /* user is present after 10 reads */ + if (count == 10) { + printf("User got in the room.\n"); + sensor_state = 1; + switch_state = 1; + count++; + } + /* and stay there for 5 more reads */ + else if (count == 15) { + printf("User left the room.\n"); + off_count++; + sensor_state = 0; + /* most of times she remembers to swith off lights + * when she leaves */ + if (off_count % 4 == 0) { + printf("Oops! User forgot to turn lights off.\n"); + } else { + switch_state = 0; + } + count = 0; + } + /* ... forever on this cycle */ + else { + count++; + } + + inputs = sml_get_input_list(sml); + sensor = sml_variables_list_index(sml, inputs, 0); + sml_variable_set_value(sml, sensor, sensor_state); + + outputs = sml_get_output_list(sml); + light = sml_variables_list_index(sml, outputs, 0); + sml_variable_set_value(sml, light, switch_state); + + return true; +} + +static void +output_state_changed_cb(struct sml_object *sml, + struct sml_variables_list *changed, void *data) +{ + struct sml_variable *light; + double prediction; + + light = sml_variables_list_index(sml, changed, 0); + prediction = sml_variable_get_value(sml, light); + + /* When SML can't predict a value, it'll be set to NaN */ + if (isnan(prediction)) { + printf("Sorry, can't predict light state.\n"); + return; + } + + /* prediction is equal to current state */ + if ((prediction > 0.5) == switch_state) { + return; + } + + if (prediction > 0.5) { + printf("Light should be turned ON.\n"); + } else { + printf("Light should be turned OFF.\n"); + } +} + +int +main(int argc, char *argv[]) +{ + struct sml_object *sml; + struct sml_variable *sensor, *light; + + sml = sml_fuzzy_new(); + + sensor = sml_new_input(sml, "PresenceSensor"); + sml_variable_set_range(sml, sensor, 0, 1); + sml_fuzzy_variable_add_term_ramp(sml, sensor, "Off", 0.6, 0, 1); + sml_fuzzy_variable_add_term_ramp(sml, sensor, "On", 0.4, 1.0, 1); + + light = sml_new_output(sml, "Light"); + sml_variable_set_range(sml, light, 0, 1); + sml_fuzzy_variable_add_term_ramp(sml, light, "Off", 0.6, 0, 1); + sml_fuzzy_variable_add_term_ramp(sml, light, "On", 0.4, 1.0, 1); + + sml_set_read_state_callback(sml, read_state_cb, NULL); + sml_set_output_state_changed_callback(sml, output_state_changed_cb, NULL); + + for (int i = 0; i < 150; i++) { + sml_process(sml); + } + + sml_free(sml); + + return 0; +} diff --git a/examples/example_sensor_file.c b/examples/example_sensor_file.c new file mode 100644 index 0000000..786b541 --- /dev/null +++ b/examples/example_sensor_file.c @@ -0,0 +1,369 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Example sensor file: + * Run a SML simulation based on sensors and output status data saved in a file + * Conf file is a standard fll file with inputs and outputs description. + * Data file is a regular text file with data read from sensors and outputs. + * Each line contains data from one SML iteration, separated by whitespaces. + * Inputs data should be written in order, followed by outputs data and then, + * optionally, by expected outputs data. If expected output data is provided, + * this example will print staticts results about the SML execution + */ +#include +#include +#include +#include +#include +#include +#include + +#define THRESHOLD (0.1) +#define LINE_LEN (1024) +#define INITIAL_REQUIRED_OBS (10) +#define FUZZY_ENGINE 0 +#define ANN_ENGINE 1 + +typedef struct { + /* + * For this test output_state_changed_cb calls that have incorrect values are + * considered false_positives and calls with correct values are considered + * true positives. When we are suppose to call output_state_changed_cb, but it isn't + * called, it is a false_negative. True negatives are when we are not + * suppose to call output_state_changed_cb and it is not called. + * Note that if we are suppose to call output_state_changed_cb and it is called with + * an incorrect value, it is considered a false positive + * A value is considered correct if the difference between the expected + * value and the real value is below a threshold. + */ + unsigned int false_positives; + unsigned int false_negatives; + unsigned int true_negatives; + unsigned int true_positives; + float mse; //Mean Square Error +} Stat; + +typedef struct { + FILE *f; + unsigned int read_count; + unsigned int output_state_changed_count; + float threshold; + float *outputs; + float *output_state_changed_outputs; + float *expected_outputs; + Stat *stats; +} Context; + +static void +_initialize_context(Context *ctx, struct sml_object *sml) +{ + struct sml_variables_list *output_list = sml_get_output_list(sml); + uint16_t len = sml_variables_list_get_length(sml, output_list); + + memset(ctx, 0, sizeof(Context)); + ctx->outputs = malloc(sizeof(float) * len); + ctx->expected_outputs = malloc(sizeof(float) * len); + ctx->output_state_changed_outputs = malloc(sizeof(float) * len); + ctx->stats = calloc(1, sizeof(Stat) * len); +} + +static void +_clear_context(Context *ctx) +{ + fclose(ctx->f); + free(ctx->outputs); + free(ctx->expected_outputs); + free(ctx->output_state_changed_outputs); + free(ctx->stats); +} + +static bool +_read_line(FILE *f, char *line, size_t len) +{ + char *ret; + + if (feof(f)) + return false; + + while ((ret = fgets(line, len, f))) + if (line[0] == '#' || line[0] == '\n') + continue; + else + break; + + return ret != NULL; +} + +/* + * Read sensors values stored in data file + */ +static bool +_read_state_cb(struct sml_object *sml, void *data) +{ + uint16_t i, ind, input_len, output_len, tokens_len; + float value; + char line[LINE_LEN]; + char **tokens; + Context *ctx = data; + struct sml_variables_list *input_list, *output_list; + struct sml_variable *sml_variable; + + input_list = sml_get_input_list(sml); + output_list = sml_get_output_list(sml); + input_len = sml_variables_list_get_length(sml, output_list); + output_len = sml_variables_list_get_length(sml, output_list); + + if (!_read_line(ctx->f, line, LINE_LEN)) + return false; + + tokens = g_strsplit(line, " ", 0); + if (!tokens) + return false; + + tokens_len = g_strv_length(tokens); + if (tokens_len < input_len + output_len) { + fprintf(stderr, "Line in file has not enought data\n"); + g_strfreev(tokens); + return false; + } + + printf("Reading sensors: Inputs {"); + for (i = 0; i < input_len; i++) { + sml_variable = sml_variables_list_index(sml, input_list, i); + value = atof(tokens[i]); + sml_variable_set_value(sml, sml_variable, value); + if (i != 0) + printf(", "); + printf("%s: %f", sml_variable_get_name(sml, sml_variable), value); + } + printf("}, Outputs {"); + + for (i = 0; i < output_len; i++) { + sml_variable = sml_variables_list_index(sml, output_list, i); + value = atof(tokens[input_len + i]); + ctx->outputs[i] = value; + sml_variable_set_value(sml, sml_variable, value); + if (i != 0) + printf(", "); + printf("%s: %f", sml_variable_get_name(sml, sml_variable), value); + } + printf("}, Expected {"); + + for (i = 0; i < output_len; i++) { + ind = input_len + output_len + i; + sml_variable = sml_variables_list_index(sml, output_list, i); + if (i != 0) + printf(", "); + printf("%s: ", sml_variable_get_name(sml, sml_variable)); + if (ind < tokens_len && tokens[ind][0] != 0 && tokens[ind][0] != '?') { + ctx->expected_outputs[i] = atof(tokens[ind]); + printf("%f", ctx->expected_outputs[i]); + } else { + printf("?"); + ctx->expected_outputs[i] = NAN; + } + } + printf("}\n"); + g_strfreev(tokens); + + for (i = 0; i < output_len; i++) + ctx->output_state_changed_outputs[i] = NAN; + + ctx->read_count++; + return true; +} + +static void +_output_state_changed_cb(struct sml_object *sml, + struct sml_variables_list *changed, void *data) +{ + uint16_t i, j, len, changed_len, found = 0; + struct sml_variable *var, *changed_var; + struct sml_variables_list *list; + Context *ctx = data; + + printf("SML Change State {"); + list = sml_get_output_list(sml); + changed_len = sml_variables_list_get_length(sml, changed); + len = sml_variables_list_get_length(sml, list); + for (i = 0; i < len; i++) { + var = sml_variables_list_index(sml, list, i); + for (j = 0; j < changed_len; j++) { + changed_var = sml_variables_list_index(sml, list, j); + if (var == changed_var) { + ctx->output_state_changed_outputs[i] = sml_variable_get_value( + sml, var); + if (found++ > 0) + printf(", "); + printf("%s: %f", sml_variable_get_name(sml, var), + ctx->output_state_changed_outputs[i]); + } + } + } + printf("}\n"); +} + +static bool +compare(float new, float old, float threshold) +{ + if (isnan(new)) + return true; + return fabs(new - old) < threshold; +} + +static void +_process_state(struct sml_object *sml, Context *ctx) +{ + unsigned int i, len; + + len = sml_variables_list_get_length(sml, sml_get_output_list(sml)); + for (i = 0; i < len; i++) { + float new_output = ctx->output_state_changed_outputs[i]; + if (!compare(new_output, ctx->expected_outputs[i], ctx->threshold)) { + if (compare(new_output, ctx->outputs[i], ctx->threshold)) + ctx->stats[i].false_negatives++; + else + ctx->stats[i].false_positives++; + } else { + if (compare(new_output, ctx->outputs[i], ctx->threshold)) + ctx->stats[i].true_negatives++; + else + ctx->stats[i].true_positives++; + } + float error = ctx->expected_outputs[i] - new_output; + if (!isnan(error)) + ctx->stats[i].mse += error * error; + } +} + +static void +_print_results(Context *ctx, struct sml_object *sml) +{ + unsigned int i, len; + + printf("Total Tests: %d\n", ctx->read_count); + len = sml_variables_list_get_length(sml, sml_get_output_list(sml)); + for (i = 0; i < len; i++) { + printf("Output %d:\n", i); + Stat *stat = &ctx->stats[i]; + unsigned int total = stat->false_positives + stat->false_negatives + + stat->true_positives + stat->true_negatives; + unsigned int threshold_error = stat->false_positives + + stat->false_negatives; + + float precision = stat->true_positives / + (float)(stat->true_positives + stat->false_positives); + float recall = stat->true_positives / + (float)(stat->false_negatives + stat->true_positives); + printf("\tErrors: %d (%1.2f%%)\n", threshold_error, + (threshold_error / (float)total) * 100); + printf("\tAccuracy: %f\n", + (stat->true_positives + stat->true_negatives) / (float)total); + printf("\tPrecision: %f\n", precision); + printf("\tF-Score: %f\n", 2 * (precision * recall) / + (precision + recall)); + printf("\tMean Square Root: %f\n", stat->mse / total); + } + printf("\n"); +} + +static struct sml_object * +_sml_new(int id) +{ + switch (id) { + case FUZZY_ENGINE: + return sml_fuzzy_new(); + case ANN_ENGINE: + return sml_ann_new(); + } + return NULL; +} + +int +main(int argc, char *argv[]) +{ + struct sml_object *sml; + Context ctx; + + if (argc < 4) { + fprintf(stderr, "Correct usage %s " + "description.fll data.dat \n", argv[0]); + fprintf(stderr, "Test Fuzzy: %s 0 examples/data/example_in_out.fll " + "examples/data/example_in_out.txt\n", argv[0]); + fprintf(stderr, "Test ANN: %s 1 examples/data/example_in_out.fll " + "examples/data/example_in_out.txt\n", argv[0]); + return 1; + } + + sml = _sml_new(atoi(argv[1])); + if (!sml) { + fprintf(stderr, "Failed to create sml\n"); + return 1; + } + + if (!sml_load_fll_file(sml, argv[2])) { + fprintf(stderr, "Failed to open %s\n", argv[2]); + return 2; + } + + _initialize_context(&ctx, sml); + printf("file %s\n", argv[3]); + ctx.f = fopen(argv[3], "r"); + if (!ctx.f) { + fprintf(stderr, "Failed to open %s\n", argv[3]); + return 4; + } + + if (argc > 4) { + ctx.threshold = atof(argv[4]); + if (ctx.threshold <= 0) { + fprintf(stderr, "threshold must be positive\n"); + return 5; + } + } else + ctx.threshold = THRESHOLD; + + sml_set_read_state_callback(sml, _read_state_cb, &ctx); + sml_set_output_state_changed_callback(sml, _output_state_changed_cb, &ctx); + sml_ann_set_initial_required_observations(sml, INITIAL_REQUIRED_OBS); + while (!sml_process(sml)) + _process_state(sml, &ctx); + + _print_results(&ctx, sml); + _clear_context(&ctx); + + sml_print_debug(sml, false); + sml_free(sml); + + return 0; +} diff --git a/examples/foosball_example.c b/examples/foosball_example.c new file mode 100644 index 0000000..6ab6287 --- /dev/null +++ b/examples/foosball_example.c @@ -0,0 +1,389 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Foosball game prediction example + * + * This example loads from a file data from foosball matches. It feeds SML with + * games results and use it to predict future winners. + * + * Team1 is using red uniforms and team2 is using yellow uniforms + */ +#include +#include +#include +#include +#include +#include +#include + +#define LINE_SIZE (256) +#define DISCRETE_THRESHOLD (0.45) +#define REQUIRED_OBS 5 +#define TERM_NAME_SIZE 20 +#define THRESHOLD (0.1) +#define FUZZY_ENGINE 0 +#define ANN_ENGINE 1 +#define MIN_PLAYERS 4 +#define WINNER_NONE 0 +#define WINNER1 1 +#define WINNER2 2 + +typedef struct { + FILE *f; + struct sml_object *sml; + int sml_engine; + uint16_t num_players; + int reads, predictions, rights; + uint16_t val_offense1, val_defense1, val_offense2, val_defense2; + int val_score1, val_score2, val_winner; + char line[LINE_SIZE]; + bool first_train; + + struct sml_variable *offense1, *defense1; + struct sml_variable *offense2, *defense2; + + struct sml_variable *winner; + char **players; +} Context; + +static bool +_read_next_line(char *line, int len, FILE *f) +{ + while (fgets(line, len, f)) { + if (line[0] == '\n' || line[0] == '\0' || line[0] == '#') + continue; + return true; + } + + return false; +} + +static bool +_find_player_by_name(Context *ctx, const char *name, uint16_t *number) +{ + uint16_t i; + + for (i = 0; i < ctx->num_players; i++) + if (!strcmp(ctx->players[i], name)) { + *number = i; + return true; + } + + fprintf(stderr, "Player %s not found\n", name); + return false; +} + +static bool +_read_data(Context *ctx) +{ + int ret; + char p1[LINE_SIZE], p2[LINE_SIZE], p3[LINE_SIZE], p4[LINE_SIZE]; + + if (!_read_next_line(ctx->line, LINE_SIZE, ctx->f)) + return false; + + ret = sscanf(ctx->line, "%s %s %s %s %d %d", p1, p2, p3, p4, + &ctx->val_score1, &ctx->val_score2); + if (ret < 6) + return false; + + if (!_find_player_by_name(ctx, p1, &ctx->val_offense1)) + return false; + + if (!_find_player_by_name(ctx, p2, &ctx->val_defense1)) + return false; + + if (!_find_player_by_name(ctx, p3, &ctx->val_offense2)) + return false; + + if (!_find_player_by_name(ctx, p4, &ctx->val_defense2)) + return false; + + if (ctx->val_score1 > ctx->val_score2) + ctx->val_winner = WINNER1; + else if (ctx->val_score2 > ctx->val_score1) + ctx->val_winner = WINNER2; + else + ctx->val_winner = WINNER_NONE; + + return true; +} + +static bool +_read_state_cb(struct sml_object *sml, void *data) +{ + Context *ctx = data; + + if (ctx->first_train) { + sml_variable_set_value(sml, ctx->offense1, ctx->val_offense1); + sml_variable_set_value(sml, ctx->defense1, ctx->val_defense1); + sml_variable_set_value(sml, ctx->offense2, ctx->val_offense2); + sml_variable_set_value(sml, ctx->defense2, ctx->val_defense2); + sml_variable_set_value(ctx->sml, ctx->winner, ctx->val_winner); + } else { + sml_variable_set_value(sml, ctx->offense1, ctx->val_offense2); + sml_variable_set_value(sml, ctx->defense1, ctx->val_defense2); + sml_variable_set_value(sml, ctx->offense2, ctx->val_offense1); + sml_variable_set_value(sml, ctx->defense2, ctx->val_defense1); + if (ctx->val_winner == WINNER_NONE) + sml_variable_set_value(ctx->sml, ctx->winner, WINNER_NONE); + else if (ctx->val_winner == WINNER1) + sml_variable_set_value(ctx->sml, ctx->winner, WINNER2); + else + sml_variable_set_value(ctx->sml, ctx->winner, WINNER1); + } + + + return true; +} + +static bool +_do_prediction(Context *ctx) +{ + char *result = ""; + float prediction; + + sml_variable_set_value(ctx->sml, ctx->offense1, ctx->val_offense1); + sml_variable_set_value(ctx->sml, ctx->defense1, ctx->val_defense1); + sml_variable_set_value(ctx->sml, ctx->offense2, ctx->val_offense2); + sml_variable_set_value(ctx->sml, ctx->defense2, ctx->val_defense2); + sml_variable_set_value(ctx->sml, ctx->winner, NAN); + + sml_predict(ctx->sml); + ctx->reads++; + prediction = roundf(sml_variable_get_value(ctx->sml, ctx->winner)); + + if (!isnan(prediction)) { + ctx->predictions++; + if (ctx->val_winner == ((int)prediction)) { + ctx->rights++; + result = "right"; + } else + result = "wrong"; + } + + printf("Game %d team 1 (%d, %d) x team2 (%d, %d): predicted winner: %.0f " + "real winner: %d %s\n", ctx->reads, + ctx->val_offense1, ctx->val_defense1, ctx->val_offense2, + ctx->val_defense2, prediction, ctx->val_winner, result); + + + return true; +} + +static struct sml_object * +_sml_new(int id) +{ + switch (id) { + case FUZZY_ENGINE: + return sml_fuzzy_new(); + case ANN_ENGINE: + return sml_ann_new(); + } + return NULL; +} + +static struct sml_variable * +_create_input(Context *ctx, const char *name) +{ + char term_name[TERM_NAME_SIZE]; + struct sml_variable *v; + uint16_t i; + + v = sml_new_input(ctx->sml, name); + sml_variable_set_range(ctx->sml, v, 0, ctx->num_players - 1); + + if (ctx->sml_engine == FUZZY_ENGINE) { + snprintf(term_name, LINE_SIZE, "%s_%s", name, ctx->players[0]); + sml_fuzzy_variable_add_term_ramp(ctx->sml, v, term_name, + 0 + DISCRETE_THRESHOLD, 0, 1); + for (i = 1; i < ctx->num_players - 1; i++) { + snprintf(term_name, LINE_SIZE, "%s_%s", name, ctx->players[i]); + sml_fuzzy_variable_add_term_triangle(ctx->sml, v, term_name, + i - DISCRETE_THRESHOLD, i, + i + DISCRETE_THRESHOLD, 1); + } + snprintf(term_name, LINE_SIZE, "%s_%s", name, ctx->players[i]); + sml_fuzzy_variable_add_term_ramp(ctx->sml, v, term_name, + ctx->num_players - 1 - DISCRETE_THRESHOLD, + ctx->num_players - 1, 1); + } + + return v; +} + +static bool +_initialize_sml(Context *ctx) +{ + sml_set_stabilization_hits(ctx->sml, 0); + sml_set_read_state_callback(ctx->sml, _read_state_cb, ctx); + if (ctx->sml_engine == ANN_ENGINE) + sml_ann_set_initial_required_observations(ctx->sml, REQUIRED_OBS); + + ctx->offense1 = _create_input(ctx, "red_striker"); + ctx->defense1 = _create_input(ctx, "red_goalkeeper"); + ctx->offense2 = _create_input(ctx, "yellow_striker"); + ctx->defense2 = _create_input(ctx, "yellow_goalkeeper"); + + //number of the winner team + ctx->winner = sml_new_output(ctx->sml, "winner"); + sml_variable_set_range(ctx->sml, ctx->winner, 0, 2); + if (ctx->sml_engine == FUZZY_ENGINE) { + sml_fuzzy_variable_add_term_ramp(ctx->sml, ctx->winner, "none", + 0 + DISCRETE_THRESHOLD, 0, 1); + sml_fuzzy_variable_add_term_triangle(ctx->sml, ctx->winner, + "red_winner", WINNER1 - DISCRETE_THRESHOLD, WINNER1, + WINNER1 + DISCRETE_THRESHOLD, 1); + sml_fuzzy_variable_add_term_ramp(ctx->sml, ctx->winner, "yellow_winner", + WINNER2 - DISCRETE_THRESHOLD, WINNER2, + 1); + } + + return true; +} + +static void +_free_players(char **players, uint16_t num_players) +{ + uint16_t i; + + for (i = 0; i < num_players; i++) + free(players[i]); + free(players); +} + +static bool +_read_config(Context *ctx, const char *filename) +{ + uint16_t i; + FILE *f; + size_t line_len; + + f = fopen(filename, "r"); + if (!f) { + fprintf(stderr, "Failed to open the config file: %s\n", filename); + return false; + } + + if (!_read_next_line(ctx->line, LINE_SIZE, f)) + goto config_error; + + ctx->num_players = atoi(ctx->line); + if (ctx->num_players < MIN_PLAYERS) { + fprintf(stderr, "%d is not enough players.\n", ctx->num_players); + goto config_error; + } + + printf("%d players:\n", ctx->num_players); + ctx->players = malloc(sizeof(char *) * ctx->num_players); + for (i = 0; i < ctx->num_players; i++) { + if (!_read_next_line(ctx->line, LINE_SIZE, f)) { + _free_players(ctx->players, i); + goto config_error; + } + + line_len = strlen(ctx->line); + ctx->line[line_len - 1] = 0; + ctx->players[i] = malloc(strlen(ctx->line) + 100); + strncpy(ctx->players[i], ctx->line, line_len); + printf("\t%s\n", ctx->players[i]); + } + printf("\n"); + + fclose(f); + return true; + +config_error: + fclose(f); + return false; +} + +int +main(int argc, char *argv[]) +{ + int error = 0; + Context ctx; + + if (argc < 4) { + fprintf(stderr, "Correct usage %s \n", + argv[0]); + return -1; + } + + if (!_read_config(&ctx, argv[1])) + return -1; + + ctx.f = fopen(argv[2], "r"); + if (!ctx.f) { + fprintf(stderr, "Failed to open %s\n", argv[1]); + return -1; + } + + ctx.sml_engine = atoi(argv[3]); + ctx.sml = _sml_new(ctx.sml_engine); + ctx.reads = ctx.rights = ctx.predictions = 0; + if (!ctx.sml || !_initialize_sml(&ctx)) { + fprintf(stderr, "Failed to initialize sml\n"); + error = -1; + goto end; + } + + while (_read_data(&ctx)) { + _do_prediction(&ctx); + ctx.first_train = true; + if ((error = sml_process(ctx.sml))) { + fprintf(stderr, "sml_process error number %d\n", error); + break; + } + + ctx.first_train = false; + if ((error = sml_process(ctx.sml))) { + fprintf(stderr, "sml_process error number %d\n", error); + break; + } + } + + sml_print_debug(ctx.sml, false); + printf("Right guesses: %d of %d (%d games) \n", ctx.rights, + ctx.predictions, ctx.reads); + printf("Right predictions percentage:%f%%\n", + ctx.rights * 100.0 / ctx.reads); + printf("Total right predictions percentage:%f%%\n", + ctx.rights * 100.0 / ctx.predictions); + sml_free(ctx.sml); + _free_players(ctx.players, ctx.num_players); + +end: + fclose(ctx.f); + return error; +} diff --git a/examples/fuzzy_test.cpp b/examples/fuzzy_test.cpp new file mode 100644 index 0000000..ef6fc5c --- /dev/null +++ b/examples/fuzzy_test.cpp @@ -0,0 +1,397 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FUZZY_ENGINE 0 +#define ANN_ENGINE 1 + +typedef struct { + fl::Engine *engine; + struct sml_object *sml; + int repeat; + double increment; + double error; + double noise; + bool use_incorrect_output; + int false_positive; + int positive_count; +} Context; + +double _double_rand(double min, double max) { + return min + (((double) rand() / RAND_MAX) * + (max - min)); +} + +static void +_engine_initialize(Context *ctx) +{ + std::vector inputs = ctx->engine->inputVariables(); + for (std::vector::const_iterator it = + inputs.begin(); + it != inputs.end(); ++it) { + fl::InputVariable *input = *it; + input->setInputValue(input->getMinimum()); + } + ctx->engine->process(); +} + +static fl::Variable * +_search_variable(Context *ctx, const char *id) +{ + std::vector inputs = ctx->engine->inputVariables(); + for (std::vector::const_iterator it = + inputs.begin(); + it != inputs.end(); ++it) { + fl::InputVariable *input = *it; + if (!strcmp(input->getName().c_str(), id)) { + return input; + } + } + + std::vector outputs = ctx->engine->outputVariables(); + for (std::vector::const_iterator it = + outputs.begin(); + it != outputs.end(); ++it) { + fl::OutputVariable *output = *it; + if (!strcmp(output->getName().c_str(), id)) { + return output; + } + } + return NULL; +} + +static fl::scalar +_value_from_variable(Context *ctx, fl::Variable *v) +{ + fl::InputVariable *in = dynamic_cast(v); + if (in != NULL) + return in->getInputValue(); + + if (ctx->use_incorrect_output) { + fl::OutputVariable *out = dynamic_cast(v); + if (out != 0) { + if ((out->getMaximum() - out->getOutputValue()) < + (out->getOutputValue() - out->getMinimum())) + return out->getMinimum(); + return out->getMaximum(); + } + } + + fl::OutputVariable *out = dynamic_cast(v); + if (out != 0) + return out->getOutputValue(); + + return 0; +} + +void +set_value(Context *ctx, struct sml_variable *sml_variable) +{ + float value; + fl::Variable *v = _search_variable(ctx, + sml_variable_get_name(ctx->sml, sml_variable)); + + if (v == NULL) { + sml_variable_set_value(ctx->sml, sml_variable, NAN); + return; + } + + if (ctx->error > 0 && (rand() % ((int) (1 / ctx->error)) == 0)) + value = _double_rand(v->getMinimum(), v->getMaximum()); + else { + value = _value_from_variable(ctx, v); + if (ctx->noise > 0) { + value += _double_rand(-ctx->noise, ctx->noise); + } + if (value < v->getMinimum()) + value = v->getMinimum(); + else if (value > v->getMaximum()) + value = v->getMaximum(); + } + sml_variable_set_value(ctx->sml, sml_variable, value); + printf("%s> %f\n", sml_variable_get_name(ctx->sml, sml_variable), value); + for (int i = 0; i < v->numberOfTerms(); i++) { + fl::Term *t = v->getTerm(i); + printf(" %s> %f\n", t->getName().c_str(), t->membership(value)); + } +} + +void +set_list_values(Context *ctx, struct sml_variables_list *list) +{ + unsigned int i, len; + len = sml_variables_list_get_length(ctx->sml, list); + for (i = 0; i < len; i++) { + struct sml_variable *sml_variable = sml_variables_list_index(ctx->sml, list, i); + set_value(ctx, sml_variable); + } +} + +bool +read_state_cb(struct sml_object *sml, void *data) +{ + Context *ctx = (Context *)data; + struct sml_variables_list *input_list, *output_list; + + if (!ctx->repeat) + return false; + + input_list = sml_get_input_list(sml); + output_list = sml_get_output_list(sml); + + printf("\nread_state_cb:\n"); + set_list_values(ctx, input_list); + set_list_values(ctx, output_list); + + //calculate next values + std::vector inputs = ctx->engine->inputVariables(); + int pos = inputs.size() - 1; + while (pos >= 0) { + fl::InputVariable *input = inputs[pos]; + fl::scalar new_value = input->getInputValue() + ctx->increment; + if (new_value > input->getMaximum()) { + input->setInputValue(input->getMinimum()); + pos--; + } else { + input->setInputValue(new_value); + break; + } + } + + //The execution has ended + if (pos < 0) { + _engine_initialize(ctx); + ctx->repeat--; + } + ctx->engine->process(); + + return true; +} + +static void +_output_state_changed_cb_test_false_positive (struct sml_object *sml, struct sml_variables_list *changed, void *data) +{ + Context *ctx = (Context *) data; + ctx->false_positive++; + + printf("False Posive called:\n"); + unsigned int i, len; + len = sml_variables_list_get_length(sml, changed); + for (i = 0; i < len; i++) { + struct sml_variable *sml_variable = sml_variables_list_index(sml, + changed, i); + printf("%s> %f\n", sml_variable_get_name(sml, sml_variable), + sml_variable_get_value(sml, sml_variable)); + } +} + +static void +_output_state_changed_cb_false_negative (struct sml_object *sml, struct sml_variables_list *changed, void *data) +{ + Context *ctx = (Context *) data; + ctx->positive_count++; + + printf("Change State Called:\n"); + unsigned int i, len; + len = sml_variables_list_get_length(sml, changed); + for (i = 0; i < len; i++) { + struct sml_variable *sml_variable = sml_variables_list_index(sml, + changed, i); + printf("%s> %f\n", sml_variable_get_name(sml, sml_variable), + sml_variable_get_value(sml, sml_variable)); + } +} + +static unsigned int +_number_of_states (Context *ctx) +{ + unsigned int i, len, n = 1; + + std::vector inputs = ctx->engine->inputVariables(); + len = inputs.size(); + for (i=0; i < len; i++) { + fl::InputVariable *input = inputs[i]; + n *= (unsigned int) ((input->getMaximum() - input->getMinimum()) / + ctx->increment) + 1; + } + + return n; +} + +static struct sml_object * +_sml_new(int id) +{ + switch(id) { + case FUZZY_ENGINE: + return sml_fuzzy_new(); + case ANN_ENGINE: + return sml_ann_new(); + } + return NULL; +} + +int +main(int argc, char *argv[]) +{ + Context ctx; + memset(&ctx, 0, sizeof(Context)); + + if (argc < 4) { + fprintf(stderr, "Correct usage %s engine type (0 fuzzy, 1 ann)" + " in.fll out.fll " + " \n", + argv[0]); + fprintf(stderr, "Test1: %s engine type (0 fuzzy, 1 ann)" + " examples/data/fuzzy_test_1.fll " + "examples/data/fuzzy_test_1.fll 1\n", + argv[0]); + fprintf(stderr, "Test2: %s engine type (0 fuzzy, 1 ann)" + " examples/data/fuzzy_test_2.fll " + "examples/data/fuzzy_test_2.fll 0.1\n", + argv[0]); + return 1; + } + + if (argc > 4) { + ctx.increment = atof(argv[4]); + if (ctx.increment <= 0) { + fprintf(stderr, "Increment must be positive\n"); + return 2; + } + } else + ctx.increment = 0.1; + + if (argc > 5) { + ctx.repeat = atof(argv[5]); + if (ctx.repeat <= 0) { + fprintf(stderr, "Repeat must be positive\n"); + return 2; + } + } else + ctx.repeat = 1; + + if (argc > 6) { + ctx.noise = atof(argv[6]); + if (ctx.noise < 0) { + fprintf(stderr, "Noise range must be positive\n"); + return 2; + } + } + + if (argc > 7) { + ctx.error = atof(argv[7]); + if (ctx.error < 0 || ctx.error > 1) { + fprintf(stderr, "Error frequency must be between 0.0 and 1.0\n"); + return 2; + } + } + + ctx.sml = _sml_new(atoi(argv[1])); + if (!ctx.sml) { + fprintf(stderr, "Failed to create sml"); + return 1; + } + + fl::FllImporter importer; + ctx.engine = importer.fromFile(argv[2]); + _engine_initialize(&ctx); + + if (!sml_load_fll_file(ctx.sml, argv[3])) { + fprintf(stderr, "Failed to open %s\n", argv[3]); + return 3; + } + + unsigned int seed; + if (argc > 8) { + seed = (unsigned int) atol(argv[8]); + } else { + seed = time(NULL); + } + srand(seed); + + printf("Starting test with seed = %d\n", seed); + + sml_set_read_state_callback(ctx.sml, read_state_cb, &ctx); + sml_set_stabilization_hits(ctx.sml, 0); + + printf("Learning...\n"); + while (!sml_process(ctx.sml)); + + printf("Testing false positives...\n"); + + sml_set_learn_disabled(ctx.sml, true); + sml_set_output_state_changed_callback(ctx.sml, _output_state_changed_cb_test_false_positive, + &ctx); + ctx.repeat = 1; + ctx.error = 0; + ctx.noise = 0; + + _engine_initialize(&ctx); + + while (!sml_process(ctx.sml)); + + printf("Testing false negatives...\n"); + sml_set_output_state_changed_callback(ctx.sml, _output_state_changed_cb_false_negative, + &ctx); + ctx.repeat = 1; + ctx.use_incorrect_output = true; + _engine_initialize(&ctx); + + while (!sml_process(ctx.sml)); + + sml_print_debug(ctx.sml, false); + + unsigned int number_of_states = _number_of_states(&ctx); + printf("==========================================================\n"); + printf("Tests performed in the same dataset used to learn.\n" + "False positives and false negatives should be 0.\n\n"); + printf("False positives (change state called when not needed): %d of %d\n", + ctx.false_positive, number_of_states); + printf("False negative (change state not called when needed): %d of %d\n", + number_of_states - ctx.positive_count, number_of_states); + printf("==========================================================\n"); + + sml_free(ctx.sml); + delete ctx.engine; + + return 0; +} diff --git a/examples/test_memory.c b/examples/test_memory.c new file mode 100644 index 0000000..090f808 --- /dev/null +++ b/examples/test_memory.c @@ -0,0 +1,161 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define STRLEN 20 +#define FUZZY_ENGINE 0 +#define ANN_ENGINE 1 + +static void +_set_list_values(struct sml_object *sml, struct sml_variables_list *list) +{ + unsigned int i, len; + struct sml_variable *sml_variable; + + len = sml_variables_list_get_length(sml, list); + for (i = 0; i < len; i++) { + sml_variable = sml_variables_list_index(sml, list, i); + sml_variable_set_value(sml, sml_variable, rand()); + } +} + +static bool +_read_state_cb(struct sml_object *sml, void *data) +{ + int *executions = data; + + if (*executions == 0) + return false; + (*executions)--; + + struct sml_variables_list *input_list, *output_list; + + input_list = sml_get_input_list(sml); + output_list = sml_get_output_list(sml); + + _set_list_values(sml, input_list); + _set_list_values(sml, output_list); + + return true; +} + +static void +_add_terms(struct sml_object *sml, struct sml_variable *var, char *strbuf, + int id, unsigned int num_terms) +{ + unsigned int i, step; + + step = RAND_MAX / num_terms; + for (i = 0; i < num_terms; i++) { + snprintf(strbuf, STRLEN, "term%d.%d", id, i); + sml_fuzzy_variable_add_term_triangle(sml, var, strbuf, step * i, + step * (i + 0.5), step * (i + 1), 1.0); + } +} + +static struct sml_object * +_sml_new(int id) +{ + switch (id) { + case FUZZY_ENGINE: + return sml_fuzzy_new(); + case ANN_ENGINE: + return sml_ann_new(); + } + return NULL; +} + +int +main(int argc, char *argv[]) +{ + unsigned int inputs, outputs, executions, num_terms; + char strbuf[STRLEN]; + struct sml_variable *var; + struct sml_object *sml; + + if (argc < 5) { + fprintf(stderr, "Usage: %s " + " \n", argv[0]); + fprintf(stderr, "Fuzzy Test: %s 0 10 2 100 10\n", argv[0]); + fprintf(stderr, "ANN Test: %s 1 10 2 100 10\n", argv[0]); + return 1; + } + + inputs = atoi(argv[2]); + outputs = atoi(argv[3]); + executions = atoi(argv[4]); + num_terms = atoi(argv[5]); + + if (argc > 6) + srand((unsigned int)atol(argv[6])); + else + srand(time(NULL)); + + sml = _sml_new(atoi(argv[1])); + if (!sml) { + fprintf(stderr, "Failed to create sml\n"); + return 1; + } + + + sml_set_read_state_callback(sml, _read_state_cb, &executions); + sml_set_stabilization_hits(sml, 0); + + while (inputs) { + snprintf(strbuf, STRLEN, "input%d", inputs); + var = sml_new_input(sml, strbuf); + sml_variable_set_range(sml, var, 0, RAND_MAX); + _add_terms(sml, var, strbuf, inputs, num_terms); + + inputs--; + } + + while (outputs) { + snprintf(strbuf, STRLEN, "output%d", outputs); + var = sml_new_output(sml, strbuf); + sml_variable_set_range(sml, var, 0, RAND_MAX); + _add_terms(sml, var, strbuf, outputs, num_terms); + outputs--; + } + + while (!sml_process(sml)) ; + sml_free(sml); + + return 0; +} diff --git a/simulator/CMakeLists.txt b/simulator/CMakeLists.txt new file mode 100644 index 0000000..be16b34 --- /dev/null +++ b/simulator/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 2.8) + +project(simulator) + +include_directories(${SML_INCLUDE_DIR} ${GLIB_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/sml/sml_naive/include/) +link_directories(${GLIB_LIBRARY_DIRS} ${FANN_LIBRARY_DIRS} ${FUZZY_LITE_LIBRARY_DIRS} ${SOLETTA_LIBRARY_DIRS}) + +add_executable(sml_simulator.out sml_simulator.c) +target_link_libraries(sml_simulator.out ${GLIB_LIBRARIES} sml_libs naive_engine_libs m) diff --git a/simulator/run_all_simulations.sh b/simulator/run_all_simulations.sh new file mode 100755 index 0000000..2295437 --- /dev/null +++ b/simulator/run_all_simulations.sh @@ -0,0 +1,230 @@ +#!/bin/sh + +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +results_dir="" + +function parse_results() +{ + prefix=$1 + total=0 + count=0 + total_duration=0 + max_it_duration=0 + avg_anns=0 + anns=0 + observations=0 + avg_observations=0 + for result in ${results_dir}/result_${prefix}_${conf}.${data}.*; do + value=$(cat $result | grep "Variable${i}"|cut -d ' ' -f 10) + it_duration=$(cat $result | grep "Max Iteration Duration"|cut -d ' ' -f 6) + duration=$(cat $result | grep "Average Duration"|cut -d ' ' -f 5) + if [[ "$prefix" == "ann" ]]; then + anns=$(cat $result | grep "Total ANNs created" | cut -d ' ' -f 6 | sed 's/[()]//g') + avg_anns=$(echo $anns + $avg_anns | bc -l) + observations=$(cat $result | grep "Required observations" | cut -d ' ' -f 5) + avg_observations=$(echo $observations + $avg_observations | bc -l) + fi + total=$(echo $total + $value | bc -l) + total_duration=$(echo $total_duration + $duration | bc -l) + if [ $(echo "$max_it_duration < $it_duration" | bc -l) -eq 1 ]; then + max_it_duration=$it_duration + fi + count=$(echo $count + 1 | bc) + done + duration=$(echo "scale=2; $total_duration / $count" | bc -l) + result=$(echo "scale=4; $total / $count" | bc -l) + + if [[ "$prefix" == "ann" ]]; then + avg_anns=$(echo "scale=2; $avg_anns / $count" | bc -l) + avg_observations=$(echo "scale=2; $avg_observations / $count" | bc -l) + fi +} + +function get_engine_number() +{ + engine=$1 + if [[ "$engine" == "fuzzy" ]]; then + return 0 + elif [[ "$engine" == "ann" ]]; then + return 1 + elif [[ "$engine" == "naive" ]]; then + return 2 + elif [[ "$engine" == "fuzzy_no_simplification" ]]; then + return 3 + fi + return 0 #default +} + +function run_simulation() +{ + engine=$1 + get_engine_number $engine + engine_number=$? + seed=$2 + memory_size=$3 + cache_size=$4 + pseudo_rehearsal=$5 + for conf in $(ls *.conf); do + for data in $(ls ${conf/.conf/}.*data); do + ${SIM_EXE} $conf $data $seed 1 ${engine_number} ${memory_size} ${cache_size} ${pseudo_rehearsal} > "${results_dir}/result_${engine}_${conf}.${data}.${seed}" 2>&1 & + done + done + jobs + wait +} + +function print_results() +{ + engine=$1 + if [[ "$engine" == "ann" ]]; then + OUTPUT="$engine Results Max_It_Duration Avg_It_Duration Avg_Anns_Created Avg_Max_Observations" + else + OUTPUT="$engine Results Max_It_Duration Avg_It_Duration" + fi + + #parse results + for conf in $(ls *.conf); do + for data in $(ls ${conf/.conf/}.*data); do + file=$(ls ${results_dir}/result_${engine}_${conf}.${data}.* | head -n 1) + i=0 + #for each variable + while cat ${file} | grep "Variable${i}" > /dev/null 2> /dev/null; do + var_name=$(cat $file | grep "Variable${i}"|cut -d ' ' -f 2) + + parse_results ${engine} + engine_result=$result + engine_max_it_duration=${max_it_duration} + engine_duration=${duration} + + if [[ "$engine" == "ann" ]]; then + OUTPUT="$OUTPUT\n${data/.data/}.$var_name ${engine_result} ${engine_max_it_duration} ${engine_duration} ${avg_anns} ${avg_observations}" + else + OUTPUT="$OUTPUT\n${data/.data/}.$var_name ${engine_result} ${engine_max_it_duration} ${engine_duration}" + fi + + i=$(echo $i + 1 | bc) + done + done + done +} + +function create_dir() +{ + local prefix="./" + if [ $# -ne 0 ]; then + prefix="${1}/" + fi + + results_dir="${prefix}simulation_results_"$(date +"%d_%b_%Y_%T") + mkdir -p $results_dir + if [ $? -ne 0 ]; then + echo "Could not create the dir $results_dir" + exit + fi + results_dir=$(realpath $results_dir) + echo "Result dir at: ${results_dir}" +} + +if [[ $# < 2 ]]; then + echo "Correct use ./run_all_simulations.sh " \ + " " \ + " [result_dir_path]" + exit -1 +fi + +SIM_EXE=$(realpath $1) +SIM_DIR=$2 + +if ! pushd $SIM_DIR; then + exit +fi + +if [[ $# < 3 ]]; then + repeat=10 +else + repeat=${3} +fi + +if [[ $# < 4 ]]; then + engines="1 2 3 4" +else + engines=${4} +fi + +if [[ $# < 5 ]]; then + start_seed=$(date +%s) +else + start_seed=${5} +fi + +if [[ $# < 6 ]]; then + memory_size=0 +else + memory_size=${6} +fi + +if [[ $# < 7 ]]; then + cache_size=0 +else + cache_size=${7} +fi + +if [[ $# < 8 ]]; then + pseudo_rehearsal=0 +else + pseudo_rehearsal=${8} +fi + +create_dir ${9} + +for engine in $engines; do + echo "Running engine $i" + echo "Start seed: $start_seed" + for i in $(seq ${repeat}); do + seed=$(echo "${start_seed} + ${i}" | bc) + run_simulation $engine $seed $memory_size $cache_size $pseudo_rehearsal + done +done + +echo "=========================================================================================" +print_results $engine +echo -ne "$OUTPUT\n" | column -t > ${results_dir}/results.txt + +if [ $? -ne 0 ]; then + echo -ne "$OUTPUT\n" | column -t + echo "Could not save the output as file!" +else + cat ${results_dir}/results.txt + echo "Results saved at:${results_dir}/results.txt" +fi + +popd diff --git a/simulator/run_massif_simulations.sh b/simulator/run_massif_simulations.sh new file mode 100755 index 0000000..9c2e12f --- /dev/null +++ b/simulator/run_massif_simulations.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +function run_massif() +{ + prefix=$1 + alg=$2 + memory=$3 + cache=$4 + echo "=== ${prefix} ===" + OUTPUT="" + for conf in $(ls *.conf); do + for data in $(ls ${conf/.conf/}.*data); do + OUTPUT="$OUTPUT\n${data/.data/} " + massif="massif_${prefix}_${conf}.${data}.${seed}" + valgrind --tool=massif --massif-out-file=${massif} ${SIM_EXE} $conf $data $seed 1 $alg $memory $cache > "result_massif_${prefix}_${conf}.${data}.${seed}" 2>&1 + OUTPUT="$OUTPUT $(cat ${massif} | grep --color=never mem_heap_B | sed -e 's/mem_heap_B=//' | sort -g | tail -n 1)" + done + done + OUTPUT="$OUTPUT" + echo -e $OUTPUT |column -t + echo +} + +if [[ $# < 2 ]]; then + echo "Correct use ./run_massif_simulations.sh " \ + " " + exit -1 +fi + +SIM_EXE=$(realpath $1) +SIM_DIR=$2 + +if ! pushd $SIM_DIR; then + exit +fi + +if [[ $# < 3 ]]; then + seed=$(date +%s) +else + seed=${3} +fi + +echo "Seed: $seed" +OUTPUT="" +run_massif fuzzy 0 0 0 +run_massif ann 1 0 0 +run_massif naive 2 0 0 +run_massif fuzzy_no_simplification 3 0 0 + +run_massif ann_1k 1 1024 10 +run_massif ann_10k 1 10240 10 +run_massif ann_100k 1 102400 10 + +run_massif fuzzy_1k 0 1024 0 +run_massif fuzzy_10k 0 10240 0 +run_massif fuzzy_100k 0 102400 0 + +popd diff --git a/simulator/simulations/car_ac.conf b/simulator/simulations/car_ac.conf new file mode 100644 index 0000000..27c8c81 --- /dev/null +++ b/simulator/simulations/car_ac.conf @@ -0,0 +1,66 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config + +# a day will be splitted in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 21 + +# Inputs +# Block times per day and weekdays are created by default + +INPUT EnvTemperature -30 60 + +INPUT User 0 3 +TERM Nobody 0 0 +TERM Bruno 1 1 +TERM Guilherme 2 2 +TERM Otavio 3 3 + +INPUT BodyTemperature 35 40 + +# actually it depends a lot on user age, but for our +# purposes it doesn't matter +INPUT HeartRate 0 250 +TERM Dead 0 1 +TERM Dying 0 30 +TERM Sleeping 25 70 +TERM Awake 65 100 +TERM ModerateActivity 95 120 +TERM WeightControl 115 140 +TERM Aerobic 135 160 +TERM Anaerobic 155 180 +TERM MaximumEffort 175 200 + +INPUT PeopleQuantity 1 5 + +OUTPUT ACTemperature 0 30 diff --git a/simulator/simulations/car_ac.data b/simulator/simulations/car_ac.data new file mode 100644 index 0000000..2106576 --- /dev/null +++ b/simulator/simulations/car_ac.data @@ -0,0 +1,790 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# initial state +0 0:00 EnvTemperature 22 +0 0:00 User Nobody +0 0:00 BodyTemperature 0 +0 0:00 HeartRate 0 + +0 0:00 PeopleQuantity 0 +0 0:00 ACTemperature 0 +0 0:00 EXP_ACTemperature 0 + +###Normal week### +### Monday ### + +0 08:00 EnvTemperature 22 +0 08:00 User Guilherme +0 08:00 BodyTemperature 36 +0 08:00 HeartRate 78 +0 08:01 PeopleQuantity 1 +0 08:01 ACTemperature 24 +0 08:01 EXP_ACTemperature 24 + +0 08:30 User Nobody +0 08:30 BodyTemperature 0 +0 08:30 HeartRate 0 +0 08:30 PeopleQuantity 0 +0 08:30 ACTemperature 0 +0 08:30 EXP_ACTemperature 0 + + +0 18:00 EnvTemperature 24 +0 18:00 User Guilherme +0 18:00 BodyTemperature 36 +0 18:00 HeartRate 76 +0 18:01 PeopleQuantity 1 +0 18:01 ACTemperature 24 +0 18:01 EXP_ACTemperature 24 + + +0 18:30 User Nobody +0 18:30 BodyTemperature 0 +0 18:30 HeartRate 0 +0 18:30 PeopleQuantity 0 +0 18:30 ACTemperature 0 +0 18:30 EXP_ACTemperature 0 + +### Tuesday ### + +1 08:00 BEGIN_EXPECTATIONS +1 08:00 EnvTemperature 22 +1 08:00 User Guilherme +1 08:00 BodyTemperature 36 +1 08:00 HeartRate 67 +1 08:01 PeopleQuantity 1 +1 08:01 ACTemperature 24 +1 08:01 EXP_ACTemperature 24 +1 08:01 END_EXPECTATIONS + +1 08:30 BEGIN_EXPECTATIONS +1 08:30 User Nobody +1 08:30 BodyTemperature 0 +1 08:30 HeartRate 0 +1 08:30 PeopleQuantity 0 +1 08:30 ACTemperature 0 +1 08:30 EXP_ACTemperature 0 +1 08:31 END_EXPECTATIONS + +1 18:00 BEGIN_EXPECTATIONS +1 18:00 EnvTemperature 24 +1 18:00 User Guilherme +1 18:00 BodyTemperature 38 +1 18:00 HeartRate 82 +1 18:01 PeopleQuantity 1 +1 18:01 ACTemperature 22 +1 18:01 EXP_ACTemperature 22 +1 18:01 END_EXPECTATIONS + +1 18:30 BEGIN_EXPECTATIONS +1 18:30 User Nobody +1 18:30 BodyTemperature 0 +1 18:30 HeartRate 0 +1 18:30 PeopleQuantity 0 +1 18:30 ACTemperature 0 +1 18:30 EXP_ACTemperature 24 +1 18:31 END_EXPECTATIONS + +### Wednesday ### + +2 08:00 BEGIN_EXPECTATIONS +2 08:00 EnvTemperature 22 +2 08:00 User Guilherme +2 08:00 BodyTemperature 39 +2 08:00 HeartRate 81 +2 08:01 PeopleQuantity 2 +2 08:01 ACTemperature 22 +2 08:01 EXP_ACTemperature 22 +2 08:01 END_EXPECTATIONS + +2 08:30 BEGIN_EXPECTATIONS +2 08:30 User Nobody +2 08:30 BodyTemperature 0 +2 08:30 HeartRate 0 +2 08:30 PeopleQuantity 0 +2 08:30 ACTemperature 0 +2 08:30 EXP_ACTemperature 0 +2 08:31 END_EXPECTATIONS + + +2 18:00 BEGIN_EXPECTATIONS +2 18:00 EnvTemperature 24 +2 18:00 User Guilherme +2 18:00 BodyTemperature 36 +2 18:00 HeartRate 70 +2 18:01 PeopleQuantity 1 +2 18:01 ACTemperature 24 +2 18:01 EXP_ACTemperature 24 +2 18:01 END_EXPECTATIONS + + +2 18:30 BEGIN_EXPECTATIONS +2 18:30 User Nobody +2 18:30 BodyTemperature 0 +2 18:30 HeartRate 0 +2 18:30 PeopleQuantity 0 +2 18:30 ACTemperature 0 +2 18:30 EXP_ACTemperature 0 +2 18:31 END_EXPECTATIONS + +### Thursday ### + +3 08:00 BEGIN_EXPECTATIONS +3 08:00 EnvTemperature 22 +3 08:00 User Guilherme +3 08:00 BodyTemperature 36 +3 08:00 HeartRate 70 +3 08:01 PeopleQuantity 2 +3 08:01 ACTemperature 24 +3 08:01 EXP_ACTemperature 24 +3 08:01 END_EXPECTATIONS + +3 08:30 BEGIN_EXPECTATIONS +3 08:30 User Nobody +3 08:30 BodyTemperature 0 +3 08:30 HeartRate 0 +3 08:30 PeopleQuantity 0 +3 08:30 ACTemperature 0 +3 08:30 EXP_ACTemperature 0 +3 08:31 END_EXPECTATIONS + + +3 18:00 BEGIN_EXPECTATIONS +3 18:00 EnvTemperature 24 +3 18:00 User Guilherme +3 18:00 BodyTemperature 36 +3 18:00 HeartRate 70 +3 18:01 PeopleQuantity 5 +3 18:01 ACTemperature 24 +3 18:01 EXP_ACTemperature 24 +3 18:01 END_EXPECTATIONS + +3 18:30 BEGIN_EXPECTATIONS +3 18:30 User Nobody +3 18:30 BodyTemperature 0 +3 18:30 HeartRate 0 +3 18:30 PeopleQuantity 0 +3 18:30 ACTemperature 0 +3 18:30 EXP_ACTemperature 0 +3 18:31 END_EXPECTATIONS + +### Friday ### + +4 08:00 BEGIN_EXPECTATIONS +4 08:00 EnvTemperature 22 +4 08:00 User Guilherme +4 08:00 BodyTemperature 36 +4 08:00 HeartRate 70 +4 08:01 PeopleQuantity 5 +4 08:01 ACTemperature 24 +4 08:01 EXP_ACTemperature 24 +4 08:01 END_EXPECTATIONS + +4 08:30 BEGIN_EXPECTATIONS +4 08:30 User Nobody +4 08:30 BodyTemperature 0 +4 08:30 HeartRate 0 +4 08:30 PeopleQuantity 0 +4 08:30 ACTemperature 0 +4 08:30 EXP_ACTemperature 0 +4 08:31 END_EXPECTATIONS + + +4 18:00 BEGIN_EXPECTATIONS +4 18:00 EnvTemperature 24 +4 18:00 User Guilherme +4 18:00 BodyTemperature 36 +4 18:00 HeartRate 70 +4 18:01 PeopleQuantity 1 +4 18:01 ACTemperature 24 +4 18:01 EXP_ACTemperature 24 +4 18:01 END_EXPECTATIONS + + +4 18:30 BEGIN_EXPECTATIONS +4 18:30 User Nobody +4 18:30 BodyTemperature 0 +4 18:30 HeartRate 0 +4 18:30 PeopleQuantity 0 +4 18:30 ACTemperature 0 +4 18:30 EXP_ACTemperature 0 +4 18:31 END_EXPECTATIONS + +### Saturday ### + +5 09:00 BEGIN_EXPECTATIONS +5 09:00 EnvTemperature 22 +5 09:00 User Guilherme +5 09:00 BodyTemperature 36 +5 09:00 HeartRate 70 +5 09:01 PeopleQuantity 1 +5 09:01 ACTemperature 24 +5 09:01 EXP_ACTemperature 24 +5 09:01 END_EXPECTATIONS + +5 09:17 BEGIN_EXPECTATIONS +5 09:17 User Nobody +5 09:17 BodyTemperature 0 +5 09:17 HeartRate 0 +5 09:18 PeopleQuantity 0 +5 09:18 ACTemperature 0 +5 09:18 EXP_ACTemperature 0 +5 09:18 END_EXPECTATIONS + +### Sunday ### + +6 21:00 BEGIN_EXPECTATIONS +6 21:00 EnvTemperature 22 +6 21:00 User Guilherme +6 21:00 BodyTemperature 36 +6 21:00 HeartRate 70 +6 21:01 PeopleQuantity 1 +6 21:01 ACTemperature 24 +6 21:01 EXP_ACTemperature 24 +6 21:01 END_EXPECTATIONS + +6 21:18 BEGIN_EXPECTATIONS +6 21:18 User Nobody +6 21:18 BodyTemperature 0 +6 21:18 HeartRate 0 +6 21:19 PeopleQuantity 0 +6 21:19 ACTemperature 0 +6 21:19 EXP_ACTemperature 0 +6 21:19 END_EXPECTATIONS + + +###Hot weather### +### Monday ### + +6 08:00 BEGIN_EXPECTATIONS +6 08:00 EnvTemperature 32 +6 08:00 User Guilherme +6 08:00 BodyTemperature 38 +6 08:00 HeartRate 70 +6 08:01 PeopleQuantity 1 +6 08:01 ACTemperature 20 +6 08:01 EXP_ACTemperature 20 + +6 08:12 ACTemperature 23 +6 08:12 EXP_ACTemperature 23 +6 08:12 END_EXPECTATIONS + +6 08:30 BEGIN_EXPECTATIONS +6 08:30 User Nobody +6 08:30 BodyTemperature 0 +6 08:30 HeartRate 0 +6 08:30 PeopleQuantity 0 +6 08:30 ACTemperature 0 +6 08:30 EXP_ACTemperature 0 +6 08:01 END_EXPECTATIONS + + +6 18:00 BEGIN_EXPECTATIONS +6 18:00 EnvTemperature 34 +6 18:00 User Guilherme +6 18:00 BodyTemperature 39 +6 18:00 HeartRate 70 +6 18:01 PeopleQuantity 1 +6 18:01 ACTemperature 18 +6 18:01 EXP_ACTemperature 18 +6 18:01 END_EXPECTATIONS + + +6 18:30 BEGIN_EXPECTATIONS +6 18:30 User Nobody +6 18:30 BodyTemperature 0 +6 18:30 HeartRate 0 +6 18:30 PeopleQuantity 0 +6 18:30 ACTemperature 0 +6 18:30 EXP_ACTemperature 0 +6 18:31 END_EXPECTATIONS + +### Tuesday ### + +7 08:00 BEGIN_EXPECTATIONS +7 08:00 EnvTemperature 40 +7 08:00 User Guilherme +7 08:00 BodyTemperature 36 +7 08:00 HeartRate 70 +7 08:01 PeopleQuantity 1 +7 08:01 ACTemperature 22 +7 08:01 EXP_ACTemperature 22 +7 08:01 END_EXPECTATIONS + +7 08:30 BEGIN_EXPECTATIONS +7 08:30 User Nobody +7 08:30 BodyTemperature 0 +7 08:30 HeartRate 0 +7 08:30 PeopleQuantity 0 +7 08:30 ACTemperature 0 +7 08:30 EXP_ACTemperature 0 +7 08:31 END_EXPECTATIONS + + +7 18:00 BEGIN_EXPECTATIONS +7 18:00 EnvTemperature 28 +7 18:00 User Guilherme +7 18:00 BodyTemperature 34 +7 18:00 HeartRate 70 +7 18:01 PeopleQuantity 2 +7 18:01 ACTemperature 24 +7 18:01 EXP_ACTemperature 24 +7 18:01 END_EXPECTATIONS + + +7 18:30 BEGIN_EXPECTATIONS +7 18:30 User Nobody +7 18:30 BodyTemperature 0 +7 18:30 HeartRate 0 +7 18:30 PeopleQuantity 0 +7 18:30 ACTemperature 0 +7 18:30 EXP_ACTemperature 0 +7 18:31 END_EXPECTATIONS + +### Wednesday ### + +8 08:00 BEGIN_EXPECTATIONS +8 08:00 EnvTemperature 42 +8 08:00 User Guilherme +8 08:00 BodyTemperature 34 +8 08:00 HeartRate 70 +8 08:01 PeopleQuantity 2 +8 08:01 ACTemperature 24 +8 08:01 EXP_ACTemperature 24 +8 08:01 END_EXPECTATIONS + +8 08:30 BEGIN_EXPECTATIONS +8 08:30 User Nobody +8 08:30 BodyTemperature 0 +8 08:30 HeartRate 0 +8 08:30 PeopleQuantity 0 +8 08:30 ACTemperature 0 +8 08:30 EXP_ACTemperature 0 +8 08:31 END_EXPECTATIONS + + +8 18:00 BEGIN_EXPECTATIONS +8 18:00 EnvTemperature 24 +8 18:00 User Guilherme +8 18:00 BodyTemperature 36 +8 18:00 HeartRate 70 +8 18:01 PeopleQuantity 5 +8 18:01 ACTemperature 24 +8 18:01 EXP_ACTemperature 24 +8 18:01 END_EXPECTATIONS + + +8 18:30 BEGIN_EXPECTATIONS +8 18:30 User Nobody +8 18:30 BodyTemperature 0 +8 18:30 HeartRate 0 +8 18:30 PeopleQuantity 0 +8 18:30 ACTemperature 0 +8 18:30 EXP_ACTemperature 0 +8 18:31 END_EXPECTATIONS + +### Thursday ### + +9 08:00 BEGIN_EXPECTATIONS +9 08:00 EnvTemperature 22 +9 08:00 User Guilherme +9 08:00 BodyTemperature 36 +9 08:00 HeartRate 70 +9 08:01 PeopleQuantity 4 +9 08:01 ACTemperature 25 +9 08:01 EXP_ACTemperature 25 +9 08:01 END_EXPECTATIONS + +9 08:30 BEGIN_EXPECTATIONS +9 08:30 User Nobody +9 08:30 BodyTemperature 0 +9 08:30 HeartRate 0 +9 08:30 PeopleQuantity 0 +9 08:30 ACTemperature 0 +9 08:30 EXP_ACTemperature 0 +9 08:31 END_EXPECTATIONS + + +9 18:00 BEGIN_EXPECTATIONS +9 18:00 EnvTemperature 24 +9 18:00 User Guilherme +9 18:00 BodyTemperature 36 +9 18:00 HeartRate 70 +9 18:01 PeopleQuantity 4 +9 18:01 ACTemperature 22 +9 18:01 EXP_ACTemperature 22 +9 18:01 END_EXPECTATIONS + +9 18:30 BEGIN_EXPECTATIONS +9 18:30 User Nobody +9 18:30 BodyTemperature 0 +9 18:30 HeartRate 0 +9 18:30 PeopleQuantity 0 +9 18:30 ACTemperature 0 +9 18:30 EXP_ACTemperature 0 +9 18:31 END_EXPECTATIONS + +### Friday ### + +10 08:00 BEGIN_EXPECTATIONS +10 08:00 EnvTemperature 22 +10 08:00 User Guilherme +10 08:00 BodyTemperature 36 +10 08:00 HeartRate 65 +10 08:01 PeopleQuantity 1 +10 08:01 ACTemperature 22 +10 08:01 EXP_ACTemperature 22 +10 08:01 END_EXPECTATIONS + +10 08:30 BEGIN_EXPECTATIONS +10 08:30 User Nobody +10 08:30 BodyTemperature 0 +10 08:30 HeartRate 0 +10 08:30 PeopleQuantity 0 +10 08:30 ACTemperature 0 +10 08:30 EXP_ACTemperature 0 +10 08:31 END_EXPECTATIONS + + +11 18:00 BEGIN_EXPECTATIONS +11 18:00 EnvTemperature 24 +11 18:00 User Guilherme +11 18:00 BodyTemperature 36 +11 18:00 HeartRate 65 +11 18:01 PeopleQuantity 1 +11 18:01 ACTemperature 24 +11 18:01 EXP_ACTemperature 24 +11 18:01 END_EXPECTATIONS + + +11 18:30 BEGIN_EXPECTATIONS +11 18:30 User Nobody +11 18:30 BodyTemperature 0 +11 18:30 HeartRate 0 +11 18:30 PeopleQuantity 0 +11 18:30 ACTemperature 0 +11 18:30 EXP_ACTemperature 0 +11 18:31 END_EXPECTATIONS + +### Saturday ### + +12 09:00 BEGIN_EXPECTATIONS +12 09:00 EnvTemperature 22 +12 09:00 User Guilherme +12 09:00 BodyTemperature 36 +12 09:00 HeartRate 75 +12 09:01 PeopleQuantity 1 +12 09:01 ACTemperature 26 +12 09:01 EXP_ACTemperature 26 +12 09:01 END_EXPECTATIONS + +12 09:17 BEGIN_EXPECTATIONS +12 09:17 User Nobody +12 09:17 BodyTemperature 0 +12 09:17 HeartRate 0 +12 09:18 PeopleQuantity 0 +12 09:18 ACTemperature 0 +12 09:18 EXP_ACTemperature 0 +12 09:18 END_EXPECTATIONS + +### Sunday ### + +13 21:00 BEGIN_EXPECTATIONS +13 21:00 EnvTemperature 22 +13 21:00 User Guilherme +13 21:00 BodyTemperature 36 +13 21:00 HeartRate 75 +13 21:01 PeopleQuantity 1 +13 21:01 ACTemperature 21 +13 21:01 EXP_ACTemperature 21 + +13 21:18 User Nobody +13 21:18 BodyTemperature 0 +13 21:18 HeartRate 0 +13 21:19 PeopleQuantity 0 +13 21:19 ACTemperature 0 +13 21:19 EXP_ACTemperature 0 +13 21:19 END_EXPECTATIONS + +###Cold weather### +### Monday ### + +14 08:00 BEGIN_EXPECTATIONS +14 08:00 EnvTemperature 10 +14 08:00 User Guilherme +14 08:00 BodyTemperature 36 +14 08:00 HeartRate 74 +14 08:01 PeopleQuantity 1 +14 08:01 ACTemperature 26 +14 08:01 EXP_ACTemperature 26 + +14 08:16 ACTemperature 23 +14 08:16 EXP_ACTemperature 23 +14 08:16 END_EXPECTATIONS + +14 08:30 BEGIN_EXPECTATIONS +14 08:30 User Nobody +14 08:30 BodyTemperature 0 +14 08:30 HeartRate 0 +14 08:30 PeopleQuantity 0 +14 08:30 ACTemperature 0 +14 08:30 EXP_ACTemperature 0 +14 08:31 END_EXPECTATIONS + + +14 18:00 BEGIN_EXPECTATIONS +14 18:00 EnvTemperature 7 +14 18:00 User Guilherme +14 18:00 BodyTemperature 34 +14 18:00 HeartRate 76 +14 18:01 PeopleQuantity 2 +14 18:01 ACTemperature 27 +14 18:01 EXP_ACTemperature 27 +14 18:01 END_EXPECTATIONS + + +14 18:30 BEGIN_EXPECTATIONS +14 18:30 User Nobody +14 18:30 BodyTemperature 0 +14 18:30 HeartRate 0 +14 18:30 PeopleQuantity 0 +14 18:30 ACTemperature 0 +14 18:30 EXP_ACTemperature 0 +14 18:31 END_EXPECTATIONS + +### Tuesday ### + +15 08:00 BEGIN_EXPECTATIONS +15 08:00 EnvTemperature 16 +15 08:00 User Guilherme +15 08:00 BodyTemperature 34 +15 08:00 HeartRate 78 +15 08:01 PeopleQuantity 3 +15 08:01 ACTemperature 26 +15 08:01 EXP_ACTemperature 26 +15 08:01 END_EXPECTATIONS + +15 08:30 BEGIN_EXPECTATIONS +15 08:30 User Nobody +15 08:30 BodyTemperature 0 +15 08:30 HeartRate 0 +15 08:30 PeopleQuantity 0 +15 08:30 ACTemperature 0 +15 08:30 EXP_ACTemperature 0 +15 08:31 END_EXPECTATIONS + + +15 18:00 BEGIN_EXPECTATIONS +15 18:00 EnvTemperature 16 +15 18:00 User Guilherme +15 18:00 BodyTemperature 36 +15 18:00 HeartRate 70 +15 18:01 PeopleQuantity 1 +15 18:01 ACTemperature 25 +15 18:01 EXP_ACTemperature 25 +15 18:01 END_EXPECTATIONS + + +15 18:30 BEGIN_EXPECTATIONS +15 18:30 User Nobody +15 18:30 BodyTemperature 0 +15 18:30 HeartRate 0 +15 18:30 PeopleQuantity 0 +15 18:30 ACTemperature 0 +15 18:30 EXP_ACTemperature 0 +15 18:31 END_EXPECTATIONS + +### Wednesday ### + +16 08:00 BEGIN_EXPECTATIONS +16 08:00 EnvTemperature 22 +16 08:00 User Guilherme +16 08:00 BodyTemperature 36 +16 08:00 HeartRate 70 +16 08:01 PeopleQuantity 1 +16 08:01 ACTemperature 24 +16 08:01 EXP_ACTemperature 24 +16 08:01 END_EXPECTATIONS + +16 08:30 BEGIN_EXPECTATIONS +16 08:30 User Nobody +16 08:30 BodyTemperature 0 +16 08:30 HeartRate 0 +16 08:30 PeopleQuantity 0 +16 08:30 ACTemperature 0 +16 08:30 EXP_ACTemperature 0 +16 08:31 END_EXPECTATIONS + + +16 18:00 BEGIN_EXPECTATIONS +16 18:00 EnvTemperature 8 +16 18:00 User Guilherme +16 18:00 BodyTemperature 33 +16 18:00 HeartRate 79 +16 18:01 PeopleQuantity 2 +16 18:01 ACTemperature 29 +16 18:01 EXP_ACTemperature 29 +16 18:01 END_EXPECTATIONS + + +16 18:30 BEGIN_EXPECTATIONS +16 18:30 User Nobody +16 18:30 BodyTemperature 0 +16 18:30 HeartRate 0 +16 18:30 PeopleQuantity 0 +16 18:30 ACTemperature 0 +16 18:30 EXP_ACTemperature 0 +16 18:31 END_EXPECTATIONS + +### Thursday ### + +17 08:00 BEGIN_EXPECTATIONS +17 08:00 EnvTemperature 22 +17 08:00 User Guilherme +17 08:00 BodyTemperature 36 +17 08:00 HeartRate 70 +17 08:01 PeopleQuantity 1 +17 08:01 ACTemperature 24 +17 08:01 EXP_ACTemperature 24 +17 08:01 END_EXPECTATIONS + +17 08:30 BEGIN_EXPECTATIONS +17 08:30 User Nobody +17 08:30 BodyTemperature 0 +17 08:30 HeartRate 0 +17 08:30 PeopleQuantity 0 +17 08:30 ACTemperature 0 +17 08:30 EXP_ACTemperature 0 +17 08:31 END_EXPECTATIONS + + +17 18:00 BEGIN_EXPECTATIONS +17 18:00 EnvTemperature 8 +17 18:00 User Guilherme +17 18:00 BodyTemperature 33 +17 18:00 HeartRate 79 +17 18:01 PeopleQuantity 2 +17 18:01 ACTemperature 29 +17 18:01 EXP_ACTemperature 29 +17 18:01 END_EXPECTATIONS + + +17 18:30 BEGIN_EXPECTATIONS +17 18:30 User Nobody +17 18:30 BodyTemperature 0 +17 18:30 HeartRate 0 +17 18:30 PeopleQuantity 0 +17 18:30 ACTemperature 0 +17 18:30 EXP_ACTemperature 0 +17 18:31 END_EXPECTATIONS + +### Friday ### + +18 08:00 BEGIN_EXPECTATIONS +18 08:00 EnvTemperature 10 +18 08:00 User Guilherme +18 08:00 BodyTemperature 38 +18 08:00 HeartRate 80 +18 08:01 PeopleQuantity 5 +18 08:01 ACTemperature 24 +18 08:01 EXP_ACTemperature 24 + +18 08:21 ACTemperature 26 +18 08:21 EXP_ACTemperature 26 +18 08:01 END_EXPECTATIONS + +18 08:30 BEGIN_EXPECTATIONS +18 08:30 User Nobody +18 08:30 BodyTemperature 0 +18 08:30 HeartRate 0 +18 08:30 PeopleQuantity 0 +18 08:30 ACTemperature 0 +18 08:30 EXP_ACTemperature 0 +18 08:31 END_EXPECTATIONS + + +18 18:00 BEGIN_EXPECTATIONS +18 18:00 EnvTemperature 14 +18 18:00 User Guilherme +18 18:00 BodyTemperature 36 +18 18:00 HeartRate 70 +18 18:01 PeopleQuantity 1 +18 18:01 ACTemperature 24 +18 18:01 EXP_ACTemperature 24 +18 18:01 END_EXPECTATIONS + + +18 18:30 BEGIN_EXPECTATIONS +18 18:30 User Nobody +18 18:30 BodyTemperature 0 +18 18:30 HeartRate 0 +18 18:30 PeopleQuantity 0 +18 18:30 ACTemperature 0 +18 18:30 EXP_ACTemperature 0 +18 18:31 END_EXPECTATIONS + +### Saturday ### + +19 09:00 BEGIN_EXPECTATIONS +19 09:00 EnvTemperature 12 +19 09:00 User Guilherme +19 09:00 BodyTemperature 34 +19 09:00 HeartRate 61 +19 09:01 PeopleQuantity 1 +19 09:01 ACTemperature 26 +19 09:01 EXP_ACTemperature 26 + +19 09:17 User Nobody +19 09:17 BodyTemperature 0 +19 09:17 HeartRate 0 +19 09:18 PeopleQuantity 0 +19 09:18 ACTemperature 0 +19 09:18 EXP_ACTemperature 0 +19 09:18 END_EXPECTATIONS + +### Sunday ### + +20 21:00 BEGIN_EXPECTATIONS +20 21:00 EnvTemperature 9 +20 21:00 User Guilherme +20 21:00 BodyTemperature 36 +20 21:00 HeartRate 65 +20 21:01 PeopleQuantity 2 +20 21:01 ACTemperature 27 +20 21:01 EXP_ACTemperature 27 + +20 21:18 User Nobody +20 21:18 BodyTemperature 0 +20 21:18 HeartRate 0 +20 21:19 PeopleQuantity 0 +20 21:19 ACTemperature 0 +20 21:19 EXP_ACTemperature 0 +20 21:01 END_EXPECTATIONS diff --git a/simulator/simulations/corner_case.annoy.data b/simulator/simulations/corner_case.annoy.data new file mode 100644 index 0000000..ad24ff6 --- /dev/null +++ b/simulator/simulations/corner_case.annoy.data @@ -0,0 +1,59 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Test created to check how annoying is sml when user decides to have an output +#with a value different from the value learned for a short time +# +#Initial Scenario +#Day 0, 1, 2 learn basic rules +0 0:00 in i0 +0 0:00 out o0 +0 0:00 EXP_out o0 + +1 0:00 in i1 +1 0:00 out o1 +1 0:00 EXP_out o1 + +#Day 3 Annoy user? +2 0:00 in i0 +2 0:00 out o0 +2 0:00 EXP_out o0 + +2 1:00 BEGIN_EXPECTATIONS +2 1:00 in i1 #User gets into a room +2 1:00 out o0 #The user don't turn the lights on +2 1:00 EXP_out o1 #It is expected that sml turns the lights on +2 1:00 END_EXPECTATIONS + +2 1:01 BEGIN_EXPECTATIONS +2 1:01 out o0 #User turns the light off +2 1:01 EXP_out o0 #Don't fight with user for the next minutes +2 1:10 END_EXPECTATIONS + diff --git a/simulator/simulations/corner_case.change_routine.data b/simulator/simulations/corner_case.change_routine.data new file mode 100644 index 0000000..b6be8aa --- /dev/null +++ b/simulator/simulations/corner_case.change_routine.data @@ -0,0 +1,121 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Test if sml is learning that a routine changes +# +#Initial Scenario +#Day 0, learn basic rules +0 0:00 in i0 +0 0:00 out o0 +0 0:00 EXP_out o0 + +0 1:00 in i1 +0 1:00 out o1 +0 1:00 EXP_out o1 + +0 2:00 in i2 +0 2:00 out o2 +0 2:00 EXP_out o2 + +0 3:00 in i3 +0 3:00 out o3 +0 3:00 EXP_out o3 + +#Day 1, 2 and 3 Change Routine for 3 days +1 0:00 in i0 +1 0:00 out o1 +1 0:00 EXP_out o1 + +1 1:00 in i1 +1 1:00 out o2 +1 1:00 EXP_out o2 + +1 2:00 in i2 +1 2:00 out o3 +1 2:00 EXP_out o3 + +1 3:00 in i3 +1 3:00 out o3 +1 3:00 EXP_out o3 + +2 0:00 in i0 +2 0:00 out o1 +2 0:00 EXP_out o1 + +2 1:00 in i1 +2 1:00 out o2 +2 1:00 EXP_out o2 + +2 2:00 in i2 +2 2:00 out o3 +2 2:00 EXP_out o3 + +2 3:00 in i3 +2 3:00 out o3 +2 3:00 EXP_out o3 + +3 0:00 in i0 +3 0:00 out o1 +3 0:00 EXP_out o1 + +3 1:00 in i1 +3 1:00 out o2 +3 1:00 EXP_out o2 + +3 2:00 in i2 +3 2:00 out o3 +3 2:00 EXP_out o3 + +3 3:00 in i3 +3 3:00 out o3 +3 3:00 EXP_out o3 + +#Day 4 Verify test changes +# +4 4:00 BEGIN_EXPECTATIONS +4 4:00 in i0 +4 4:00 out o0 +4 4:00 EXP_out o1 +4 4:00 END_EXPECTATIONS +4 4:01 out o1 + +4 5:00 BEGIN_EXPECTATIONS +4 5:00 in i1 +4 5:00 out o1 +4 5:00 EXP_out o2 +4 5:00 END_EXPECTATIONS +4 5:01 out o2 + +4 6:00 BEGIN_EXPECTATIONS +4 6:00 in i2 +4 6:00 out o2 +4 6:00 EXP_out o3 +4 6:00 END_EXPECTATIONS +4 6:01 out o3 diff --git a/simulator/simulations/corner_case.conf b/simulator/simulations/corner_case.conf new file mode 100644 index 0000000..b302dcb --- /dev/null +++ b/simulator/simulations/corner_case.conf @@ -0,0 +1,56 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config +# As simple as possible discrete input/output file used to tests corner cases +# Time and Weekday inputs are disabled + +# a day will be splited in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 5 +ENABLE_TIME_INPUT 0 +ENABLE_WEEKDAY_INPUT 0 + +# Inputs + +INPUT in 0 3 +TERM i0 0 0 +TERM i1 1 1 +TERM i2 2 2 +TERM i3 3 3 + +# Outputs + +OUTPUT out 0 3 +TERM o0 0 0 +TERM o1 1 1 +TERM o2 2 2 +TERM o3 3 3 diff --git a/simulator/simulations/corner_case.extrapolate.data b/simulator/simulations/corner_case.extrapolate.data new file mode 100644 index 0000000..63ada9b --- /dev/null +++ b/simulator/simulations/corner_case.extrapolate.data @@ -0,0 +1,51 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Check if sml learns to extrapolate when output is constant. +# +#Initial Scenario +#Day 0, learn basic rules +0 0:00 in i0 +0 0:00 out o0 +0 0:00 EXP_out o0 + +0 1:00 in i1 +0 1:00 out o0 +0 1:00 EXP_out o0 + +0 2:00 in i2 +0 2:00 out o0 +0 2:00 EXP_out o0 + +0 3:00 BEGIN_EXPECTATIONS +0 3:00 in i3 +0 3:00 out o3 +0 3:00 EXP_out o0 +0 3:00 END_EXPECTATIONS diff --git a/simulator/simulations/corner_case.extrapolate.linear.data b/simulator/simulations/corner_case.extrapolate.linear.data new file mode 100644 index 0000000..a059327 --- /dev/null +++ b/simulator/simulations/corner_case.extrapolate.linear.data @@ -0,0 +1,52 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Check if sml knows how to extrapolate outputs when values are linear +#Maybe this kind of extrapolation is not useful in real life examples +# +#Initial Scenario +#Day 0, learn basic rules +0 0:00 in i0 +0 0:00 out o0 +0 0:00 EXP_out o0 + +0 1:00 in i1 +0 1:00 out o1 +0 1:00 EXP_out o1 + +0 2:00 in i2 +0 2:00 out o2 +0 2:00 EXP_out o2 + +0 3:00 BEGIN_EXPECTATIONS +0 3:00 in i3 +0 3:00 out o2 +0 3:00 EXP_out o3 +0 3:00 END_EXPECTATIONS diff --git a/simulator/simulations/corner_case.simple.data b/simulator/simulations/corner_case.simple.data new file mode 100644 index 0000000..01a8b3a --- /dev/null +++ b/simulator/simulations/corner_case.simple.data @@ -0,0 +1,107 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Just a simple test to check if sml is working +# +#Initial Scenario +#Day 1, learn basic rules +0 0:00 in i0 +0 0:00 out o0 +0 0:00 EXP_out o0 + +0 1:00 in i1 +0 1:00 out o1 +0 1:00 EXP_out o1 + +0 2:00 in i2 +0 2:00 out o2 +0 2:00 EXP_out o2 + +0 3:00 in i0 +0 3:00 out o0 +0 3:00 EXP_out o0 + +#Day 2, test if rules were learned + +1 1:00 BEGIN_EXPECTATIONS +1 1:00 in i1 +1 1:00 out o1 +1 1:00 EXP_out o1 +1 1:00 END_EXPECTATIONS + +1 2:00 in i1 +1 2:00 out o1 +1 2:00 EXP_out o1 + +1 3:00 BEGIN_EXPECTATIONS +1 3:00 in i0 +1 3:00 out o0 +1 3:00 EXP_out o0 +1 3:00 END_EXPECTATIONS + +1 4:00 in i1 +1 4:00 out o1 +1 4:00 EXP_out o1 + +1 5:00 BEGIN_EXPECTATIONS +1 5:00 in i2 +1 5:00 out o2 +1 5:00 EXP_out o2 +1 5:00 END_EXPECTATIONS + +1 8:00 BEGIN_EXPECTATIONS +1 8:00 in i1 +1 8:00 out o0 +1 8:00 EXP_out o1 +1 8:00 END_EXPECTATIONS + +1 9:00 in i1 +1 9:00 out o1 +1 9:00 EXP_out o1 + +1 10:00 BEGIN_EXPECTATIONS +1 10:00 in i0 +1 10:00 out o1 +1 10:00 EXP_out o0 +1 10:00 END_EXPECTATIONS + +1 11:00 in i1 +1 11:00 out o1 +1 11:00 EXP_out o1 + +1 12:00 BEGIN_EXPECTATIONS +1 12:00 in i2 +1 12:00 out o0 +1 12:00 EXP_out o2 +1 12:00 END_EXPECTATIONS + +1 20:00 in i0 +1 20:00 out o0 +1 20:00 EXP_out o0 diff --git a/simulator/simulations/corner_case_disable.conf b/simulator/simulations/corner_case_disable.conf new file mode 100644 index 0000000..4702293 --- /dev/null +++ b/simulator/simulations/corner_case_disable.conf @@ -0,0 +1,68 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config +# As simple as possible discrete input/output file used to tests corner cases +# Time and Weekday inputs are disabled + +# a day will be splited in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 3 +ENABLE_TIME_INPUT 0 +ENABLE_WEEKDAY_INPUT 0 + +# Inputs + +INPUT in 0 3 +TERM i0 0 0 +TERM i1 1 1 +TERM i2 2 2 +TERM i3 3 3 + +INPUT in2 0 3 +TERM i0 0 0 +TERM i1 1 1 +TERM i2 2 2 +TERM i3 3 3 + +# Outputs + +OUTPUT out 0 3 +TERM o0 0 0 +TERM o1 1 1 +TERM o2 2 2 +TERM o3 3 3 + +OUTPUT out2 0 3 +TERM o0 0 0 +TERM o1 1 1 +TERM o2 2 2 +TERM o3 3 3 diff --git a/simulator/simulations/corner_case_disable.test1.data b/simulator/simulations/corner_case_disable.test1.data new file mode 100644 index 0000000..fd83f87 --- /dev/null +++ b/simulator/simulations/corner_case_disable.test1.data @@ -0,0 +1,194 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Just a simple test to check if sml is working +# +#Initial Scenario +#Day 0, learn basic rules +##i2 is irrelevant so disabling it shouldn't affect results +0 0:00 in i0 +0 0:00 in2 i0 +0 0:00 out o0 +0 0:00 out2 o0 + +0 1:00 in2 i1 +0 2:00 in2 i2 +0 3:00 in2 i3 + +0 4:00 in i1 +0 4:00 in2 i0 +0 4:00 out o1 +0 4:00 out2 o1 + +0 5:00 in2 i1 +0 6:00 in2 i2 +0 7:00 in2 i3 + +0 8:00 in i2 +0 8:00 in2 i0 +0 8:00 out o2 +0 8:00 out2 o2 + +0 9:00 in2 i1 +0 10:00 in2 i2 +0 11:00 in2 i3 + +0 12:00 in i0 +0 12:00 in2 i0 +0 12:00 out o0 +0 12:00 out2 o0 + +#Day 1, test if rules were learned +1 0:00 in i1 +1 0:00 out o1 +1 0:00 out2 o1 + +1 1:00 in i0 +1 1:00 EXP_out o0 +1 1:00 EXP_out2 o0 + +1 1:00 BEGIN_EXPECTATIONS +1 1:00 in2 i0 +1 1:00 out o1 +1 1:00 out2 o1 +1 1:00 END_EXPECTATIONS +1 1:01 out o0 +1 1:01 out2 o0 + +1 2:00 BEGIN_EXPECTATIONS +1 2:00 in2 i1 +1 2:00 out o1 +1 2:00 out2 o1 +1 2:00 END_EXPECTATIONS +1 2:01 out o0 +1 2:01 out2 o0 + +1 3:00 BEGIN_EXPECTATIONS +1 3:00 in2 i2 +1 3:00 out o1 +1 3:00 out2 o1 +1 3:00 END_EXPECTATIONS +1 3:01 out o0 +1 3:01 out2 o0 + +1 4:00 BEGIN_EXPECTATIONS +1 4:00 in2 i3 +1 4:00 out o1 +1 4:00 out2 o1 +1 4:00 END_EXPECTATIONS +1 4:01 out o0 +1 4:01 out2 o0 + +#Day 1, i2 disabled +1 10:00 in2 [DISABLED] + +1 10:00 in i1 +1 10:00 out o1 +1 10:00 out2 o1 + +1 11:00 in i0 +1 11:00 EXP_out o0 +1 11:00 EXP_out2 o0 + +1 11:00 BEGIN_EXPECTATIONS +1 11:00 in2 i0 +1 11:00 out o1 +1 11:00 out2 o1 +1 11:00 END_EXPECTATIONS +1 11:01 out o0 +1 11:01 out2 o0 + +1 12:00 BEGIN_EXPECTATIONS +1 12:00 in2 i1 +1 12:00 out o1 +1 12:00 out2 o1 +1 12:00 END_EXPECTATIONS +1 12:01 out o0 +1 12:01 out2 o0 + +1 13:00 BEGIN_EXPECTATIONS +1 13:00 in2 i2 +1 13:00 out o1 +1 13:00 out2 o1 +1 13:00 END_EXPECTATIONS +1 13:01 out o0 +1 13:01 out2 o0 + +1 14:00 BEGIN_EXPECTATIONS +1 14:00 in2 i3 +1 14:00 out o1 +1 14:00 out2 o1 +1 14:00 END_EXPECTATIONS +1 14:01 out o0 +1 14:01 out2 o0 + +#Day 2, Same as day 1, but with i2 enabled and out2 disabled +2 0:00 in2 [ENABLED] +2 0:00 out2 [DISABLED] + +2 0:00 in i1 +2 0:00 out o1 +2 0:00 out2 o1 + +2 1:00 in i0 +2 1:00 EXP_out o0 +2 1:00 EXP_out2 o0 + +2 1:00 BEGIN_EXPECTATIONS +2 1:00 in2 i0 +2 1:00 out o1 +2 1:00 out2 o1 +2 1:00 END_EXPECTATIONS +2 1:01 out o0 +2 1:01 out2 o0 + +2 2:00 BEGIN_EXPECTATIONS +2 2:00 in2 i1 +2 2:00 out o1 +2 2:00 out2 o1 +2 2:00 END_EXPECTATIONS +2 2:01 out o0 +2 2:01 out2 o0 + +2 3:00 BEGIN_EXPECTATIONS +2 3:00 in2 i2 +2 3:00 out o1 +2 3:00 out2 o1 +2 3:00 END_EXPECTATIONS +2 3:01 out o0 +2 3:01 out2 o0 + +2 4:00 BEGIN_EXPECTATIONS +2 4:00 in2 i3 +2 4:00 out o1 +2 4:00 out2 o1 +2 4:00 END_EXPECTATIONS +2 4:01 out o0 +2 4:01 out2 o0 diff --git a/simulator/simulations/corner_case_time.conf b/simulator/simulations/corner_case_time.conf new file mode 100644 index 0000000..cc7db3a --- /dev/null +++ b/simulator/simulations/corner_case_time.conf @@ -0,0 +1,56 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config +# As simple as possible discrete input/output file used to tests corner cases +# Weekday input is disabled + +# a day will be splited in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 4 +ENABLE_TIME_INPUT 1 +ENABLE_WEEKDAY_INPUT 0 + +# Inputs + +INPUT in 0 3 +TERM i0 0 0 +TERM i1 1 1 +TERM i2 2 2 +TERM i3 3 3 + +# Outputs + +OUTPUT out 0 3 +TERM o0 0 0 +TERM o1 1 1 +TERM o2 2 2 +TERM o3 3 3 diff --git a/simulator/simulations/corner_case_time.extrapolate.data b/simulator/simulations/corner_case_time.extrapolate.data new file mode 100644 index 0000000..875b6a9 --- /dev/null +++ b/simulator/simulations/corner_case_time.extrapolate.data @@ -0,0 +1,62 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Check if sml learns to extrapolate output is constant in different times. +#I.E. If it is off in the morning and in the afternoon, lets assume it is off +#at night. +# +#Initial Scenario +#Day 0 +0 0:00 in i0 +0 0:00 out o0 +0 1:00 in i1 +0 1:00 out o1 +0 2:00 in i0 +0 2:00 out o0 +0 3:00 in i1 +0 3:00 out o1 +0 4:00 in i0 +0 4:00 out o0 +0 5:00 in i1 +0 5:00 out o1 + +0 6:00 BEGIN_EXPECTATIONS +0 6:00 in i0 +0 6:00 out o3 +0 6:00 EXP_out o0 +0 6:00 END_EXPECTATIONS +0 6:01 out o0 + +0 7:00 BEGIN_EXPECTATIONS +0 7:00 in i1 +0 7:00 out o3 +0 7:00 EXP_out o1 +0 7:00 END_EXPECTATIONS +0 7:01 out o1 diff --git a/simulator/simulations/corner_case_time.learn.data b/simulator/simulations/corner_case_time.learn.data new file mode 100644 index 0000000..0247428 --- /dev/null +++ b/simulator/simulations/corner_case_time.learn.data @@ -0,0 +1,76 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Initial Scenario +# +#Day 0, 1, 2 - learn +0 0:00 in i0 +0 0:00 out o0 +0 5:00 out o1 +0 10:00 out o2 + +1 0:00 out o0 +1 5:00 out o1 +1 10:00 out o2 + +2 0:00 out o0 +2 5:00 out o1 +2 10:00 out o2 + +#Day 3 - Test +3 0:00 BEGIN_EXPECTATIONS +3 0:00 out o3 +3 0:00 EXP_out o0 +3 0:00 END_EXPECTATIONS +3 0:01 out o0 + +3 2:10 BEGIN_EXPECTATIONS +3 2:10 EXP_out o0 +3 2:10 END_EXPECTATIONS + +3 5:00 BEGIN_EXPECTATIONS +3 5:00 out o3 +3 5:00 EXP_out o1 +3 5:00 END_EXPECTATIONS +3 5:01 out o1 + +3 7:37 BEGIN_EXPECTATIONS +3 7:37 EXP_out o1 +3 7:37 END_EXPECTATIONS + +3 10:00 BEGIN_EXPECTATIONS +3 10:00 out o3 +3 10:00 EXP_out o2 +3 10:00 END_EXPECTATIONS +3 10:01 out o2 + +3 19:20 BEGIN_EXPECTATIONS +3 19:20 EXP_out o2 +3 19:20 END_EXPECTATIONS diff --git a/simulator/simulations/corner_case_weekday.conf b/simulator/simulations/corner_case_weekday.conf new file mode 100644 index 0000000..26906a9 --- /dev/null +++ b/simulator/simulations/corner_case_weekday.conf @@ -0,0 +1,56 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config +# As simple as possible discrete input/output file used to tests corner cases +# Time input is disabled + +# a day will be splited in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 10 +ENABLE_TIME_INPUT 0 +ENABLE_WEEKDAY_INPUT 1 + +# Inputs + +INPUT in 0 3 +TERM i0 0 0 +TERM i1 1 1 +TERM i2 2 2 +TERM i3 3 3 + +# Outputs + +OUTPUT out 0 3 +TERM o0 0 0 +TERM o1 1 1 +TERM o2 2 2 +TERM o3 3 3 diff --git a/simulator/simulations/corner_case_weekday.extrapolate.data b/simulator/simulations/corner_case_weekday.extrapolate.data new file mode 100644 index 0000000..0e467f6 --- /dev/null +++ b/simulator/simulations/corner_case_weekday.extrapolate.data @@ -0,0 +1,67 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Check if sml learns to extrapolate output is constant in different days of week +#I.E. If it is off on mondays, tuesdays and wednesday, let's assume it is off +#on Thursdays +# +#Initial Scenario +#Day 0 +0 0:00 in i0 +0 0:00 out o0 +0 10:00 in i1 +0 10:00 out o1 + +#Day 1 +1 0:00 in i0 +1 0:00 out o0 +1 10:00 in i1 +1 10:00 out o1 + +#Day 2 +2 0:00 in i0 +2 0:00 out o0 +2 10:00 in i1 +2 10:00 out o1 + +#Day 3 +3 0:00 BEGIN_EXPECTATIONS +3 0:00 in i0 +3 0:00 out o3 +3 0:00 EXP_out o0 +3 0:00 END_EXPECTATIONS +3 0:01 out o0 + +3 2:00 BEGIN_EXPECTATIONS +3 2:00 in i1 +3 2:00 out o3 +3 2:00 EXP_out o1 +3 2:00 END_EXPECTATIONS +3 2:01 out o1 diff --git a/simulator/simulations/corner_case_weekday.extrapolate2.data b/simulator/simulations/corner_case_weekday.extrapolate2.data new file mode 100644 index 0000000..57c134b --- /dev/null +++ b/simulator/simulations/corner_case_weekday.extrapolate2.data @@ -0,0 +1,57 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Initial Scenario +#Week 0 - Learn +0 0:00 in i0 + +0 0:00 out o0 +1 0:00 out o1 +2 0:00 out o2 + +#Week 2 - Test +0 0:00 in i1 +7 0:00 BEGIN_EXPECTATIONS +7 0:00 out o3 +7 0:00 EXP_out o0 +7 0:00 END_EXPECTATIONS +7 0:01 out o0 + +8 0:00 BEGIN_EXPECTATIONS +8 0:00 out o3 +8 0:00 EXP_out o1 +8 0:00 END_EXPECTATIONS +8 0:01 out o1 + +9 0:00 BEGIN_EXPECTATIONS +9 0:00 out o3 +9 0:00 EXP_out o2 +9 0:00 END_EXPECTATIONS +9 0:01 out o2 diff --git a/simulator/simulations/corner_case_weekday.learn.data b/simulator/simulations/corner_case_weekday.learn.data new file mode 100644 index 0000000..2d5058d --- /dev/null +++ b/simulator/simulations/corner_case_weekday.learn.data @@ -0,0 +1,58 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Initial Scenario +# Verify if sml is able to learn a different scenario for each day of week, +# independent of other inputs +#Week 0 - Learn +0 0:00 in i0 + +0 0:00 out o0 +1 0:00 out o1 +2 0:00 out o2 + +#Week 2 - Test +7 0:00 BEGIN_EXPECTATIONS +7 0:00 out o3 +7 0:00 EXP_out o0 +7 0:00 END_EXPECTATIONS +7 0:01 out o0 + +8 0:00 BEGIN_EXPECTATIONS +8 0:00 out o3 +8 0:00 EXP_out o1 +8 0:00 END_EXPECTATIONS +8 0:01 out o1 + +9 0:00 BEGIN_EXPECTATIONS +9 0:00 out o3 +9 0:00 EXP_out o2 +9 0:00 END_EXPECTATIONS +9 0:01 out o2 diff --git a/simulator/simulations/garden.conf b/simulator/simulations/garden.conf new file mode 100644 index 0000000..22a3580 --- /dev/null +++ b/simulator/simulations/garden.conf @@ -0,0 +1,49 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config + +# a day will be splited in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 28 #4 weeks + +# Inputs +# Block times per day and weekdays are created by default + +#Temperature in C +INPUT Temperature -10 55 +#% of water in soil +INPUT Moisture 0 50 +# Around 1~2 is ok. 0 is too little and 4 or more is too much +INPUT Fertilizer 0 10 +INPUT Light 0 100 + +OUTPUT WaterVolume 0 100 diff --git a/simulator/simulations/garden.mentha.data b/simulator/simulations/garden.mentha.data new file mode 100644 index 0000000..39396da --- /dev/null +++ b/simulator/simulations/garden.mentha.data @@ -0,0 +1,6282 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#### Week 0 #### +### Monday ### +0 0:00 Temperature 24 +0 0:00 WaterVolume 0 +0 0:00 Light 10 +0 0:00 EXP_WaterVolume 0 +0 0:00 Moisture 30 +0 0:00 Fertilizer 1.8 + +0 1:00 Temperature 24 +0 1:00 WaterVolume 40 +0 1:00 Light 11 +0 1:00 EXP_WaterVolume 40 +0 1:00 Moisture 25 +0 1:00 Fertilizer 2.0 + +0 2:00 Temperature 24 +0 2:00 WaterVolume 40 +0 2:00 Light 13 +0 2:00 EXP_WaterVolume 40 +0 2:00 Moisture 28 +0 2:00 Fertilizer 2.8 + +0 3:00 Temperature 24 +0 3:00 WaterVolume 40 +0 3:00 Light 15 +0 3:00 EXP_WaterVolume 40 +0 3:00 Moisture 27 +0 3:00 Fertilizer 1.9 + +0 4:00 Temperature 25 +0 4:00 WaterVolume 40 +0 4:00 Light 20 +0 4:00 EXP_WaterVolume 40 +0 4:00 Moisture 28 +0 4:00 Fertilizer 2.8 + +0 5:00 Temperature 25 +0 5:00 WaterVolume 40 +0 5:00 Light 25 +0 5:00 EXP_WaterVolume 40 +0 5:00 Moisture 27 +0 5:00 Fertilizer 1.3 + +0 6:00 Temperature 26 +0 6:00 WaterVolume 40 +0 6:00 Light 40 +0 6:00 EXP_WaterVolume 40 +0 6:00 Moisture 27 +0 6:00 Fertilizer 2.5 + +0 7:00 Temperature 26 +0 7:00 WaterVolume 0 +0 7:00 Light 45 +0 7:00 EXP_WaterVolume 0 +0 7:00 Moisture 30 +0 7:00 Fertilizer 2.0 + +0 8:00 Temperature 26 +0 8:00 WaterVolume 40 +0 8:00 Light 50 +0 8:00 EXP_WaterVolume 40 +0 8:00 Moisture 25 +0 8:00 Fertilizer 2.3 + +0 9:00 Temperature 26 +0 9:00 WaterVolume 40 +0 9:00 Light 50 +0 9:00 EXP_WaterVolume 40 +0 9:00 Moisture 26 +0 9:00 Fertilizer 2.1 + +0 10:00 Temperature 26 +0 10:00 WaterVolume 40 +0 10:00 Light 50 +0 10:00 EXP_WaterVolume 40 +0 10:00 Moisture 28 +0 10:00 Fertilizer 2.6 + +0 11:00 Temperature 27 +0 11:00 WaterVolume 40 +0 11:00 Light 60 +0 11:00 EXP_WaterVolume 40 +0 11:00 Moisture 29 +0 11:00 Fertilizer 1.6 + +0 12:00 Temperature 28 +0 12:00 WaterVolume 0 +0 12:00 Light 80 +0 12:00 EXP_WaterVolume 0 +0 12:00 Moisture 33 +0 12:00 Fertilizer 1.8 + +0 13:00 Temperature 27 +0 13:00 WaterVolume 0 +0 13:00 Light 70 +0 13:00 EXP_WaterVolume 0 +0 13:00 Moisture 32 +0 13:00 Fertilizer 2.4 + +0 14:00 Temperature 27 +0 14:00 WaterVolume 40 +0 14:00 Light 70 +0 14:00 EXP_WaterVolume 40 +0 14:00 Moisture 29 +0 14:00 Fertilizer 1.8 + +0 15:00 Temperature 27 +0 15:00 WaterVolume 0 +0 15:00 Light 70 +0 15:00 EXP_WaterVolume 0 +0 15:00 Moisture 50 +0 15:00 Fertilizer 2.7 + +0 16:00 Temperature 27 +0 16:00 WaterVolume 0 +0 16:00 Light 65 +0 16:00 EXP_WaterVolume 0 +0 16:00 Moisture 49 +0 16:00 Fertilizer 1.7 + +0 17:00 Temperature 27 +0 17:00 WaterVolume 0 +0 17:00 Light 60 +0 17:00 EXP_WaterVolume 0 +0 17:00 Moisture 44 +0 17:00 Fertilizer 1.9 + +0 18:00 Temperature 26 +0 18:00 WaterVolume 0 +0 18:00 Light 50 +0 18:00 EXP_WaterVolume 0 +0 18:00 Moisture 40 +0 18:00 Fertilizer 2.0 + +0 19:00 Temperature 25 +0 19:00 WaterVolume 0 +0 19:00 Light 30 +0 19:00 EXP_WaterVolume 0 +0 19:00 Moisture 40 +0 19:00 Fertilizer 1.6 + +0 20:00 Temperature 24 +0 20:00 WaterVolume 0 +0 20:00 Light 10 +0 20:00 EXP_WaterVolume 0 +0 20:00 Moisture 40 +0 20:00 Fertilizer 2.3 + +0 21:00 Temperature 24 +0 21:00 WaterVolume 0 +0 21:00 Light 10 +0 21:00 EXP_WaterVolume 0 +0 21:00 Moisture 36 +0 21:00 Fertilizer 2.2 + +0 22:00 Temperature 24 +0 22:00 WaterVolume 0 +0 22:00 Light 10 +0 22:00 EXP_WaterVolume 0 +0 22:00 Moisture 34 +0 22:00 Fertilizer 1.5 + +0 23:00 Temperature 24 +0 23:00 WaterVolume 0 +0 23:00 Light 10 +0 23:00 EXP_WaterVolume 0 +0 23:00 Moisture 30 +0 23:00 Fertilizer 2.0 + +### Tuesday ### +1 0:00 Temperature 19 +1 0:00 WaterVolume 0 +1 0:00 Light 10 +1 0:00 EXP_WaterVolume 0 +1 0:00 Moisture 30 +1 0:00 Fertilizer 1.4 + +1 1:00 Temperature 19 +1 1:00 WaterVolume 40 +1 1:00 Light 11 +1 1:00 EXP_WaterVolume 40 +1 1:00 Moisture 26 +1 1:00 Fertilizer 1.3 + +1 2:00 Temperature 19 +1 2:00 WaterVolume 40 +1 2:00 Light 13 +1 2:00 EXP_WaterVolume 40 +1 2:00 Moisture 25 +1 2:00 Fertilizer 2.0 + +1 3:00 Temperature 19 +1 3:00 WaterVolume 40 +1 3:00 Light 15 +1 3:00 EXP_WaterVolume 40 +1 3:00 Moisture 29 +1 3:00 Fertilizer 1.3 + +1 4:00 Temperature 20 +1 4:00 WaterVolume 0 +1 4:00 Light 20 +1 4:00 EXP_WaterVolume 0 +1 4:00 Moisture 31 +1 4:00 Fertilizer 2.4 + +1 5:00 Temperature 20 +1 5:00 WaterVolume 0 +1 5:00 Light 25 +1 5:00 EXP_WaterVolume 0 +1 5:00 Moisture 31 +1 5:00 Fertilizer 1.3 + +1 6:00 Temperature 21 +1 6:00 WaterVolume 0 +1 6:00 Light 40 +1 6:00 EXP_WaterVolume 0 +1 6:00 Moisture 31 +1 6:00 Fertilizer 1.7 + +1 7:00 Temperature 21 +1 7:00 WaterVolume 0 +1 7:00 Light 45 +1 7:00 EXP_WaterVolume 0 +1 7:00 Moisture 30 +1 7:00 Fertilizer 2.9 + +1 8:00 Temperature 21 +1 8:00 WaterVolume 0 +1 8:00 Light 50 +1 8:00 EXP_WaterVolume 0 +1 8:00 Moisture 30 +1 8:00 Fertilizer 2.7 + +1 9:00 Temperature 21 +1 9:00 WaterVolume 0 +1 9:00 Light 50 +1 9:00 EXP_WaterVolume 0 +1 9:00 Moisture 30 +1 9:00 Fertilizer 1.6 + +1 10:00 Temperature 21 +1 10:00 WaterVolume 40 +1 10:00 Light 50 +1 10:00 EXP_WaterVolume 40 +1 10:00 Moisture 26 +1 10:00 Fertilizer 1.0 + +1 11:00 Temperature 22 +1 11:00 WaterVolume 0 +1 11:00 Light 60 +1 11:00 EXP_WaterVolume 0 +1 11:00 Moisture 30 +1 11:00 Fertilizer 2.7 + +1 12:00 Temperature 23 +1 12:00 WaterVolume 0 +1 12:00 Light 80 +1 12:00 EXP_WaterVolume 0 +1 12:00 Moisture 30 +1 12:00 Fertilizer 2.3 + +1 13:00 Temperature 22 +1 13:00 WaterVolume 40 +1 13:00 Light 70 +1 13:00 EXP_WaterVolume 40 +1 13:00 Moisture 27 +1 13:00 Fertilizer 1.0 + +1 14:00 Temperature 22 +1 14:00 WaterVolume 40 +1 14:00 Light 70 +1 14:00 EXP_WaterVolume 40 +1 14:00 Moisture 28 +1 14:00 Fertilizer 2.4 + +1 15:00 Temperature 22 +1 15:00 WaterVolume 0 +1 15:00 Light 70 +1 15:00 EXP_WaterVolume 0 +1 15:00 Moisture 30 +1 15:00 Fertilizer 2.3 + +1 16:00 Temperature 22 +1 16:00 WaterVolume 40 +1 16:00 Light 65 +1 16:00 EXP_WaterVolume 40 +1 16:00 Moisture 27 +1 16:00 Fertilizer 1.9 + +1 17:00 Temperature 22 +1 17:00 WaterVolume 0 +1 17:00 Light 60 +1 17:00 EXP_WaterVolume 0 +1 17:00 Moisture 30 +1 17:00 Fertilizer 2.8 + +1 18:00 Temperature 21 +1 18:00 WaterVolume 40 +1 18:00 Light 50 +1 18:00 EXP_WaterVolume 40 +1 18:00 Moisture 27 +1 18:00 Fertilizer 1.1 + +1 19:00 Temperature 20 +1 19:00 WaterVolume 40 +1 19:00 Light 30 +1 19:00 EXP_WaterVolume 40 +1 19:00 Moisture 28 +1 19:00 Fertilizer 1.3 + +1 20:00 Temperature 19 +1 20:00 WaterVolume 0 +1 20:00 Light 10 +1 20:00 EXP_WaterVolume 0 +1 20:00 Moisture 32 +1 20:00 Fertilizer 2.3 + +1 21:00 Temperature 19 +1 21:00 WaterVolume 0 +1 21:00 Light 10 +1 21:00 EXP_WaterVolume 0 +1 21:00 Moisture 32 +1 21:00 Fertilizer 2.3 + +1 22:00 Temperature 19 +1 22:00 WaterVolume 0 +1 22:00 Light 10 +1 22:00 EXP_WaterVolume 0 +1 22:00 Moisture 32 +1 22:00 Fertilizer 1.5 + +1 23:00 Temperature 19 +1 23:00 WaterVolume 40 +1 23:00 Light 10 +1 23:00 EXP_WaterVolume 40 +1 23:00 Moisture 29 +1 23:00 Fertilizer 2.2 + +### Wednesday ### +2 0:00 Temperature 23 +2 0:00 WaterVolume 40 +2 0:00 Light 10 +2 0:00 EXP_WaterVolume 40 +2 0:00 Moisture 29 +2 0:00 Fertilizer 1.5 + +2 1:00 Temperature 23 +2 1:00 WaterVolume 0 +2 1:00 Light 11 +2 1:00 EXP_WaterVolume 0 +2 1:00 Moisture 30 +2 1:00 Fertilizer 2.9 + +2 2:00 Temperature 23 +2 2:00 WaterVolume 40 +2 2:00 Light 13 +2 2:00 EXP_WaterVolume 40 +2 2:00 Moisture 25 +2 2:00 Fertilizer 2.4 + +2 3:00 Temperature 23 +2 3:00 WaterVolume 40 +2 3:00 Light 15 +2 3:00 EXP_WaterVolume 40 +2 3:00 Moisture 25 +2 3:00 Fertilizer 2.0 + +2 4:00 Temperature 24 +2 4:00 WaterVolume 40 +2 4:00 Light 20 +2 4:00 EXP_WaterVolume 40 +2 4:00 Moisture 26 +2 4:00 Fertilizer 1.5 + +2 5:00 Temperature 24 +2 5:00 WaterVolume 0 +2 5:00 Light 25 +2 5:00 EXP_WaterVolume 0 +2 5:00 Moisture 30 +2 5:00 Fertilizer 2.6 + +2 6:00 Temperature 25 +2 6:00 WaterVolume 40 +2 6:00 Light 40 +2 6:00 EXP_WaterVolume 40 +2 6:00 Moisture 26 +2 6:00 Fertilizer 1.0 + +2 7:00 Temperature 25 +2 7:00 WaterVolume 40 +2 7:00 Light 45 +2 7:00 EXP_WaterVolume 40 +2 7:00 Moisture 26 +2 7:00 Fertilizer 2.8 + +2 8:00 Temperature 25 +2 8:00 WaterVolume 40 +2 8:00 Light 50 +2 8:00 EXP_WaterVolume 40 +2 8:00 Moisture 27 +2 8:00 Fertilizer 1.8 + +2 9:00 Temperature 25 +2 9:00 WaterVolume 0 +2 9:00 Light 50 +2 9:00 EXP_WaterVolume 0 +2 9:00 Moisture 30 +2 9:00 Fertilizer 1.5 + +2 10:00 Temperature 25 +2 10:00 WaterVolume 40 +2 10:00 Light 50 +2 10:00 EXP_WaterVolume 40 +2 10:00 Moisture 27 +2 10:00 Fertilizer 2.0 + +2 11:00 Temperature 26 +2 11:00 WaterVolume 40 +2 11:00 Light 60 +2 11:00 EXP_WaterVolume 40 +2 11:00 Moisture 28 +2 11:00 Fertilizer 1.8 + +2 12:00 Temperature 27 +2 12:00 WaterVolume 40 +2 12:00 Light 80 +2 12:00 EXP_WaterVolume 40 +2 12:00 Moisture 28 +2 12:00 Fertilizer 1.3 + +2 13:00 Temperature 26 +2 13:00 WaterVolume 0 +2 13:00 Light 70 +2 13:00 EXP_WaterVolume 0 +2 13:00 Moisture 30 +2 13:00 Fertilizer 1.0 + +2 14:00 Temperature 26 +2 14:00 WaterVolume 0 +2 14:00 Light 70 +2 14:00 EXP_WaterVolume 0 +2 14:00 Moisture 30 +2 14:00 Fertilizer 1.2 + +2 15:00 Temperature 26 +2 15:00 WaterVolume 80 +2 15:00 Light 70 +2 15:00 EXP_WaterVolume 80 +2 15:00 Moisture 0 +2 15:00 Fertilizer 2.0 + +2 16:00 Temperature 26 +2 16:00 WaterVolume 80 +2 16:00 Light 65 +2 16:00 EXP_WaterVolume 80 +2 16:00 Moisture 6 +2 16:00 Fertilizer 1.7 + +2 17:00 Temperature 26 +2 17:00 WaterVolume 60 +2 17:00 Light 60 +2 17:00 EXP_WaterVolume 60 +2 17:00 Moisture 14 +2 17:00 Fertilizer 2.1 + +2 18:00 Temperature 25 +2 18:00 WaterVolume 60 +2 18:00 Light 50 +2 18:00 EXP_WaterVolume 60 +2 18:00 Moisture 17 +2 18:00 Fertilizer 2.7 + +2 19:00 Temperature 24 +2 19:00 WaterVolume 40 +2 19:00 Light 30 +2 19:00 EXP_WaterVolume 40 +2 19:00 Moisture 20 +2 19:00 Fertilizer 2.0 + +2 20:00 Temperature 23 +2 20:00 WaterVolume 60 +2 20:00 Light 10 +2 20:00 EXP_WaterVolume 60 +2 20:00 Moisture 19 +2 20:00 Fertilizer 1.0 + +2 21:00 Temperature 23 +2 21:00 WaterVolume 40 +2 21:00 Light 10 +2 21:00 EXP_WaterVolume 40 +2 21:00 Moisture 24 +2 21:00 Fertilizer 2.8 + +2 22:00 Temperature 23 +2 22:00 WaterVolume 40 +2 22:00 Light 10 +2 22:00 EXP_WaterVolume 40 +2 22:00 Moisture 24 +2 22:00 Fertilizer 1.6 + +2 23:00 Temperature 23 +2 23:00 WaterVolume 40 +2 23:00 Light 10 +2 23:00 EXP_WaterVolume 40 +2 23:00 Moisture 23 +2 23:00 Fertilizer 2.6 + +### Thursday ### +3 0:00 Temperature 21 +3 0:00 WaterVolume 40 +3 0:00 Light 10 +3 0:00 EXP_WaterVolume 40 +3 0:00 Moisture 22 +3 0:00 Fertilizer 1.0 + +3 1:00 Temperature 21 +3 1:00 WaterVolume 40 +3 1:00 Light 11 +3 1:00 EXP_WaterVolume 40 +3 1:00 Moisture 25 +3 1:00 Fertilizer 1.1 + +3 2:00 Temperature 21 +3 2:00 WaterVolume 40 +3 2:00 Light 13 +3 2:00 EXP_WaterVolume 40 +3 2:00 Moisture 24 +3 2:00 Fertilizer 1.2 + +3 3:00 Temperature 21 +3 3:00 WaterVolume 40 +3 3:00 Light 15 +3 3:00 EXP_WaterVolume 40 +3 3:00 Moisture 28 +3 3:00 Fertilizer 1.1 + +3 4:00 Temperature 22 +3 4:00 WaterVolume 0 +3 4:00 Light 20 +3 4:00 EXP_WaterVolume 0 +3 4:00 Moisture 31 +3 4:00 Fertilizer 1.3 + +3 5:00 Temperature 22 +3 5:00 WaterVolume 0 +3 5:00 Light 25 +3 5:00 EXP_WaterVolume 0 +3 5:00 Moisture 31 +3 5:00 Fertilizer 1.9 + +3 6:00 Temperature 23 +3 6:00 WaterVolume 40 +3 6:00 Light 40 +3 6:00 EXP_WaterVolume 40 +3 6:00 Moisture 28 +3 6:00 Fertilizer 1.8 + +3 7:00 Temperature 23 +3 7:00 WaterVolume 0 +3 7:00 Light 45 +3 7:00 EXP_WaterVolume 0 +3 7:00 Moisture 30 +3 7:00 Fertilizer 1.9 + +3 8:00 Temperature 23 +3 8:00 WaterVolume 0 +3 8:00 Light 50 +3 8:00 EXP_WaterVolume 0 +3 8:00 Moisture 30 +3 8:00 Fertilizer 1.8 + +3 9:00 Temperature 23 +3 9:00 WaterVolume 40 +3 9:00 Light 50 +3 9:00 EXP_WaterVolume 40 +3 9:00 Moisture 25 +3 9:00 Fertilizer 1.5 + +3 10:00 Temperature 23 +3 10:00 WaterVolume 40 +3 10:00 Light 50 +3 10:00 EXP_WaterVolume 40 +3 10:00 Moisture 28 +3 10:00 Fertilizer 1.4 + +3 11:00 Temperature 24 +3 11:00 WaterVolume 40 +3 11:00 Light 60 +3 11:00 EXP_WaterVolume 40 +3 11:00 Moisture 29 +3 11:00 Fertilizer 2.0 + +3 12:00 Temperature 25 +3 12:00 WaterVolume 0 +3 12:00 Light 80 +3 12:00 EXP_WaterVolume 0 +3 12:00 Moisture 32 +3 12:00 Fertilizer 2.5 + +3 13:00 Temperature 24 +3 13:00 WaterVolume 0 +3 13:00 Light 70 +3 13:00 EXP_WaterVolume 0 +3 13:00 Moisture 30 +3 13:00 Fertilizer 2.1 + +3 14:00 Temperature 24 +3 14:00 WaterVolume 40 +3 14:00 Light 70 +3 14:00 EXP_WaterVolume 40 +3 14:00 Moisture 29 +3 14:00 Fertilizer 1.6 + +3 15:00 Temperature 24 +3 15:00 WaterVolume 40 +3 15:00 Light 70 +3 15:00 EXP_WaterVolume 40 +3 15:00 Moisture 28 +3 15:00 Fertilizer 1.7 + +3 16:00 Temperature 24 +3 16:00 WaterVolume 40 +3 16:00 Light 65 +3 16:00 EXP_WaterVolume 40 +3 16:00 Moisture 28 +3 16:00 Fertilizer 1.2 + +3 17:00 Temperature 24 +3 17:00 WaterVolume 40 +3 17:00 Light 60 +3 17:00 EXP_WaterVolume 40 +3 17:00 Moisture 29 +3 17:00 Fertilizer 1.1 + +3 18:00 Temperature 23 +3 18:00 WaterVolume 0 +3 18:00 Light 50 +3 18:00 EXP_WaterVolume 0 +3 18:00 Moisture 33 +3 18:00 Fertilizer 2.6 + +3 19:00 Temperature 22 +3 19:00 WaterVolume 0 +3 19:00 Light 30 +3 19:00 EXP_WaterVolume 0 +3 19:00 Moisture 32 +3 19:00 Fertilizer 1.8 + +3 20:00 Temperature 21 +3 20:00 WaterVolume 0 +3 20:00 Light 10 +3 20:00 EXP_WaterVolume 0 +3 20:00 Moisture 30 +3 20:00 Fertilizer 2.1 + +3 21:00 Temperature 21 +3 21:00 WaterVolume 40 +3 21:00 Light 10 +3 21:00 EXP_WaterVolume 40 +3 21:00 Moisture 26 +3 21:00 Fertilizer 2.3 + +3 22:00 Temperature 21 +3 22:00 WaterVolume 40 +3 22:00 Light 10 +3 22:00 EXP_WaterVolume 40 +3 22:00 Moisture 25 +3 22:00 Fertilizer 1.8 + +3 23:00 Temperature 21 +3 23:00 WaterVolume 40 +3 23:00 Light 10 +3 23:00 EXP_WaterVolume 40 +3 23:00 Moisture 25 +3 23:00 Fertilizer 2.1 + +### Friday ### +4 0:00 Temperature 24 +4 0:00 WaterVolume 40 +4 0:00 Light 10 +4 0:00 EXP_WaterVolume 40 +4 0:00 Moisture 29 +4 0:00 Fertilizer 2.0 + +4 1:00 Temperature 24 +4 1:00 WaterVolume 0 +4 1:00 Light 11 +4 1:00 EXP_WaterVolume 0 +4 1:00 Moisture 33 +4 1:00 Fertilizer 2.0 + +4 2:00 Temperature 24 +4 2:00 WaterVolume 0 +4 2:00 Light 13 +4 2:00 EXP_WaterVolume 0 +4 2:00 Moisture 33 +4 2:00 Fertilizer 2.2 + +4 3:00 Temperature 24 +4 3:00 WaterVolume 0 +4 3:00 Light 15 +4 3:00 EXP_WaterVolume 0 +4 3:00 Moisture 33 +4 3:00 Fertilizer 1.4 + +4 4:00 Temperature 25 +4 4:00 WaterVolume 0 +4 4:00 Light 20 +4 4:00 EXP_WaterVolume 0 +4 4:00 Moisture 30 +4 4:00 Fertilizer 1.5 + +4 5:00 Temperature 25 +4 5:00 WaterVolume 40 +4 5:00 Light 25 +4 5:00 EXP_WaterVolume 40 +4 5:00 Moisture 29 +4 5:00 Fertilizer 1.4 + +4 6:00 Temperature 26 +4 6:00 WaterVolume 0 +4 6:00 Light 40 +4 6:00 EXP_WaterVolume 0 +4 6:00 Moisture 32 +4 6:00 Fertilizer 1.9 + +4 7:00 Temperature 26 +4 7:00 WaterVolume 40 +4 7:00 Light 45 +4 7:00 EXP_WaterVolume 40 +4 7:00 Moisture 27 +4 7:00 Fertilizer 1.7 + +4 8:00 Temperature 26 +4 8:00 WaterVolume 40 +4 8:00 Light 50 +4 8:00 EXP_WaterVolume 40 +4 8:00 Moisture 27 +4 8:00 Fertilizer 2.2 + +4 9:00 Temperature 26 +4 9:00 WaterVolume 0 +4 9:00 Light 50 +4 9:00 EXP_WaterVolume 0 +4 9:00 Moisture 31 +4 9:00 Fertilizer 2.7 + +4 10:00 Temperature 26 +4 10:00 WaterVolume 0 +4 10:00 Light 50 +4 10:00 EXP_WaterVolume 0 +4 10:00 Moisture 30 +4 10:00 Fertilizer 2.8 + +4 11:00 Temperature 27 +4 11:00 WaterVolume 40 +4 11:00 Light 60 +4 11:00 EXP_WaterVolume 40 +4 11:00 Moisture 29 +4 11:00 Fertilizer 1.6 + +4 12:00 Temperature 28 +4 12:00 WaterVolume 0 +4 12:00 Light 80 +4 12:00 EXP_WaterVolume 0 +4 12:00 Moisture 32 +4 12:00 Fertilizer 2.9 + +4 13:00 Temperature 27 +4 13:00 WaterVolume 0 +4 13:00 Light 70 +4 13:00 EXP_WaterVolume 0 +4 13:00 Moisture 31 +4 13:00 Fertilizer 1.2 + +4 14:00 Temperature 27 +4 14:00 WaterVolume 0 +4 14:00 Light 70 +4 14:00 EXP_WaterVolume 0 +4 14:00 Moisture 30 +4 14:00 Fertilizer 2.7 + +4 15:00 Temperature 27 +4 15:00 WaterVolume 40 +4 15:00 Light 70 +4 15:00 EXP_WaterVolume 40 +4 15:00 Moisture 25 +4 15:00 Fertilizer 1.5 + +4 16:00 Temperature 27 +4 16:00 WaterVolume 40 +4 16:00 Light 65 +4 16:00 EXP_WaterVolume 40 +4 16:00 Moisture 27 +4 16:00 Fertilizer 1.4 + +4 17:00 Temperature 27 +4 17:00 WaterVolume 40 +4 17:00 Light 60 +4 17:00 EXP_WaterVolume 40 +4 17:00 Moisture 28 +4 17:00 Fertilizer 1.0 + +4 18:00 Temperature 26 +4 18:00 WaterVolume 0 +4 18:00 Light 50 +4 18:00 EXP_WaterVolume 0 +4 18:00 Moisture 30 +4 18:00 Fertilizer 2.1 + +4 19:00 Temperature 25 +4 19:00 WaterVolume 0 +4 19:00 Light 30 +4 19:00 EXP_WaterVolume 0 +4 19:00 Moisture 30 +4 19:00 Fertilizer 2.2 + +4 20:00 Temperature 24 +4 20:00 WaterVolume 40 +4 20:00 Light 10 +4 20:00 EXP_WaterVolume 40 +4 20:00 Moisture 27 +4 20:00 Fertilizer 2.6 + +4 21:00 Temperature 24 +4 21:00 WaterVolume 40 +4 21:00 Light 10 +4 21:00 EXP_WaterVolume 40 +4 21:00 Moisture 27 +4 21:00 Fertilizer 2.1 + +4 22:00 Temperature 24 +4 22:00 WaterVolume 40 +4 22:00 Light 10 +4 22:00 EXP_WaterVolume 40 +4 22:00 Moisture 29 +4 22:00 Fertilizer 1.2 + +4 23:00 Temperature 24 +4 23:00 WaterVolume 40 +4 23:00 Light 10 +4 23:00 EXP_WaterVolume 40 +4 23:00 Moisture 28 +4 23:00 Fertilizer 1.2 + +### Saturday ### +5 0:00 Temperature 20 +5 0:00 WaterVolume 40 +5 0:00 Light 10 +5 0:00 EXP_WaterVolume 40 +5 0:00 Moisture 27 +5 0:00 Fertilizer 1.1 + +5 1:00 Temperature 20 +5 1:00 WaterVolume 40 +5 1:00 Light 11 +5 1:00 EXP_WaterVolume 40 +5 1:00 Moisture 27 +5 1:00 Fertilizer 2.2 + +5 2:00 Temperature 20 +5 2:00 WaterVolume 40 +5 2:00 Light 13 +5 2:00 EXP_WaterVolume 40 +5 2:00 Moisture 28 +5 2:00 Fertilizer 2.9 + +5 3:00 Temperature 20 +5 3:00 WaterVolume 40 +5 3:00 Light 15 +5 3:00 EXP_WaterVolume 40 +5 3:00 Moisture 29 +5 3:00 Fertilizer 2.3 + +5 4:00 Temperature 21 +5 4:00 WaterVolume 40 +5 4:00 Light 20 +5 4:00 EXP_WaterVolume 40 +5 4:00 Moisture 28 +5 4:00 Fertilizer 2.7 + +5 5:00 Temperature 21 +5 5:00 WaterVolume 0 +5 5:00 Light 25 +5 5:00 EXP_WaterVolume 0 +5 5:00 Moisture 30 +5 5:00 Fertilizer 2.1 + +5 6:00 Temperature 22 +5 6:00 WaterVolume 40 +5 6:00 Light 40 +5 6:00 EXP_WaterVolume 40 +5 6:00 Moisture 27 +5 6:00 Fertilizer 1.3 + +5 7:00 Temperature 22 +5 7:00 WaterVolume 40 +5 7:00 Light 45 +5 7:00 EXP_WaterVolume 40 +5 7:00 Moisture 26 +5 7:00 Fertilizer 2.2 + +5 8:00 Temperature 22 +5 8:00 WaterVolume 40 +5 8:00 Light 50 +5 8:00 EXP_WaterVolume 40 +5 8:00 Moisture 28 +5 8:00 Fertilizer 1.7 + +5 9:00 Temperature 22 +5 9:00 WaterVolume 0 +5 9:00 Light 50 +5 9:00 EXP_WaterVolume 0 +5 9:00 Moisture 31 +5 9:00 Fertilizer 1.4 + +5 10:00 Temperature 22 +5 10:00 WaterVolume 40 +5 10:00 Light 50 +5 10:00 EXP_WaterVolume 40 +5 10:00 Moisture 26 +5 10:00 Fertilizer 2.2 + +5 11:00 Temperature 23 +5 11:00 WaterVolume 40 +5 11:00 Light 60 +5 11:00 EXP_WaterVolume 40 +5 11:00 Moisture 28 +5 11:00 Fertilizer 1.8 + +5 12:00 Temperature 24 +5 12:00 WaterVolume 0 +5 12:00 Light 80 +5 12:00 EXP_WaterVolume 0 +5 12:00 Moisture 30 +5 12:00 Fertilizer 2.4 + +5 13:00 Temperature 23 +5 13:00 WaterVolume 40 +5 13:00 Light 70 +5 13:00 EXP_WaterVolume 40 +5 13:00 Moisture 25 +5 13:00 Fertilizer 1.7 + +5 14:00 Temperature 23 +5 14:00 WaterVolume 40 +5 14:00 Light 70 +5 14:00 EXP_WaterVolume 40 +5 14:00 Moisture 28 +5 14:00 Fertilizer 1.4 + +5 15:00 Temperature 23 +5 15:00 WaterVolume 0 +5 15:00 Light 70 +5 15:00 EXP_WaterVolume 0 +5 15:00 Moisture 32 +5 15:00 Fertilizer 1.8 + +5 16:00 Temperature 23 +5 16:00 WaterVolume 0 +5 16:00 Light 65 +5 16:00 EXP_WaterVolume 0 +5 16:00 Moisture 30 +5 16:00 Fertilizer 1.5 + +5 17:00 Temperature 23 +5 17:00 WaterVolume 40 +5 17:00 Light 60 +5 17:00 EXP_WaterVolume 40 +5 17:00 Moisture 25 +5 17:00 Fertilizer 1.3 + +5 18:00 Temperature 22 +5 18:00 WaterVolume 40 +5 18:00 Light 50 +5 18:00 EXP_WaterVolume 40 +5 18:00 Moisture 29 +5 18:00 Fertilizer 1.5 + +5 19:00 Temperature 21 +5 19:00 WaterVolume 0 +5 19:00 Light 30 +5 19:00 EXP_WaterVolume 0 +5 19:00 Moisture 32 +5 19:00 Fertilizer 1.0 + +5 20:00 Temperature 20 +5 20:00 WaterVolume 0 +5 20:00 Light 10 +5 20:00 EXP_WaterVolume 0 +5 20:00 Moisture 31 +5 20:00 Fertilizer 2.4 + +5 21:00 Temperature 20 +5 21:00 WaterVolume 40 +5 21:00 Light 10 +5 21:00 EXP_WaterVolume 40 +5 21:00 Moisture 28 +5 21:00 Fertilizer 1.9 + +5 22:00 Temperature 20 +5 22:00 WaterVolume 0 +5 22:00 Light 10 +5 22:00 EXP_WaterVolume 0 +5 22:00 Moisture 30 +5 22:00 Fertilizer 2.3 + +5 23:00 Temperature 20 +5 23:00 WaterVolume 0 +5 23:00 Light 10 +5 23:00 EXP_WaterVolume 0 +5 23:00 Moisture 30 +5 23:00 Fertilizer 1.9 + +### Sunday ### +6 0:00 Temperature 17 +6 0:00 WaterVolume 40 +6 0:00 Light 10 +6 0:00 EXP_WaterVolume 40 +6 0:00 Moisture 27 +6 0:00 Fertilizer 2.5 + +6 1:00 Temperature 17 +6 1:00 WaterVolume 0 +6 1:00 Light 11 +6 1:00 EXP_WaterVolume 0 +6 1:00 Moisture 31 +6 1:00 Fertilizer 2.8 + +6 2:00 Temperature 17 +6 2:00 WaterVolume 40 +6 2:00 Light 13 +6 2:00 EXP_WaterVolume 40 +6 2:00 Moisture 26 +6 2:00 Fertilizer 1.7 + +6 3:00 Temperature 17 +6 3:00 WaterVolume 40 +6 3:00 Light 15 +6 3:00 EXP_WaterVolume 40 +6 3:00 Moisture 28 +6 3:00 Fertilizer 1.8 + +6 4:00 Temperature 18 +6 4:00 WaterVolume 0 +6 4:00 Light 20 +6 4:00 EXP_WaterVolume 0 +6 4:00 Moisture 32 +6 4:00 Fertilizer 1.9 + +6 5:00 Temperature 18 +6 5:00 WaterVolume 0 +6 5:00 Light 25 +6 5:00 EXP_WaterVolume 0 +6 5:00 Moisture 30 +6 5:00 Fertilizer 2.8 + +6 6:00 Temperature 19 +6 6:00 WaterVolume 40 +6 6:00 Light 40 +6 6:00 EXP_WaterVolume 40 +6 6:00 Moisture 27 +6 6:00 Fertilizer 2.2 + +6 7:00 Temperature 19 +6 7:00 WaterVolume 40 +6 7:00 Light 45 +6 7:00 EXP_WaterVolume 40 +6 7:00 Moisture 27 +6 7:00 Fertilizer 1.7 + +6 8:00 Temperature 19 +6 8:00 WaterVolume 40 +6 8:00 Light 50 +6 8:00 EXP_WaterVolume 40 +6 8:00 Moisture 27 +6 8:00 Fertilizer 1.5 + +6 9:00 Temperature 19 +6 9:00 WaterVolume 40 +6 9:00 Light 50 +6 9:00 EXP_WaterVolume 40 +6 9:00 Moisture 28 +6 9:00 Fertilizer 1.0 + +6 10:00 Temperature 19 +6 10:00 WaterVolume 40 +6 10:00 Light 50 +6 10:00 EXP_WaterVolume 40 +6 10:00 Moisture 28 +6 10:00 Fertilizer 1.6 + +6 11:00 Temperature 20 +6 11:00 WaterVolume 40 +6 11:00 Light 60 +6 11:00 EXP_WaterVolume 40 +6 11:00 Moisture 29 +6 11:00 Fertilizer 1.2 + +6 12:00 Temperature 21 +6 12:00 WaterVolume 0 +6 12:00 Light 80 +6 12:00 EXP_WaterVolume 0 +6 12:00 Moisture 33 +6 12:00 Fertilizer 1.4 + +6 13:00 Temperature 20 +6 13:00 WaterVolume 0 +6 13:00 Light 70 +6 13:00 EXP_WaterVolume 0 +6 13:00 Moisture 33 +6 13:00 Fertilizer 1.3 + +6 14:00 Temperature 20 +6 14:00 WaterVolume 0 +6 14:00 Light 70 +6 14:00 EXP_WaterVolume 0 +6 14:00 Moisture 31 +6 14:00 Fertilizer 2.0 + +6 15:00 Temperature 20 +6 15:00 WaterVolume 40 +6 15:00 Light 70 +6 15:00 EXP_WaterVolume 40 +6 15:00 Moisture 26 +6 15:00 Fertilizer 1.4 + +6 16:00 Temperature 20 +6 16:00 WaterVolume 0 +6 16:00 Light 65 +6 16:00 EXP_WaterVolume 0 +6 16:00 Moisture 30 +6 16:00 Fertilizer 2.7 + +6 17:00 Temperature 20 +6 17:00 WaterVolume 40 +6 17:00 Light 60 +6 17:00 EXP_WaterVolume 40 +6 17:00 Moisture 29 +6 17:00 Fertilizer 1.5 + +6 18:00 Temperature 19 +6 18:00 WaterVolume 0 +6 18:00 Light 50 +6 18:00 EXP_WaterVolume 0 +6 18:00 Moisture 32 +6 18:00 Fertilizer 2.0 + +6 19:00 Temperature 18 +6 19:00 WaterVolume 40 +6 19:00 Light 30 +6 19:00 EXP_WaterVolume 40 +6 19:00 Moisture 28 +6 19:00 Fertilizer 1.1 + +6 20:00 Temperature 17 +6 20:00 WaterVolume 40 +6 20:00 Light 10 +6 20:00 EXP_WaterVolume 40 +6 20:00 Moisture 27 +6 20:00 Fertilizer 2.7 + +6 21:00 Temperature 17 +6 21:00 WaterVolume 0 +6 21:00 Light 10 +6 21:00 EXP_WaterVolume 0 +6 21:00 Moisture 30 +6 21:00 Fertilizer 2.4 + +6 22:00 Temperature 17 +6 22:00 WaterVolume 80 +6 22:00 Light 10 +6 22:00 EXP_WaterVolume 80 +6 22:00 Moisture 0 +6 22:00 Fertilizer 2.2 + +6 23:00 Temperature 17 +6 23:00 WaterVolume 80 +6 23:00 Light 10 +6 23:00 EXP_WaterVolume 80 +6 23:00 Moisture 3 +6 23:00 Fertilizer 2.0 + + +#### Week 1 #### +### Monday ### +7 0:00 BEGIN_EXPECTATIONS +7 0:00 Temperature 23 +7 0:00 WaterVolume 0 +7 0:00 Light 10 +7 0:00 EXP_WaterVolume 80 +7 0:00 Moisture 8 +7 0:00 Fertilizer 1.1 +7 0:00 END_EXPECTATIONS +7 0:01 WaterVolume 80 + +7 1:00 BEGIN_EXPECTATIONS +7 1:00 Temperature 23 +7 1:00 WaterVolume 0 +7 1:00 Light 11 +7 1:00 EXP_WaterVolume 60 +7 1:00 Moisture 13 +7 1:00 Fertilizer 2.8 +7 1:00 END_EXPECTATIONS +7 1:01 WaterVolume 60 + +7 2:00 BEGIN_EXPECTATIONS +7 2:00 Temperature 23 +7 2:00 WaterVolume 0 +7 2:00 Light 13 +7 2:00 EXP_WaterVolume 60 +7 2:00 Moisture 15 +7 2:00 Fertilizer 1.9 +7 2:00 END_EXPECTATIONS +7 2:01 WaterVolume 60 + +7 3:00 BEGIN_EXPECTATIONS +7 3:00 Temperature 23 +7 3:00 WaterVolume 0 +7 3:00 Light 15 +7 3:00 EXP_WaterVolume 40 +7 3:00 Moisture 20 +7 3:00 Fertilizer 2.3 +7 3:00 END_EXPECTATIONS +7 3:01 WaterVolume 40 + +7 4:00 BEGIN_EXPECTATIONS +7 4:00 Temperature 24 +7 4:00 WaterVolume 0 +7 4:00 Light 20 +7 4:00 EXP_WaterVolume 40 +7 4:00 Moisture 24 +7 4:00 Fertilizer 1.3 +7 4:00 END_EXPECTATIONS +7 4:01 WaterVolume 40 + +7 5:00 BEGIN_EXPECTATIONS +7 5:00 Temperature 24 +7 5:00 WaterVolume 0 +7 5:00 Light 25 +7 5:00 EXP_WaterVolume 40 +7 5:00 Moisture 23 +7 5:00 Fertilizer 2.5 +7 5:00 END_EXPECTATIONS +7 5:01 WaterVolume 40 + +7 6:00 BEGIN_EXPECTATIONS +7 6:00 Temperature 25 +7 6:00 WaterVolume 0 +7 6:00 Light 40 +7 6:00 EXP_WaterVolume 40 +7 6:00 Moisture 23 +7 6:00 Fertilizer 2.5 +7 6:00 END_EXPECTATIONS +7 6:01 WaterVolume 40 + +7 7:00 BEGIN_EXPECTATIONS +7 7:00 Temperature 25 +7 7:00 WaterVolume 0 +7 7:00 Light 45 +7 7:00 EXP_WaterVolume 40 +7 7:00 Moisture 22 +7 7:00 Fertilizer 1.4 +7 7:00 END_EXPECTATIONS +7 7:01 WaterVolume 40 + +7 8:00 BEGIN_EXPECTATIONS +7 8:00 Temperature 25 +7 8:00 WaterVolume 0 +7 8:00 Light 50 +7 8:00 EXP_WaterVolume 40 +7 8:00 Moisture 25 +7 8:00 Fertilizer 2.9 +7 8:00 END_EXPECTATIONS +7 8:01 WaterVolume 40 + +7 9:00 BEGIN_EXPECTATIONS +7 9:00 Temperature 25 +7 9:00 WaterVolume 0 +7 9:00 Light 50 +7 9:00 EXP_WaterVolume 40 +7 9:00 Moisture 27 +7 9:00 Fertilizer 1.2 +7 9:00 END_EXPECTATIONS +7 9:01 WaterVolume 40 + +7 10:00 BEGIN_EXPECTATIONS +7 10:00 Temperature 25 +7 10:00 WaterVolume 0 +7 10:00 Light 50 +7 10:00 EXP_WaterVolume 0 +7 10:00 Moisture 30 +7 10:00 Fertilizer 1.8 +7 10:00 END_EXPECTATIONS +7 10:01 WaterVolume 0 + +7 11:00 BEGIN_EXPECTATIONS +7 11:00 Temperature 26 +7 11:00 WaterVolume 0 +7 11:00 Light 60 +7 11:00 EXP_WaterVolume 40 +7 11:00 Moisture 26 +7 11:00 Fertilizer 1.9 +7 11:00 END_EXPECTATIONS +7 11:01 WaterVolume 40 + +7 12:00 BEGIN_EXPECTATIONS +7 12:00 Temperature 27 +7 12:00 WaterVolume 0 +7 12:00 Light 80 +7 12:00 EXP_WaterVolume 40 +7 12:00 Moisture 28 +7 12:00 Fertilizer 2.3 +7 12:00 END_EXPECTATIONS +7 12:01 WaterVolume 40 + +7 13:00 BEGIN_EXPECTATIONS +7 13:00 Temperature 26 +7 13:00 WaterVolume 0 +7 13:00 Light 70 +7 13:00 EXP_WaterVolume 40 +7 13:00 Moisture 28 +7 13:00 Fertilizer 1.2 +7 13:00 END_EXPECTATIONS +7 13:01 WaterVolume 40 + +7 14:00 BEGIN_EXPECTATIONS +7 14:00 Temperature 26 +7 14:00 WaterVolume 0 +7 14:00 Light 70 +7 14:00 EXP_WaterVolume 0 +7 14:00 Moisture 30 +7 14:00 Fertilizer 1.6 +7 14:00 END_EXPECTATIONS +7 14:01 WaterVolume 0 + +7 15:00 BEGIN_EXPECTATIONS +7 15:00 Temperature 26 +7 15:00 WaterVolume 0 +7 15:00 Light 70 +7 15:00 EXP_WaterVolume 40 +7 15:00 Moisture 29 +7 15:00 Fertilizer 2.2 +7 15:00 END_EXPECTATIONS +7 15:01 WaterVolume 40 + +7 16:00 BEGIN_EXPECTATIONS +7 16:00 Temperature 26 +7 16:00 WaterVolume 0 +7 16:00 Light 65 +7 16:00 EXP_WaterVolume 0 +7 16:00 Moisture 30 +7 16:00 Fertilizer 2.5 +7 16:00 END_EXPECTATIONS +7 16:01 WaterVolume 0 + +7 17:00 BEGIN_EXPECTATIONS +7 17:00 Temperature 26 +7 17:00 WaterVolume 0 +7 17:00 Light 60 +7 17:00 EXP_WaterVolume 0 +7 17:00 Moisture 30 +7 17:00 Fertilizer 1.6 +7 17:00 END_EXPECTATIONS +7 17:01 WaterVolume 0 + +7 18:00 BEGIN_EXPECTATIONS +7 18:00 Temperature 25 +7 18:00 WaterVolume 0 +7 18:00 Light 50 +7 18:00 EXP_WaterVolume 40 +7 18:00 Moisture 25 +7 18:00 Fertilizer 1.3 +7 18:00 END_EXPECTATIONS +7 18:01 WaterVolume 40 + +7 19:00 BEGIN_EXPECTATIONS +7 19:00 Temperature 24 +7 19:00 WaterVolume 0 +7 19:00 Light 30 +7 19:00 EXP_WaterVolume 40 +7 19:00 Moisture 24 +7 19:00 Fertilizer 1.2 +7 19:00 END_EXPECTATIONS +7 19:01 WaterVolume 40 + +7 20:00 BEGIN_EXPECTATIONS +7 20:00 Temperature 23 +7 20:00 WaterVolume 0 +7 20:00 Light 10 +7 20:00 EXP_WaterVolume 40 +7 20:00 Moisture 25 +7 20:00 Fertilizer 1.9 +7 20:00 END_EXPECTATIONS +7 20:01 WaterVolume 40 + +7 21:00 BEGIN_EXPECTATIONS +7 21:00 Temperature 23 +7 21:00 WaterVolume 0 +7 21:00 Light 10 +7 21:00 EXP_WaterVolume 40 +7 21:00 Moisture 24 +7 21:00 Fertilizer 1.6 +7 21:00 END_EXPECTATIONS +7 21:01 WaterVolume 40 + +7 22:00 BEGIN_EXPECTATIONS +7 22:00 Temperature 23 +7 22:00 WaterVolume 0 +7 22:00 Light 10 +7 22:00 EXP_WaterVolume 40 +7 22:00 Moisture 23 +7 22:00 Fertilizer 2.1 +7 22:00 END_EXPECTATIONS +7 22:01 WaterVolume 40 + +7 23:00 BEGIN_EXPECTATIONS +7 23:00 Temperature 23 +7 23:00 WaterVolume 0 +7 23:00 Light 10 +7 23:00 EXP_WaterVolume 40 +7 23:00 Moisture 25 +7 23:00 Fertilizer 2.2 +7 23:00 END_EXPECTATIONS +7 23:01 WaterVolume 40 + +### Tuesday ### +8 0:00 BEGIN_EXPECTATIONS +8 0:00 Temperature 17 +8 0:00 WaterVolume 0 +8 0:00 Light 10 +8 0:00 EXP_WaterVolume 40 +8 0:00 Moisture 25 +8 0:00 Fertilizer 2.9 +8 0:00 END_EXPECTATIONS +8 0:01 WaterVolume 40 + +8 1:00 BEGIN_EXPECTATIONS +8 1:00 Temperature 17 +8 1:00 WaterVolume 0 +8 1:00 Light 11 +8 1:00 EXP_WaterVolume 40 +8 1:00 Moisture 26 +8 1:00 Fertilizer 1.2 +8 1:00 END_EXPECTATIONS +8 1:01 WaterVolume 40 + +8 2:00 BEGIN_EXPECTATIONS +8 2:00 Temperature 17 +8 2:00 WaterVolume 0 +8 2:00 Light 13 +8 2:00 EXP_WaterVolume 40 +8 2:00 Moisture 25 +8 2:00 Fertilizer 2.3 +8 2:00 END_EXPECTATIONS +8 2:01 WaterVolume 40 + +8 3:00 BEGIN_EXPECTATIONS +8 3:00 Temperature 17 +8 3:00 WaterVolume 0 +8 3:00 Light 15 +8 3:00 EXP_WaterVolume 40 +8 3:00 Moisture 28 +8 3:00 Fertilizer 2.1 +8 3:00 END_EXPECTATIONS +8 3:01 WaterVolume 40 + +8 4:00 BEGIN_EXPECTATIONS +8 4:00 Temperature 18 +8 4:00 WaterVolume 0 +8 4:00 Light 20 +8 4:00 EXP_WaterVolume 0 +8 4:00 Moisture 32 +8 4:00 Fertilizer 1.9 +8 4:00 END_EXPECTATIONS +8 4:01 WaterVolume 0 + +8 5:00 BEGIN_EXPECTATIONS +8 5:00 Temperature 18 +8 5:00 WaterVolume 0 +8 5:00 Light 25 +8 5:00 EXP_WaterVolume 40 +8 5:00 Moisture 28 +8 5:00 Fertilizer 2.7 +8 5:00 END_EXPECTATIONS +8 5:01 WaterVolume 40 + +8 6:00 BEGIN_EXPECTATIONS +8 6:00 Temperature 19 +8 6:00 WaterVolume 0 +8 6:00 Light 40 +8 6:00 EXP_WaterVolume 40 +8 6:00 Moisture 27 +8 6:00 Fertilizer 2.3 +8 6:00 END_EXPECTATIONS +8 6:01 WaterVolume 40 + +8 7:00 BEGIN_EXPECTATIONS +8 7:00 Temperature 19 +8 7:00 WaterVolume 0 +8 7:00 Light 45 +8 7:00 EXP_WaterVolume 40 +8 7:00 Moisture 27 +8 7:00 Fertilizer 1.4 +8 7:00 END_EXPECTATIONS +8 7:01 WaterVolume 40 + +8 8:00 BEGIN_EXPECTATIONS +8 8:00 Temperature 19 +8 8:00 WaterVolume 0 +8 8:00 Light 50 +8 8:00 EXP_WaterVolume 40 +8 8:00 Moisture 26 +8 8:00 Fertilizer 2.5 +8 8:00 END_EXPECTATIONS +8 8:01 WaterVolume 40 + +8 9:00 BEGIN_EXPECTATIONS +8 9:00 Temperature 19 +8 9:00 WaterVolume 0 +8 9:00 Light 50 +8 9:00 EXP_WaterVolume 40 +8 9:00 Moisture 27 +8 9:00 Fertilizer 1.2 +8 9:00 END_EXPECTATIONS +8 9:01 WaterVolume 40 + +8 10:00 BEGIN_EXPECTATIONS +8 10:00 Temperature 19 +8 10:00 WaterVolume 0 +8 10:00 Light 50 +8 10:00 EXP_WaterVolume 40 +8 10:00 Moisture 28 +8 10:00 Fertilizer 1.8 +8 10:00 END_EXPECTATIONS +8 10:01 WaterVolume 40 + +8 11:00 BEGIN_EXPECTATIONS +8 11:00 Temperature 20 +8 11:00 WaterVolume 0 +8 11:00 Light 60 +8 11:00 EXP_WaterVolume 40 +8 11:00 Moisture 27 +8 11:00 Fertilizer 2.8 +8 11:00 END_EXPECTATIONS +8 11:01 WaterVolume 40 + +8 12:00 BEGIN_EXPECTATIONS +8 12:00 Temperature 21 +8 12:00 WaterVolume 0 +8 12:00 Light 80 +8 12:00 EXP_WaterVolume 0 +8 12:00 Moisture 31 +8 12:00 Fertilizer 1.7 +8 12:00 END_EXPECTATIONS +8 12:01 WaterVolume 0 + +8 13:00 BEGIN_EXPECTATIONS +8 13:00 Temperature 20 +8 13:00 WaterVolume 0 +8 13:00 Light 70 +8 13:00 EXP_WaterVolume 40 +8 13:00 Moisture 29 +8 13:00 Fertilizer 1.3 +8 13:00 END_EXPECTATIONS +8 13:01 WaterVolume 40 + +8 14:00 BEGIN_EXPECTATIONS +8 14:00 Temperature 20 +8 14:00 WaterVolume 0 +8 14:00 Light 70 +8 14:00 EXP_WaterVolume 0 +8 14:00 Moisture 31 +8 14:00 Fertilizer 2.8 +8 14:00 END_EXPECTATIONS +8 14:01 WaterVolume 0 + +8 15:00 BEGIN_EXPECTATIONS +8 15:00 Temperature 20 +8 15:00 WaterVolume 0 +8 15:00 Light 70 +8 15:00 EXP_WaterVolume 40 +8 15:00 Moisture 28 +8 15:00 Fertilizer 1.2 +8 15:00 END_EXPECTATIONS +8 15:01 WaterVolume 40 + +8 16:00 BEGIN_EXPECTATIONS +8 16:00 Temperature 20 +8 16:00 WaterVolume 0 +8 16:00 Light 65 +8 16:00 EXP_WaterVolume 40 +8 16:00 Moisture 29 +8 16:00 Fertilizer 1.6 +8 16:00 END_EXPECTATIONS +8 16:01 WaterVolume 40 + +8 17:00 BEGIN_EXPECTATIONS +8 17:00 Temperature 20 +8 17:00 WaterVolume 0 +8 17:00 Light 60 +8 17:00 EXP_WaterVolume 40 +8 17:00 Moisture 29 +8 17:00 Fertilizer 2.7 +8 17:00 END_EXPECTATIONS +8 17:01 WaterVolume 40 + +8 18:00 BEGIN_EXPECTATIONS +8 18:00 Temperature 19 +8 18:00 WaterVolume 0 +8 18:00 Light 50 +8 18:00 EXP_WaterVolume 0 +8 18:00 Moisture 50 +8 18:00 Fertilizer 1.6 +8 18:00 END_EXPECTATIONS +8 18:01 WaterVolume 0 + +8 19:00 BEGIN_EXPECTATIONS +8 19:00 Temperature 18 +8 19:00 WaterVolume 0 +8 19:00 Light 30 +8 19:00 EXP_WaterVolume 0 +8 19:00 Moisture 48 +8 19:00 Fertilizer 1.4 +8 19:00 END_EXPECTATIONS +8 19:01 WaterVolume 0 + +8 20:00 BEGIN_EXPECTATIONS +8 20:00 Temperature 17 +8 20:00 WaterVolume 0 +8 20:00 Light 10 +8 20:00 EXP_WaterVolume 0 +8 20:00 Moisture 43 +8 20:00 Fertilizer 2.2 +8 20:00 END_EXPECTATIONS +8 20:01 WaterVolume 0 + +8 21:00 BEGIN_EXPECTATIONS +8 21:00 Temperature 17 +8 21:00 WaterVolume 0 +8 21:00 Light 10 +8 21:00 EXP_WaterVolume 80 +8 21:00 Moisture 0 +8 21:00 Fertilizer 1.3 +8 21:00 END_EXPECTATIONS +8 21:01 WaterVolume 80 + +8 22:00 BEGIN_EXPECTATIONS +8 22:00 Temperature 17 +8 22:00 WaterVolume 0 +8 22:00 Light 10 +8 22:00 EXP_WaterVolume 80 +8 22:00 Moisture 3 +8 22:00 Fertilizer 2.6 +8 22:00 END_EXPECTATIONS +8 22:01 WaterVolume 80 + +8 23:00 BEGIN_EXPECTATIONS +8 23:00 Temperature 17 +8 23:00 WaterVolume 0 +8 23:00 Light 10 +8 23:00 EXP_WaterVolume 80 +8 23:00 Moisture 9 +8 23:00 Fertilizer 2.6 +8 23:00 END_EXPECTATIONS +8 23:01 WaterVolume 80 + +### Wednesday ### +9 0:00 BEGIN_EXPECTATIONS +9 0:00 Temperature 18 +9 0:00 WaterVolume 0 +9 0:00 Light 10 +9 0:00 EXP_WaterVolume 60 +9 0:00 Moisture 16 +9 0:00 Fertilizer 1.2 +9 0:00 END_EXPECTATIONS +9 0:01 WaterVolume 60 + +9 1:00 BEGIN_EXPECTATIONS +9 1:00 Temperature 18 +9 1:00 WaterVolume 0 +9 1:00 Light 11 +9 1:00 EXP_WaterVolume 40 +9 1:00 Moisture 22 +9 1:00 Fertilizer 1.9 +9 1:00 END_EXPECTATIONS +9 1:01 WaterVolume 40 + +9 2:00 BEGIN_EXPECTATIONS +9 2:00 Temperature 18 +9 2:00 WaterVolume 0 +9 2:00 Light 13 +9 2:00 EXP_WaterVolume 40 +9 2:00 Moisture 22 +9 2:00 Fertilizer 2.2 +9 2:00 END_EXPECTATIONS +9 2:01 WaterVolume 40 + +9 3:00 BEGIN_EXPECTATIONS +9 3:00 Temperature 18 +9 3:00 WaterVolume 0 +9 3:00 Light 15 +9 3:00 EXP_WaterVolume 40 +9 3:00 Moisture 22 +9 3:00 Fertilizer 1.4 +9 3:00 END_EXPECTATIONS +9 3:01 WaterVolume 40 + +9 4:00 BEGIN_EXPECTATIONS +9 4:00 Temperature 19 +9 4:00 WaterVolume 0 +9 4:00 Light 20 +9 4:00 EXP_WaterVolume 40 +9 4:00 Moisture 23 +9 4:00 Fertilizer 2.4 +9 4:00 END_EXPECTATIONS +9 4:01 WaterVolume 40 + +9 5:00 BEGIN_EXPECTATIONS +9 5:00 Temperature 19 +9 5:00 WaterVolume 0 +9 5:00 Light 25 +9 5:00 EXP_WaterVolume 40 +9 5:00 Moisture 26 +9 5:00 Fertilizer 2.8 +9 5:00 END_EXPECTATIONS +9 5:01 WaterVolume 40 + +9 6:00 BEGIN_EXPECTATIONS +9 6:00 Temperature 20 +9 6:00 WaterVolume 0 +9 6:00 Light 40 +9 6:00 EXP_WaterVolume 0 +9 6:00 Moisture 30 +9 6:00 Fertilizer 1.9 +9 6:00 END_EXPECTATIONS +9 6:01 WaterVolume 0 + +9 7:00 BEGIN_EXPECTATIONS +9 7:00 Temperature 20 +9 7:00 WaterVolume 0 +9 7:00 Light 45 +9 7:00 EXP_WaterVolume 40 +9 7:00 Moisture 27 +9 7:00 Fertilizer 1.6 +9 7:00 END_EXPECTATIONS +9 7:01 WaterVolume 40 + +9 8:00 BEGIN_EXPECTATIONS +9 8:00 Temperature 20 +9 8:00 WaterVolume 0 +9 8:00 Light 50 +9 8:00 EXP_WaterVolume 40 +9 8:00 Moisture 26 +9 8:00 Fertilizer 1.9 +9 8:00 END_EXPECTATIONS +9 8:01 WaterVolume 40 + +9 9:00 BEGIN_EXPECTATIONS +9 9:00 Temperature 20 +9 9:00 WaterVolume 0 +9 9:00 Light 50 +9 9:00 EXP_WaterVolume 80 +9 9:00 Moisture 0 +9 9:00 Fertilizer 1.9 +9 9:00 END_EXPECTATIONS +9 9:01 WaterVolume 80 + +9 10:00 BEGIN_EXPECTATIONS +9 10:00 Temperature 20 +9 10:00 WaterVolume 0 +9 10:00 Light 50 +9 10:00 EXP_WaterVolume 80 +9 10:00 Moisture 8 +9 10:00 Fertilizer 2.1 +9 10:00 END_EXPECTATIONS +9 10:01 WaterVolume 80 + +9 11:00 BEGIN_EXPECTATIONS +9 11:00 Temperature 21 +9 11:00 WaterVolume 0 +9 11:00 Light 60 +9 11:00 EXP_WaterVolume 60 +9 11:00 Moisture 11 +9 11:00 Fertilizer 1.6 +9 11:00 END_EXPECTATIONS +9 11:01 WaterVolume 60 + +9 12:00 BEGIN_EXPECTATIONS +9 12:00 Temperature 22 +9 12:00 WaterVolume 0 +9 12:00 Light 80 +9 12:00 EXP_WaterVolume 60 +9 12:00 Moisture 13 +9 12:00 Fertilizer 2.0 +9 12:00 END_EXPECTATIONS +9 12:01 WaterVolume 60 + +9 13:00 BEGIN_EXPECTATIONS +9 13:00 Temperature 21 +9 13:00 WaterVolume 0 +9 13:00 Light 70 +9 13:00 EXP_WaterVolume 60 +9 13:00 Moisture 19 +9 13:00 Fertilizer 2.2 +9 13:00 END_EXPECTATIONS +9 13:01 WaterVolume 60 + +9 14:00 BEGIN_EXPECTATIONS +9 14:00 Temperature 21 +9 14:00 WaterVolume 0 +9 14:00 Light 70 +9 14:00 EXP_WaterVolume 40 +9 14:00 Moisture 23 +9 14:00 Fertilizer 1.6 +9 14:00 END_EXPECTATIONS +9 14:01 WaterVolume 40 + +9 15:00 BEGIN_EXPECTATIONS +9 15:00 Temperature 21 +9 15:00 WaterVolume 0 +9 15:00 Light 70 +9 15:00 EXP_WaterVolume 80 +9 15:00 Moisture 0 +9 15:00 Fertilizer 1.1 +9 15:00 END_EXPECTATIONS +9 15:01 WaterVolume 80 + +9 16:00 BEGIN_EXPECTATIONS +9 16:00 Temperature 21 +9 16:00 WaterVolume 0 +9 16:00 Light 65 +9 16:00 EXP_WaterVolume 80 +9 16:00 Moisture 3 +9 16:00 Fertilizer 1.9 +9 16:00 END_EXPECTATIONS +9 16:01 WaterVolume 80 + +9 17:00 BEGIN_EXPECTATIONS +9 17:00 Temperature 21 +9 17:00 WaterVolume 0 +9 17:00 Light 60 +9 17:00 EXP_WaterVolume 80 +9 17:00 Moisture 9 +9 17:00 Fertilizer 2.9 +9 17:00 END_EXPECTATIONS +9 17:01 WaterVolume 80 + +9 18:00 BEGIN_EXPECTATIONS +9 18:00 Temperature 20 +9 18:00 WaterVolume 0 +9 18:00 Light 50 +9 18:00 EXP_WaterVolume 60 +9 18:00 Moisture 13 +9 18:00 Fertilizer 2.0 +9 18:00 END_EXPECTATIONS +9 18:01 WaterVolume 60 + +9 19:00 BEGIN_EXPECTATIONS +9 19:00 Temperature 19 +9 19:00 WaterVolume 0 +9 19:00 Light 30 +9 19:00 EXP_WaterVolume 60 +9 19:00 Moisture 18 +9 19:00 Fertilizer 1.4 +9 19:00 END_EXPECTATIONS +9 19:01 WaterVolume 60 + +9 20:00 BEGIN_EXPECTATIONS +9 20:00 Temperature 18 +9 20:00 WaterVolume 0 +9 20:00 Light 10 +9 20:00 EXP_WaterVolume 40 +9 20:00 Moisture 23 +9 20:00 Fertilizer 1.3 +9 20:00 END_EXPECTATIONS +9 20:01 WaterVolume 40 + +9 21:00 BEGIN_EXPECTATIONS +9 21:00 Temperature 18 +9 21:00 WaterVolume 0 +9 21:00 Light 10 +9 21:00 EXP_WaterVolume 40 +9 21:00 Moisture 27 +9 21:00 Fertilizer 1.6 +9 21:00 END_EXPECTATIONS +9 21:01 WaterVolume 40 + +9 22:00 BEGIN_EXPECTATIONS +9 22:00 Temperature 18 +9 22:00 WaterVolume 0 +9 22:00 Light 10 +9 22:00 EXP_WaterVolume 40 +9 22:00 Moisture 26 +9 22:00 Fertilizer 2.5 +9 22:00 END_EXPECTATIONS +9 22:01 WaterVolume 40 + +9 23:00 BEGIN_EXPECTATIONS +9 23:00 Temperature 18 +9 23:00 WaterVolume 0 +9 23:00 Light 10 +9 23:00 EXP_WaterVolume 40 +9 23:00 Moisture 28 +9 23:00 Fertilizer 1.5 +9 23:00 END_EXPECTATIONS +9 23:01 WaterVolume 40 + +### Thursday ### +10 0:00 BEGIN_EXPECTATIONS +10 0:00 Temperature 24 +10 0:00 WaterVolume 0 +10 0:00 Light 10 +10 0:00 EXP_WaterVolume 40 +10 0:00 Moisture 27 +10 0:00 Fertilizer 2.4 +10 0:00 END_EXPECTATIONS +10 0:01 WaterVolume 40 + +10 1:00 BEGIN_EXPECTATIONS +10 1:00 Temperature 24 +10 1:00 WaterVolume 0 +10 1:00 Light 11 +10 1:00 EXP_WaterVolume 40 +10 1:00 Moisture 29 +10 1:00 Fertilizer 2.2 +10 1:00 END_EXPECTATIONS +10 1:01 WaterVolume 40 + +10 2:00 BEGIN_EXPECTATIONS +10 2:00 Temperature 24 +10 2:00 WaterVolume 0 +10 2:00 Light 13 +10 2:00 EXP_WaterVolume 40 +10 2:00 Moisture 28 +10 2:00 Fertilizer 1.6 +10 2:00 END_EXPECTATIONS +10 2:01 WaterVolume 40 + +10 3:00 BEGIN_EXPECTATIONS +10 3:00 Temperature 24 +10 3:00 WaterVolume 0 +10 3:00 Light 15 +10 3:00 EXP_WaterVolume 40 +10 3:00 Moisture 29 +10 3:00 Fertilizer 2.4 +10 3:00 END_EXPECTATIONS +10 3:01 WaterVolume 40 + +10 4:00 BEGIN_EXPECTATIONS +10 4:00 Temperature 25 +10 4:00 WaterVolume 0 +10 4:00 Light 20 +10 4:00 EXP_WaterVolume 40 +10 4:00 Moisture 29 +10 4:00 Fertilizer 1.2 +10 4:00 END_EXPECTATIONS +10 4:01 WaterVolume 40 + +10 5:00 BEGIN_EXPECTATIONS +10 5:00 Temperature 25 +10 5:00 WaterVolume 0 +10 5:00 Light 25 +10 5:00 EXP_WaterVolume 0 +10 5:00 Moisture 30 +10 5:00 Fertilizer 2.5 +10 5:00 END_EXPECTATIONS +10 5:01 WaterVolume 0 + +10 6:00 BEGIN_EXPECTATIONS +10 6:00 Temperature 26 +10 6:00 WaterVolume 0 +10 6:00 Light 40 +10 6:00 EXP_WaterVolume 40 +10 6:00 Moisture 28 +10 6:00 Fertilizer 2.2 +10 6:00 END_EXPECTATIONS +10 6:01 WaterVolume 40 + +10 7:00 BEGIN_EXPECTATIONS +10 7:00 Temperature 26 +10 7:00 WaterVolume 0 +10 7:00 Light 45 +10 7:00 EXP_WaterVolume 40 +10 7:00 Moisture 28 +10 7:00 Fertilizer 2.8 +10 7:00 END_EXPECTATIONS +10 7:01 WaterVolume 40 + +10 8:00 BEGIN_EXPECTATIONS +10 8:00 Temperature 26 +10 8:00 WaterVolume 0 +10 8:00 Light 50 +10 8:00 EXP_WaterVolume 0 +10 8:00 Moisture 31 +10 8:00 Fertilizer 1.1 +10 8:00 END_EXPECTATIONS +10 8:01 WaterVolume 0 + +10 9:00 BEGIN_EXPECTATIONS +10 9:00 Temperature 26 +10 9:00 WaterVolume 0 +10 9:00 Light 50 +10 9:00 EXP_WaterVolume 40 +10 9:00 Moisture 27 +10 9:00 Fertilizer 2.7 +10 9:00 END_EXPECTATIONS +10 9:01 WaterVolume 40 + +10 10:00 BEGIN_EXPECTATIONS +10 10:00 Temperature 26 +10 10:00 WaterVolume 0 +10 10:00 Light 50 +10 10:00 EXP_WaterVolume 0 +10 10:00 Moisture 30 +10 10:00 Fertilizer 2.3 +10 10:00 END_EXPECTATIONS +10 10:01 WaterVolume 0 + +10 11:00 BEGIN_EXPECTATIONS +10 11:00 Temperature 27 +10 11:00 WaterVolume 0 +10 11:00 Light 60 +10 11:00 EXP_WaterVolume 0 +10 11:00 Moisture 30 +10 11:00 Fertilizer 2.9 +10 11:00 END_EXPECTATIONS +10 11:01 WaterVolume 0 + +10 12:00 BEGIN_EXPECTATIONS +10 12:00 Temperature 28 +10 12:00 WaterVolume 0 +10 12:00 Light 80 +10 12:00 EXP_WaterVolume 40 +10 12:00 Moisture 27 +10 12:00 Fertilizer 1.6 +10 12:00 END_EXPECTATIONS +10 12:01 WaterVolume 40 + +10 13:00 BEGIN_EXPECTATIONS +10 13:00 Temperature 27 +10 13:00 WaterVolume 0 +10 13:00 Light 70 +10 13:00 EXP_WaterVolume 40 +10 13:00 Moisture 27 +10 13:00 Fertilizer 1.6 +10 13:00 END_EXPECTATIONS +10 13:01 WaterVolume 40 + +10 14:00 BEGIN_EXPECTATIONS +10 14:00 Temperature 27 +10 14:00 WaterVolume 0 +10 14:00 Light 70 +10 14:00 EXP_WaterVolume 40 +10 14:00 Moisture 27 +10 14:00 Fertilizer 1.3 +10 14:00 END_EXPECTATIONS +10 14:01 WaterVolume 40 + +10 15:00 BEGIN_EXPECTATIONS +10 15:00 Temperature 27 +10 15:00 WaterVolume 0 +10 15:00 Light 70 +10 15:00 EXP_WaterVolume 0 +10 15:00 Moisture 30 +10 15:00 Fertilizer 1.9 +10 15:00 END_EXPECTATIONS +10 15:01 WaterVolume 0 + +10 16:00 BEGIN_EXPECTATIONS +10 16:00 Temperature 27 +10 16:00 WaterVolume 0 +10 16:00 Light 65 +10 16:00 EXP_WaterVolume 40 +10 16:00 Moisture 27 +10 16:00 Fertilizer 1.2 +10 16:00 END_EXPECTATIONS +10 16:01 WaterVolume 40 + +10 17:00 BEGIN_EXPECTATIONS +10 17:00 Temperature 27 +10 17:00 WaterVolume 0 +10 17:00 Light 60 +10 17:00 EXP_WaterVolume 40 +10 17:00 Moisture 28 +10 17:00 Fertilizer 1.4 +10 17:00 END_EXPECTATIONS +10 17:01 WaterVolume 40 + +10 18:00 BEGIN_EXPECTATIONS +10 18:00 Temperature 26 +10 18:00 WaterVolume 0 +10 18:00 Light 50 +10 18:00 EXP_WaterVolume 0 +10 18:00 Moisture 32 +10 18:00 Fertilizer 2.8 +10 18:00 END_EXPECTATIONS +10 18:01 WaterVolume 0 + +10 19:00 BEGIN_EXPECTATIONS +10 19:00 Temperature 25 +10 19:00 WaterVolume 0 +10 19:00 Light 30 +10 19:00 EXP_WaterVolume 0 +10 19:00 Moisture 30 +10 19:00 Fertilizer 2.2 +10 19:00 END_EXPECTATIONS +10 19:01 WaterVolume 0 + +10 20:00 BEGIN_EXPECTATIONS +10 20:00 Temperature 24 +10 20:00 WaterVolume 0 +10 20:00 Light 10 +10 20:00 EXP_WaterVolume 40 +10 20:00 Moisture 28 +10 20:00 Fertilizer 1.5 +10 20:00 END_EXPECTATIONS +10 20:01 WaterVolume 40 + +10 21:00 BEGIN_EXPECTATIONS +10 21:00 Temperature 24 +10 21:00 WaterVolume 0 +10 21:00 Light 10 +10 21:00 EXP_WaterVolume 0 +10 21:00 Moisture 32 +10 21:00 Fertilizer 1.7 +10 21:00 END_EXPECTATIONS +10 21:01 WaterVolume 0 + +10 22:00 BEGIN_EXPECTATIONS +10 22:00 Temperature 24 +10 22:00 WaterVolume 0 +10 22:00 Light 10 +10 22:00 EXP_WaterVolume 0 +10 22:00 Moisture 30 +10 22:00 Fertilizer 1.3 +10 22:00 END_EXPECTATIONS +10 22:01 WaterVolume 0 + +10 23:00 BEGIN_EXPECTATIONS +10 23:00 Temperature 24 +10 23:00 WaterVolume 0 +10 23:00 Light 10 +10 23:00 EXP_WaterVolume 40 +10 23:00 Moisture 26 +10 23:00 Fertilizer 2.5 +10 23:00 END_EXPECTATIONS +10 23:01 WaterVolume 40 + +### Friday ### +11 0:00 BEGIN_EXPECTATIONS +11 0:00 Temperature 19 +11 0:00 WaterVolume 0 +11 0:00 Light 10 +11 0:00 EXP_WaterVolume 40 +11 0:00 Moisture 28 +11 0:00 Fertilizer 2.6 +11 0:00 END_EXPECTATIONS +11 0:01 WaterVolume 40 + +11 1:00 BEGIN_EXPECTATIONS +11 1:00 Temperature 19 +11 1:00 WaterVolume 0 +11 1:00 Light 11 +11 1:00 EXP_WaterVolume 0 +11 1:00 Moisture 30 +11 1:00 Fertilizer 1.5 +11 1:00 END_EXPECTATIONS +11 1:01 WaterVolume 0 + +11 2:00 BEGIN_EXPECTATIONS +11 2:00 Temperature 19 +11 2:00 WaterVolume 0 +11 2:00 Light 13 +11 2:00 EXP_WaterVolume 40 +11 2:00 Moisture 29 +11 2:00 Fertilizer 2.4 +11 2:00 END_EXPECTATIONS +11 2:01 WaterVolume 40 + +11 3:00 BEGIN_EXPECTATIONS +11 3:00 Temperature 19 +11 3:00 WaterVolume 0 +11 3:00 Light 15 +11 3:00 EXP_WaterVolume 0 +11 3:00 Moisture 33 +11 3:00 Fertilizer 1.3 +11 3:00 END_EXPECTATIONS +11 3:01 WaterVolume 0 + +11 4:00 BEGIN_EXPECTATIONS +11 4:00 Temperature 20 +11 4:00 WaterVolume 0 +11 4:00 Light 20 +11 4:00 EXP_WaterVolume 40 +11 4:00 Moisture 29 +11 4:00 Fertilizer 1.2 +11 4:00 END_EXPECTATIONS +11 4:01 WaterVolume 40 + +11 5:00 BEGIN_EXPECTATIONS +11 5:00 Temperature 20 +11 5:00 WaterVolume 0 +11 5:00 Light 25 +11 5:00 EXP_WaterVolume 40 +11 5:00 Moisture 28 +11 5:00 Fertilizer 2.3 +11 5:00 END_EXPECTATIONS +11 5:01 WaterVolume 40 + +11 6:00 BEGIN_EXPECTATIONS +11 6:00 Temperature 21 +11 6:00 WaterVolume 0 +11 6:00 Light 40 +11 6:00 EXP_WaterVolume 0 +11 6:00 Moisture 30 +11 6:00 Fertilizer 1.1 +11 6:00 END_EXPECTATIONS +11 6:01 WaterVolume 0 + +11 7:00 BEGIN_EXPECTATIONS +11 7:00 Temperature 21 +11 7:00 WaterVolume 0 +11 7:00 Light 45 +11 7:00 EXP_WaterVolume 40 +11 7:00 Moisture 28 +11 7:00 Fertilizer 1.4 +11 7:00 END_EXPECTATIONS +11 7:01 WaterVolume 40 + +11 8:00 BEGIN_EXPECTATIONS +11 8:00 Temperature 21 +11 8:00 WaterVolume 0 +11 8:00 Light 50 +11 8:00 EXP_WaterVolume 40 +11 8:00 Moisture 27 +11 8:00 Fertilizer 2.9 +11 8:00 END_EXPECTATIONS +11 8:01 WaterVolume 40 + +11 9:00 BEGIN_EXPECTATIONS +11 9:00 Temperature 21 +11 9:00 WaterVolume 0 +11 9:00 Light 50 +11 9:00 EXP_WaterVolume 40 +11 9:00 Moisture 29 +11 9:00 Fertilizer 1.0 +11 9:00 END_EXPECTATIONS +11 9:01 WaterVolume 40 + +11 10:00 BEGIN_EXPECTATIONS +11 10:00 Temperature 21 +11 10:00 WaterVolume 0 +11 10:00 Light 50 +11 10:00 EXP_WaterVolume 40 +11 10:00 Moisture 29 +11 10:00 Fertilizer 1.2 +11 10:00 END_EXPECTATIONS +11 10:01 WaterVolume 40 + +11 11:00 BEGIN_EXPECTATIONS +11 11:00 Temperature 22 +11 11:00 WaterVolume 0 +11 11:00 Light 60 +11 11:00 EXP_WaterVolume 40 +11 11:00 Moisture 28 +11 11:00 Fertilizer 2.6 +11 11:00 END_EXPECTATIONS +11 11:01 WaterVolume 40 + +11 12:00 BEGIN_EXPECTATIONS +11 12:00 Temperature 23 +11 12:00 WaterVolume 0 +11 12:00 Light 80 +11 12:00 EXP_WaterVolume 40 +11 12:00 Moisture 28 +11 12:00 Fertilizer 1.8 +11 12:00 END_EXPECTATIONS +11 12:01 WaterVolume 40 + +11 13:00 BEGIN_EXPECTATIONS +11 13:00 Temperature 22 +11 13:00 WaterVolume 0 +11 13:00 Light 70 +11 13:00 EXP_WaterVolume 40 +11 13:00 Moisture 29 +11 13:00 Fertilizer 1.5 +11 13:00 END_EXPECTATIONS +11 13:01 WaterVolume 40 + +11 14:00 BEGIN_EXPECTATIONS +11 14:00 Temperature 22 +11 14:00 WaterVolume 0 +11 14:00 Light 70 +11 14:00 EXP_WaterVolume 40 +11 14:00 Moisture 29 +11 14:00 Fertilizer 2.2 +11 14:00 END_EXPECTATIONS +11 14:01 WaterVolume 40 + +11 15:00 BEGIN_EXPECTATIONS +11 15:00 Temperature 22 +11 15:00 WaterVolume 0 +11 15:00 Light 70 +11 15:00 EXP_WaterVolume 80 +11 15:00 Moisture 0 +11 15:00 Fertilizer 1.5 +11 15:00 END_EXPECTATIONS +11 15:01 WaterVolume 80 + +11 16:00 BEGIN_EXPECTATIONS +11 16:00 Temperature 22 +11 16:00 WaterVolume 0 +11 16:00 Light 65 +11 16:00 EXP_WaterVolume 80 +11 16:00 Moisture 3 +11 16:00 Fertilizer 1.7 +11 16:00 END_EXPECTATIONS +11 16:01 WaterVolume 80 + +11 17:00 BEGIN_EXPECTATIONS +11 17:00 Temperature 22 +11 17:00 WaterVolume 0 +11 17:00 Light 60 +11 17:00 EXP_WaterVolume 60 +11 17:00 Moisture 10 +11 17:00 Fertilizer 1.2 +11 17:00 END_EXPECTATIONS +11 17:01 WaterVolume 60 + +11 18:00 BEGIN_EXPECTATIONS +11 18:00 Temperature 21 +11 18:00 WaterVolume 0 +11 18:00 Light 50 +11 18:00 EXP_WaterVolume 60 +11 18:00 Moisture 13 +11 18:00 Fertilizer 1.2 +11 18:00 END_EXPECTATIONS +11 18:01 WaterVolume 60 + +11 19:00 BEGIN_EXPECTATIONS +11 19:00 Temperature 20 +11 19:00 WaterVolume 0 +11 19:00 Light 30 +11 19:00 EXP_WaterVolume 60 +11 19:00 Moisture 15 +11 19:00 Fertilizer 2.2 +11 19:00 END_EXPECTATIONS +11 19:01 WaterVolume 60 + +11 20:00 BEGIN_EXPECTATIONS +11 20:00 Temperature 19 +11 20:00 WaterVolume 0 +11 20:00 Light 10 +11 20:00 EXP_WaterVolume 60 +11 20:00 Moisture 18 +11 20:00 Fertilizer 2.5 +11 20:00 END_EXPECTATIONS +11 20:01 WaterVolume 60 + +11 21:00 BEGIN_EXPECTATIONS +11 21:00 Temperature 19 +11 21:00 WaterVolume 0 +11 21:00 Light 10 +11 21:00 EXP_WaterVolume 40 +11 21:00 Moisture 20 +11 21:00 Fertilizer 2.8 +11 21:00 END_EXPECTATIONS +11 21:01 WaterVolume 40 + +11 22:00 BEGIN_EXPECTATIONS +11 22:00 Temperature 19 +11 22:00 WaterVolume 0 +11 22:00 Light 10 +11 22:00 EXP_WaterVolume 40 +11 22:00 Moisture 20 +11 22:00 Fertilizer 2.7 +11 22:00 END_EXPECTATIONS +11 22:01 WaterVolume 40 + +11 23:00 BEGIN_EXPECTATIONS +11 23:00 Temperature 19 +11 23:00 WaterVolume 0 +11 23:00 Light 10 +11 23:00 EXP_WaterVolume 40 +11 23:00 Moisture 20 +11 23:00 Fertilizer 2.0 +11 23:00 END_EXPECTATIONS +11 23:01 WaterVolume 40 + +### Saturday ### +12 0:00 BEGIN_EXPECTATIONS +12 0:00 Temperature 23 +12 0:00 WaterVolume 0 +12 0:00 Light 10 +12 0:00 EXP_WaterVolume 40 +12 0:00 Moisture 20 +12 0:00 Fertilizer 1.0 +12 0:00 END_EXPECTATIONS +12 0:01 WaterVolume 40 + +12 1:00 BEGIN_EXPECTATIONS +12 1:00 Temperature 23 +12 1:00 WaterVolume 0 +12 1:00 Light 11 +12 1:00 EXP_WaterVolume 60 +12 1:00 Moisture 19 +12 1:00 Fertilizer 1.8 +12 1:00 END_EXPECTATIONS +12 1:01 WaterVolume 60 + +12 2:00 BEGIN_EXPECTATIONS +12 2:00 Temperature 23 +12 2:00 WaterVolume 0 +12 2:00 Light 13 +12 2:00 EXP_WaterVolume 40 +12 2:00 Moisture 24 +12 2:00 Fertilizer 2.9 +12 2:00 END_EXPECTATIONS +12 2:01 WaterVolume 40 + +12 3:00 BEGIN_EXPECTATIONS +12 3:00 Temperature 23 +12 3:00 WaterVolume 0 +12 3:00 Light 15 +12 3:00 EXP_WaterVolume 40 +12 3:00 Moisture 24 +12 3:00 Fertilizer 1.0 +12 3:00 END_EXPECTATIONS +12 3:01 WaterVolume 40 + +12 4:00 BEGIN_EXPECTATIONS +12 4:00 Temperature 24 +12 4:00 WaterVolume 0 +12 4:00 Light 20 +12 4:00 EXP_WaterVolume 40 +12 4:00 Moisture 26 +12 4:00 Fertilizer 2.5 +12 4:00 END_EXPECTATIONS +12 4:01 WaterVolume 40 + +12 5:00 BEGIN_EXPECTATIONS +12 5:00 Temperature 24 +12 5:00 WaterVolume 0 +12 5:00 Light 25 +12 5:00 EXP_WaterVolume 40 +12 5:00 Moisture 25 +12 5:00 Fertilizer 2.2 +12 5:00 END_EXPECTATIONS +12 5:01 WaterVolume 40 + +12 6:00 BEGIN_EXPECTATIONS +12 6:00 Temperature 25 +12 6:00 WaterVolume 0 +12 6:00 Light 40 +12 6:00 EXP_WaterVolume 40 +12 6:00 Moisture 24 +12 6:00 Fertilizer 1.4 +12 6:00 END_EXPECTATIONS +12 6:01 WaterVolume 40 + +12 7:00 BEGIN_EXPECTATIONS +12 7:00 Temperature 25 +12 7:00 WaterVolume 0 +12 7:00 Light 45 +12 7:00 EXP_WaterVolume 40 +12 7:00 Moisture 23 +12 7:00 Fertilizer 1.3 +12 7:00 END_EXPECTATIONS +12 7:01 WaterVolume 40 + +12 8:00 BEGIN_EXPECTATIONS +12 8:00 Temperature 25 +12 8:00 WaterVolume 0 +12 8:00 Light 50 +12 8:00 EXP_WaterVolume 40 +12 8:00 Moisture 23 +12 8:00 Fertilizer 1.6 +12 8:00 END_EXPECTATIONS +12 8:01 WaterVolume 40 + +12 9:00 BEGIN_EXPECTATIONS +12 9:00 Temperature 25 +12 9:00 WaterVolume 0 +12 9:00 Light 50 +12 9:00 EXP_WaterVolume 40 +12 9:00 Moisture 24 +12 9:00 Fertilizer 1.7 +12 9:00 END_EXPECTATIONS +12 9:01 WaterVolume 40 + +12 10:00 BEGIN_EXPECTATIONS +12 10:00 Temperature 25 +12 10:00 WaterVolume 0 +12 10:00 Light 50 +12 10:00 EXP_WaterVolume 40 +12 10:00 Moisture 27 +12 10:00 Fertilizer 1.4 +12 10:00 END_EXPECTATIONS +12 10:01 WaterVolume 40 + +12 11:00 BEGIN_EXPECTATIONS +12 11:00 Temperature 26 +12 11:00 WaterVolume 0 +12 11:00 Light 60 +12 11:00 EXP_WaterVolume 40 +12 11:00 Moisture 28 +12 11:00 Fertilizer 2.3 +12 11:00 END_EXPECTATIONS +12 11:01 WaterVolume 40 + +12 12:00 BEGIN_EXPECTATIONS +12 12:00 Temperature 27 +12 12:00 WaterVolume 0 +12 12:00 Light 80 +12 12:00 EXP_WaterVolume 0 +12 12:00 Moisture 30 +12 12:00 Fertilizer 2.7 +12 12:00 END_EXPECTATIONS +12 12:01 WaterVolume 0 + +12 13:00 BEGIN_EXPECTATIONS +12 13:00 Temperature 26 +12 13:00 WaterVolume 0 +12 13:00 Light 70 +12 13:00 EXP_WaterVolume 40 +12 13:00 Moisture 26 +12 13:00 Fertilizer 2.3 +12 13:00 END_EXPECTATIONS +12 13:01 WaterVolume 40 + +12 14:00 BEGIN_EXPECTATIONS +12 14:00 Temperature 26 +12 14:00 WaterVolume 0 +12 14:00 Light 70 +12 14:00 EXP_WaterVolume 40 +12 14:00 Moisture 26 +12 14:00 Fertilizer 1.8 +12 14:00 END_EXPECTATIONS +12 14:01 WaterVolume 40 + +12 15:00 BEGIN_EXPECTATIONS +12 15:00 Temperature 26 +12 15:00 WaterVolume 0 +12 15:00 Light 70 +12 15:00 EXP_WaterVolume 40 +12 15:00 Moisture 25 +12 15:00 Fertilizer 1.9 +12 15:00 END_EXPECTATIONS +12 15:01 WaterVolume 40 + +12 16:00 BEGIN_EXPECTATIONS +12 16:00 Temperature 26 +12 16:00 WaterVolume 0 +12 16:00 Light 65 +12 16:00 EXP_WaterVolume 40 +12 16:00 Moisture 25 +12 16:00 Fertilizer 1.3 +12 16:00 END_EXPECTATIONS +12 16:01 WaterVolume 40 + +12 17:00 BEGIN_EXPECTATIONS +12 17:00 Temperature 26 +12 17:00 WaterVolume 0 +12 17:00 Light 60 +12 17:00 EXP_WaterVolume 40 +12 17:00 Moisture 24 +12 17:00 Fertilizer 1.0 +12 17:00 END_EXPECTATIONS +12 17:01 WaterVolume 40 + +12 18:00 BEGIN_EXPECTATIONS +12 18:00 Temperature 25 +12 18:00 WaterVolume 0 +12 18:00 Light 50 +12 18:00 EXP_WaterVolume 40 +12 18:00 Moisture 24 +12 18:00 Fertilizer 1.0 +12 18:00 END_EXPECTATIONS +12 18:01 WaterVolume 40 + +12 19:00 BEGIN_EXPECTATIONS +12 19:00 Temperature 24 +12 19:00 WaterVolume 0 +12 19:00 Light 30 +12 19:00 EXP_WaterVolume 40 +12 19:00 Moisture 27 +12 19:00 Fertilizer 2.2 +12 19:00 END_EXPECTATIONS +12 19:01 WaterVolume 40 + +12 20:00 BEGIN_EXPECTATIONS +12 20:00 Temperature 23 +12 20:00 WaterVolume 0 +12 20:00 Light 10 +12 20:00 EXP_WaterVolume 40 +12 20:00 Moisture 26 +12 20:00 Fertilizer 2.0 +12 20:00 END_EXPECTATIONS +12 20:01 WaterVolume 40 + +12 21:00 BEGIN_EXPECTATIONS +12 21:00 Temperature 23 +12 21:00 WaterVolume 0 +12 21:00 Light 10 +12 21:00 EXP_WaterVolume 40 +12 21:00 Moisture 25 +12 21:00 Fertilizer 1.7 +12 21:00 END_EXPECTATIONS +12 21:01 WaterVolume 40 + +12 22:00 BEGIN_EXPECTATIONS +12 22:00 Temperature 23 +12 22:00 WaterVolume 0 +12 22:00 Light 10 +12 22:00 EXP_WaterVolume 40 +12 22:00 Moisture 27 +12 22:00 Fertilizer 1.9 +12 22:00 END_EXPECTATIONS +12 22:01 WaterVolume 40 + +12 23:00 BEGIN_EXPECTATIONS +12 23:00 Temperature 23 +12 23:00 WaterVolume 0 +12 23:00 Light 10 +12 23:00 EXP_WaterVolume 40 +12 23:00 Moisture 28 +12 23:00 Fertilizer 2.4 +12 23:00 END_EXPECTATIONS +12 23:01 WaterVolume 40 + +### Sunday ### +13 0:00 BEGIN_EXPECTATIONS +13 0:00 Temperature 24 +13 0:00 WaterVolume 0 +13 0:00 Light 10 +13 0:00 EXP_WaterVolume 40 +13 0:00 Moisture 29 +13 0:00 Fertilizer 2.4 +13 0:00 END_EXPECTATIONS +13 0:01 WaterVolume 40 + +13 1:00 BEGIN_EXPECTATIONS +13 1:00 Temperature 24 +13 1:00 WaterVolume 0 +13 1:00 Light 11 +13 1:00 EXP_WaterVolume 0 +13 1:00 Moisture 32 +13 1:00 Fertilizer 1.0 +13 1:00 END_EXPECTATIONS +13 1:01 WaterVolume 0 + +13 2:00 BEGIN_EXPECTATIONS +13 2:00 Temperature 24 +13 2:00 WaterVolume 0 +13 2:00 Light 13 +13 2:00 EXP_WaterVolume 0 +13 2:00 Moisture 30 +13 2:00 Fertilizer 1.2 +13 2:00 END_EXPECTATIONS +13 2:01 WaterVolume 0 + +13 3:00 BEGIN_EXPECTATIONS +13 3:00 Temperature 24 +13 3:00 WaterVolume 0 +13 3:00 Light 15 +13 3:00 EXP_WaterVolume 40 +13 3:00 Moisture 26 +13 3:00 Fertilizer 1.0 +13 3:00 END_EXPECTATIONS +13 3:01 WaterVolume 40 + +13 4:00 BEGIN_EXPECTATIONS +13 4:00 Temperature 25 +13 4:00 WaterVolume 0 +13 4:00 Light 20 +13 4:00 EXP_WaterVolume 40 +13 4:00 Moisture 26 +13 4:00 Fertilizer 1.1 +13 4:00 END_EXPECTATIONS +13 4:01 WaterVolume 40 + +13 5:00 BEGIN_EXPECTATIONS +13 5:00 Temperature 25 +13 5:00 WaterVolume 0 +13 5:00 Light 25 +13 5:00 EXP_WaterVolume 40 +13 5:00 Moisture 29 +13 5:00 Fertilizer 2.5 +13 5:00 END_EXPECTATIONS +13 5:01 WaterVolume 40 + +13 6:00 BEGIN_EXPECTATIONS +13 6:00 Temperature 26 +13 6:00 WaterVolume 0 +13 6:00 Light 40 +13 6:00 EXP_WaterVolume 0 +13 6:00 Moisture 31 +13 6:00 Fertilizer 1.8 +13 6:00 END_EXPECTATIONS +13 6:01 WaterVolume 0 + +13 7:00 BEGIN_EXPECTATIONS +13 7:00 Temperature 26 +13 7:00 WaterVolume 0 +13 7:00 Light 45 +13 7:00 EXP_WaterVolume 40 +13 7:00 Moisture 26 +13 7:00 Fertilizer 1.8 +13 7:00 END_EXPECTATIONS +13 7:01 WaterVolume 40 + +13 8:00 BEGIN_EXPECTATIONS +13 8:00 Temperature 26 +13 8:00 WaterVolume 0 +13 8:00 Light 50 +13 8:00 EXP_WaterVolume 40 +13 8:00 Moisture 25 +13 8:00 Fertilizer 1.8 +13 8:00 END_EXPECTATIONS +13 8:01 WaterVolume 40 + +13 9:00 BEGIN_EXPECTATIONS +13 9:00 Temperature 26 +13 9:00 WaterVolume 0 +13 9:00 Light 50 +13 9:00 EXP_WaterVolume 40 +13 9:00 Moisture 29 +13 9:00 Fertilizer 1.2 +13 9:00 END_EXPECTATIONS +13 9:01 WaterVolume 40 + +13 10:00 BEGIN_EXPECTATIONS +13 10:00 Temperature 26 +13 10:00 WaterVolume 0 +13 10:00 Light 50 +13 10:00 EXP_WaterVolume 40 +13 10:00 Moisture 29 +13 10:00 Fertilizer 1.8 +13 10:00 END_EXPECTATIONS +13 10:01 WaterVolume 40 + +13 11:00 BEGIN_EXPECTATIONS +13 11:00 Temperature 27 +13 11:00 WaterVolume 0 +13 11:00 Light 60 +13 11:00 EXP_WaterVolume 0 +13 11:00 Moisture 31 +13 11:00 Fertilizer 2.0 +13 11:00 END_EXPECTATIONS +13 11:01 WaterVolume 0 + +13 12:00 BEGIN_EXPECTATIONS +13 12:00 Temperature 28 +13 12:00 WaterVolume 0 +13 12:00 Light 80 +13 12:00 EXP_WaterVolume 40 +13 12:00 Moisture 27 +13 12:00 Fertilizer 2.6 +13 12:00 END_EXPECTATIONS +13 12:01 WaterVolume 40 + +13 13:00 BEGIN_EXPECTATIONS +13 13:00 Temperature 27 +13 13:00 WaterVolume 0 +13 13:00 Light 70 +13 13:00 EXP_WaterVolume 40 +13 13:00 Moisture 28 +13 13:00 Fertilizer 2.7 +13 13:00 END_EXPECTATIONS +13 13:01 WaterVolume 40 + +13 14:00 BEGIN_EXPECTATIONS +13 14:00 Temperature 27 +13 14:00 WaterVolume 0 +13 14:00 Light 70 +13 14:00 EXP_WaterVolume 80 +13 14:00 Moisture 0 +13 14:00 Fertilizer 2.8 +13 14:00 END_EXPECTATIONS +13 14:01 WaterVolume 80 + +13 15:00 BEGIN_EXPECTATIONS +13 15:00 Temperature 27 +13 15:00 WaterVolume 0 +13 15:00 Light 70 +13 15:00 EXP_WaterVolume 80 +13 15:00 Moisture 5 +13 15:00 Fertilizer 1.0 +13 15:00 END_EXPECTATIONS +13 15:01 WaterVolume 80 + +13 16:00 BEGIN_EXPECTATIONS +13 16:00 Temperature 27 +13 16:00 WaterVolume 0 +13 16:00 Light 65 +13 16:00 EXP_WaterVolume 80 +13 16:00 Moisture 8 +13 16:00 Fertilizer 1.6 +13 16:00 END_EXPECTATIONS +13 16:01 WaterVolume 80 + +13 17:00 BEGIN_EXPECTATIONS +13 17:00 Temperature 27 +13 17:00 WaterVolume 0 +13 17:00 Light 60 +13 17:00 EXP_WaterVolume 60 +13 17:00 Moisture 11 +13 17:00 Fertilizer 2.5 +13 17:00 END_EXPECTATIONS +13 17:01 WaterVolume 60 + +13 18:00 BEGIN_EXPECTATIONS +13 18:00 Temperature 26 +13 18:00 WaterVolume 0 +13 18:00 Light 50 +13 18:00 EXP_WaterVolume 60 +13 18:00 Moisture 15 +13 18:00 Fertilizer 1.5 +13 18:00 END_EXPECTATIONS +13 18:01 WaterVolume 60 + +13 19:00 BEGIN_EXPECTATIONS +13 19:00 Temperature 25 +13 19:00 WaterVolume 0 +13 19:00 Light 30 +13 19:00 EXP_WaterVolume 40 +13 19:00 Moisture 20 +13 19:00 Fertilizer 2.9 +13 19:00 END_EXPECTATIONS +13 19:01 WaterVolume 40 + +13 20:00 BEGIN_EXPECTATIONS +13 20:00 Temperature 24 +13 20:00 WaterVolume 0 +13 20:00 Light 10 +13 20:00 EXP_WaterVolume 40 +13 20:00 Moisture 23 +13 20:00 Fertilizer 1.4 +13 20:00 END_EXPECTATIONS +13 20:01 WaterVolume 40 + +13 21:00 BEGIN_EXPECTATIONS +13 21:00 Temperature 24 +13 21:00 WaterVolume 0 +13 21:00 Light 10 +13 21:00 EXP_WaterVolume 40 +13 21:00 Moisture 23 +13 21:00 Fertilizer 2.8 +13 21:00 END_EXPECTATIONS +13 21:01 WaterVolume 40 + +13 22:00 BEGIN_EXPECTATIONS +13 22:00 Temperature 24 +13 22:00 WaterVolume 0 +13 22:00 Light 10 +13 22:00 EXP_WaterVolume 40 +13 22:00 Moisture 26 +13 22:00 Fertilizer 1.7 +13 22:00 END_EXPECTATIONS +13 22:01 WaterVolume 40 + +13 23:00 BEGIN_EXPECTATIONS +13 23:00 Temperature 24 +13 23:00 WaterVolume 0 +13 23:00 Light 10 +13 23:00 EXP_WaterVolume 40 +13 23:00 Moisture 27 +13 23:00 Fertilizer 1.2 +13 23:00 END_EXPECTATIONS +13 23:01 WaterVolume 40 + + +#### Week 2 #### +### Monday ### +14 0:00 BEGIN_EXPECTATIONS +14 0:00 Temperature 19 +14 0:00 WaterVolume 0 +14 0:00 Light 10 +14 0:00 EXP_WaterVolume 0 +14 0:00 Moisture 31 +14 0:00 Fertilizer 2.6 +14 0:00 END_EXPECTATIONS +14 0:01 WaterVolume 0 + +14 1:00 BEGIN_EXPECTATIONS +14 1:00 Temperature 19 +14 1:00 WaterVolume 0 +14 1:00 Light 11 +14 1:00 EXP_WaterVolume 0 +14 1:00 Moisture 30 +14 1:00 Fertilizer 1.5 +14 1:00 END_EXPECTATIONS +14 1:01 WaterVolume 0 + +14 2:00 BEGIN_EXPECTATIONS +14 2:00 Temperature 19 +14 2:00 WaterVolume 0 +14 2:00 Light 13 +14 2:00 EXP_WaterVolume 40 +14 2:00 Moisture 28 +14 2:00 Fertilizer 1.3 +14 2:00 END_EXPECTATIONS +14 2:01 WaterVolume 40 + +14 3:00 BEGIN_EXPECTATIONS +14 3:00 Temperature 19 +14 3:00 WaterVolume 0 +14 3:00 Light 15 +14 3:00 EXP_WaterVolume 40 +14 3:00 Moisture 28 +14 3:00 Fertilizer 2.3 +14 3:00 END_EXPECTATIONS +14 3:01 WaterVolume 40 + +14 4:00 BEGIN_EXPECTATIONS +14 4:00 Temperature 20 +14 4:00 WaterVolume 0 +14 4:00 Light 20 +14 4:00 EXP_WaterVolume 0 +14 4:00 Moisture 31 +14 4:00 Fertilizer 2.0 +14 4:00 END_EXPECTATIONS +14 4:01 WaterVolume 0 + +14 5:00 BEGIN_EXPECTATIONS +14 5:00 Temperature 20 +14 5:00 WaterVolume 0 +14 5:00 Light 25 +14 5:00 EXP_WaterVolume 40 +14 5:00 Moisture 29 +14 5:00 Fertilizer 2.6 +14 5:00 END_EXPECTATIONS +14 5:01 WaterVolume 40 + +14 6:00 BEGIN_EXPECTATIONS +14 6:00 Temperature 21 +14 6:00 WaterVolume 0 +14 6:00 Light 40 +14 6:00 EXP_WaterVolume 0 +14 6:00 Moisture 30 +14 6:00 Fertilizer 1.2 +14 6:00 END_EXPECTATIONS +14 6:01 WaterVolume 0 + +14 7:00 BEGIN_EXPECTATIONS +14 7:00 Temperature 21 +14 7:00 WaterVolume 0 +14 7:00 Light 45 +14 7:00 EXP_WaterVolume 40 +14 7:00 Moisture 27 +14 7:00 Fertilizer 1.5 +14 7:00 END_EXPECTATIONS +14 7:01 WaterVolume 40 + +14 8:00 BEGIN_EXPECTATIONS +14 8:00 Temperature 21 +14 8:00 WaterVolume 0 +14 8:00 Light 50 +14 8:00 EXP_WaterVolume 0 +14 8:00 Moisture 31 +14 8:00 Fertilizer 1.3 +14 8:00 END_EXPECTATIONS +14 8:01 WaterVolume 0 + +14 9:00 BEGIN_EXPECTATIONS +14 9:00 Temperature 21 +14 9:00 WaterVolume 0 +14 9:00 Light 50 +14 9:00 EXP_WaterVolume 0 +14 9:00 Moisture 31 +14 9:00 Fertilizer 2.9 +14 9:00 END_EXPECTATIONS +14 9:01 WaterVolume 0 + +14 10:00 BEGIN_EXPECTATIONS +14 10:00 Temperature 21 +14 10:00 WaterVolume 0 +14 10:00 Light 50 +14 10:00 EXP_WaterVolume 0 +14 10:00 Moisture 31 +14 10:00 Fertilizer 1.3 +14 10:00 END_EXPECTATIONS +14 10:01 WaterVolume 0 + +14 11:00 BEGIN_EXPECTATIONS +14 11:00 Temperature 22 +14 11:00 WaterVolume 0 +14 11:00 Light 60 +14 11:00 EXP_WaterVolume 0 +14 11:00 Moisture 30 +14 11:00 Fertilizer 2.1 +14 11:00 END_EXPECTATIONS +14 11:01 WaterVolume 0 + +14 12:00 BEGIN_EXPECTATIONS +14 12:00 Temperature 23 +14 12:00 WaterVolume 0 +14 12:00 Light 80 +14 12:00 EXP_WaterVolume 0 +14 12:00 Moisture 30 +14 12:00 Fertilizer 2.4 +14 12:00 END_EXPECTATIONS +14 12:01 WaterVolume 0 + +14 13:00 BEGIN_EXPECTATIONS +14 13:00 Temperature 22 +14 13:00 WaterVolume 0 +14 13:00 Light 70 +14 13:00 EXP_WaterVolume 0 +14 13:00 Moisture 30 +14 13:00 Fertilizer 1.5 +14 13:00 END_EXPECTATIONS +14 13:01 WaterVolume 0 + +14 14:00 BEGIN_EXPECTATIONS +14 14:00 Temperature 22 +14 14:00 WaterVolume 0 +14 14:00 Light 70 +14 14:00 EXP_WaterVolume 40 +14 14:00 Moisture 26 +14 14:00 Fertilizer 2.4 +14 14:00 END_EXPECTATIONS +14 14:01 WaterVolume 40 + +14 15:00 BEGIN_EXPECTATIONS +14 15:00 Temperature 22 +14 15:00 WaterVolume 0 +14 15:00 Light 70 +14 15:00 EXP_WaterVolume 40 +14 15:00 Moisture 25 +14 15:00 Fertilizer 1.7 +14 15:00 END_EXPECTATIONS +14 15:01 WaterVolume 40 + +14 16:00 BEGIN_EXPECTATIONS +14 16:00 Temperature 22 +14 16:00 WaterVolume 0 +14 16:00 Light 65 +14 16:00 EXP_WaterVolume 40 +14 16:00 Moisture 29 +14 16:00 Fertilizer 2.7 +14 16:00 END_EXPECTATIONS +14 16:01 WaterVolume 40 + +14 17:00 BEGIN_EXPECTATIONS +14 17:00 Temperature 22 +14 17:00 WaterVolume 0 +14 17:00 Light 60 +14 17:00 EXP_WaterVolume 40 +14 17:00 Moisture 28 +14 17:00 Fertilizer 1.2 +14 17:00 END_EXPECTATIONS +14 17:01 WaterVolume 40 + +14 18:00 BEGIN_EXPECTATIONS +14 18:00 Temperature 21 +14 18:00 WaterVolume 0 +14 18:00 Light 50 +14 18:00 EXP_WaterVolume 40 +14 18:00 Moisture 27 +14 18:00 Fertilizer 1.1 +14 18:00 END_EXPECTATIONS +14 18:01 WaterVolume 40 + +14 19:00 BEGIN_EXPECTATIONS +14 19:00 Temperature 20 +14 19:00 WaterVolume 0 +14 19:00 Light 30 +14 19:00 EXP_WaterVolume 40 +14 19:00 Moisture 26 +14 19:00 Fertilizer 2.8 +14 19:00 END_EXPECTATIONS +14 19:01 WaterVolume 40 + +14 20:00 BEGIN_EXPECTATIONS +14 20:00 Temperature 19 +14 20:00 WaterVolume 0 +14 20:00 Light 10 +14 20:00 EXP_WaterVolume 40 +14 20:00 Moisture 29 +14 20:00 Fertilizer 2.2 +14 20:00 END_EXPECTATIONS +14 20:01 WaterVolume 40 + +14 21:00 BEGIN_EXPECTATIONS +14 21:00 Temperature 19 +14 21:00 WaterVolume 0 +14 21:00 Light 10 +14 21:00 EXP_WaterVolume 0 +14 21:00 Moisture 31 +14 21:00 Fertilizer 1.6 +14 21:00 END_EXPECTATIONS +14 21:01 WaterVolume 0 + +14 22:00 BEGIN_EXPECTATIONS +14 22:00 Temperature 19 +14 22:00 WaterVolume 0 +14 22:00 Light 10 +14 22:00 EXP_WaterVolume 40 +14 22:00 Moisture 27 +14 22:00 Fertilizer 1.1 +14 22:00 END_EXPECTATIONS +14 22:01 WaterVolume 40 + +14 23:00 BEGIN_EXPECTATIONS +14 23:00 Temperature 19 +14 23:00 WaterVolume 0 +14 23:00 Light 10 +14 23:00 EXP_WaterVolume 40 +14 23:00 Moisture 29 +14 23:00 Fertilizer 1.6 +14 23:00 END_EXPECTATIONS +14 23:01 WaterVolume 40 + +### Tuesday ### +15 0:00 BEGIN_EXPECTATIONS +15 0:00 Temperature 18 +15 0:00 WaterVolume 0 +15 0:00 Light 10 +15 0:00 EXP_WaterVolume 0 +15 0:00 Moisture 31 +15 0:00 Fertilizer 1.3 +15 0:00 END_EXPECTATIONS +15 0:01 WaterVolume 0 + +15 1:00 BEGIN_EXPECTATIONS +15 1:00 Temperature 18 +15 1:00 WaterVolume 0 +15 1:00 Light 11 +15 1:00 EXP_WaterVolume 40 +15 1:00 Moisture 29 +15 1:00 Fertilizer 2.6 +15 1:00 END_EXPECTATIONS +15 1:01 WaterVolume 40 + +15 2:00 BEGIN_EXPECTATIONS +15 2:00 Temperature 18 +15 2:00 WaterVolume 0 +15 2:00 Light 13 +15 2:00 EXP_WaterVolume 0 +15 2:00 Moisture 32 +15 2:00 Fertilizer 1.0 +15 2:00 END_EXPECTATIONS +15 2:01 WaterVolume 0 + +15 3:00 BEGIN_EXPECTATIONS +15 3:00 Temperature 18 +15 3:00 WaterVolume 0 +15 3:00 Light 15 +15 3:00 EXP_WaterVolume 40 +15 3:00 Moisture 29 +15 3:00 Fertilizer 1.5 +15 3:00 END_EXPECTATIONS +15 3:01 WaterVolume 40 + +15 4:00 BEGIN_EXPECTATIONS +15 4:00 Temperature 19 +15 4:00 WaterVolume 0 +15 4:00 Light 20 +15 4:00 EXP_WaterVolume 0 +15 4:00 Moisture 32 +15 4:00 Fertilizer 2.6 +15 4:00 END_EXPECTATIONS +15 4:01 WaterVolume 0 + +15 5:00 BEGIN_EXPECTATIONS +15 5:00 Temperature 19 +15 5:00 WaterVolume 0 +15 5:00 Light 25 +15 5:00 EXP_WaterVolume 40 +15 5:00 Moisture 29 +15 5:00 Fertilizer 1.2 +15 5:00 END_EXPECTATIONS +15 5:01 WaterVolume 40 + +15 6:00 BEGIN_EXPECTATIONS +15 6:00 Temperature 20 +15 6:00 WaterVolume 0 +15 6:00 Light 40 +15 6:00 EXP_WaterVolume 0 +15 6:00 Moisture 30 +15 6:00 Fertilizer 1.8 +15 6:00 END_EXPECTATIONS +15 6:01 WaterVolume 0 + +15 7:00 BEGIN_EXPECTATIONS +15 7:00 Temperature 20 +15 7:00 WaterVolume 0 +15 7:00 Light 45 +15 7:00 EXP_WaterVolume 40 +15 7:00 Moisture 29 +15 7:00 Fertilizer 1.1 +15 7:00 END_EXPECTATIONS +15 7:01 WaterVolume 40 + +15 8:00 BEGIN_EXPECTATIONS +15 8:00 Temperature 20 +15 8:00 WaterVolume 0 +15 8:00 Light 50 +15 8:00 EXP_WaterVolume 0 +15 8:00 Moisture 50 +15 8:00 Fertilizer 1.2 +15 8:00 END_EXPECTATIONS +15 8:01 WaterVolume 0 + +15 9:00 BEGIN_EXPECTATIONS +15 9:00 Temperature 20 +15 9:00 WaterVolume 0 +15 9:00 Light 50 +15 9:00 EXP_WaterVolume 0 +15 9:00 Moisture 49 +15 9:00 Fertilizer 2.6 +15 9:00 END_EXPECTATIONS +15 9:01 WaterVolume 0 + +15 10:00 BEGIN_EXPECTATIONS +15 10:00 Temperature 20 +15 10:00 WaterVolume 0 +15 10:00 Light 50 +15 10:00 EXP_WaterVolume 0 +15 10:00 Moisture 47 +15 10:00 Fertilizer 1.6 +15 10:00 END_EXPECTATIONS +15 10:01 WaterVolume 0 + +15 11:00 BEGIN_EXPECTATIONS +15 11:00 Temperature 21 +15 11:00 WaterVolume 0 +15 11:00 Light 60 +15 11:00 EXP_WaterVolume 0 +15 11:00 Moisture 43 +15 11:00 Fertilizer 2.4 +15 11:00 END_EXPECTATIONS +15 11:01 WaterVolume 0 + +15 12:00 BEGIN_EXPECTATIONS +15 12:00 Temperature 22 +15 12:00 WaterVolume 0 +15 12:00 Light 80 +15 12:00 EXP_WaterVolume 0 +15 12:00 Moisture 41 +15 12:00 Fertilizer 1.0 +15 12:00 END_EXPECTATIONS +15 12:01 WaterVolume 0 + +15 13:00 BEGIN_EXPECTATIONS +15 13:00 Temperature 21 +15 13:00 WaterVolume 0 +15 13:00 Light 70 +15 13:00 EXP_WaterVolume 0 +15 13:00 Moisture 36 +15 13:00 Fertilizer 1.3 +15 13:00 END_EXPECTATIONS +15 13:01 WaterVolume 0 + +15 14:00 BEGIN_EXPECTATIONS +15 14:00 Temperature 21 +15 14:00 WaterVolume 0 +15 14:00 Light 70 +15 14:00 EXP_WaterVolume 0 +15 14:00 Moisture 36 +15 14:00 Fertilizer 2.4 +15 14:00 END_EXPECTATIONS +15 14:01 WaterVolume 0 + +15 15:00 BEGIN_EXPECTATIONS +15 15:00 Temperature 21 +15 15:00 WaterVolume 0 +15 15:00 Light 70 +15 15:00 EXP_WaterVolume 0 +15 15:00 Moisture 35 +15 15:00 Fertilizer 1.2 +15 15:00 END_EXPECTATIONS +15 15:01 WaterVolume 0 + +15 16:00 BEGIN_EXPECTATIONS +15 16:00 Temperature 21 +15 16:00 WaterVolume 0 +15 16:00 Light 65 +15 16:00 EXP_WaterVolume 0 +15 16:00 Moisture 33 +15 16:00 Fertilizer 1.7 +15 16:00 END_EXPECTATIONS +15 16:01 WaterVolume 0 + +15 17:00 BEGIN_EXPECTATIONS +15 17:00 Temperature 21 +15 17:00 WaterVolume 0 +15 17:00 Light 60 +15 17:00 EXP_WaterVolume 40 +15 17:00 Moisture 29 +15 17:00 Fertilizer 1.0 +15 17:00 END_EXPECTATIONS +15 17:01 WaterVolume 40 + +15 18:00 BEGIN_EXPECTATIONS +15 18:00 Temperature 20 +15 18:00 WaterVolume 0 +15 18:00 Light 50 +15 18:00 EXP_WaterVolume 0 +15 18:00 Moisture 32 +15 18:00 Fertilizer 1.9 +15 18:00 END_EXPECTATIONS +15 18:01 WaterVolume 0 + +15 19:00 BEGIN_EXPECTATIONS +15 19:00 Temperature 19 +15 19:00 WaterVolume 0 +15 19:00 Light 30 +15 19:00 EXP_WaterVolume 40 +15 19:00 Moisture 27 +15 19:00 Fertilizer 2.3 +15 19:00 END_EXPECTATIONS +15 19:01 WaterVolume 40 + +15 20:00 BEGIN_EXPECTATIONS +15 20:00 Temperature 18 +15 20:00 WaterVolume 0 +15 20:00 Light 10 +15 20:00 EXP_WaterVolume 40 +15 20:00 Moisture 26 +15 20:00 Fertilizer 2.1 +15 20:00 END_EXPECTATIONS +15 20:01 WaterVolume 40 + +15 21:00 BEGIN_EXPECTATIONS +15 21:00 Temperature 18 +15 21:00 WaterVolume 0 +15 21:00 Light 10 +15 21:00 EXP_WaterVolume 0 +15 21:00 Moisture 30 +15 21:00 Fertilizer 2.7 +15 21:00 END_EXPECTATIONS +15 21:01 WaterVolume 0 + +15 22:00 BEGIN_EXPECTATIONS +15 22:00 Temperature 18 +15 22:00 WaterVolume 0 +15 22:00 Light 10 +15 22:00 EXP_WaterVolume 0 +15 22:00 Moisture 30 +15 22:00 Fertilizer 1.5 +15 22:00 END_EXPECTATIONS +15 22:01 WaterVolume 0 + +15 23:00 BEGIN_EXPECTATIONS +15 23:00 Temperature 18 +15 23:00 WaterVolume 0 +15 23:00 Light 10 +15 23:00 EXP_WaterVolume 40 +15 23:00 Moisture 27 +15 23:00 Fertilizer 1.0 +15 23:00 END_EXPECTATIONS +15 23:01 WaterVolume 40 + +### Wednesday ### +16 0:00 BEGIN_EXPECTATIONS +16 0:00 Temperature 15 +16 0:00 WaterVolume 0 +16 0:00 Light 10 +16 0:00 EXP_WaterVolume 0 +16 0:00 Moisture 50 +16 0:00 Fertilizer 1.5 +16 0:00 END_EXPECTATIONS +16 0:01 WaterVolume 0 + +16 1:00 BEGIN_EXPECTATIONS +16 1:00 Temperature 15 +16 1:00 WaterVolume 0 +16 1:00 Light 11 +16 1:00 EXP_WaterVolume 0 +16 1:00 Moisture 47 +16 1:00 Fertilizer 2.6 +16 1:00 END_EXPECTATIONS +16 1:01 WaterVolume 0 + +16 2:00 BEGIN_EXPECTATIONS +16 2:00 Temperature 15 +16 2:00 WaterVolume 0 +16 2:00 Light 13 +16 2:00 EXP_WaterVolume 0 +16 2:00 Moisture 47 +16 2:00 Fertilizer 2.9 +16 2:00 END_EXPECTATIONS +16 2:01 WaterVolume 0 + +16 3:00 BEGIN_EXPECTATIONS +16 3:00 Temperature 15 +16 3:00 WaterVolume 0 +16 3:00 Light 15 +16 3:00 EXP_WaterVolume 0 +16 3:00 Moisture 42 +16 3:00 Fertilizer 1.1 +16 3:00 END_EXPECTATIONS +16 3:01 WaterVolume 0 + +16 4:00 BEGIN_EXPECTATIONS +16 4:00 Temperature 16 +16 4:00 WaterVolume 0 +16 4:00 Light 20 +16 4:00 EXP_WaterVolume 0 +16 4:00 Moisture 40 +16 4:00 Fertilizer 2.1 +16 4:00 END_EXPECTATIONS +16 4:01 WaterVolume 0 + +16 5:00 BEGIN_EXPECTATIONS +16 5:00 Temperature 16 +16 5:00 WaterVolume 0 +16 5:00 Light 25 +16 5:00 EXP_WaterVolume 0 +16 5:00 Moisture 35 +16 5:00 Fertilizer 2.1 +16 5:00 END_EXPECTATIONS +16 5:01 WaterVolume 0 + +16 6:00 BEGIN_EXPECTATIONS +16 6:00 Temperature 17 +16 6:00 WaterVolume 0 +16 6:00 Light 40 +16 6:00 EXP_WaterVolume 0 +16 6:00 Moisture 32 +16 6:00 Fertilizer 1.8 +16 6:00 END_EXPECTATIONS +16 6:01 WaterVolume 0 + +16 7:00 BEGIN_EXPECTATIONS +16 7:00 Temperature 17 +16 7:00 WaterVolume 0 +16 7:00 Light 45 +16 7:00 EXP_WaterVolume 0 +16 7:00 Moisture 32 +16 7:00 Fertilizer 2.2 +16 7:00 END_EXPECTATIONS +16 7:01 WaterVolume 0 + +16 8:00 BEGIN_EXPECTATIONS +16 8:00 Temperature 17 +16 8:00 WaterVolume 0 +16 8:00 Light 50 +16 8:00 EXP_WaterVolume 0 +16 8:00 Moisture 32 +16 8:00 Fertilizer 2.9 +16 8:00 END_EXPECTATIONS +16 8:01 WaterVolume 0 + +16 9:00 BEGIN_EXPECTATIONS +16 9:00 Temperature 17 +16 9:00 WaterVolume 0 +16 9:00 Light 50 +16 9:00 EXP_WaterVolume 0 +16 9:00 Moisture 32 +16 9:00 Fertilizer 2.8 +16 9:00 END_EXPECTATIONS +16 9:01 WaterVolume 0 + +16 10:00 BEGIN_EXPECTATIONS +16 10:00 Temperature 17 +16 10:00 WaterVolume 0 +16 10:00 Light 50 +16 10:00 EXP_WaterVolume 40 +16 10:00 Moisture 27 +16 10:00 Fertilizer 2.5 +16 10:00 END_EXPECTATIONS +16 10:01 WaterVolume 40 + +16 11:00 BEGIN_EXPECTATIONS +16 11:00 Temperature 18 +16 11:00 WaterVolume 0 +16 11:00 Light 60 +16 11:00 EXP_WaterVolume 40 +16 11:00 Moisture 28 +16 11:00 Fertilizer 2.8 +16 11:00 END_EXPECTATIONS +16 11:01 WaterVolume 40 + +16 12:00 BEGIN_EXPECTATIONS +16 12:00 Temperature 19 +16 12:00 WaterVolume 0 +16 12:00 Light 80 +16 12:00 EXP_WaterVolume 0 +16 12:00 Moisture 32 +16 12:00 Fertilizer 1.7 +16 12:00 END_EXPECTATIONS +16 12:01 WaterVolume 0 + +16 13:00 BEGIN_EXPECTATIONS +16 13:00 Temperature 18 +16 13:00 WaterVolume 0 +16 13:00 Light 70 +16 13:00 EXP_WaterVolume 0 +16 13:00 Moisture 30 +16 13:00 Fertilizer 1.0 +16 13:00 END_EXPECTATIONS +16 13:01 WaterVolume 0 + +16 14:00 BEGIN_EXPECTATIONS +16 14:00 Temperature 18 +16 14:00 WaterVolume 0 +16 14:00 Light 70 +16 14:00 EXP_WaterVolume 40 +16 14:00 Moisture 27 +16 14:00 Fertilizer 1.8 +16 14:00 END_EXPECTATIONS +16 14:01 WaterVolume 40 + +16 15:00 BEGIN_EXPECTATIONS +16 15:00 Temperature 18 +16 15:00 WaterVolume 0 +16 15:00 Light 70 +16 15:00 EXP_WaterVolume 40 +16 15:00 Moisture 27 +16 15:00 Fertilizer 1.0 +16 15:00 END_EXPECTATIONS +16 15:01 WaterVolume 40 + +16 16:00 BEGIN_EXPECTATIONS +16 16:00 Temperature 18 +16 16:00 WaterVolume 0 +16 16:00 Light 65 +16 16:00 EXP_WaterVolume 40 +16 16:00 Moisture 29 +16 16:00 Fertilizer 2.5 +16 16:00 END_EXPECTATIONS +16 16:01 WaterVolume 40 + +16 17:00 BEGIN_EXPECTATIONS +16 17:00 Temperature 18 +16 17:00 WaterVolume 0 +16 17:00 Light 60 +16 17:00 EXP_WaterVolume 0 +16 17:00 Moisture 33 +16 17:00 Fertilizer 1.9 +16 17:00 END_EXPECTATIONS +16 17:01 WaterVolume 0 + +16 18:00 BEGIN_EXPECTATIONS +16 18:00 Temperature 17 +16 18:00 WaterVolume 0 +16 18:00 Light 50 +16 18:00 EXP_WaterVolume 40 +16 18:00 Moisture 29 +16 18:00 Fertilizer 1.5 +16 18:00 END_EXPECTATIONS +16 18:01 WaterVolume 40 + +16 19:00 BEGIN_EXPECTATIONS +16 19:00 Temperature 16 +16 19:00 WaterVolume 0 +16 19:00 Light 30 +16 19:00 EXP_WaterVolume 40 +16 19:00 Moisture 29 +16 19:00 Fertilizer 1.2 +16 19:00 END_EXPECTATIONS +16 19:01 WaterVolume 40 + +16 20:00 BEGIN_EXPECTATIONS +16 20:00 Temperature 15 +16 20:00 WaterVolume 0 +16 20:00 Light 10 +16 20:00 EXP_WaterVolume 40 +16 20:00 Moisture 28 +16 20:00 Fertilizer 2.1 +16 20:00 END_EXPECTATIONS +16 20:01 WaterVolume 40 + +16 21:00 BEGIN_EXPECTATIONS +16 21:00 Temperature 15 +16 21:00 WaterVolume 0 +16 21:00 Light 10 +16 21:00 EXP_WaterVolume 0 +16 21:00 Moisture 32 +16 21:00 Fertilizer 1.8 +16 21:00 END_EXPECTATIONS +16 21:01 WaterVolume 0 + +16 22:00 BEGIN_EXPECTATIONS +16 22:00 Temperature 15 +16 22:00 WaterVolume 0 +16 22:00 Light 10 +16 22:00 EXP_WaterVolume 40 +16 22:00 Moisture 28 +16 22:00 Fertilizer 1.7 +16 22:00 END_EXPECTATIONS +16 22:01 WaterVolume 40 + +16 23:00 BEGIN_EXPECTATIONS +16 23:00 Temperature 15 +16 23:00 WaterVolume 0 +16 23:00 Light 10 +16 23:00 EXP_WaterVolume 0 +16 23:00 Moisture 50 +16 23:00 Fertilizer 1.6 +16 23:00 END_EXPECTATIONS +16 23:01 WaterVolume 0 + +### Thursday ### +17 0:00 BEGIN_EXPECTATIONS +17 0:00 Temperature 23 +17 0:00 WaterVolume 0 +17 0:00 Light 10 +17 0:00 EXP_WaterVolume 0 +17 0:00 Moisture 49 +17 0:00 Fertilizer 1.1 +17 0:00 END_EXPECTATIONS +17 0:01 WaterVolume 0 + +17 1:00 BEGIN_EXPECTATIONS +17 1:00 Temperature 23 +17 1:00 WaterVolume 0 +17 1:00 Light 11 +17 1:00 EXP_WaterVolume 0 +17 1:00 Moisture 46 +17 1:00 Fertilizer 2.5 +17 1:00 END_EXPECTATIONS +17 1:01 WaterVolume 0 + +17 2:00 BEGIN_EXPECTATIONS +17 2:00 Temperature 23 +17 2:00 WaterVolume 0 +17 2:00 Light 13 +17 2:00 EXP_WaterVolume 0 +17 2:00 Moisture 44 +17 2:00 Fertilizer 2.1 +17 2:00 END_EXPECTATIONS +17 2:01 WaterVolume 0 + +17 3:00 BEGIN_EXPECTATIONS +17 3:00 Temperature 23 +17 3:00 WaterVolume 0 +17 3:00 Light 15 +17 3:00 EXP_WaterVolume 0 +17 3:00 Moisture 41 +17 3:00 Fertilizer 2.3 +17 3:00 END_EXPECTATIONS +17 3:01 WaterVolume 0 + +17 4:00 BEGIN_EXPECTATIONS +17 4:00 Temperature 24 +17 4:00 WaterVolume 0 +17 4:00 Light 20 +17 4:00 EXP_WaterVolume 0 +17 4:00 Moisture 41 +17 4:00 Fertilizer 1.2 +17 4:00 END_EXPECTATIONS +17 4:01 WaterVolume 0 + +17 5:00 BEGIN_EXPECTATIONS +17 5:00 Temperature 24 +17 5:00 WaterVolume 0 +17 5:00 Light 25 +17 5:00 EXP_WaterVolume 0 +17 5:00 Moisture 38 +17 5:00 Fertilizer 1.7 +17 5:00 END_EXPECTATIONS +17 5:01 WaterVolume 0 + +17 6:00 BEGIN_EXPECTATIONS +17 6:00 Temperature 25 +17 6:00 WaterVolume 0 +17 6:00 Light 40 +17 6:00 EXP_WaterVolume 0 +17 6:00 Moisture 37 +17 6:00 Fertilizer 2.9 +17 6:00 END_EXPECTATIONS +17 6:01 WaterVolume 0 + +17 7:00 BEGIN_EXPECTATIONS +17 7:00 Temperature 25 +17 7:00 WaterVolume 0 +17 7:00 Light 45 +17 7:00 EXP_WaterVolume 0 +17 7:00 Moisture 32 +17 7:00 Fertilizer 2.7 +17 7:00 END_EXPECTATIONS +17 7:01 WaterVolume 0 + +17 8:00 BEGIN_EXPECTATIONS +17 8:00 Temperature 25 +17 8:00 WaterVolume 0 +17 8:00 Light 50 +17 8:00 EXP_WaterVolume 40 +17 8:00 Moisture 29 +17 8:00 Fertilizer 2.1 +17 8:00 END_EXPECTATIONS +17 8:01 WaterVolume 40 + +17 9:00 BEGIN_EXPECTATIONS +17 9:00 Temperature 25 +17 9:00 WaterVolume 0 +17 9:00 Light 50 +17 9:00 EXP_WaterVolume 0 +17 9:00 Moisture 33 +17 9:00 Fertilizer 2.7 +17 9:00 END_EXPECTATIONS +17 9:01 WaterVolume 0 + +17 10:00 BEGIN_EXPECTATIONS +17 10:00 Temperature 25 +17 10:00 WaterVolume 0 +17 10:00 Light 50 +17 10:00 EXP_WaterVolume 40 +17 10:00 Moisture 28 +17 10:00 Fertilizer 1.6 +17 10:00 END_EXPECTATIONS +17 10:01 WaterVolume 40 + +17 11:00 BEGIN_EXPECTATIONS +17 11:00 Temperature 26 +17 11:00 WaterVolume 0 +17 11:00 Light 60 +17 11:00 EXP_WaterVolume 40 +17 11:00 Moisture 27 +17 11:00 Fertilizer 1.8 +17 11:00 END_EXPECTATIONS +17 11:01 WaterVolume 40 + +17 12:00 BEGIN_EXPECTATIONS +17 12:00 Temperature 27 +17 12:00 WaterVolume 0 +17 12:00 Light 80 +17 12:00 EXP_WaterVolume 40 +17 12:00 Moisture 27 +17 12:00 Fertilizer 2.9 +17 12:00 END_EXPECTATIONS +17 12:01 WaterVolume 40 + +17 13:00 BEGIN_EXPECTATIONS +17 13:00 Temperature 26 +17 13:00 WaterVolume 0 +17 13:00 Light 70 +17 13:00 EXP_WaterVolume 40 +17 13:00 Moisture 26 +17 13:00 Fertilizer 1.9 +17 13:00 END_EXPECTATIONS +17 13:01 WaterVolume 40 + +17 14:00 BEGIN_EXPECTATIONS +17 14:00 Temperature 26 +17 14:00 WaterVolume 0 +17 14:00 Light 70 +17 14:00 EXP_WaterVolume 40 +17 14:00 Moisture 25 +17 14:00 Fertilizer 2.6 +17 14:00 END_EXPECTATIONS +17 14:01 WaterVolume 40 + +17 15:00 BEGIN_EXPECTATIONS +17 15:00 Temperature 26 +17 15:00 WaterVolume 0 +17 15:00 Light 70 +17 15:00 EXP_WaterVolume 40 +17 15:00 Moisture 26 +17 15:00 Fertilizer 2.5 +17 15:00 END_EXPECTATIONS +17 15:01 WaterVolume 40 + +17 16:00 BEGIN_EXPECTATIONS +17 16:00 Temperature 26 +17 16:00 WaterVolume 0 +17 16:00 Light 65 +17 16:00 EXP_WaterVolume 40 +17 16:00 Moisture 25 +17 16:00 Fertilizer 2.8 +17 16:00 END_EXPECTATIONS +17 16:01 WaterVolume 40 + +17 17:00 BEGIN_EXPECTATIONS +17 17:00 Temperature 26 +17 17:00 WaterVolume 0 +17 17:00 Light 60 +17 17:00 EXP_WaterVolume 40 +17 17:00 Moisture 29 +17 17:00 Fertilizer 1.0 +17 17:00 END_EXPECTATIONS +17 17:01 WaterVolume 40 + +17 18:00 BEGIN_EXPECTATIONS +17 18:00 Temperature 25 +17 18:00 WaterVolume 0 +17 18:00 Light 50 +17 18:00 EXP_WaterVolume 0 +17 18:00 Moisture 33 +17 18:00 Fertilizer 2.0 +17 18:00 END_EXPECTATIONS +17 18:01 WaterVolume 0 + +17 19:00 BEGIN_EXPECTATIONS +17 19:00 Temperature 24 +17 19:00 WaterVolume 0 +17 19:00 Light 30 +17 19:00 EXP_WaterVolume 40 +17 19:00 Moisture 28 +17 19:00 Fertilizer 2.8 +17 19:00 END_EXPECTATIONS +17 19:01 WaterVolume 40 + +17 20:00 BEGIN_EXPECTATIONS +17 20:00 Temperature 23 +17 20:00 WaterVolume 0 +17 20:00 Light 10 +17 20:00 EXP_WaterVolume 0 +17 20:00 Moisture 31 +17 20:00 Fertilizer 1.9 +17 20:00 END_EXPECTATIONS +17 20:01 WaterVolume 0 + +17 21:00 BEGIN_EXPECTATIONS +17 21:00 Temperature 23 +17 21:00 WaterVolume 0 +17 21:00 Light 10 +17 21:00 EXP_WaterVolume 40 +17 21:00 Moisture 27 +17 21:00 Fertilizer 2.1 +17 21:00 END_EXPECTATIONS +17 21:01 WaterVolume 40 + +17 22:00 BEGIN_EXPECTATIONS +17 22:00 Temperature 23 +17 22:00 WaterVolume 0 +17 22:00 Light 10 +17 22:00 EXP_WaterVolume 40 +17 22:00 Moisture 26 +17 22:00 Fertilizer 1.5 +17 22:00 END_EXPECTATIONS +17 22:01 WaterVolume 40 + +17 23:00 BEGIN_EXPECTATIONS +17 23:00 Temperature 23 +17 23:00 WaterVolume 0 +17 23:00 Light 10 +17 23:00 EXP_WaterVolume 40 +17 23:00 Moisture 27 +17 23:00 Fertilizer 2.2 +17 23:00 END_EXPECTATIONS +17 23:01 WaterVolume 40 + +### Friday ### +18 0:00 BEGIN_EXPECTATIONS +18 0:00 Temperature 18 +18 0:00 WaterVolume 0 +18 0:00 Light 10 +18 0:00 EXP_WaterVolume 0 +18 0:00 Moisture 30 +18 0:00 Fertilizer 1.1 +18 0:00 END_EXPECTATIONS +18 0:01 WaterVolume 0 + +18 1:00 BEGIN_EXPECTATIONS +18 1:00 Temperature 18 +18 1:00 WaterVolume 0 +18 1:00 Light 11 +18 1:00 EXP_WaterVolume 40 +18 1:00 Moisture 25 +18 1:00 Fertilizer 2.8 +18 1:00 END_EXPECTATIONS +18 1:01 WaterVolume 40 + +18 2:00 BEGIN_EXPECTATIONS +18 2:00 Temperature 18 +18 2:00 WaterVolume 0 +18 2:00 Light 13 +18 2:00 EXP_WaterVolume 40 +18 2:00 Moisture 29 +18 2:00 Fertilizer 1.5 +18 2:00 END_EXPECTATIONS +18 2:01 WaterVolume 40 + +18 3:00 BEGIN_EXPECTATIONS +18 3:00 Temperature 18 +18 3:00 WaterVolume 0 +18 3:00 Light 15 +18 3:00 EXP_WaterVolume 40 +18 3:00 Moisture 29 +18 3:00 Fertilizer 1.6 +18 3:00 END_EXPECTATIONS +18 3:01 WaterVolume 40 + +18 4:00 BEGIN_EXPECTATIONS +18 4:00 Temperature 19 +18 4:00 WaterVolume 0 +18 4:00 Light 20 +18 4:00 EXP_WaterVolume 0 +18 4:00 Moisture 33 +18 4:00 Fertilizer 1.3 +18 4:00 END_EXPECTATIONS +18 4:01 WaterVolume 0 + +18 5:00 BEGIN_EXPECTATIONS +18 5:00 Temperature 19 +18 5:00 WaterVolume 0 +18 5:00 Light 25 +18 5:00 EXP_WaterVolume 0 +18 5:00 Moisture 30 +18 5:00 Fertilizer 1.7 +18 5:00 END_EXPECTATIONS +18 5:01 WaterVolume 0 + +18 6:00 BEGIN_EXPECTATIONS +18 6:00 Temperature 20 +18 6:00 WaterVolume 0 +18 6:00 Light 40 +18 6:00 EXP_WaterVolume 40 +18 6:00 Moisture 28 +18 6:00 Fertilizer 1.0 +18 6:00 END_EXPECTATIONS +18 6:01 WaterVolume 40 + +18 7:00 BEGIN_EXPECTATIONS +18 7:00 Temperature 20 +18 7:00 WaterVolume 0 +18 7:00 Light 45 +18 7:00 EXP_WaterVolume 40 +18 7:00 Moisture 27 +18 7:00 Fertilizer 1.6 +18 7:00 END_EXPECTATIONS +18 7:01 WaterVolume 40 + +18 8:00 BEGIN_EXPECTATIONS +18 8:00 Temperature 20 +18 8:00 WaterVolume 0 +18 8:00 Light 50 +18 8:00 EXP_WaterVolume 0 +18 8:00 Moisture 31 +18 8:00 Fertilizer 1.8 +18 8:00 END_EXPECTATIONS +18 8:01 WaterVolume 0 + +18 9:00 BEGIN_EXPECTATIONS +18 9:00 Temperature 20 +18 9:00 WaterVolume 0 +18 9:00 Light 50 +18 9:00 EXP_WaterVolume 0 +18 9:00 Moisture 30 +18 9:00 Fertilizer 2.7 +18 9:00 END_EXPECTATIONS +18 9:01 WaterVolume 0 + +18 10:00 BEGIN_EXPECTATIONS +18 10:00 Temperature 20 +18 10:00 WaterVolume 0 +18 10:00 Light 50 +18 10:00 EXP_WaterVolume 40 +18 10:00 Moisture 27 +18 10:00 Fertilizer 2.2 +18 10:00 END_EXPECTATIONS +18 10:01 WaterVolume 40 + +18 11:00 BEGIN_EXPECTATIONS +18 11:00 Temperature 21 +18 11:00 WaterVolume 0 +18 11:00 Light 60 +18 11:00 EXP_WaterVolume 40 +18 11:00 Moisture 29 +18 11:00 Fertilizer 2.4 +18 11:00 END_EXPECTATIONS +18 11:01 WaterVolume 40 + +18 12:00 BEGIN_EXPECTATIONS +18 12:00 Temperature 22 +18 12:00 WaterVolume 0 +18 12:00 Light 80 +18 12:00 EXP_WaterVolume 0 +18 12:00 Moisture 33 +18 12:00 Fertilizer 1.4 +18 12:00 END_EXPECTATIONS +18 12:01 WaterVolume 0 + +18 13:00 BEGIN_EXPECTATIONS +18 13:00 Temperature 21 +18 13:00 WaterVolume 0 +18 13:00 Light 70 +18 13:00 EXP_WaterVolume 0 +18 13:00 Moisture 31 +18 13:00 Fertilizer 2.9 +18 13:00 END_EXPECTATIONS +18 13:01 WaterVolume 0 + +18 14:00 BEGIN_EXPECTATIONS +18 14:00 Temperature 21 +18 14:00 WaterVolume 0 +18 14:00 Light 70 +18 14:00 EXP_WaterVolume 40 +18 14:00 Moisture 26 +18 14:00 Fertilizer 2.0 +18 14:00 END_EXPECTATIONS +18 14:01 WaterVolume 40 + +18 15:00 BEGIN_EXPECTATIONS +18 15:00 Temperature 21 +18 15:00 WaterVolume 0 +18 15:00 Light 70 +18 15:00 EXP_WaterVolume 40 +18 15:00 Moisture 28 +18 15:00 Fertilizer 1.9 +18 15:00 END_EXPECTATIONS +18 15:01 WaterVolume 40 + +18 16:00 BEGIN_EXPECTATIONS +18 16:00 Temperature 21 +18 16:00 WaterVolume 0 +18 16:00 Light 65 +18 16:00 EXP_WaterVolume 40 +18 16:00 Moisture 27 +18 16:00 Fertilizer 2.0 +18 16:00 END_EXPECTATIONS +18 16:01 WaterVolume 40 + +18 17:00 BEGIN_EXPECTATIONS +18 17:00 Temperature 21 +18 17:00 WaterVolume 0 +18 17:00 Light 60 +18 17:00 EXP_WaterVolume 40 +18 17:00 Moisture 26 +18 17:00 Fertilizer 2.0 +18 17:00 END_EXPECTATIONS +18 17:01 WaterVolume 40 + +18 18:00 BEGIN_EXPECTATIONS +18 18:00 Temperature 20 +18 18:00 WaterVolume 0 +18 18:00 Light 50 +18 18:00 EXP_WaterVolume 40 +18 18:00 Moisture 27 +18 18:00 Fertilizer 1.7 +18 18:00 END_EXPECTATIONS +18 18:01 WaterVolume 40 + +18 19:00 BEGIN_EXPECTATIONS +18 19:00 Temperature 19 +18 19:00 WaterVolume 0 +18 19:00 Light 30 +18 19:00 EXP_WaterVolume 0 +18 19:00 Moisture 30 +18 19:00 Fertilizer 2.2 +18 19:00 END_EXPECTATIONS +18 19:01 WaterVolume 0 + +18 20:00 BEGIN_EXPECTATIONS +18 20:00 Temperature 18 +18 20:00 WaterVolume 0 +18 20:00 Light 10 +18 20:00 EXP_WaterVolume 40 +18 20:00 Moisture 26 +18 20:00 Fertilizer 2.1 +18 20:00 END_EXPECTATIONS +18 20:01 WaterVolume 40 + +18 21:00 BEGIN_EXPECTATIONS +18 21:00 Temperature 18 +18 21:00 WaterVolume 0 +18 21:00 Light 10 +18 21:00 EXP_WaterVolume 40 +18 21:00 Moisture 29 +18 21:00 Fertilizer 1.4 +18 21:00 END_EXPECTATIONS +18 21:01 WaterVolume 40 + +18 22:00 BEGIN_EXPECTATIONS +18 22:00 Temperature 18 +18 22:00 WaterVolume 0 +18 22:00 Light 10 +18 22:00 EXP_WaterVolume 40 +18 22:00 Moisture 29 +18 22:00 Fertilizer 1.7 +18 22:00 END_EXPECTATIONS +18 22:01 WaterVolume 40 + +18 23:00 BEGIN_EXPECTATIONS +18 23:00 Temperature 18 +18 23:00 WaterVolume 0 +18 23:00 Light 10 +18 23:00 EXP_WaterVolume 0 +18 23:00 Moisture 33 +18 23:00 Fertilizer 1.3 +18 23:00 END_EXPECTATIONS +18 23:01 WaterVolume 0 + +### Saturday ### +19 0:00 BEGIN_EXPECTATIONS +19 0:00 Temperature 19 +19 0:00 WaterVolume 0 +19 0:00 Light 10 +19 0:00 EXP_WaterVolume 0 +19 0:00 Moisture 30 +19 0:00 Fertilizer 2.4 +19 0:00 END_EXPECTATIONS +19 0:01 WaterVolume 0 + +19 1:00 BEGIN_EXPECTATIONS +19 1:00 Temperature 19 +19 1:00 WaterVolume 0 +19 1:00 Light 11 +19 1:00 EXP_WaterVolume 0 +19 1:00 Moisture 30 +19 1:00 Fertilizer 1.8 +19 1:00 END_EXPECTATIONS +19 1:01 WaterVolume 0 + +19 2:00 BEGIN_EXPECTATIONS +19 2:00 Temperature 19 +19 2:00 WaterVolume 0 +19 2:00 Light 13 +19 2:00 EXP_WaterVolume 40 +19 2:00 Moisture 26 +19 2:00 Fertilizer 2.1 +19 2:00 END_EXPECTATIONS +19 2:01 WaterVolume 40 + +19 3:00 BEGIN_EXPECTATIONS +19 3:00 Temperature 19 +19 3:00 WaterVolume 0 +19 3:00 Light 15 +19 3:00 EXP_WaterVolume 40 +19 3:00 Moisture 26 +19 3:00 Fertilizer 2.5 +19 3:00 END_EXPECTATIONS +19 3:01 WaterVolume 40 + +19 4:00 BEGIN_EXPECTATIONS +19 4:00 Temperature 20 +19 4:00 WaterVolume 0 +19 4:00 Light 20 +19 4:00 EXP_WaterVolume 40 +19 4:00 Moisture 26 +19 4:00 Fertilizer 1.4 +19 4:00 END_EXPECTATIONS +19 4:01 WaterVolume 40 + +19 5:00 BEGIN_EXPECTATIONS +19 5:00 Temperature 20 +19 5:00 WaterVolume 0 +19 5:00 Light 25 +19 5:00 EXP_WaterVolume 40 +19 5:00 Moisture 28 +19 5:00 Fertilizer 2.2 +19 5:00 END_EXPECTATIONS +19 5:01 WaterVolume 40 + +19 6:00 BEGIN_EXPECTATIONS +19 6:00 Temperature 21 +19 6:00 WaterVolume 0 +19 6:00 Light 40 +19 6:00 EXP_WaterVolume 40 +19 6:00 Moisture 28 +19 6:00 Fertilizer 2.9 +19 6:00 END_EXPECTATIONS +19 6:01 WaterVolume 40 + +19 7:00 BEGIN_EXPECTATIONS +19 7:00 Temperature 21 +19 7:00 WaterVolume 0 +19 7:00 Light 45 +19 7:00 EXP_WaterVolume 0 +19 7:00 Moisture 31 +19 7:00 Fertilizer 1.2 +19 7:00 END_EXPECTATIONS +19 7:01 WaterVolume 0 + +19 8:00 BEGIN_EXPECTATIONS +19 8:00 Temperature 21 +19 8:00 WaterVolume 0 +19 8:00 Light 50 +19 8:00 EXP_WaterVolume 0 +19 8:00 Moisture 30 +19 8:00 Fertilizer 2.8 +19 8:00 END_EXPECTATIONS +19 8:01 WaterVolume 0 + +19 9:00 BEGIN_EXPECTATIONS +19 9:00 Temperature 21 +19 9:00 WaterVolume 0 +19 9:00 Light 50 +19 9:00 EXP_WaterVolume 40 +19 9:00 Moisture 27 +19 9:00 Fertilizer 1.8 +19 9:00 END_EXPECTATIONS +19 9:01 WaterVolume 40 + +19 10:00 BEGIN_EXPECTATIONS +19 10:00 Temperature 21 +19 10:00 WaterVolume 0 +19 10:00 Light 50 +19 10:00 EXP_WaterVolume 0 +19 10:00 Moisture 31 +19 10:00 Fertilizer 1.3 +19 10:00 END_EXPECTATIONS +19 10:01 WaterVolume 0 + +19 11:00 BEGIN_EXPECTATIONS +19 11:00 Temperature 22 +19 11:00 WaterVolume 0 +19 11:00 Light 60 +19 11:00 EXP_WaterVolume 40 +19 11:00 Moisture 29 +19 11:00 Fertilizer 2.2 +19 11:00 END_EXPECTATIONS +19 11:01 WaterVolume 40 + +19 12:00 BEGIN_EXPECTATIONS +19 12:00 Temperature 23 +19 12:00 WaterVolume 0 +19 12:00 Light 80 +19 12:00 EXP_WaterVolume 0 +19 12:00 Moisture 30 +19 12:00 Fertilizer 2.8 +19 12:00 END_EXPECTATIONS +19 12:01 WaterVolume 0 + +19 13:00 BEGIN_EXPECTATIONS +19 13:00 Temperature 22 +19 13:00 WaterVolume 0 +19 13:00 Light 70 +19 13:00 EXP_WaterVolume 40 +19 13:00 Moisture 28 +19 13:00 Fertilizer 1.0 +19 13:00 END_EXPECTATIONS +19 13:01 WaterVolume 40 + +19 14:00 BEGIN_EXPECTATIONS +19 14:00 Temperature 22 +19 14:00 WaterVolume 0 +19 14:00 Light 70 +19 14:00 EXP_WaterVolume 40 +19 14:00 Moisture 29 +19 14:00 Fertilizer 2.9 +19 14:00 END_EXPECTATIONS +19 14:01 WaterVolume 40 + +19 15:00 BEGIN_EXPECTATIONS +19 15:00 Temperature 22 +19 15:00 WaterVolume 0 +19 15:00 Light 70 +19 15:00 EXP_WaterVolume 0 +19 15:00 Moisture 32 +19 15:00 Fertilizer 2.4 +19 15:00 END_EXPECTATIONS +19 15:01 WaterVolume 0 + +19 16:00 BEGIN_EXPECTATIONS +19 16:00 Temperature 22 +19 16:00 WaterVolume 0 +19 16:00 Light 65 +19 16:00 EXP_WaterVolume 0 +19 16:00 Moisture 30 +19 16:00 Fertilizer 1.0 +19 16:00 END_EXPECTATIONS +19 16:01 WaterVolume 0 + +19 17:00 BEGIN_EXPECTATIONS +19 17:00 Temperature 22 +19 17:00 WaterVolume 0 +19 17:00 Light 60 +19 17:00 EXP_WaterVolume 40 +19 17:00 Moisture 25 +19 17:00 Fertilizer 2.3 +19 17:00 END_EXPECTATIONS +19 17:01 WaterVolume 40 + +19 18:00 BEGIN_EXPECTATIONS +19 18:00 Temperature 21 +19 18:00 WaterVolume 0 +19 18:00 Light 50 +19 18:00 EXP_WaterVolume 40 +19 18:00 Moisture 25 +19 18:00 Fertilizer 1.9 +19 18:00 END_EXPECTATIONS +19 18:01 WaterVolume 40 + +19 19:00 BEGIN_EXPECTATIONS +19 19:00 Temperature 20 +19 19:00 WaterVolume 0 +19 19:00 Light 30 +19 19:00 EXP_WaterVolume 40 +19 19:00 Moisture 27 +19 19:00 Fertilizer 1.6 +19 19:00 END_EXPECTATIONS +19 19:01 WaterVolume 40 + +19 20:00 BEGIN_EXPECTATIONS +19 20:00 Temperature 19 +19 20:00 WaterVolume 0 +19 20:00 Light 10 +19 20:00 EXP_WaterVolume 40 +19 20:00 Moisture 26 +19 20:00 Fertilizer 1.5 +19 20:00 END_EXPECTATIONS +19 20:01 WaterVolume 40 + +19 21:00 BEGIN_EXPECTATIONS +19 21:00 Temperature 19 +19 21:00 WaterVolume 0 +19 21:00 Light 10 +19 21:00 EXP_WaterVolume 40 +19 21:00 Moisture 27 +19 21:00 Fertilizer 2.8 +19 21:00 END_EXPECTATIONS +19 21:01 WaterVolume 40 + +19 22:00 BEGIN_EXPECTATIONS +19 22:00 Temperature 19 +19 22:00 WaterVolume 0 +19 22:00 Light 10 +19 22:00 EXP_WaterVolume 40 +19 22:00 Moisture 29 +19 22:00 Fertilizer 2.7 +19 22:00 END_EXPECTATIONS +19 22:01 WaterVolume 40 + +19 23:00 BEGIN_EXPECTATIONS +19 23:00 Temperature 19 +19 23:00 WaterVolume 0 +19 23:00 Light 10 +19 23:00 EXP_WaterVolume 40 +19 23:00 Moisture 28 +19 23:00 Fertilizer 1.8 +19 23:00 END_EXPECTATIONS +19 23:01 WaterVolume 40 + +### Sunday ### +20 0:00 BEGIN_EXPECTATIONS +20 0:00 Temperature 21 +20 0:00 WaterVolume 0 +20 0:00 Light 10 +20 0:00 EXP_WaterVolume 40 +20 0:00 Moisture 27 +20 0:00 Fertilizer 2.4 +20 0:00 END_EXPECTATIONS +20 0:01 WaterVolume 40 + +20 1:00 BEGIN_EXPECTATIONS +20 1:00 Temperature 21 +20 1:00 WaterVolume 0 +20 1:00 Light 11 +20 1:00 EXP_WaterVolume 40 +20 1:00 Moisture 28 +20 1:00 Fertilizer 1.9 +20 1:00 END_EXPECTATIONS +20 1:01 WaterVolume 40 + +20 2:00 BEGIN_EXPECTATIONS +20 2:00 Temperature 21 +20 2:00 WaterVolume 0 +20 2:00 Light 13 +20 2:00 EXP_WaterVolume 0 +20 2:00 Moisture 32 +20 2:00 Fertilizer 1.8 +20 2:00 END_EXPECTATIONS +20 2:01 WaterVolume 0 + +20 3:00 BEGIN_EXPECTATIONS +20 3:00 Temperature 21 +20 3:00 WaterVolume 0 +20 3:00 Light 15 +20 3:00 EXP_WaterVolume 0 +20 3:00 Moisture 31 +20 3:00 Fertilizer 1.1 +20 3:00 END_EXPECTATIONS +20 3:01 WaterVolume 0 + +20 4:00 BEGIN_EXPECTATIONS +20 4:00 Temperature 22 +20 4:00 WaterVolume 0 +20 4:00 Light 20 +20 4:00 EXP_WaterVolume 40 +20 4:00 Moisture 26 +20 4:00 Fertilizer 2.9 +20 4:00 END_EXPECTATIONS +20 4:01 WaterVolume 40 + +20 5:00 BEGIN_EXPECTATIONS +20 5:00 Temperature 22 +20 5:00 WaterVolume 0 +20 5:00 Light 25 +20 5:00 EXP_WaterVolume 40 +20 5:00 Moisture 25 +20 5:00 Fertilizer 2.1 +20 5:00 END_EXPECTATIONS +20 5:01 WaterVolume 40 + +20 6:00 BEGIN_EXPECTATIONS +20 6:00 Temperature 23 +20 6:00 WaterVolume 0 +20 6:00 Light 40 +20 6:00 EXP_WaterVolume 40 +20 6:00 Moisture 24 +20 6:00 Fertilizer 1.2 +20 6:00 END_EXPECTATIONS +20 6:01 WaterVolume 40 + +20 7:00 BEGIN_EXPECTATIONS +20 7:00 Temperature 23 +20 7:00 WaterVolume 0 +20 7:00 Light 45 +20 7:00 EXP_WaterVolume 40 +20 7:00 Moisture 25 +20 7:00 Fertilizer 1.1 +20 7:00 END_EXPECTATIONS +20 7:01 WaterVolume 40 + +20 8:00 BEGIN_EXPECTATIONS +20 8:00 Temperature 23 +20 8:00 WaterVolume 0 +20 8:00 Light 50 +20 8:00 EXP_WaterVolume 40 +20 8:00 Moisture 24 +20 8:00 Fertilizer 2.5 +20 8:00 END_EXPECTATIONS +20 8:01 WaterVolume 40 + +20 9:00 BEGIN_EXPECTATIONS +20 9:00 Temperature 23 +20 9:00 WaterVolume 0 +20 9:00 Light 50 +20 9:00 EXP_WaterVolume 40 +20 9:00 Moisture 24 +20 9:00 Fertilizer 2.9 +20 9:00 END_EXPECTATIONS +20 9:01 WaterVolume 40 + +20 10:00 BEGIN_EXPECTATIONS +20 10:00 Temperature 23 +20 10:00 WaterVolume 0 +20 10:00 Light 50 +20 10:00 EXP_WaterVolume 40 +20 10:00 Moisture 27 +20 10:00 Fertilizer 1.0 +20 10:00 END_EXPECTATIONS +20 10:01 WaterVolume 40 + +20 11:00 BEGIN_EXPECTATIONS +20 11:00 Temperature 24 +20 11:00 WaterVolume 0 +20 11:00 Light 60 +20 11:00 EXP_WaterVolume 40 +20 11:00 Moisture 26 +20 11:00 Fertilizer 2.6 +20 11:00 END_EXPECTATIONS +20 11:01 WaterVolume 40 + +20 12:00 BEGIN_EXPECTATIONS +20 12:00 Temperature 25 +20 12:00 WaterVolume 0 +20 12:00 Light 80 +20 12:00 EXP_WaterVolume 40 +20 12:00 Moisture 29 +20 12:00 Fertilizer 1.3 +20 12:00 END_EXPECTATIONS +20 12:01 WaterVolume 40 + +20 13:00 BEGIN_EXPECTATIONS +20 13:00 Temperature 24 +20 13:00 WaterVolume 0 +20 13:00 Light 70 +20 13:00 EXP_WaterVolume 40 +20 13:00 Moisture 28 +20 13:00 Fertilizer 1.2 +20 13:00 END_EXPECTATIONS +20 13:01 WaterVolume 40 + +20 14:00 BEGIN_EXPECTATIONS +20 14:00 Temperature 24 +20 14:00 WaterVolume 0 +20 14:00 Light 70 +20 14:00 EXP_WaterVolume 40 +20 14:00 Moisture 28 +20 14:00 Fertilizer 2.7 +20 14:00 END_EXPECTATIONS +20 14:01 WaterVolume 40 + +20 15:00 BEGIN_EXPECTATIONS +20 15:00 Temperature 24 +20 15:00 WaterVolume 0 +20 15:00 Light 70 +20 15:00 EXP_WaterVolume 40 +20 15:00 Moisture 29 +20 15:00 Fertilizer 2.5 +20 15:00 END_EXPECTATIONS +20 15:01 WaterVolume 40 + +20 16:00 BEGIN_EXPECTATIONS +20 16:00 Temperature 24 +20 16:00 WaterVolume 0 +20 16:00 Light 65 +20 16:00 EXP_WaterVolume 0 +20 16:00 Moisture 31 +20 16:00 Fertilizer 2.0 +20 16:00 END_EXPECTATIONS +20 16:01 WaterVolume 0 + +20 17:00 BEGIN_EXPECTATIONS +20 17:00 Temperature 24 +20 17:00 WaterVolume 0 +20 17:00 Light 60 +20 17:00 EXP_WaterVolume 40 +20 17:00 Moisture 27 +20 17:00 Fertilizer 2.6 +20 17:00 END_EXPECTATIONS +20 17:01 WaterVolume 40 + +20 18:00 BEGIN_EXPECTATIONS +20 18:00 Temperature 23 +20 18:00 WaterVolume 0 +20 18:00 Light 50 +20 18:00 EXP_WaterVolume 40 +20 18:00 Moisture 28 +20 18:00 Fertilizer 1.5 +20 18:00 END_EXPECTATIONS +20 18:01 WaterVolume 40 + +20 19:00 BEGIN_EXPECTATIONS +20 19:00 Temperature 22 +20 19:00 WaterVolume 0 +20 19:00 Light 30 +20 19:00 EXP_WaterVolume 0 +20 19:00 Moisture 31 +20 19:00 Fertilizer 1.6 +20 19:00 END_EXPECTATIONS +20 19:01 WaterVolume 0 + +20 20:00 BEGIN_EXPECTATIONS +20 20:00 Temperature 21 +20 20:00 WaterVolume 0 +20 20:00 Light 10 +20 20:00 EXP_WaterVolume 0 +20 20:00 Moisture 31 +20 20:00 Fertilizer 1.4 +20 20:00 END_EXPECTATIONS +20 20:01 WaterVolume 0 + +20 21:00 BEGIN_EXPECTATIONS +20 21:00 Temperature 21 +20 21:00 WaterVolume 0 +20 21:00 Light 10 +20 21:00 EXP_WaterVolume 40 +20 21:00 Moisture 28 +20 21:00 Fertilizer 1.4 +20 21:00 END_EXPECTATIONS +20 21:01 WaterVolume 40 + +20 22:00 BEGIN_EXPECTATIONS +20 22:00 Temperature 21 +20 22:00 WaterVolume 0 +20 22:00 Light 10 +20 22:00 EXP_WaterVolume 0 +20 22:00 Moisture 30 +20 22:00 Fertilizer 2.0 +20 22:00 END_EXPECTATIONS +20 22:01 WaterVolume 0 + +20 23:00 BEGIN_EXPECTATIONS +20 23:00 Temperature 21 +20 23:00 WaterVolume 0 +20 23:00 Light 10 +20 23:00 EXP_WaterVolume 0 +20 23:00 Moisture 30 +20 23:00 Fertilizer 2.4 +20 23:00 END_EXPECTATIONS +20 23:01 WaterVolume 0 + + +#### Week 3 #### +### Monday ### +21 0:00 BEGIN_EXPECTATIONS +21 0:00 Temperature 22 +21 0:00 WaterVolume 0 +21 0:00 Light 10 +21 0:00 EXP_WaterVolume 40 +21 0:00 Moisture 29 +21 0:00 Fertilizer 1.2 +21 0:00 END_EXPECTATIONS +21 0:01 WaterVolume 40 + +21 1:00 BEGIN_EXPECTATIONS +21 1:00 Temperature 22 +21 1:00 WaterVolume 0 +21 1:00 Light 11 +21 1:00 EXP_WaterVolume 0 +21 1:00 Moisture 33 +21 1:00 Fertilizer 1.5 +21 1:00 END_EXPECTATIONS +21 1:01 WaterVolume 0 + +21 2:00 BEGIN_EXPECTATIONS +21 2:00 Temperature 22 +21 2:00 WaterVolume 0 +21 2:00 Light 13 +21 2:00 EXP_WaterVolume 40 +21 2:00 Moisture 28 +21 2:00 Fertilizer 2.3 +21 2:00 END_EXPECTATIONS +21 2:01 WaterVolume 40 + +21 3:00 BEGIN_EXPECTATIONS +21 3:00 Temperature 22 +21 3:00 WaterVolume 0 +21 3:00 Light 15 +21 3:00 EXP_WaterVolume 40 +21 3:00 Moisture 27 +21 3:00 Fertilizer 1.3 +21 3:00 END_EXPECTATIONS +21 3:01 WaterVolume 40 + +21 4:00 BEGIN_EXPECTATIONS +21 4:00 Temperature 23 +21 4:00 WaterVolume 0 +21 4:00 Light 20 +21 4:00 EXP_WaterVolume 40 +21 4:00 Moisture 27 +21 4:00 Fertilizer 1.2 +21 4:00 END_EXPECTATIONS +21 4:01 WaterVolume 40 + +21 5:00 BEGIN_EXPECTATIONS +21 5:00 Temperature 23 +21 5:00 WaterVolume 0 +21 5:00 Light 25 +21 5:00 EXP_WaterVolume 40 +21 5:00 Moisture 29 +21 5:00 Fertilizer 1.7 +21 5:00 END_EXPECTATIONS +21 5:01 WaterVolume 40 + +21 6:00 BEGIN_EXPECTATIONS +21 6:00 Temperature 24 +21 6:00 WaterVolume 0 +21 6:00 Light 40 +21 6:00 EXP_WaterVolume 0 +21 6:00 Moisture 31 +21 6:00 Fertilizer 1.7 +21 6:00 END_EXPECTATIONS +21 6:01 WaterVolume 0 + +21 7:00 BEGIN_EXPECTATIONS +21 7:00 Temperature 24 +21 7:00 WaterVolume 0 +21 7:00 Light 45 +21 7:00 EXP_WaterVolume 40 +21 7:00 Moisture 26 +21 7:00 Fertilizer 1.1 +21 7:00 END_EXPECTATIONS +21 7:01 WaterVolume 40 + +21 8:00 BEGIN_EXPECTATIONS +21 8:00 Temperature 24 +21 8:00 WaterVolume 0 +21 8:00 Light 50 +21 8:00 EXP_WaterVolume 0 +21 8:00 Moisture 30 +21 8:00 Fertilizer 1.3 +21 8:00 END_EXPECTATIONS +21 8:01 WaterVolume 0 + +21 9:00 BEGIN_EXPECTATIONS +21 9:00 Temperature 24 +21 9:00 WaterVolume 0 +21 9:00 Light 50 +21 9:00 EXP_WaterVolume 40 +21 9:00 Moisture 29 +21 9:00 Fertilizer 1.1 +21 9:00 END_EXPECTATIONS +21 9:01 WaterVolume 40 + +21 10:00 BEGIN_EXPECTATIONS +21 10:00 Temperature 24 +21 10:00 WaterVolume 0 +21 10:00 Light 50 +21 10:00 EXP_WaterVolume 0 +21 10:00 Moisture 30 +21 10:00 Fertilizer 1.5 +21 10:00 END_EXPECTATIONS +21 10:01 WaterVolume 0 + +21 11:00 BEGIN_EXPECTATIONS +21 11:00 Temperature 25 +21 11:00 WaterVolume 0 +21 11:00 Light 60 +21 11:00 EXP_WaterVolume 40 +21 11:00 Moisture 26 +21 11:00 Fertilizer 1.0 +21 11:00 END_EXPECTATIONS +21 11:01 WaterVolume 40 + +21 12:00 BEGIN_EXPECTATIONS +21 12:00 Temperature 26 +21 12:00 WaterVolume 0 +21 12:00 Light 80 +21 12:00 EXP_WaterVolume 40 +21 12:00 Moisture 29 +21 12:00 Fertilizer 1.7 +21 12:00 END_EXPECTATIONS +21 12:01 WaterVolume 40 + +21 13:00 BEGIN_EXPECTATIONS +21 13:00 Temperature 25 +21 13:00 WaterVolume 0 +21 13:00 Light 70 +21 13:00 EXP_WaterVolume 0 +21 13:00 Moisture 32 +21 13:00 Fertilizer 2.7 +21 13:00 END_EXPECTATIONS +21 13:01 WaterVolume 0 + +21 14:00 BEGIN_EXPECTATIONS +21 14:00 Temperature 25 +21 14:00 WaterVolume 0 +21 14:00 Light 70 +21 14:00 EXP_WaterVolume 40 +21 14:00 Moisture 29 +21 14:00 Fertilizer 1.2 +21 14:00 END_EXPECTATIONS +21 14:01 WaterVolume 40 + +21 15:00 BEGIN_EXPECTATIONS +21 15:00 Temperature 25 +21 15:00 WaterVolume 0 +21 15:00 Light 70 +21 15:00 EXP_WaterVolume 0 +21 15:00 Moisture 32 +21 15:00 Fertilizer 2.0 +21 15:00 END_EXPECTATIONS +21 15:01 WaterVolume 0 + +21 16:00 BEGIN_EXPECTATIONS +21 16:00 Temperature 25 +21 16:00 WaterVolume 0 +21 16:00 Light 65 +21 16:00 EXP_WaterVolume 0 +21 16:00 Moisture 31 +21 16:00 Fertilizer 2.4 +21 16:00 END_EXPECTATIONS +21 16:01 WaterVolume 0 + +21 17:00 BEGIN_EXPECTATIONS +21 17:00 Temperature 25 +21 17:00 WaterVolume 0 +21 17:00 Light 60 +21 17:00 EXP_WaterVolume 0 +21 17:00 Moisture 31 +21 17:00 Fertilizer 1.8 +21 17:00 END_EXPECTATIONS +21 17:01 WaterVolume 0 + +21 18:00 BEGIN_EXPECTATIONS +21 18:00 Temperature 24 +21 18:00 WaterVolume 0 +21 18:00 Light 50 +21 18:00 EXP_WaterVolume 0 +21 18:00 Moisture 31 +21 18:00 Fertilizer 2.9 +21 18:00 END_EXPECTATIONS +21 18:01 WaterVolume 0 + +21 19:00 BEGIN_EXPECTATIONS +21 19:00 Temperature 23 +21 19:00 WaterVolume 0 +21 19:00 Light 30 +21 19:00 EXP_WaterVolume 0 +21 19:00 Moisture 30 +21 19:00 Fertilizer 1.4 +21 19:00 END_EXPECTATIONS +21 19:01 WaterVolume 0 + +21 20:00 BEGIN_EXPECTATIONS +21 20:00 Temperature 22 +21 20:00 WaterVolume 0 +21 20:00 Light 10 +21 20:00 EXP_WaterVolume 40 +21 20:00 Moisture 27 +21 20:00 Fertilizer 2.4 +21 20:00 END_EXPECTATIONS +21 20:01 WaterVolume 40 + +21 21:00 BEGIN_EXPECTATIONS +21 21:00 Temperature 22 +21 21:00 WaterVolume 0 +21 21:00 Light 10 +21 21:00 EXP_WaterVolume 0 +21 21:00 Moisture 30 +21 21:00 Fertilizer 2.4 +21 21:00 END_EXPECTATIONS +21 21:01 WaterVolume 0 + +21 22:00 BEGIN_EXPECTATIONS +21 22:00 Temperature 22 +21 22:00 WaterVolume 0 +21 22:00 Light 10 +21 22:00 EXP_WaterVolume 0 +21 22:00 Moisture 30 +21 22:00 Fertilizer 2.9 +21 22:00 END_EXPECTATIONS +21 22:01 WaterVolume 0 + +21 23:00 BEGIN_EXPECTATIONS +21 23:00 Temperature 22 +21 23:00 WaterVolume 0 +21 23:00 Light 10 +21 23:00 EXP_WaterVolume 40 +21 23:00 Moisture 29 +21 23:00 Fertilizer 2.7 +21 23:00 END_EXPECTATIONS +21 23:01 WaterVolume 40 + +### Tuesday ### +22 0:00 BEGIN_EXPECTATIONS +22 0:00 Temperature 17 +22 0:00 WaterVolume 0 +22 0:00 Light 10 +22 0:00 EXP_WaterVolume 0 +22 0:00 Moisture 50 +22 0:00 Fertilizer 2.7 +22 0:00 END_EXPECTATIONS +22 0:01 WaterVolume 0 + +22 1:00 BEGIN_EXPECTATIONS +22 1:00 Temperature 17 +22 1:00 WaterVolume 0 +22 1:00 Light 11 +22 1:00 EXP_WaterVolume 0 +22 1:00 Moisture 49 +22 1:00 Fertilizer 2.1 +22 1:00 END_EXPECTATIONS +22 1:01 WaterVolume 0 + +22 2:00 BEGIN_EXPECTATIONS +22 2:00 Temperature 17 +22 2:00 WaterVolume 0 +22 2:00 Light 13 +22 2:00 EXP_WaterVolume 0 +22 2:00 Moisture 45 +22 2:00 Fertilizer 1.5 +22 2:00 END_EXPECTATIONS +22 2:01 WaterVolume 0 + +22 3:00 BEGIN_EXPECTATIONS +22 3:00 Temperature 17 +22 3:00 WaterVolume 0 +22 3:00 Light 15 +22 3:00 EXP_WaterVolume 0 +22 3:00 Moisture 45 +22 3:00 Fertilizer 2.9 +22 3:00 END_EXPECTATIONS +22 3:01 WaterVolume 0 + +22 4:00 BEGIN_EXPECTATIONS +22 4:00 Temperature 18 +22 4:00 WaterVolume 0 +22 4:00 Light 20 +22 4:00 EXP_WaterVolume 0 +22 4:00 Moisture 40 +22 4:00 Fertilizer 1.4 +22 4:00 END_EXPECTATIONS +22 4:01 WaterVolume 0 + +22 5:00 BEGIN_EXPECTATIONS +22 5:00 Temperature 18 +22 5:00 WaterVolume 0 +22 5:00 Light 25 +22 5:00 EXP_WaterVolume 0 +22 5:00 Moisture 39 +22 5:00 Fertilizer 1.8 +22 5:00 END_EXPECTATIONS +22 5:01 WaterVolume 0 + +22 6:00 BEGIN_EXPECTATIONS +22 6:00 Temperature 19 +22 6:00 WaterVolume 0 +22 6:00 Light 40 +22 6:00 EXP_WaterVolume 0 +22 6:00 Moisture 35 +22 6:00 Fertilizer 2.8 +22 6:00 END_EXPECTATIONS +22 6:01 WaterVolume 0 + +22 7:00 BEGIN_EXPECTATIONS +22 7:00 Temperature 19 +22 7:00 WaterVolume 0 +22 7:00 Light 45 +22 7:00 EXP_WaterVolume 0 +22 7:00 Moisture 30 +22 7:00 Fertilizer 1.5 +22 7:00 END_EXPECTATIONS +22 7:01 WaterVolume 0 + +22 8:00 BEGIN_EXPECTATIONS +22 8:00 Temperature 19 +22 8:00 WaterVolume 0 +22 8:00 Light 50 +22 8:00 EXP_WaterVolume 40 +22 8:00 Moisture 25 +22 8:00 Fertilizer 1.7 +22 8:00 END_EXPECTATIONS +22 8:01 WaterVolume 40 + +22 9:00 BEGIN_EXPECTATIONS +22 9:00 Temperature 19 +22 9:00 WaterVolume 0 +22 9:00 Light 50 +22 9:00 EXP_WaterVolume 40 +22 9:00 Moisture 25 +22 9:00 Fertilizer 2.5 +22 9:00 END_EXPECTATIONS +22 9:01 WaterVolume 40 + +22 10:00 BEGIN_EXPECTATIONS +22 10:00 Temperature 19 +22 10:00 WaterVolume 0 +22 10:00 Light 50 +22 10:00 EXP_WaterVolume 40 +22 10:00 Moisture 27 +22 10:00 Fertilizer 1.5 +22 10:00 END_EXPECTATIONS +22 10:01 WaterVolume 40 + +22 11:00 BEGIN_EXPECTATIONS +22 11:00 Temperature 20 +22 11:00 WaterVolume 0 +22 11:00 Light 60 +22 11:00 EXP_WaterVolume 40 +22 11:00 Moisture 26 +22 11:00 Fertilizer 2.8 +22 11:00 END_EXPECTATIONS +22 11:01 WaterVolume 40 + +22 12:00 BEGIN_EXPECTATIONS +22 12:00 Temperature 21 +22 12:00 WaterVolume 0 +22 12:00 Light 80 +22 12:00 EXP_WaterVolume 0 +22 12:00 Moisture 30 +22 12:00 Fertilizer 1.3 +22 12:00 END_EXPECTATIONS +22 12:01 WaterVolume 0 + +22 13:00 BEGIN_EXPECTATIONS +22 13:00 Temperature 20 +22 13:00 WaterVolume 0 +22 13:00 Light 70 +22 13:00 EXP_WaterVolume 40 +22 13:00 Moisture 25 +22 13:00 Fertilizer 2.0 +22 13:00 END_EXPECTATIONS +22 13:01 WaterVolume 40 + +22 14:00 BEGIN_EXPECTATIONS +22 14:00 Temperature 20 +22 14:00 WaterVolume 0 +22 14:00 Light 70 +22 14:00 EXP_WaterVolume 80 +22 14:00 Moisture 0 +22 14:00 Fertilizer 2.0 +22 14:00 END_EXPECTATIONS +22 14:01 WaterVolume 80 + +22 15:00 BEGIN_EXPECTATIONS +22 15:00 Temperature 20 +22 15:00 WaterVolume 0 +22 15:00 Light 70 +22 15:00 EXP_WaterVolume 80 +22 15:00 Moisture 3 +22 15:00 Fertilizer 2.7 +22 15:00 END_EXPECTATIONS +22 15:01 WaterVolume 80 + +22 16:00 BEGIN_EXPECTATIONS +22 16:00 Temperature 20 +22 16:00 WaterVolume 0 +22 16:00 Light 65 +22 16:00 EXP_WaterVolume 80 +22 16:00 Moisture 6 +22 16:00 Fertilizer 2.3 +22 16:00 END_EXPECTATIONS +22 16:01 WaterVolume 80 + +22 17:00 BEGIN_EXPECTATIONS +22 17:00 Temperature 20 +22 17:00 WaterVolume 0 +22 17:00 Light 60 +22 17:00 EXP_WaterVolume 60 +22 17:00 Moisture 13 +22 17:00 Fertilizer 2.8 +22 17:00 END_EXPECTATIONS +22 17:01 WaterVolume 60 + +22 18:00 BEGIN_EXPECTATIONS +22 18:00 Temperature 19 +22 18:00 WaterVolume 0 +22 18:00 Light 50 +22 18:00 EXP_WaterVolume 60 +22 18:00 Moisture 19 +22 18:00 Fertilizer 1.7 +22 18:00 END_EXPECTATIONS +22 18:01 WaterVolume 60 + +22 19:00 BEGIN_EXPECTATIONS +22 19:00 Temperature 18 +22 19:00 WaterVolume 0 +22 19:00 Light 30 +22 19:00 EXP_WaterVolume 40 +22 19:00 Moisture 25 +22 19:00 Fertilizer 2.3 +22 19:00 END_EXPECTATIONS +22 19:01 WaterVolume 40 + +22 20:00 BEGIN_EXPECTATIONS +22 20:00 Temperature 17 +22 20:00 WaterVolume 0 +22 20:00 Light 10 +22 20:00 EXP_WaterVolume 40 +22 20:00 Moisture 28 +22 20:00 Fertilizer 2.1 +22 20:00 END_EXPECTATIONS +22 20:01 WaterVolume 40 + +22 21:00 BEGIN_EXPECTATIONS +22 21:00 Temperature 17 +22 21:00 WaterVolume 0 +22 21:00 Light 10 +22 21:00 EXP_WaterVolume 40 +22 21:00 Moisture 28 +22 21:00 Fertilizer 1.8 +22 21:00 END_EXPECTATIONS +22 21:01 WaterVolume 40 + +22 22:00 BEGIN_EXPECTATIONS +22 22:00 Temperature 17 +22 22:00 WaterVolume 0 +22 22:00 Light 10 +22 22:00 EXP_WaterVolume 0 +22 22:00 Moisture 32 +22 22:00 Fertilizer 2.9 +22 22:00 END_EXPECTATIONS +22 22:01 WaterVolume 0 + +22 23:00 BEGIN_EXPECTATIONS +22 23:00 Temperature 17 +22 23:00 WaterVolume 0 +22 23:00 Light 10 +22 23:00 EXP_WaterVolume 0 +22 23:00 Moisture 31 +22 23:00 Fertilizer 1.4 +22 23:00 END_EXPECTATIONS +22 23:01 WaterVolume 0 + +### Wednesday ### +23 0:00 BEGIN_EXPECTATIONS +23 0:00 Temperature 20 +23 0:00 WaterVolume 0 +23 0:00 Light 10 +23 0:00 EXP_WaterVolume 40 +23 0:00 Moisture 28 +23 0:00 Fertilizer 1.6 +23 0:00 END_EXPECTATIONS +23 0:01 WaterVolume 40 + +23 1:00 BEGIN_EXPECTATIONS +23 1:00 Temperature 20 +23 1:00 WaterVolume 0 +23 1:00 Light 11 +23 1:00 EXP_WaterVolume 40 +23 1:00 Moisture 29 +23 1:00 Fertilizer 1.6 +23 1:00 END_EXPECTATIONS +23 1:01 WaterVolume 40 + +23 2:00 BEGIN_EXPECTATIONS +23 2:00 Temperature 20 +23 2:00 WaterVolume 0 +23 2:00 Light 13 +23 2:00 EXP_WaterVolume 0 +23 2:00 Moisture 30 +23 2:00 Fertilizer 1.0 +23 2:00 END_EXPECTATIONS +23 2:01 WaterVolume 0 + +23 3:00 BEGIN_EXPECTATIONS +23 3:00 Temperature 20 +23 3:00 WaterVolume 0 +23 3:00 Light 15 +23 3:00 EXP_WaterVolume 40 +23 3:00 Moisture 28 +23 3:00 Fertilizer 2.4 +23 3:00 END_EXPECTATIONS +23 3:01 WaterVolume 40 + +23 4:00 BEGIN_EXPECTATIONS +23 4:00 Temperature 21 +23 4:00 WaterVolume 0 +23 4:00 Light 20 +23 4:00 EXP_WaterVolume 40 +23 4:00 Moisture 28 +23 4:00 Fertilizer 1.4 +23 4:00 END_EXPECTATIONS +23 4:01 WaterVolume 40 + +23 5:00 BEGIN_EXPECTATIONS +23 5:00 Temperature 21 +23 5:00 WaterVolume 0 +23 5:00 Light 25 +23 5:00 EXP_WaterVolume 0 +23 5:00 Moisture 30 +23 5:00 Fertilizer 2.0 +23 5:00 END_EXPECTATIONS +23 5:01 WaterVolume 0 + +23 6:00 BEGIN_EXPECTATIONS +23 6:00 Temperature 22 +23 6:00 WaterVolume 0 +23 6:00 Light 40 +23 6:00 EXP_WaterVolume 40 +23 6:00 Moisture 28 +23 6:00 Fertilizer 1.6 +23 6:00 END_EXPECTATIONS +23 6:01 WaterVolume 40 + +23 7:00 BEGIN_EXPECTATIONS +23 7:00 Temperature 22 +23 7:00 WaterVolume 0 +23 7:00 Light 45 +23 7:00 EXP_WaterVolume 0 +23 7:00 Moisture 31 +23 7:00 Fertilizer 1.8 +23 7:00 END_EXPECTATIONS +23 7:01 WaterVolume 0 + +23 8:00 BEGIN_EXPECTATIONS +23 8:00 Temperature 22 +23 8:00 WaterVolume 0 +23 8:00 Light 50 +23 8:00 EXP_WaterVolume 40 +23 8:00 Moisture 28 +23 8:00 Fertilizer 1.3 +23 8:00 END_EXPECTATIONS +23 8:01 WaterVolume 40 + +23 9:00 BEGIN_EXPECTATIONS +23 9:00 Temperature 22 +23 9:00 WaterVolume 0 +23 9:00 Light 50 +23 9:00 EXP_WaterVolume 0 +23 9:00 Moisture 32 +23 9:00 Fertilizer 1.5 +23 9:00 END_EXPECTATIONS +23 9:01 WaterVolume 0 + +23 10:00 BEGIN_EXPECTATIONS +23 10:00 Temperature 22 +23 10:00 WaterVolume 0 +23 10:00 Light 50 +23 10:00 EXP_WaterVolume 0 +23 10:00 Moisture 31 +23 10:00 Fertilizer 1.0 +23 10:00 END_EXPECTATIONS +23 10:01 WaterVolume 0 + +23 11:00 BEGIN_EXPECTATIONS +23 11:00 Temperature 23 +23 11:00 WaterVolume 0 +23 11:00 Light 60 +23 11:00 EXP_WaterVolume 40 +23 11:00 Moisture 28 +23 11:00 Fertilizer 2.2 +23 11:00 END_EXPECTATIONS +23 11:01 WaterVolume 40 + +23 12:00 BEGIN_EXPECTATIONS +23 12:00 Temperature 24 +23 12:00 WaterVolume 0 +23 12:00 Light 80 +23 12:00 EXP_WaterVolume 0 +23 12:00 Moisture 31 +23 12:00 Fertilizer 1.2 +23 12:00 END_EXPECTATIONS +23 12:01 WaterVolume 0 + +23 13:00 BEGIN_EXPECTATIONS +23 13:00 Temperature 23 +23 13:00 WaterVolume 0 +23 13:00 Light 70 +23 13:00 EXP_WaterVolume 0 +23 13:00 Moisture 31 +23 13:00 Fertilizer 2.1 +23 13:00 END_EXPECTATIONS +23 13:01 WaterVolume 0 + +23 14:00 BEGIN_EXPECTATIONS +23 14:00 Temperature 23 +23 14:00 WaterVolume 0 +23 14:00 Light 70 +23 14:00 EXP_WaterVolume 0 +23 14:00 Moisture 31 +23 14:00 Fertilizer 1.4 +23 14:00 END_EXPECTATIONS +23 14:01 WaterVolume 0 + +23 15:00 BEGIN_EXPECTATIONS +23 15:00 Temperature 23 +23 15:00 WaterVolume 0 +23 15:00 Light 70 +23 15:00 EXP_WaterVolume 0 +23 15:00 Moisture 30 +23 15:00 Fertilizer 2.2 +23 15:00 END_EXPECTATIONS +23 15:01 WaterVolume 0 + +23 16:00 BEGIN_EXPECTATIONS +23 16:00 Temperature 23 +23 16:00 WaterVolume 0 +23 16:00 Light 65 +23 16:00 EXP_WaterVolume 0 +23 16:00 Moisture 30 +23 16:00 Fertilizer 1.6 +23 16:00 END_EXPECTATIONS +23 16:01 WaterVolume 0 + +23 17:00 BEGIN_EXPECTATIONS +23 17:00 Temperature 23 +23 17:00 WaterVolume 0 +23 17:00 Light 60 +23 17:00 EXP_WaterVolume 80 +23 17:00 Moisture 0 +23 17:00 Fertilizer 1.0 +23 17:00 END_EXPECTATIONS +23 17:01 WaterVolume 80 + +23 18:00 BEGIN_EXPECTATIONS +23 18:00 Temperature 22 +23 18:00 WaterVolume 0 +23 18:00 Light 50 +23 18:00 EXP_WaterVolume 80 +23 18:00 Moisture 5 +23 18:00 Fertilizer 2.1 +23 18:00 END_EXPECTATIONS +23 18:01 WaterVolume 80 + +23 19:00 BEGIN_EXPECTATIONS +23 19:00 Temperature 21 +23 19:00 WaterVolume 0 +23 19:00 Light 30 +23 19:00 EXP_WaterVolume 80 +23 19:00 Moisture 8 +23 19:00 Fertilizer 1.3 +23 19:00 END_EXPECTATIONS +23 19:01 WaterVolume 80 + +23 20:00 BEGIN_EXPECTATIONS +23 20:00 Temperature 20 +23 20:00 WaterVolume 0 +23 20:00 Light 10 +23 20:00 EXP_WaterVolume 60 +23 20:00 Moisture 12 +23 20:00 Fertilizer 1.1 +23 20:00 END_EXPECTATIONS +23 20:01 WaterVolume 60 + +23 21:00 BEGIN_EXPECTATIONS +23 21:00 Temperature 20 +23 21:00 WaterVolume 0 +23 21:00 Light 10 +23 21:00 EXP_WaterVolume 60 +23 21:00 Moisture 13 +23 21:00 Fertilizer 1.0 +23 21:00 END_EXPECTATIONS +23 21:01 WaterVolume 60 + +23 22:00 BEGIN_EXPECTATIONS +23 22:00 Temperature 20 +23 22:00 WaterVolume 0 +23 22:00 Light 10 +23 22:00 EXP_WaterVolume 60 +23 22:00 Moisture 19 +23 22:00 Fertilizer 1.9 +23 22:00 END_EXPECTATIONS +23 22:01 WaterVolume 60 + +23 23:00 BEGIN_EXPECTATIONS +23 23:00 Temperature 20 +23 23:00 WaterVolume 0 +23 23:00 Light 10 +23 23:00 EXP_WaterVolume 40 +23 23:00 Moisture 21 +23 23:00 Fertilizer 2.0 +23 23:00 END_EXPECTATIONS +23 23:01 WaterVolume 40 + +### Thursday ### +24 0:00 BEGIN_EXPECTATIONS +24 0:00 Temperature 17 +24 0:00 WaterVolume 0 +24 0:00 Light 10 +24 0:00 EXP_WaterVolume 40 +24 0:00 Moisture 20 +24 0:00 Fertilizer 2.2 +24 0:00 END_EXPECTATIONS +24 0:01 WaterVolume 40 + +24 1:00 BEGIN_EXPECTATIONS +24 1:00 Temperature 17 +24 1:00 WaterVolume 0 +24 1:00 Light 11 +24 1:00 EXP_WaterVolume 40 +24 1:00 Moisture 24 +24 1:00 Fertilizer 1.8 +24 1:00 END_EXPECTATIONS +24 1:01 WaterVolume 40 + +24 2:00 BEGIN_EXPECTATIONS +24 2:00 Temperature 17 +24 2:00 WaterVolume 0 +24 2:00 Light 13 +24 2:00 EXP_WaterVolume 40 +24 2:00 Moisture 23 +24 2:00 Fertilizer 1.7 +24 2:00 END_EXPECTATIONS +24 2:01 WaterVolume 40 + +24 3:00 BEGIN_EXPECTATIONS +24 3:00 Temperature 17 +24 3:00 WaterVolume 0 +24 3:00 Light 15 +24 3:00 EXP_WaterVolume 40 +24 3:00 Moisture 26 +24 3:00 Fertilizer 2.0 +24 3:00 END_EXPECTATIONS +24 3:01 WaterVolume 40 + +24 4:00 BEGIN_EXPECTATIONS +24 4:00 Temperature 18 +24 4:00 WaterVolume 0 +24 4:00 Light 20 +24 4:00 EXP_WaterVolume 0 +24 4:00 Moisture 30 +24 4:00 Fertilizer 1.1 +24 4:00 END_EXPECTATIONS +24 4:01 WaterVolume 0 + +24 5:00 BEGIN_EXPECTATIONS +24 5:00 Temperature 18 +24 5:00 WaterVolume 0 +24 5:00 Light 25 +24 5:00 EXP_WaterVolume 40 +24 5:00 Moisture 29 +24 5:00 Fertilizer 1.0 +24 5:00 END_EXPECTATIONS +24 5:01 WaterVolume 40 + +24 6:00 BEGIN_EXPECTATIONS +24 6:00 Temperature 19 +24 6:00 WaterVolume 0 +24 6:00 Light 40 +24 6:00 EXP_WaterVolume 0 +24 6:00 Moisture 30 +24 6:00 Fertilizer 2.8 +24 6:00 END_EXPECTATIONS +24 6:01 WaterVolume 0 + +24 7:00 BEGIN_EXPECTATIONS +24 7:00 Temperature 19 +24 7:00 WaterVolume 0 +24 7:00 Light 45 +24 7:00 EXP_WaterVolume 0 +24 7:00 Moisture 30 +24 7:00 Fertilizer 2.1 +24 7:00 END_EXPECTATIONS +24 7:01 WaterVolume 0 + +24 8:00 BEGIN_EXPECTATIONS +24 8:00 Temperature 19 +24 8:00 WaterVolume 0 +24 8:00 Light 50 +24 8:00 EXP_WaterVolume 40 +24 8:00 Moisture 29 +24 8:00 Fertilizer 1.2 +24 8:00 END_EXPECTATIONS +24 8:01 WaterVolume 40 + +24 9:00 BEGIN_EXPECTATIONS +24 9:00 Temperature 19 +24 9:00 WaterVolume 0 +24 9:00 Light 50 +24 9:00 EXP_WaterVolume 40 +24 9:00 Moisture 29 +24 9:00 Fertilizer 1.0 +24 9:00 END_EXPECTATIONS +24 9:01 WaterVolume 40 + +24 10:00 BEGIN_EXPECTATIONS +24 10:00 Temperature 19 +24 10:00 WaterVolume 0 +24 10:00 Light 50 +24 10:00 EXP_WaterVolume 0 +24 10:00 Moisture 33 +24 10:00 Fertilizer 1.0 +24 10:00 END_EXPECTATIONS +24 10:01 WaterVolume 0 + +24 11:00 BEGIN_EXPECTATIONS +24 11:00 Temperature 20 +24 11:00 WaterVolume 0 +24 11:00 Light 60 +24 11:00 EXP_WaterVolume 0 +24 11:00 Moisture 30 +24 11:00 Fertilizer 2.9 +24 11:00 END_EXPECTATIONS +24 11:01 WaterVolume 0 + +24 12:00 BEGIN_EXPECTATIONS +24 12:00 Temperature 21 +24 12:00 WaterVolume 0 +24 12:00 Light 80 +24 12:00 EXP_WaterVolume 0 +24 12:00 Moisture 30 +24 12:00 Fertilizer 1.2 +24 12:00 END_EXPECTATIONS +24 12:01 WaterVolume 0 + +24 13:00 BEGIN_EXPECTATIONS +24 13:00 Temperature 20 +24 13:00 WaterVolume 0 +24 13:00 Light 70 +24 13:00 EXP_WaterVolume 40 +24 13:00 Moisture 25 +24 13:00 Fertilizer 1.2 +24 13:00 END_EXPECTATIONS +24 13:01 WaterVolume 40 + +24 14:00 BEGIN_EXPECTATIONS +24 14:00 Temperature 20 +24 14:00 WaterVolume 0 +24 14:00 Light 70 +24 14:00 EXP_WaterVolume 40 +24 14:00 Moisture 24 +24 14:00 Fertilizer 1.3 +24 14:00 END_EXPECTATIONS +24 14:01 WaterVolume 40 + +24 15:00 BEGIN_EXPECTATIONS +24 15:00 Temperature 20 +24 15:00 WaterVolume 0 +24 15:00 Light 70 +24 15:00 EXP_WaterVolume 40 +24 15:00 Moisture 24 +24 15:00 Fertilizer 1.9 +24 15:00 END_EXPECTATIONS +24 15:01 WaterVolume 40 + +24 16:00 BEGIN_EXPECTATIONS +24 16:00 Temperature 20 +24 16:00 WaterVolume 0 +24 16:00 Light 65 +24 16:00 EXP_WaterVolume 40 +24 16:00 Moisture 28 +24 16:00 Fertilizer 2.8 +24 16:00 END_EXPECTATIONS +24 16:01 WaterVolume 40 + +24 17:00 BEGIN_EXPECTATIONS +24 17:00 Temperature 20 +24 17:00 WaterVolume 0 +24 17:00 Light 60 +24 17:00 EXP_WaterVolume 40 +24 17:00 Moisture 27 +24 17:00 Fertilizer 1.1 +24 17:00 END_EXPECTATIONS +24 17:01 WaterVolume 40 + +24 18:00 BEGIN_EXPECTATIONS +24 18:00 Temperature 19 +24 18:00 WaterVolume 0 +24 18:00 Light 50 +24 18:00 EXP_WaterVolume 40 +24 18:00 Moisture 26 +24 18:00 Fertilizer 2.3 +24 18:00 END_EXPECTATIONS +24 18:01 WaterVolume 40 + +24 19:00 BEGIN_EXPECTATIONS +24 19:00 Temperature 18 +24 19:00 WaterVolume 0 +24 19:00 Light 30 +24 19:00 EXP_WaterVolume 40 +24 19:00 Moisture 26 +24 19:00 Fertilizer 2.1 +24 19:00 END_EXPECTATIONS +24 19:01 WaterVolume 40 + +24 20:00 BEGIN_EXPECTATIONS +24 20:00 Temperature 17 +24 20:00 WaterVolume 0 +24 20:00 Light 10 +24 20:00 EXP_WaterVolume 40 +24 20:00 Moisture 26 +24 20:00 Fertilizer 1.9 +24 20:00 END_EXPECTATIONS +24 20:01 WaterVolume 40 + +24 21:00 BEGIN_EXPECTATIONS +24 21:00 Temperature 17 +24 21:00 WaterVolume 0 +24 21:00 Light 10 +24 21:00 EXP_WaterVolume 40 +24 21:00 Moisture 25 +24 21:00 Fertilizer 1.5 +24 21:00 END_EXPECTATIONS +24 21:01 WaterVolume 40 + +24 22:00 BEGIN_EXPECTATIONS +24 22:00 Temperature 17 +24 22:00 WaterVolume 0 +24 22:00 Light 10 +24 22:00 EXP_WaterVolume 40 +24 22:00 Moisture 26 +24 22:00 Fertilizer 2.7 +24 22:00 END_EXPECTATIONS +24 22:01 WaterVolume 40 + +24 23:00 BEGIN_EXPECTATIONS +24 23:00 Temperature 17 +24 23:00 WaterVolume 0 +24 23:00 Light 10 +24 23:00 EXP_WaterVolume 40 +24 23:00 Moisture 25 +24 23:00 Fertilizer 1.0 +24 23:00 END_EXPECTATIONS +24 23:01 WaterVolume 40 + +### Friday ### +25 0:00 BEGIN_EXPECTATIONS +25 0:00 Temperature 20 +25 0:00 WaterVolume 0 +25 0:00 Light 10 +25 0:00 EXP_WaterVolume 40 +25 0:00 Moisture 25 +25 0:00 Fertilizer 2.5 +25 0:00 END_EXPECTATIONS +25 0:01 WaterVolume 40 + +25 1:00 BEGIN_EXPECTATIONS +25 1:00 Temperature 20 +25 1:00 WaterVolume 0 +25 1:00 Light 11 +25 1:00 EXP_WaterVolume 40 +25 1:00 Moisture 27 +25 1:00 Fertilizer 2.2 +25 1:00 END_EXPECTATIONS +25 1:01 WaterVolume 40 + +25 2:00 BEGIN_EXPECTATIONS +25 2:00 Temperature 20 +25 2:00 WaterVolume 0 +25 2:00 Light 13 +25 2:00 EXP_WaterVolume 0 +25 2:00 Moisture 31 +25 2:00 Fertilizer 2.9 +25 2:00 END_EXPECTATIONS +25 2:01 WaterVolume 0 + +25 3:00 BEGIN_EXPECTATIONS +25 3:00 Temperature 20 +25 3:00 WaterVolume 0 +25 3:00 Light 15 +25 3:00 EXP_WaterVolume 40 +25 3:00 Moisture 27 +25 3:00 Fertilizer 1.2 +25 3:00 END_EXPECTATIONS +25 3:01 WaterVolume 40 + +25 4:00 BEGIN_EXPECTATIONS +25 4:00 Temperature 21 +25 4:00 WaterVolume 0 +25 4:00 Light 20 +25 4:00 EXP_WaterVolume 40 +25 4:00 Moisture 29 +25 4:00 Fertilizer 1.5 +25 4:00 END_EXPECTATIONS +25 4:01 WaterVolume 40 + +25 5:00 BEGIN_EXPECTATIONS +25 5:00 Temperature 21 +25 5:00 WaterVolume 0 +25 5:00 Light 25 +25 5:00 EXP_WaterVolume 40 +25 5:00 Moisture 28 +25 5:00 Fertilizer 2.4 +25 5:00 END_EXPECTATIONS +25 5:01 WaterVolume 40 + +25 6:00 BEGIN_EXPECTATIONS +25 6:00 Temperature 22 +25 6:00 WaterVolume 0 +25 6:00 Light 40 +25 6:00 EXP_WaterVolume 40 +25 6:00 Moisture 27 +25 6:00 Fertilizer 1.8 +25 6:00 END_EXPECTATIONS +25 6:01 WaterVolume 40 + +25 7:00 BEGIN_EXPECTATIONS +25 7:00 Temperature 22 +25 7:00 WaterVolume 0 +25 7:00 Light 45 +25 7:00 EXP_WaterVolume 0 +25 7:00 Moisture 31 +25 7:00 Fertilizer 1.1 +25 7:00 END_EXPECTATIONS +25 7:01 WaterVolume 0 + +25 8:00 BEGIN_EXPECTATIONS +25 8:00 Temperature 22 +25 8:00 WaterVolume 0 +25 8:00 Light 50 +25 8:00 EXP_WaterVolume 0 +25 8:00 Moisture 31 +25 8:00 Fertilizer 2.6 +25 8:00 END_EXPECTATIONS +25 8:01 WaterVolume 0 + +25 9:00 BEGIN_EXPECTATIONS +25 9:00 Temperature 22 +25 9:00 WaterVolume 0 +25 9:00 Light 50 +25 9:00 EXP_WaterVolume 40 +25 9:00 Moisture 26 +25 9:00 Fertilizer 1.1 +25 9:00 END_EXPECTATIONS +25 9:01 WaterVolume 40 + +25 10:00 BEGIN_EXPECTATIONS +25 10:00 Temperature 22 +25 10:00 WaterVolume 0 +25 10:00 Light 50 +25 10:00 EXP_WaterVolume 40 +25 10:00 Moisture 28 +25 10:00 Fertilizer 1.6 +25 10:00 END_EXPECTATIONS +25 10:01 WaterVolume 40 + +25 11:00 BEGIN_EXPECTATIONS +25 11:00 Temperature 23 +25 11:00 WaterVolume 0 +25 11:00 Light 60 +25 11:00 EXP_WaterVolume 0 +25 11:00 Moisture 31 +25 11:00 Fertilizer 1.8 +25 11:00 END_EXPECTATIONS +25 11:01 WaterVolume 0 + +25 12:00 BEGIN_EXPECTATIONS +25 12:00 Temperature 24 +25 12:00 WaterVolume 0 +25 12:00 Light 80 +25 12:00 EXP_WaterVolume 40 +25 12:00 Moisture 27 +25 12:00 Fertilizer 1.9 +25 12:00 END_EXPECTATIONS +25 12:01 WaterVolume 40 + +25 13:00 BEGIN_EXPECTATIONS +25 13:00 Temperature 23 +25 13:00 WaterVolume 0 +25 13:00 Light 70 +25 13:00 EXP_WaterVolume 40 +25 13:00 Moisture 29 +25 13:00 Fertilizer 2.5 +25 13:00 END_EXPECTATIONS +25 13:01 WaterVolume 40 + +25 14:00 BEGIN_EXPECTATIONS +25 14:00 Temperature 23 +25 14:00 WaterVolume 0 +25 14:00 Light 70 +25 14:00 EXP_WaterVolume 0 +25 14:00 Moisture 30 +25 14:00 Fertilizer 2.4 +25 14:00 END_EXPECTATIONS +25 14:01 WaterVolume 0 + +25 15:00 BEGIN_EXPECTATIONS +25 15:00 Temperature 23 +25 15:00 WaterVolume 0 +25 15:00 Light 70 +25 15:00 EXP_WaterVolume 40 +25 15:00 Moisture 26 +25 15:00 Fertilizer 2.2 +25 15:00 END_EXPECTATIONS +25 15:01 WaterVolume 40 + +25 16:00 BEGIN_EXPECTATIONS +25 16:00 Temperature 23 +25 16:00 WaterVolume 0 +25 16:00 Light 65 +25 16:00 EXP_WaterVolume 40 +25 16:00 Moisture 27 +25 16:00 Fertilizer 1.8 +25 16:00 END_EXPECTATIONS +25 16:01 WaterVolume 40 + +25 17:00 BEGIN_EXPECTATIONS +25 17:00 Temperature 23 +25 17:00 WaterVolume 0 +25 17:00 Light 60 +25 17:00 EXP_WaterVolume 0 +25 17:00 Moisture 30 +25 17:00 Fertilizer 1.9 +25 17:00 END_EXPECTATIONS +25 17:01 WaterVolume 0 + +25 18:00 BEGIN_EXPECTATIONS +25 18:00 Temperature 22 +25 18:00 WaterVolume 0 +25 18:00 Light 50 +25 18:00 EXP_WaterVolume 40 +25 18:00 Moisture 26 +25 18:00 Fertilizer 1.7 +25 18:00 END_EXPECTATIONS +25 18:01 WaterVolume 40 + +25 19:00 BEGIN_EXPECTATIONS +25 19:00 Temperature 21 +25 19:00 WaterVolume 0 +25 19:00 Light 30 +25 19:00 EXP_WaterVolume 40 +25 19:00 Moisture 26 +25 19:00 Fertilizer 2.9 +25 19:00 END_EXPECTATIONS +25 19:01 WaterVolume 40 + +25 20:00 BEGIN_EXPECTATIONS +25 20:00 Temperature 20 +25 20:00 WaterVolume 0 +25 20:00 Light 10 +25 20:00 EXP_WaterVolume 40 +25 20:00 Moisture 28 +25 20:00 Fertilizer 2.6 +25 20:00 END_EXPECTATIONS +25 20:01 WaterVolume 40 + +25 21:00 BEGIN_EXPECTATIONS +25 21:00 Temperature 20 +25 21:00 WaterVolume 0 +25 21:00 Light 10 +25 21:00 EXP_WaterVolume 40 +25 21:00 Moisture 28 +25 21:00 Fertilizer 1.8 +25 21:00 END_EXPECTATIONS +25 21:01 WaterVolume 40 + +25 22:00 BEGIN_EXPECTATIONS +25 22:00 Temperature 20 +25 22:00 WaterVolume 0 +25 22:00 Light 10 +25 22:00 EXP_WaterVolume 40 +25 22:00 Moisture 28 +25 22:00 Fertilizer 2.9 +25 22:00 END_EXPECTATIONS +25 22:01 WaterVolume 40 + +25 23:00 BEGIN_EXPECTATIONS +25 23:00 Temperature 20 +25 23:00 WaterVolume 0 +25 23:00 Light 10 +25 23:00 EXP_WaterVolume 40 +25 23:00 Moisture 28 +25 23:00 Fertilizer 1.7 +25 23:00 END_EXPECTATIONS +25 23:01 WaterVolume 40 + +### Saturday ### +26 0:00 BEGIN_EXPECTATIONS +26 0:00 Temperature 18 +26 0:00 WaterVolume 0 +26 0:00 Light 10 +26 0:00 EXP_WaterVolume 40 +26 0:00 Moisture 28 +26 0:00 Fertilizer 2.6 +26 0:00 END_EXPECTATIONS +26 0:01 WaterVolume 40 + +26 1:00 BEGIN_EXPECTATIONS +26 1:00 Temperature 18 +26 1:00 WaterVolume 0 +26 1:00 Light 11 +26 1:00 EXP_WaterVolume 40 +26 1:00 Moisture 29 +26 1:00 Fertilizer 1.1 +26 1:00 END_EXPECTATIONS +26 1:01 WaterVolume 40 + +26 2:00 BEGIN_EXPECTATIONS +26 2:00 Temperature 18 +26 2:00 WaterVolume 0 +26 2:00 Light 13 +26 2:00 EXP_WaterVolume 0 +26 2:00 Moisture 33 +26 2:00 Fertilizer 2.0 +26 2:00 END_EXPECTATIONS +26 2:01 WaterVolume 0 + +26 3:00 BEGIN_EXPECTATIONS +26 3:00 Temperature 18 +26 3:00 WaterVolume 0 +26 3:00 Light 15 +26 3:00 EXP_WaterVolume 0 +26 3:00 Moisture 31 +26 3:00 Fertilizer 1.0 +26 3:00 END_EXPECTATIONS +26 3:01 WaterVolume 0 + +26 4:00 BEGIN_EXPECTATIONS +26 4:00 Temperature 19 +26 4:00 WaterVolume 0 +26 4:00 Light 20 +26 4:00 EXP_WaterVolume 40 +26 4:00 Moisture 28 +26 4:00 Fertilizer 1.1 +26 4:00 END_EXPECTATIONS +26 4:01 WaterVolume 40 + +26 5:00 BEGIN_EXPECTATIONS +26 5:00 Temperature 19 +26 5:00 WaterVolume 0 +26 5:00 Light 25 +26 5:00 EXP_WaterVolume 0 +26 5:00 Moisture 32 +26 5:00 Fertilizer 1.7 +26 5:00 END_EXPECTATIONS +26 5:01 WaterVolume 0 + +26 6:00 BEGIN_EXPECTATIONS +26 6:00 Temperature 20 +26 6:00 WaterVolume 0 +26 6:00 Light 40 +26 6:00 EXP_WaterVolume 0 +26 6:00 Moisture 30 +26 6:00 Fertilizer 1.3 +26 6:00 END_EXPECTATIONS +26 6:01 WaterVolume 0 + +26 7:00 BEGIN_EXPECTATIONS +26 7:00 Temperature 20 +26 7:00 WaterVolume 0 +26 7:00 Light 45 +26 7:00 EXP_WaterVolume 0 +26 7:00 Moisture 30 +26 7:00 Fertilizer 1.7 +26 7:00 END_EXPECTATIONS +26 7:01 WaterVolume 0 + +26 8:00 BEGIN_EXPECTATIONS +26 8:00 Temperature 20 +26 8:00 WaterVolume 0 +26 8:00 Light 50 +26 8:00 EXP_WaterVolume 40 +26 8:00 Moisture 27 +26 8:00 Fertilizer 2.1 +26 8:00 END_EXPECTATIONS +26 8:01 WaterVolume 40 + +26 9:00 BEGIN_EXPECTATIONS +26 9:00 Temperature 20 +26 9:00 WaterVolume 0 +26 9:00 Light 50 +26 9:00 EXP_WaterVolume 40 +26 9:00 Moisture 28 +26 9:00 Fertilizer 2.7 +26 9:00 END_EXPECTATIONS +26 9:01 WaterVolume 40 + +26 10:00 BEGIN_EXPECTATIONS +26 10:00 Temperature 20 +26 10:00 WaterVolume 0 +26 10:00 Light 50 +26 10:00 EXP_WaterVolume 40 +26 10:00 Moisture 29 +26 10:00 Fertilizer 2.2 +26 10:00 END_EXPECTATIONS +26 10:01 WaterVolume 40 + +26 11:00 BEGIN_EXPECTATIONS +26 11:00 Temperature 21 +26 11:00 WaterVolume 0 +26 11:00 Light 60 +26 11:00 EXP_WaterVolume 40 +26 11:00 Moisture 29 +26 11:00 Fertilizer 1.0 +26 11:00 END_EXPECTATIONS +26 11:01 WaterVolume 40 + +26 12:00 BEGIN_EXPECTATIONS +26 12:00 Temperature 22 +26 12:00 WaterVolume 0 +26 12:00 Light 80 +26 12:00 EXP_WaterVolume 0 +26 12:00 Moisture 30 +26 12:00 Fertilizer 2.6 +26 12:00 END_EXPECTATIONS +26 12:01 WaterVolume 0 + +26 13:00 BEGIN_EXPECTATIONS +26 13:00 Temperature 21 +26 13:00 WaterVolume 0 +26 13:00 Light 70 +26 13:00 EXP_WaterVolume 40 +26 13:00 Moisture 26 +26 13:00 Fertilizer 1.5 +26 13:00 END_EXPECTATIONS +26 13:01 WaterVolume 40 + +26 14:00 BEGIN_EXPECTATIONS +26 14:00 Temperature 21 +26 14:00 WaterVolume 0 +26 14:00 Light 70 +26 14:00 EXP_WaterVolume 40 +26 14:00 Moisture 28 +26 14:00 Fertilizer 1.5 +26 14:00 END_EXPECTATIONS +26 14:01 WaterVolume 40 + +26 15:00 BEGIN_EXPECTATIONS +26 15:00 Temperature 21 +26 15:00 WaterVolume 0 +26 15:00 Light 70 +26 15:00 EXP_WaterVolume 40 +26 15:00 Moisture 28 +26 15:00 Fertilizer 2.7 +26 15:00 END_EXPECTATIONS +26 15:01 WaterVolume 40 + +26 16:00 BEGIN_EXPECTATIONS +26 16:00 Temperature 21 +26 16:00 WaterVolume 0 +26 16:00 Light 65 +26 16:00 EXP_WaterVolume 0 +26 16:00 Moisture 32 +26 16:00 Fertilizer 2.9 +26 16:00 END_EXPECTATIONS +26 16:01 WaterVolume 0 + +26 17:00 BEGIN_EXPECTATIONS +26 17:00 Temperature 21 +26 17:00 WaterVolume 0 +26 17:00 Light 60 +26 17:00 EXP_WaterVolume 40 +26 17:00 Moisture 29 +26 17:00 Fertilizer 2.9 +26 17:00 END_EXPECTATIONS +26 17:01 WaterVolume 40 + +26 18:00 BEGIN_EXPECTATIONS +26 18:00 Temperature 20 +26 18:00 WaterVolume 0 +26 18:00 Light 50 +26 18:00 EXP_WaterVolume 40 +26 18:00 Moisture 29 +26 18:00 Fertilizer 1.4 +26 18:00 END_EXPECTATIONS +26 18:01 WaterVolume 40 + +26 19:00 BEGIN_EXPECTATIONS +26 19:00 Temperature 19 +26 19:00 WaterVolume 0 +26 19:00 Light 30 +26 19:00 EXP_WaterVolume 0 +26 19:00 Moisture 30 +26 19:00 Fertilizer 2.3 +26 19:00 END_EXPECTATIONS +26 19:01 WaterVolume 0 + +26 20:00 BEGIN_EXPECTATIONS +26 20:00 Temperature 18 +26 20:00 WaterVolume 0 +26 20:00 Light 10 +26 20:00 EXP_WaterVolume 40 +26 20:00 Moisture 27 +26 20:00 Fertilizer 2.6 +26 20:00 END_EXPECTATIONS +26 20:01 WaterVolume 40 + +26 21:00 BEGIN_EXPECTATIONS +26 21:00 Temperature 18 +26 21:00 WaterVolume 0 +26 21:00 Light 10 +26 21:00 EXP_WaterVolume 40 +26 21:00 Moisture 27 +26 21:00 Fertilizer 2.6 +26 21:00 END_EXPECTATIONS +26 21:01 WaterVolume 40 + +26 22:00 BEGIN_EXPECTATIONS +26 22:00 Temperature 18 +26 22:00 WaterVolume 0 +26 22:00 Light 10 +26 22:00 EXP_WaterVolume 0 +26 22:00 Moisture 50 +26 22:00 Fertilizer 1.9 +26 22:00 END_EXPECTATIONS +26 22:01 WaterVolume 0 + +26 23:00 BEGIN_EXPECTATIONS +26 23:00 Temperature 18 +26 23:00 WaterVolume 0 +26 23:00 Light 10 +26 23:00 EXP_WaterVolume 0 +26 23:00 Moisture 46 +26 23:00 Fertilizer 2.1 +26 23:00 END_EXPECTATIONS +26 23:01 WaterVolume 0 + +### Sunday ### +27 0:00 BEGIN_EXPECTATIONS +27 0:00 Temperature 23 +27 0:00 WaterVolume 0 +27 0:00 Light 10 +27 0:00 EXP_WaterVolume 0 +27 0:00 Moisture 43 +27 0:00 Fertilizer 1.5 +27 0:00 END_EXPECTATIONS +27 0:01 WaterVolume 0 + +27 1:00 BEGIN_EXPECTATIONS +27 1:00 Temperature 23 +27 1:00 WaterVolume 0 +27 1:00 Light 11 +27 1:00 EXP_WaterVolume 0 +27 1:00 Moisture 40 +27 1:00 Fertilizer 2.1 +27 1:00 END_EXPECTATIONS +27 1:01 WaterVolume 0 + +27 2:00 BEGIN_EXPECTATIONS +27 2:00 Temperature 23 +27 2:00 WaterVolume 0 +27 2:00 Light 13 +27 2:00 EXP_WaterVolume 0 +27 2:00 Moisture 39 +27 2:00 Fertilizer 2.1 +27 2:00 END_EXPECTATIONS +27 2:01 WaterVolume 0 + +27 3:00 BEGIN_EXPECTATIONS +27 3:00 Temperature 23 +27 3:00 WaterVolume 0 +27 3:00 Light 15 +27 3:00 EXP_WaterVolume 0 +27 3:00 Moisture 34 +27 3:00 Fertilizer 2.2 +27 3:00 END_EXPECTATIONS +27 3:01 WaterVolume 0 + +27 4:00 BEGIN_EXPECTATIONS +27 4:00 Temperature 24 +27 4:00 WaterVolume 0 +27 4:00 Light 20 +27 4:00 EXP_WaterVolume 0 +27 4:00 Moisture 31 +27 4:00 Fertilizer 1.8 +27 4:00 END_EXPECTATIONS +27 4:01 WaterVolume 0 + +27 5:00 BEGIN_EXPECTATIONS +27 5:00 Temperature 24 +27 5:00 WaterVolume 0 +27 5:00 Light 25 +27 5:00 EXP_WaterVolume 0 +27 5:00 Moisture 30 +27 5:00 Fertilizer 2.3 +27 5:00 END_EXPECTATIONS +27 5:01 WaterVolume 0 + +27 6:00 BEGIN_EXPECTATIONS +27 6:00 Temperature 25 +27 6:00 WaterVolume 0 +27 6:00 Light 40 +27 6:00 EXP_WaterVolume 40 +27 6:00 Moisture 28 +27 6:00 Fertilizer 2.3 +27 6:00 END_EXPECTATIONS +27 6:01 WaterVolume 40 + +27 7:00 BEGIN_EXPECTATIONS +27 7:00 Temperature 25 +27 7:00 WaterVolume 0 +27 7:00 Light 45 +27 7:00 EXP_WaterVolume 40 +27 7:00 Moisture 29 +27 7:00 Fertilizer 1.1 +27 7:00 END_EXPECTATIONS +27 7:01 WaterVolume 40 + +27 8:00 BEGIN_EXPECTATIONS +27 8:00 Temperature 25 +27 8:00 WaterVolume 0 +27 8:00 Light 50 +27 8:00 EXP_WaterVolume 0 +27 8:00 Moisture 33 +27 8:00 Fertilizer 2.8 +27 8:00 END_EXPECTATIONS +27 8:01 WaterVolume 0 + +27 9:00 BEGIN_EXPECTATIONS +27 9:00 Temperature 25 +27 9:00 WaterVolume 0 +27 9:00 Light 50 +27 9:00 EXP_WaterVolume 0 +27 9:00 Moisture 50 +27 9:00 Fertilizer 2.5 +27 9:00 END_EXPECTATIONS +27 9:01 WaterVolume 0 + +27 10:00 BEGIN_EXPECTATIONS +27 10:00 Temperature 25 +27 10:00 WaterVolume 0 +27 10:00 Light 50 +27 10:00 EXP_WaterVolume 0 +27 10:00 Moisture 50 +27 10:00 Fertilizer 2.8 +27 10:00 END_EXPECTATIONS +27 10:01 WaterVolume 0 + +27 11:00 BEGIN_EXPECTATIONS +27 11:00 Temperature 26 +27 11:00 WaterVolume 0 +27 11:00 Light 60 +27 11:00 EXP_WaterVolume 0 +27 11:00 Moisture 46 +27 11:00 Fertilizer 2.0 +27 11:00 END_EXPECTATIONS +27 11:01 WaterVolume 0 + +27 12:00 BEGIN_EXPECTATIONS +27 12:00 Temperature 27 +27 12:00 WaterVolume 0 +27 12:00 Light 80 +27 12:00 EXP_WaterVolume 0 +27 12:00 Moisture 41 +27 12:00 Fertilizer 1.5 +27 12:00 END_EXPECTATIONS +27 12:01 WaterVolume 0 + +27 13:00 BEGIN_EXPECTATIONS +27 13:00 Temperature 26 +27 13:00 WaterVolume 0 +27 13:00 Light 70 +27 13:00 EXP_WaterVolume 0 +27 13:00 Moisture 40 +27 13:00 Fertilizer 1.0 +27 13:00 END_EXPECTATIONS +27 13:01 WaterVolume 0 + +27 14:00 BEGIN_EXPECTATIONS +27 14:00 Temperature 26 +27 14:00 WaterVolume 0 +27 14:00 Light 70 +27 14:00 EXP_WaterVolume 0 +27 14:00 Moisture 40 +27 14:00 Fertilizer 1.7 +27 14:00 END_EXPECTATIONS +27 14:01 WaterVolume 0 + +27 15:00 BEGIN_EXPECTATIONS +27 15:00 Temperature 26 +27 15:00 WaterVolume 0 +27 15:00 Light 70 +27 15:00 EXP_WaterVolume 0 +27 15:00 Moisture 38 +27 15:00 Fertilizer 2.7 +27 15:00 END_EXPECTATIONS +27 15:01 WaterVolume 0 + +27 16:00 BEGIN_EXPECTATIONS +27 16:00 Temperature 26 +27 16:00 WaterVolume 0 +27 16:00 Light 65 +27 16:00 EXP_WaterVolume 0 +27 16:00 Moisture 34 +27 16:00 Fertilizer 1.4 +27 16:00 END_EXPECTATIONS +27 16:01 WaterVolume 0 + +27 17:00 BEGIN_EXPECTATIONS +27 17:00 Temperature 26 +27 17:00 WaterVolume 0 +27 17:00 Light 60 +27 17:00 EXP_WaterVolume 0 +27 17:00 Moisture 31 +27 17:00 Fertilizer 1.0 +27 17:00 END_EXPECTATIONS +27 17:01 WaterVolume 0 + +27 18:00 BEGIN_EXPECTATIONS +27 18:00 Temperature 25 +27 18:00 WaterVolume 0 +27 18:00 Light 50 +27 18:00 EXP_WaterVolume 40 +27 18:00 Moisture 27 +27 18:00 Fertilizer 2.1 +27 18:00 END_EXPECTATIONS +27 18:01 WaterVolume 40 + +27 19:00 BEGIN_EXPECTATIONS +27 19:00 Temperature 24 +27 19:00 WaterVolume 0 +27 19:00 Light 30 +27 19:00 EXP_WaterVolume 40 +27 19:00 Moisture 28 +27 19:00 Fertilizer 2.0 +27 19:00 END_EXPECTATIONS +27 19:01 WaterVolume 40 + +27 20:00 BEGIN_EXPECTATIONS +27 20:00 Temperature 23 +27 20:00 WaterVolume 0 +27 20:00 Light 10 +27 20:00 EXP_WaterVolume 0 +27 20:00 Moisture 30 +27 20:00 Fertilizer 2.7 +27 20:00 END_EXPECTATIONS +27 20:01 WaterVolume 0 + +27 21:00 BEGIN_EXPECTATIONS +27 21:00 Temperature 23 +27 21:00 WaterVolume 0 +27 21:00 Light 10 +27 21:00 EXP_WaterVolume 40 +27 21:00 Moisture 27 +27 21:00 Fertilizer 2.1 +27 21:00 END_EXPECTATIONS +27 21:01 WaterVolume 40 + +27 22:00 BEGIN_EXPECTATIONS +27 22:00 Temperature 23 +27 22:00 WaterVolume 0 +27 22:00 Light 10 +27 22:00 EXP_WaterVolume 0 +27 22:00 Moisture 30 +27 22:00 Fertilizer 2.8 +27 22:00 END_EXPECTATIONS +27 22:01 WaterVolume 0 + +27 23:00 BEGIN_EXPECTATIONS +27 23:00 Temperature 23 +27 23:00 WaterVolume 0 +27 23:00 Light 10 +27 23:00 EXP_WaterVolume 40 +27 23:00 Moisture 25 +27 23:00 Fertilizer 2.8 +27 23:00 END_EXPECTATIONS +27 23:01 WaterVolume 40 + diff --git a/simulator/simulations/party.conf b/simulator/simulations/party.conf new file mode 100644 index 0000000..b9d5a1a --- /dev/null +++ b/simulator/simulations/party.conf @@ -0,0 +1,51 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config + +# A day will be splited in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 35 + +#Inputs +INPUT PeopleAgglomeration 0 10 +TERM Empty 0 1 +TERM Alone 1 2 +TERM Couple 2 3 +TERM Group 3 4 +TERM Riot 4 10 + +#Output +OUTPUT Volume 0 10 +TERM Mute 0 1 +TERM Low 1 3 +TERM Medium 3 7 +TERM High 7 10 diff --git a/simulator/simulations/party.project_x.data b/simulator/simulations/party.project_x.data new file mode 100644 index 0000000..cb673e8 --- /dev/null +++ b/simulator/simulations/party.project_x.data @@ -0,0 +1,697 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Scenario +# In a house a couple likes to listen the radio together. +# During lunch time the wife listen to the radio with a Medium volume for one +# hour. +# During the night the couple listen to the radio together at low volume from +# 8pm to 10pm. +# The rest of the time the radio remains mute. This behavior repeats every day +# However for two week the husband is giving a party during the whole weekend, +# during the party that lasts all day, the volume is set to high. + +# Initial scenario +0 0:00 PeopleAgglomeration Empty +0 0:00 Volume Mute +0 0:00 EXP_Volume Mute + +# First two week no parties on saturday and sunday. +# Then two week with parties. +# Last week with no party. + +# Mon +0 12:00 PeopleAgglomeration Alone +0 12:03 EXP_Volume Medium +0 12:03 Volume Medium + +0 13:00 PeopleAgglomeration Empty +0 13:01 EXP_Volume Mute +0 13:01 Volume Mute + +0 20:00 PeopleAgglomeration Couple +0 20:03 EXP_Volume Low +0 20:03 Volume Low + +0 22:00 PeopleAgglomeration Empty +0 22:02 EXP_Volume Mute +0 22:02 Volume Mute + +# Tue +1 12:30 PeopleAgglomeration Alone +1 12:33 EXP_Volume Medium +1 12:33 Volume Medium + +1 13:10 PeopleAgglomeration Empty +1 13:11 EXP_Volume Mute +1 13:11 Volume Mute + +1 20:05 PeopleAgglomeration Couple +1 20:08 EXP_Volume Low +1 20:08 Volume Low + +1 22:10 PeopleAgglomeration Empty +1 22:12 EXP_Volume Mute +1 22:12 Volume Mute + +# Wed +2 12:00 PeopleAgglomeration Alone +2 12:03 EXP_Volume Medium +2 12:03 Volume Medium + +2 13:00 PeopleAgglomeration Empty +2 13:01 EXP_Volume Mute +2 13:01 Volume Mute + +2 20:00 PeopleAgglomeration Couple +2 20:03 EXP_Volume Low +2 20:03 Volume Low + +2 22:00 PeopleAgglomeration Empty +2 22:02 EXP_Volume Mute +2 22:02 Volume Mute + +# Thue +3 12:00 PeopleAgglomeration Alone +3 12:03 EXP_Volume Medium +3 12:03 Volume Medium + +3 13:00 PeopleAgglomeration Empty +3 13:01 EXP_Volume Mute +3 13:01 Volume Mute + +3 20:00 PeopleAgglomeration Couple +3 20:03 EXP_Volume Low +3 20:03 Volume Low + +3 22:00 PeopleAgglomeration Empty +3 22:02 EXP_Volume Mute +3 22:02 Volume Mute + +# Friday +4 12:00 PeopleAgglomeration Alone +4 12:03 EXP_Volume Medium +4 12:03 Volume Medium + +4 13:00 PeopleAgglomeration Empty +4 13:01 EXP_Volume Mute +4 13:01 Volume Mute + +4 20:00 PeopleAgglomeration Couple +4 20:03 EXP_Volume Low +4 20:03 Volume Low + +4 22:00 PeopleAgglomeration Empty +4 22:02 EXP_Volume Mute +4 22:02 Volume Mute + +# Saturday +5 12:00 PeopleAgglomeration Alone +5 12:03 EXP_Volume Medium +5 12:03 Volume Medium + +5 13:00 PeopleAgglomeration Empty +5 13:01 EXP_Volume Mute +5 13:01 Volume Mute + +5 20:00 PeopleAgglomeration Couple +5 20:03 EXP_Volume Low +5 20:03 Volume Low + +5 1:00 PeopleAgglomeration Empty +5 1:02 EXP_Volume Mute +5 1:02 Volume Mute + +# Sunday +6 12:00 PeopleAgglomeration Alone +6 12:03 EXP_Volume Medium +6 12:03 Volume Medium + +6 13:00 PeopleAgglomeration Empty +6 13:01 EXP_Volume Mute +6 13:01 Volume Mute + +6 20:00 PeopleAgglomeration Couple +6 20:03 EXP_Volume Low +6 20:03 Volume Low + +6 22:00 PeopleAgglomeration Empty +6 22:02 EXP_Volume Mute +6 22:02 Volume Mute + +# Mon +7 00:00 BEGIN_EXPECTATIONS regular_day_1_mute +7 12:02 END_EXPECTATIONS + +7 12:03 BEGIN_EXPECTATIONS regular_day_1_medium +7 12:03 PeopleAgglomeration Alone +7 12:03 EXP_Volume Medium +7 12:03 Volume Medium +7 12:03 END_EXPECTATIONS + +7 13:01 BEGIN_EXPECTATIONS regular_day_1_mute2 +7 13:01 PeopleAgglomeration Empty +7 13:01 EXP_Volume Mute +7 13:01 Volume Mute +7 13:01 END_EXPECTATIONS + +7 20:03 BEGIN_EXPECTATIONS regular_day_1_low +7 20:03 PeopleAgglomeration Couple +7 20:03 EXP_Volume Low +7 20:03 Volume Low +7 20:03 END_EXPECTATIONS + +7 22:02 BEGIN_EXPECTATIONS regular_day_1_mute3 +7 22:02 PeopleAgglomeration Empty +7 22:02 EXP_Volume Mute +7 22:02 Volume Mute +7 23:59 END_EXPECTATIONS + +# Tue +8 00:00 BEGIN_EXPECTATIONS regular_day_2_mute +8 00:00 Volume nan +8 12:32 END_EXPECTATIONS + +8 12:33 BEGIN_EXPECTATIONS regular_day_2_medium +8 12:33 PeopleAgglomeration Alone +8 12:33 EXP_Volume Medium +8 12:33 END_EXPECTATIONS + +8 13:11 BEGIN_EXPECTATIONS regular_day_2_mute2 +8 13:11 PeopleAgglomeration Empty +8 13:11 EXP_Volume Mute +8 13:11 END_EXPECTATIONS + +8 20:08 BEGIN_EXPECTATIONS regular_day_2_low +8 20:08 PeopleAgglomeration Couple +8 20:08 EXP_Volume Low +8 20:08 END_EXPECTATIONS + +8 22:12 BEGIN_EXPECTATIONS regular_day_2_mute3 +8 22:12 PeopleAgglomeration Empty +8 22:12 EXP_Volume Mute +8 23:59 END_EXPECTATIONS + +# Wed +9 00:00 Volume Mute +9 12:00 PeopleAgglomeration Alone +9 12:03 EXP_Volume Medium +9 12:03 Volume Medium + +9 13:00 PeopleAgglomeration Empty +9 13:01 EXP_Volume Mute +9 13:01 Volume Mute + +9 20:00 PeopleAgglomeration Couple +9 20:03 EXP_Volume Low +9 20:03 Volume Low + +9 22:00 PeopleAgglomeration Empty +9 22:02 EXP_Volume Mute +9 22:02 Volume Mute + +# Thue +10 12:00 PeopleAgglomeration Alone +10 12:03 EXP_Volume Medium +10 12:03 Volume Medium + +10 13:00 PeopleAgglomeration Empty +10 13:01 EXP_Volume Mute +10 13:01 Volume Mute + +10 20:00 PeopleAgglomeration Couple +10 20:03 EXP_Volume Low +10 20:03 Volume Low + +10 22:00 PeopleAgglomeration Empty +10 22:02 EXP_Volume Mute +10 22:02 Volume Mute + +# Friday +11 12:00 PeopleAgglomeration Alone +11 12:03 EXP_Volume Medium +11 12:03 Volume Medium + +11 13:00 PeopleAgglomeration Empty +11 13:01 EXP_Volume Mute +11 13:01 Volume Mute + +11 20:00 PeopleAgglomeration Couple +11 20:03 EXP_Volume Low +11 20:03 Volume Low + +11 22:00 PeopleAgglomeration Empty +11 22:02 EXP_Volume Mute +11 22:02 Volume Mute + +# Saturday +12 12:00 PeopleAgglomeration Alone +12 12:03 EXP_Volume Medium +12 12:03 Volume Medium + +12 13:00 PeopleAgglomeration Empty +12 13:01 EXP_Volume Mute +12 13:01 Volume Mute + +12 20:00 PeopleAgglomeration Couple +12 20:03 EXP_Volume Low +12 20:03 Volume Low + +12 1:00 PeopleAgglomeration Empty +12 1:02 EXP_Volume Mute +12 1:02 Volume Mute + +# Sunday +13 12:00 PeopleAgglomeration Alone +13 12:03 EXP_Volume Medium +13 12:03 Volume Medium + +13 13:00 PeopleAgglomeration Empty +13 13:01 EXP_Volume Mute +13 13:01 Volume Mute + +13 20:00 PeopleAgglomeration Couple +13 20:03 EXP_Volume Low +13 20:03 Volume Low + +13 22:00 PeopleAgglomeration Empty +13 22:02 EXP_Volume Mute +13 22:02 Volume Mute + +# Mon +14 12:00 PeopleAgglomeration Alone +14 12:03 EXP_Volume Medium +14 12:03 Volume Medium + +14 13:00 PeopleAgglomeration Empty +14 13:01 EXP_Volume Mute +14 13:01 Volume Mute + +14 20:00 PeopleAgglomeration Couple +14 20:03 EXP_Volume Low +14 20:03 Volume Low + +14 22:00 PeopleAgglomeration Empty +14 22:02 EXP_Volume Mute +14 22:02 Volume Mute + +# Tue +15 12:30 PeopleAgglomeration Alone +15 12:33 EXP_Volume Medium +15 12:33 Volume Medium + +15 13:10 PeopleAgglomeration Empty +15 13:11 EXP_Volume Mute +15 13:11 Volume Mute + +15 20:05 PeopleAgglomeration Couple +15 20:00 EXP_Volume Low +15 20:08 Volume Low + +15 22:10 PeopleAgglomeration Empty +15 22:12 EXP_Volume Mute +15 22:12 Volume Mute + +# Wed +16 12:00 PeopleAgglomeration Alone +16 12:03 EXP_Volume Medium +16 12:03 Volume Medium + +16 13:00 PeopleAgglomeration Empty +16 13:01 EXP_Volume Mute +16 13:01 Volume Mute + +16 20:00 PeopleAgglomeration Couple +16 20:03 EXP_Volume Low +16 20:03 Volume Low + +16 22:00 PeopleAgglomeration Empty +16 22:02 EXP_Volume Mute +16 22:02 Volume Mute + +# Thue +17 12:00 PeopleAgglomeration Alone +17 12:03 EXP_Volume Medium +17 12:03 Volume Medium + +17 13:00 PeopleAgglomeration Empty +17 13:01 EXP_Volume Mute +17 13:01 Volume Mute + +17 20:00 PeopleAgglomeration Couple +17 20:03 EXP_Volume Low +17 20:03 Volume Low + +17 22:00 PeopleAgglomeration Empty +17 22:02 EXP_Volume Mute +17 22:02 Volume Mute + +# Friday +18 12:00 PeopleAgglomeration Alone +18 12:03 EXP_Volume Medium +18 12:03 Volume Medium + +18 13:00 PeopleAgglomeration Empty +18 13:01 EXP_Volume Mute +18 13:01 Volume Mute + +18 20:00 PeopleAgglomeration Couple +18 20:03 EXP_Volume Low +18 20:03 Volume Low + +18 22:00 PeopleAgglomeration Empty +18 22:02 EXP_Volume Mute +18 22:02 Volume Mute + +# Saturday +19 12:03 BEGIN_EXPECTATIONS party_day_1 +19 12:00 PeopleAgglomeration Riot +19 12:03 EXP_Volume High +19 12:03 Volume High +19 12:03 END_EXPECTATIONS + +19 13:00 PeopleAgglomeration Riot +19 13:01 EXP_Volume High +19 13:01 Volume High + +19 20:00 PeopleAgglomeration Riot +19 20:03 EXP_Volume High +19 20:03 Volume High + +19 23:59 BEGIN_EXPECTATIONS party_day_1_end +19 23:59 PeopleAgglomeration Empty +19 23:59 EXP_Volume Mute +19 23:59 Volume Mute +19 23:59 END_EXPECTATIONS + +# Sunday +20 12:13 BEGIN_EXPECTATIONS party_day_2 +20 12:10 PeopleAgglomeration Riot +20 12:13 EXP_Volume High +20 12:13 Volume High +20 12:13 END_EXPECTATIONS + +20 13:10 PeopleAgglomeration Riot +20 13:11 EXP_Volume High +20 13:11 Volume High + +20 20:10 PeopleAgglomeration Riot +20 20:13 EXP_Volume High +20 20:13 Volume High + +20 22:59 BEGIN_EXPECTATIONS party_day_2_end +20 22:59 PeopleAgglomeration Empty +20 22:59 EXP_Volume Mute +20 22:59 Volume Mute +20 22:59 END_EXPECTATIONS + +# Mon +21 00:00 BEGIN_EXPECTATIONS after_party_1_mute +21 00:00 Volume nan +21 12:02 END_EXPECTATIONS + +21 12:03 BEGIN_EXPECTATIONS after_party_1_medium +21 12:03 PeopleAgglomeration Alone +21 12:03 EXP_Volume Medium +21 12:03 END_EXPECTATIONS + +21 13:01 BEGIN_EXPECTATIONS after_party_1_mute2 +21 13:01 PeopleAgglomeration Empty +21 13:01 EXP_Volume Mute +21 13:01 END_EXPECTATIONS + +21 20:03 BEGIN_EXPECTATIONS after_party_1_low +21 20:03 PeopleAgglomeration Couple +21 20:03 EXP_Volume Low +21 20:03 END_EXPECTATIONS + +21 22:02 BEGIN_EXPECTATIONS after_party_1_mute3 +21 22:02 PeopleAgglomeration Empty +21 22:02 EXP_Volume Mute +21 23:59 END_EXPECTATIONS + +22 00:00 Volume nan +# Tue +22 12:30 PeopleAgglomeration Alone +22 12:33 EXP_Volume Medium +22 12:33 Volume Medium + +22 13:10 PeopleAgglomeration Empty +22 13:11 EXP_Volume Mute +22 13:11 Volume Mute + +22 20:05 PeopleAgglomeration Couple +22 20:08 EXP_Volume Low +22 20:08 Volume Low + +22 22:10 PeopleAgglomeration Empty +22 22:12 EXP_Volume Mute +22 22:12 Volume Mute + +# Wed +23 12:00 PeopleAgglomeration Alone +23 12:03 EXP_Volume Medium +23 12:03 Volume Medium + +23 13:00 PeopleAgglomeration Empty +23 13:01 EXP_Volume Mute +23 13:01 Volume Mute + +23 20:00 PeopleAgglomeration Couple +23 20:03 EXP_Volume Low +23 20:03 Volume Low + +23 22:00 PeopleAgglomeration Empty +23 22:02 EXP_Volume Mute +23 22:02 Volume Mute + +# Thue +24 12:00 PeopleAgglomeration Alone +24 12:03 EXP_Volume Medium +24 12:03 Volume Medium + +24 13:00 PeopleAgglomeration Empty +24 13:01 EXP_Volume Mute +24 13:01 Volume Mute + +24 20:00 PeopleAgglomeration Couple +24 20:03 EXP_Volume Low +24 20:03 Volume Low + +24 22:00 PeopleAgglomeration Empty +24 22:02 EXP_Volume Mute +24 22:02 Volume Mute + +# Friday +25 12:00 PeopleAgglomeration Alone +25 12:03 EXP_Volume Medium +25 12:03 Volume Medium + +25 13:00 PeopleAgglomeration Empty +25 13:01 EXP_Volume Mute +25 13:01 Volume Mute + +25 20:00 PeopleAgglomeration Couple +25 20:03 EXP_Volume Low +25 20:03 Volume Low + +25 22:00 PeopleAgglomeration Empty +25 22:02 EXP_Volume Mute +25 22:02 Volume Mute + +# Saturday +26 12:23 BEGIN_EXPECTATIONS party_day_3 +26 12:20 PeopleAgglomeration Riot +26 12:23 EXP_Volume High +26 12:23 Volume High +26 12:23 END_EXPECTATIONS + +26 13:20 PeopleAgglomeration Riot +26 13:21 EXP_Volume High +26 13:21 Volume High + +26 20:20 PeopleAgglomeration Riot +26 20:23 EXP_Volume High +26 20:23 Volume High + +26 23:19 BEGIN_EXPECTATIONS party_day_3_end +26 23:19 PeopleAgglomeration Empty +26 23:19 EXP_Volume Mute +26 23:19 Volume Mute +26 23:19 END_EXPECTATIONS + +# Sunday +27 12:13 BEGIN_EXPECTATIONS party_day_4 +27 12:10 PeopleAgglomeration Riot +27 12:13 EXP_Volume High +27 12:13 Volume High +27 12:13 END_EXPECTATIONS + +27 13:10 PeopleAgglomeration Riot +27 13:11 EXP_Volume High +27 13:11 Volume High + +27 20:10 PeopleAgglomeration Riot +27 20:13 EXP_Volume High +27 20:13 Volume High + +27 22:59 BEGIN_EXPECTATIONS party_day_2_end +27 22:59 PeopleAgglomeration Empty +27 22:59 EXP_Volume Mute +27 22:59 Volume Mute +27 22:59 END_EXPECTATIONS + +# Mon +28 12:00 PeopleAgglomeration Alone +28 12:03 EXP_Volume Medium +28 12:03 Volume Medium + +28 13:00 PeopleAgglomeration Empty +28 13:01 EXP_Volume Mute +28 13:01 Volume Mute + +28 20:00 PeopleAgglomeration Couple +28 20:03 EXP_Volume Low +28 20:03 Volume Low + +28 22:00 PeopleAgglomeration Empty +28 22:02 EXP_Volume Mute +28 22:02 Volume Mute + +# Tue +29 12:30 PeopleAgglomeration Alone +29 12:33 EXP_Volume Medium +29 12:33 Volume Medium + +29 13:10 PeopleAgglomeration Empty +29 13:11 EXP_Volume Mute +29 13:11 Volume Mute + +29 20:05 PeopleAgglomeration Couple +29 20:08 EXP_Volume Low +29 20:08 Volume Low + +29 22:10 PeopleAgglomeration Empty +29 22:12 EXP_Volume Mute +29 22:12 Volume Mute + +# Wed +30 12:00 PeopleAgglomeration Alone +30 12:03 EXP_Volume Medium +30 12:03 Volume Medium + +30 13:00 PeopleAgglomeration Empty +30 13:01 EXP_Volume Mute +30 13:01 Volume Mute + +30 20:00 PeopleAgglomeration Couple +30 20:03 EXP_Volume Low +30 20:03 Volume Low + +30 22:00 PeopleAgglomeration Empty +30 22:02 EXP_Volume Mute +30 22:02 Volume Mute + +# Thue +31 12:00 PeopleAgglomeration Alone +31 12:03 EXP_Volume Medium +31 12:03 Volume Medium + +31 13:00 PeopleAgglomeration Empty +31 13:01 EXP_Volume Mute +31 13:01 Volume Mute + +31 20:00 PeopleAgglomeration Couple +31 20:03 EXP_Volume Low +31 20:03 Volume Low + +31 22:00 PeopleAgglomeration Empty +31 22:02 EXP_Volume Mute +31 22:02 Volume Mute + +# Friday +32 12:00 PeopleAgglomeration Alone +32 12:03 EXP_Volume Medium +32 12:03 Volume Medium + +32 13:00 PeopleAgglomeration Empty +32 13:01 EXP_Volume Mute +32 13:01 Volume Mute + +32 20:00 PeopleAgglomeration Couple +32 20:03 EXP_Volume Low +32 20:03 Volume Low + +32 22:00 PeopleAgglomeration Empty +32 22:02 EXP_Volume Mute +32 22:02 Volume Mute + +# Saturday +33 00:00 Volume nan +33 00:00 BEGIN_EXPECTATIONS after_party_2_mute +33 12:02 END_EXPECTATIONS + +33 12:03 BEGIN_EXPECTATIONS after_party_2_medium +33 12:03 PeopleAgglomeration Alone +33 12:03 EXP_Volume Medium +33 12:03 END_EXPECTATIONS + +33 13:01 BEGIN_EXPECTATIONS after_party_2_mute2 +33 13:01 PeopleAgglomeration Empty +33 13:01 EXP_Volume Mute +33 13:01 END_EXPECTATIONS + +33 20:03 BEGIN_EXPECTATIONS after_party_2_low +33 20:03 PeopleAgglomeration Couple +33 20:03 EXP_Volume Low +33 20:03 END_EXPECTATIONS + +33 22:02 BEGIN_EXPECTATIONS after_party_2_mute3 +33 22:02 PeopleAgglomeration Empty +33 22:02 EXP_Volume Mute +33 23:59 END_EXPECTATIONS + +34 00:00 Volume Mute +# Sunday +34 12:00 PeopleAgglomeration Alone +34 12:03 EXP_Volume Medium +34 12:03 Volume Medium + +34 13:00 PeopleAgglomeration Empty +34 13:01 EXP_Volume Mute +34 13:01 Volume Mute + +34 20:00 PeopleAgglomeration Couple +34 20:03 EXP_Volume Low +34 20:03 Volume Low + +34 22:00 PeopleAgglomeration Empty +34 22:02 EXP_Volume Mute +34 22:02 Volume Mute diff --git a/simulator/simulations/shower.conf b/simulator/simulations/shower.conf new file mode 100644 index 0000000..a7e57d1 --- /dev/null +++ b/simulator/simulations/shower.conf @@ -0,0 +1,74 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config + +# a day will be splited in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 14 + +# Inputs +# Block times per day and weekdays are created by default + +INPUT EnvTemperature -30 60 + +INPUT User 0 3 +TERM Nobody 0 0 +TERM Bruno 1 1 +TERM Guilherme 2 2 +TERM Otavio 3 3 + +INPUT BodyTemperature 35 40 + +# actually it depends a lot on user age, but for our +# purposes it doesn't matter +INPUT HeartRate 0 250 +TERM Dead 0 1 +TERM Dying 0 30 +TERM Sleeping 25 70 +TERM Awake 65 100 +TERM ModerateActivity 95 120 +TERM WeightControl 115 140 +TERM Aerobic 135 160 +TERM Anaerobic 155 180 +TERM MaximumEffort 175 200 + +# Outputs +# Expectation variables are created by default with name EXP_Name + +# 0-90 -> don't know how flow rate is usually measured +OUTPUT WaterVolume 0 90 +TERM CLOSED 0 3 +TERM SMALL 2 30 +TERM MEDIUM 25 60 +TERM BIG 55 90 + +OUTPUT WaterTemperature -30 100 diff --git a/simulator/simulations/shower.multiple_users.data b/simulator/simulations/shower.multiple_users.data new file mode 100644 index 0000000..8924514 --- /dev/null +++ b/simulator/simulations/shower.multiple_users.data @@ -0,0 +1,620 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# initial state +0 0:00 EnvTemperature 16 +0 0:00 User Nobody +0 0:00 BodyTemperature 35 +0 0:00 HeartRate 0 + +0 0:00 WaterVolume 0 +0 0:00 EXP_WaterVolume 0 +0 0:00 WaterTemperature 22 +0 0:00 EXP_WaterTemperature 22 + +### Monday ### + +# Bruno take shower every +# weekday when he wakes up +0 07:30 EnvTemperature 22 +0 07:45 User Bruno +0 07:46 HeartRate Awake +0 07:46 BodyTemperature 37.4 + +0 07:47 WaterVolume 60 +0 07:47 WaterTemperature 55 +0 07:47 EXP_WaterVolume 60 +0 07:47 EXP_WaterTemperature 55 + +0 08:00 EnvTemperature 25 + +0 08:10 WaterVolume 0 +0 08:10 WaterTemperature 22 +0 08:10 EXP_WaterVolume 0 +0 08:10 EXP_WaterTemperature 22 +0 08:10 User Nobody + +# Guilherme take shower every day +# after workout +0 09:05 User Guilherme +0 09:05 HeartRate Aerobic +0 09:05 BodyTemperature 37.6 + +0 09:05 WaterVolume 90 +0 09:05 WaterTemperature 28 +0 09:05 EXP_WaterVolume 90 +0 09:05 EXP_WaterTemperature 28 + +0 09:15 WaterVolume 0 +0 09:15 WaterTemperature 25 +0 09:15 EXP_WaterVolume 0 +0 09:15 EXP_WaterTemperature 25 +0 09:15 User Nobody + +0 12:00 EnvTemperature 32 + +0 21:00 EnvTemperature 17 + +# Otavio takes shower some days at night. +# On Mon, Wed, Fri, after workouts +0 21:12 User Otavio +0 21:12 HeartRate Anaerobic +0 21:12 BodyTemperature 36.5 + +0 21:15 WaterVolume 90 +0 21:15 WaterTemperature 24 +0 21:15 EXP_WaterVolume 90 +0 21:15 EXP_WaterTemperature 24 + +0 21:45 WaterVolume 0 +0 21:45 WaterTemperature 17 +0 21:45 EXP_WaterVolume 0 +0 21:45 EXP_WaterTemperature 17 +0 21:45 User Nobody + +### Tuesday ### + +1 07:12 EnvTemperature 18 +1 07:35 User Bruno +1 07:36 HeartRate Awake +1 07:36 BodyTemperature 37.2 + +1 07:37 WaterVolume 65 +1 07:37 WaterTemperature 60 +1 07:37 EXP_WaterVolume 65 +1 07:37 EXP_WaterTemperature 60 + +1 07:51 WaterVolume 0 +1 07:51 WaterTemperature 18 +1 07:51 EXP_WaterVolume 0 +1 07:51 EXP_WaterTemperature 18 +1 07:51 User Nobody + +1 08:30 EnvTemperature 23 + +1 09:20 User Guilherme +1 09:20 HeartRate WeightControl +1 09:20 BodyTemperature 37.3 + +1 09:05 WaterVolume 90 +1 09:05 WaterTemperature 25 +1 09:05 EXP_WaterVolume 90 +1 09:05 EXP_WaterTemperature 25 + +1 09:15 WaterVolume 0 +1 09:15 WaterTemperature 23 +1 09:15 EXP_WaterVolume 0 +1 09:15 EXP_WaterTemperature 23 +1 09:15 User Nobody + +1 13:14 EnvTemperature 29 + +1 21:15 EnvTemperature 18 + +### Wednesday ### + +2 07:12 EnvTemperature 14 +2 08:03 User Bruno +2 08:03 HeartRate Awake +2 08:03 BodyTemperature 37.3 + +2 08:03 WaterVolume 52 +2 08:03 WaterTemperature 63 +2 08:03 EXP_WaterVolume 52 +2 08:03 EXP_WaterTemperature 63 + +2 08:10 WaterVolume 0 +2 08:10 WaterTemperature 14 +2 08:10 EXP_WaterVolume 0 +2 08:10 EXP_WaterTemperature 14 +2 08:10 User Nobody + +2 08:30 EnvTemperature 20 + +2 09:20 User Guilherme +2 09:20 HeartRate Aerobic +2 09:20 BodyTemperature 37.2 + +2 09:20 WaterVolume 90 +2 09:20 WaterTemperature 24 +2 09:20 EXP_WaterVolume 90 +2 09:20 EXP_WaterTemperature 24 + +2 09:43 WaterVolume 0 +2 09:43 WaterTemperature 20 +2 09:43 EXP_WaterVolume 0 +2 09:43 EXP_WaterTemperature 20 +2 09:43 User Nobody + +2 12:00 EnvTemperature 23 + +2 21:00 EnvTemperature 25 + +2 21:50 User Otavio +2 21:50 HeartRate Anaerobic +2 21:50 BodyTemperature 36.8 + +2 21:52 WaterVolume 86 +2 21:52 WaterTemperature 28 +2 21:52 EXP_WaterVolume 86 +2 21:52 EXP_WaterTemperature 28 + +2 21:45 WaterVolume 0 +2 21:45 WaterTemperature 25 +2 21:45 EXP_WaterVolume 0 +2 21:45 EXP_WaterTemperature 25 +2 21:45 User Nobody + +### Thursday ### + +3 08:30 EnvTemperature 25 + +3 09:00 User Guilherme +3 09:00 HeartRate Anaerobic +3 09:00 BodyTemperature 37.4 + +3 09:00 WaterVolume 90 +3 09:00 WaterTemperature 27 +3 09:00 EXP_WaterVolume 90 +3 09:00 EXP_WaterTemperature 27 + +3 09:25 WaterVolume 0 +3 09:25 WaterTemperature 20 +3 09:25 EXP_WaterVolume 0 +3 09:25 EXP_WaterTemperature 20 +3 09:25 User Nobody + +3 10:03 User Bruno +3 10:03 HeartRate Awake +3 10:03 BodyTemperature 37.4 + +3 10:03 WaterVolume 66 +3 10:03 WaterTemperature 63 +3 10:03 EXP_WaterVolume 66 +3 10:03 EXP_WaterTemperature 63 + +3 10:03 WaterTemperature 30 +3 10:03 EXP_WaterTemperature 30 + +3 10:20 WaterVolume 0 +3 10:20 WaterTemperature 14 +3 10:20 EXP_WaterVolume 0 +3 10:20 EXP_WaterTemperature 14 +3 10:20 User Nobody + +3 12:15 EnvTemperature 34 + +3 19:00 EnvTemperature 27 + +3 20:50 User Otavio +3 20:50 HeartRate Awake +3 20:50 BodyTemperature 36.4 + +3 20:52 WaterVolume 90 +3 20:52 WaterTemperature 50 +3 20:52 EXP_WaterVolume 90 +3 20:52 EXP_WaterTemperature 50 + +3 20:45 WaterVolume 0 +3 20:45 WaterTemperature 27 +3 20:45 EXP_WaterVolume 0 +3 20:45 EXP_WaterTemperature 27 +3 20:45 User Nobody + +### Friday ### + +4 07:12 EnvTemperature 8 + +4 08:12 User Bruno +4 08:12 HeartRate Awake +4 08:12 BodyTemperature 37.0 + +4 08:12 WaterVolume 60 +4 08:12 WaterTemperature 80 +4 08:12 EXP_WaterVolume 60 +4 08:12 EXP_WaterTemperature 80 + +4 08:30 WaterVolume 0 +4 08:30 WaterTemperature 8 +4 08:30 EXP_WaterVolume 0 +4 08:30 EXP_WaterTemperature 8 +4 08:30 User Nobody + +4 08:40 EnvTemperature 13 + +4 09:30 User Guilherme +4 09:30 HeartRate Aerobic +4 09:30 BodyTemperature 37.2 + +4 09:30 WaterVolume 90 +4 09:30 WaterTemperature 20 +4 09:30 EXP_WaterVolume 90 +4 09:30 EXP_WaterTemperature 20 + +4 09:53 WaterVolume 0 +4 09:53 WaterTemperature 13 +4 09:53 EXP_WaterVolume 0 +4 09:53 EXP_WaterTemperature 13 +4 09:53 User Nobody + +4 12:00 EnvTemperature 15 + +4 17:00 EnvTemperature 12 + +4 21:50 User Otavio +4 21:50 HeartRate Anaerobic +4 21:50 BodyTemperature 36.9 + +4 21:52 WaterVolume 90 +4 21:52 WaterTemperature 20 +4 21:52 EXP_WaterVolume 90 +4 21:52 EXP_WaterTemperature 20 + +4 21:45 WaterVolume 0 +4 21:45 WaterTemperature 12 +4 21:45 EXP_WaterVolume 0 +4 21:45 EXP_WaterTemperature 12 +4 21:45 User Nobody + +### Saturday ### + +5 07:24 EnvTemperature 18 +5 11:48 EnvTemperature 23 +5 15:07 EnvTemperature 28 +5 19:12 EnvTemperature 20 +5 23:33 EnvTemperature 12 + +### Sunday ### + +6 08:19 EnvTemperature 20 +6 13:10 EnvTemperature 31 +6 16:22 EnvTemperature 27 +6 21:00 EnvTemperature 21 + +### Monday ### + +7 07:30 EnvTemperature 22 +7 07:45 User Bruno +7 07:46 HeartRate Awake +7 07:46 BodyTemperature 37.4 + +7 07:47 BEGIN_EXPECTATIONS +7 07:47 WaterVolume nan +7 07:47 WaterTemperature nan +7 07:47 EXP_WaterVolume 60 +7 07:47 EXP_WaterTemperature 55 +7 07:47 END_EXPECTATIONS + +7 08:00 EnvTemperature 25 + +7 08:10 WaterVolume 0 +7 08:10 WaterTemperature 22 +7 08:10 EXP_WaterVolume 0 +7 08:10 EXP_WaterTemperature 22 +7 08:10 User Nobody + +7 09:05 User Guilherme +7 09:05 HeartRate Aerobic +7 09:05 BodyTemperature 37.6 + +7 09:05 BEGIN_EXPECTATIONS +7 09:05 WaterVolume nan +7 09:05 WaterTemperature nan +7 09:05 EXP_WaterVolume 90 +7 09:05 EXP_WaterTemperature 28 +7 09:05 END_EXPECTATIONS + +7 09:15 WaterVolume 0 +7 09:15 WaterTemperature 25 +7 09:15 EXP_WaterVolume 0 +7 09:15 EXP_WaterTemperature 25 +7 09:15 User Nobody + +7 12:00 EnvTemperature 32 + +7 21:00 EnvTemperature 17 + +7 21:12 User Otavio +7 21:12 HeartRate Anaerobic +7 21:12 BodyTemperature 36.5 + +7 21:15 BEGIN_EXPECTATIONS +7 21:15 WaterVolume nan +7 21:15 WaterTemperature nan +7 21:15 EXP_WaterVolume 90 +7 21:15 EXP_WaterTemperature 24 +7 21:15 END_EXPECTATIONS + +7 21:45 WaterVolume 0 +7 21:45 WaterTemperature 17 +7 21:45 EXP_WaterVolume 0 +7 21:45 EXP_WaterTemperature 17 +7 21:45 User Nobody + +### Tuesday ### + +8 07:12 EnvTemperature 18 +8 07:35 User Bruno +8 07:36 HeartRate Awake +8 07:36 BodyTemperature 37.2 + +8 07:37 BEGIN_EXPECTATIONS +8 07:37 WaterVolume nan +8 07:37 WaterTemperature nan +8 07:37 EXP_WaterVolume 65 +8 07:37 EXP_WaterTemperature 60 +8 07:37 END_EXPECTATIONS + +8 07:51 WaterVolume 0 +8 07:51 WaterTemperature 18 +8 07:51 EXP_WaterVolume 0 +8 07:51 EXP_WaterTemperature 18 +8 07:51 User Nobody + +8 08:30 EnvTemperature 23 + +8 09:20 User Guilherme +8 09:20 HeartRate WeightControl +8 09:20 BodyTemperature 37.3 + +8 09:05 BEGIN_EXPECTATIONS +8 09:05 WaterVolume nan +8 09:05 WaterTemperature nan +8 09:05 EXP_WaterVolume 90 +8 09:05 EXP_WaterTemperature 25 +8 09:05 END_EXPECTATIONS + +8 09:15 WaterVolume 0 +8 09:15 WaterTemperature 23 +8 09:15 EXP_WaterVolume 0 +8 09:15 EXP_WaterTemperature 23 +8 09:15 User Nobody + +8 13:14 EnvTemperature 29 + +8 21:15 EnvTemperature 18 + +### Wednesday ### + +9 07:12 EnvTemperature 14 +9 08:03 User Bruno +9 08:03 HeartRate Awake +9 08:03 BodyTemperature 37.3 + +9 08:03 BEGIN_EXPECTATIONS +9 08:03 WaterVolume nan +9 08:03 WaterTemperature nan +9 08:03 EXP_WaterVolume 52 +9 08:03 EXP_WaterTemperature 63 +9 08:03 END_EXPECTATIONS + +9 08:10 WaterVolume 0 +9 08:10 WaterTemperature 14 +9 08:10 EXP_WaterVolume 0 +9 08:10 EXP_WaterTemperature 14 +9 08:10 User Nobody + +9 08:30 EnvTemperature 20 + +9 09:20 User Guilherme +9 09:20 HeartRate Aerobic +9 09:20 BodyTemperature 37.2 + +9 09:20 BEGIN_EXPECTATIONS +9 09:20 WaterVolume nan +9 09:20 WaterTemperature nan +9 09:20 EXP_WaterVolume 90 +9 09:20 EXP_WaterTemperature 24 +9 09:20 END_EXPECTATIONS + +9 09:43 WaterVolume 0 +9 09:43 WaterTemperature 20 +9 09:43 EXP_WaterVolume 0 +9 09:43 EXP_WaterTemperature 20 +9 09:43 User Nobody + +9 12:00 EnvTemperature 23 + +9 21:00 EnvTemperature 25 + +9 21:50 User Otavio +9 21:50 HeartRate Anaerobic +9 21:50 BodyTemperature 36.8 + +9 21:52 BEGIN_EXPECTATIONS +9 21:52 WaterVolume nan +9 21:52 WaterTemperature nan +9 21:52 EXP_WaterVolume 86 +9 21:52 EXP_WaterTemperature 28 +9 21:52 END_EXPECTATIONS + +9 21:45 WaterVolume 0 +9 21:45 WaterTemperature 25 +9 21:45 EXP_WaterVolume 0 +9 21:45 EXP_WaterTemperature 25 +9 21:45 User Nobody + +### Thursday ### + +10 08:30 EnvTemperature 25 + +10 09:00 User Guilherme +10 09:00 HeartRate Anaerobic +10 09:00 BodyTemperature 37.4 + +10 09:00 BEGIN_EXPECTATIONS +10 09:00 WaterVolume nan +10 09:00 WaterTemperature nan +10 09:00 EXP_WaterVolume 90 +10 09:00 EXP_WaterTemperature 27 +10 09:00 END_EXPECTATIONS + +10 09:25 WaterVolume 0 +10 09:25 WaterTemperature 20 +10 09:25 EXP_WaterVolume 0 +10 09:25 EXP_WaterTemperature 20 +10 09:25 User Nobody + +10 10:03 User Bruno +10 10:03 HeartRate Awake +10 10:03 BodyTemperature 37.4 + +10 10:03 BEGIN_EXPECTATIONS +10 10:03 WaterVolume nan +10 10:03 WaterTemperature nan +10 10:03 EXP_WaterVolume 66 +10 10:03 EXP_WaterTemperature 63 +10 10:03 END_EXPECTATIONS + +10 10:03 WaterTemperature 30 +10 10:03 EXP_WaterTemperature 30 + +10 10:20 WaterVolume 0 +10 10:20 WaterTemperature 14 +10 10:20 EXP_WaterVolume 0 +10 10:20 EXP_WaterTemperature 14 +10 10:20 User Nobody + +10 12:15 EnvTemperature 34 + +10 19:00 EnvTemperature 27 + +10 20:50 User Otavio +10 20:50 HeartRate Awake +10 20:50 BodyTemperature 36.4 + +10 20:52 BEGIN_EXPECTATIONS +10 20:52 WaterVolume nan +10 20:52 WaterTemperature nan +10 20:52 EXP_WaterVolume 90 +10 20:52 EXP_WaterTemperature 50 +10 20:52 END_EXPECTATIONS + +10 20:45 WaterVolume 0 +10 20:45 WaterTemperature 27 +10 20:45 EXP_WaterVolume 0 +10 20:45 EXP_WaterTemperature 27 +10 20:45 User Nobody + +### Friday ### + +11 07:12 EnvTemperature 8 + +11 08:12 User Bruno +11 08:12 HeartRate Awake +11 08:12 BodyTemperature 37.0 + +11 08:12 BEGIN_EXPECTATIONS +11 08:12 WaterVolume nan +11 08:12 WaterTemperature nan +11 08:12 EXP_WaterVolume 60 +11 08:12 EXP_WaterTemperature 80 +11 08:12 END_EXPECTATIONS + +11 08:30 WaterVolume 0 +11 08:30 WaterTemperature 8 +11 08:30 EXP_WaterVolume 0 +11 08:30 EXP_WaterTemperature 8 +11 08:30 User Nobody + +11 08:40 EnvTemperature 13 + +11 09:30 User Guilherme +11 09:30 HeartRate Aerobic +11 09:30 BodyTemperature 37.2 + +11 09:30 BEGIN_EXPECTATIONS +11 09:30 WaterVolume nan +11 09:30 WaterTemperature nan +11 09:30 EXP_WaterVolume 90 +11 09:30 EXP_WaterTemperature 20 +11 09:30 END_EXPECTATIONS + +11 09:53 WaterVolume 0 +11 09:53 WaterTemperature 13 +11 09:53 EXP_WaterVolume 0 +11 09:53 EXP_WaterTemperature 13 +11 09:53 User Nobody + +11 12:00 EnvTemperature 15 + +11 17:00 EnvTemperature 12 + +11 21:50 User Otavio +11 21:50 HeartRate Anaerobic +11 21:50 BodyTemperature 36.9 + +11 21:52 BEGIN_EXPECTATIONS +11 21:52 WaterVolume nan +11 21:52 WaterTemperature nan +11 21:52 EXP_WaterVolume 90 +11 21:52 EXP_WaterTemperature 20 +11 21:52 END_EXPECTATIONS + +11 21:45 WaterVolume 0 +11 21:45 WaterTemperature 12 +11 21:45 EXP_WaterVolume 0 +11 21:45 EXP_WaterTemperature 12 +11 21:45 User Nobody + +### Saturday ### + +12 07:24 EnvTemperature 18 +12 11:48 EnvTemperature 23 +12 15:07 EnvTemperature 28 +12 19:12 EnvTemperature 20 +12 23:33 EnvTemperature 12 + +### Sunday ### + +13 08:19 EnvTemperature 20 +13 13:10 EnvTemperature 31 +13 16:22 EnvTemperature 27 +13 21:00 EnvTemperature 21 diff --git a/simulator/simulations/shower.single_user.data b/simulator/simulations/shower.single_user.data new file mode 100644 index 0000000..8d021b7 --- /dev/null +++ b/simulator/simulations/shower.single_user.data @@ -0,0 +1,351 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# initial state +0 0:00 EnvTemperature 16 +0 0:00 User Nobody +0 0:00 BodyTemperature 35 +0 0:00 HeartRate 0 + +0 0:00 WaterVolume 0 +0 0:00 EXP_WaterVolume 0 +0 0:00 WaterTemperature 22 +0 0:00 EXP_WaterTemperature 22 + +### Monday ### + +# Bruno take shower every +# weekday when he wakes up +0 07:30 EnvTemperature 22 +0 07:45 User Bruno +0 07:46 HeartRate Awake +0 07:46 BodyTemperature 37.4 + +0 07:47 WaterVolume 60 +0 07:47 WaterTemperature 55 +0 07:47 EXP_WaterVolume 60 +0 07:47 EXP_WaterTemperature 55 + +0 08:00 EnvTemperature 25 + +0 08:10 WaterVolume 0 +0 08:10 WaterTemperature 22 +0 08:10 EXP_WaterVolume 0 +0 08:10 EXP_WaterTemperature 22 +0 08:10 User Nobody + +0 12:00 EnvTemperature 32 + +0 21:00 EnvTemperature 17 + +### Tuesday ### + +1 07:12 EnvTemperature 18 +1 07:35 User Bruno +1 07:36 HeartRate Awake +1 07:36 BodyTemperature 37.2 + +1 07:37 WaterVolume 65 +1 07:37 WaterTemperature 60 +1 07:37 EXP_WaterVolume 65 +1 07:37 EXP_WaterTemperature 60 + +1 07:51 WaterVolume 0 +1 07:51 WaterTemperature 18 +1 07:51 EXP_WaterVolume 0 +1 07:51 EXP_WaterTemperature 18 +1 07:51 User Nobody + +1 08:30 EnvTemperature 23 + +1 13:14 EnvTemperature 29 + +1 21:15 EnvTemperature 18 + +### Wednesday ### + +2 07:12 EnvTemperature 14 +2 08:03 User Bruno +2 08:03 HeartRate Awake +2 08:03 BodyTemperature 37.3 + +2 08:03 WaterVolume 52 +2 08:03 WaterTemperature 63 +2 08:03 EXP_WaterVolume 52 +2 08:03 EXP_WaterTemperature 63 + +2 08:10 WaterVolume 0 +2 08:10 WaterTemperature 14 +2 08:10 EXP_WaterVolume 0 +2 08:10 EXP_WaterTemperature 14 +2 08:10 User Nobody + +2 08:30 EnvTemperature 20 + +2 12:00 EnvTemperature 23 + +2 21:00 EnvTemperature 25 + +### Thursday ### + +3 08:30 EnvTemperature 25 + +3 10:03 User Bruno +3 10:03 HeartRate Awake +3 10:03 BodyTemperature 37.4 + +3 10:03 WaterVolume 66 +3 10:03 WaterTemperature 63 +3 10:03 EXP_WaterVolume 66 +3 10:03 EXP_WaterTemperature 63 + +3 10:03 WaterTemperature 30 +3 10:03 EXP_WaterTemperature 30 + +3 10:20 WaterVolume 0 +3 10:20 WaterTemperature 14 +3 10:20 EXP_WaterVolume 0 +3 10:20 EXP_WaterTemperature 14 +3 10:20 User Nobody + +3 12:15 EnvTemperature 34 + +3 19:00 EnvTemperature 27 + +### Friday ### + +4 07:12 EnvTemperature 8 + +4 08:12 User Bruno +4 08:12 HeartRate Awake +4 08:12 BodyTemperature 37.0 + +4 08:12 WaterVolume 60 +4 08:12 WaterTemperature 80 +4 08:12 EXP_WaterVolume 60 +4 08:12 EXP_WaterTemperature 80 + +4 08:30 BEGIN_EXPECTATIONS off_state1 +4 08:30 WaterVolume 0 +4 08:30 WaterTemperature 8 +4 08:30 EXP_WaterVolume 0 +4 08:30 EXP_WaterTemperature nan +4 08:30 User Nobody + +4 08:40 EnvTemperature 13 + +4 12:00 EnvTemperature 15 + +4 17:00 EnvTemperature 12 + +### Saturday ### + +5 07:24 EnvTemperature 18 +5 11:48 EnvTemperature 23 +5 15:07 EnvTemperature 28 +5 19:12 EnvTemperature 20 +5 23:33 EnvTemperature 12 + +### Sunday ### + +6 08:19 EnvTemperature 20 +6 13:10 EnvTemperature 31 +6 16:22 EnvTemperature 27 +6 21:00 EnvTemperature 21 + +### Monday ### + +7 07:30 EnvTemperature 22 +7 07:40 END_EXPECTATIONS #off_state1 + +7 07:45 WaterVolume nan +7 07:45 WaterTemperature nan +7 07:45 User Bruno +7 07:46 HeartRate Awake +7 07:46 BodyTemperature 37.4 + +7 07:47 BEGIN_EXPECTATIONS shower1 +7 07:47 EXP_WaterVolume 60 +7 07:47 EXP_WaterTemperature 55 +7 07:47 END_EXPECTATIONS #shower1 + +7 08:00 EnvTemperature 25 + +7 08:10 EXP_WaterVolume 0 +7 08:10 EXP_WaterTemperature nan +7 08:10 User Nobody + +7 08:10 BEGIN_EXPECTATIONS off_state2 + +7 12:00 EnvTemperature 32 + +7 21:00 EnvTemperature 17 + +### Tuesday ### + +8 07:12 EnvTemperature 18 +8 07:30 END_EXPECTATIONS #off_state2 +8 07:35 User Bruno +8 07:36 HeartRate Awake +8 07:36 BodyTemperature 37.2 + +8 07:37 BEGIN_EXPECTATIONS shower2 +8 07:37 WaterVolume 65 +8 07:37 WaterTemperature 60 +8 07:37 EXP_WaterVolume 65 +8 07:37 EXP_WaterTemperature 60 +8 07:37 END_EXPECTATIONS #shower2 + +8 07:51 WaterVolume 0 +8 07:51 WaterTemperature 18 +8 07:51 EXP_WaterVolume 0 +8 07:51 EXP_WaterTemperature 18 +8 07:51 User Nobody + +8 08:30 EnvTemperature 23 + +8 13:14 EnvTemperature 29 + +8 21:15 EnvTemperature 18 + +### Wednesday ### + +9 07:12 EnvTemperature 14 +9 08:03 User Bruno +9 08:03 HeartRate Awake +9 08:03 BodyTemperature 37.3 + +9 08:03 BEGIN_EXPECTATIONS shower3 +9 08:03 WaterVolume 52 +9 08:03 WaterTemperature 63 +9 08:03 EXP_WaterVolume 52 +9 08:03 EXP_WaterTemperature 63 +9 08:03 END_EXPECTATIONS #shower2 + +9 08:10 WaterVolume 0 +9 08:10 WaterTemperature 14 +9 08:10 EXP_WaterVolume 0 +9 08:10 EXP_WaterTemperature nan +9 08:10 User Nobody +9 08:10 BEGIN_EXPECTATIONS off_state3 + +9 08:30 EnvTemperature 20 +9 12:00 EnvTemperature 23 +9 21:00 EnvTemperature 25 + +### Thursday ### + +10 08:30 EnvTemperature 25 +10 10:00 END_EXPECTATIONS #off_state3 + +10 10:03 BEGIN_EXPECTATIONS shower4 +10 10:03 User Bruno +10 10:03 HeartRate Awake +10 10:03 BodyTemperature 37.4 +10 10:03 WaterVolume 66 +10 10:03 WaterTemperature 63 +10 10:03 EXP_WaterVolume 66 +10 10:03 EXP_WaterTemperature 63 +10 10:03 END_EXPECTATIONS #shower4 + +10 10:03 WaterTemperature 30 +10 10:03 EXP_WaterTemperature 30 + +10 10:20 WaterVolume 0 +10 10:20 WaterTemperature 14 +10 10:20 EXP_WaterVolume 0 +10 10:20 EXP_WaterTemperature 14 +10 10:20 User Nobody + +10 12:15 EnvTemperature 34 + + +10 19:03 BEGIN_EXPECTATIONS night_shower +10 19:03 User Bruno +10 19:03 HeartRate Awake +10 19:03 BodyTemperature 37.4 +10 19:03 WaterVolume nan +10 19:03 WaterTemperature nan +10 19:03 EXP_WaterVolume 66 +10 19:03 EXP_WaterTemperature 63 +10 19:03 END_EXPECTATIONS #night_shower + +10 20:00 WaterVolume 0 +10 20:00 WaterTemperature 0 +10 20:00 User Nobody +10 21:00 EnvTemperature 27 + +### Friday ### + +11 07:10 EnvTemperature 8 + +11 08:12 BEGIN_EXPECTATIONS long_shower +11 08:12 User Bruno +11 08:12 HeartRate Awake +11 08:12 BodyTemperature 37.0 +11 08:12 WaterVolume 60 +11 08:12 WaterTemperature 80 +11 08:12 EXP_WaterVolume 60 +11 08:12 EXP_WaterTemperature 80 + +11 08:40 EnvTemperature 13 +11 08:50 EnvTemperature 20 +11 09:10 EnvTemperature 25 +11 09:20 EnvTemperature 30 +11 09:40 EnvTemperature 25 +11 10:00 EnvTemperature 20 +11 10:10 EnvTemperature 10 + +11 10:20 END_EXPECTATIONS #long_shower + +11 10:30 WaterVolume 0 +11 10:30 WaterTemperature 8 +11 10:30 EXP_WaterVolume 0 +11 10:30 EXP_WaterTemperature 8 +11 10:30 User Nobody + +11 12:00 EnvTemperature 15 + +11 17:00 EnvTemperature 12 + +### Saturday ### + +12 07:24 EnvTemperature 18 +12 11:48 EnvTemperature 23 +12 15:07 EnvTemperature 28 +12 19:12 EnvTemperature 20 +12 23:33 EnvTemperature 12 + +### Sunday ### + +13 08:19 EnvTemperature 20 +13 13:10 EnvTemperature 31 +13 16:22 EnvTemperature 27 +13 21:00 EnvTemperature 21 diff --git a/simulator/simulations/shower.single_user_workout.data b/simulator/simulations/shower.single_user_workout.data new file mode 100644 index 0000000..3c0002f --- /dev/null +++ b/simulator/simulations/shower.single_user_workout.data @@ -0,0 +1,328 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# initial state +0 0:00 EnvTemperature 16 +0 0:00 User Nobody +0 0:00 BodyTemperature 35 +0 0:00 HeartRate 0 + +0 0:00 WaterVolume 0 +0 0:00 EXP_WaterVolume 0 +0 0:00 WaterTemperature 22 +0 0:00 EXP_WaterTemperature 22 + +### Monday ### + +# Bruno take shower every +# weekday when he wakes up +0 07:30 EnvTemperature 22 +0 07:45 User Bruno +0 07:46 HeartRate Awake +0 07:46 BodyTemperature 37.4 + +0 07:47 WaterVolume 60 +0 07:47 WaterTemperature 55 +0 07:47 EXP_WaterVolume 60 +0 07:47 EXP_WaterTemperature 55 + +0 08:00 EnvTemperature 25 + +0 08:10 WaterVolume 0 +0 08:10 WaterTemperature 22 +0 08:10 EXP_WaterVolume 0 +0 08:10 EXP_WaterTemperature 22 +0 08:10 User Nobody + +0 12:00 EnvTemperature 32 + +0 21:00 EnvTemperature 17 + +### Tuesday ### + +1 07:12 EnvTemperature 18 +1 07:35 User Bruno +1 07:36 HeartRate Awake +1 07:36 BodyTemperature 37.2 + +1 07:37 WaterVolume 65 +1 07:37 WaterTemperature 60 +1 07:37 EXP_WaterVolume 65 +1 07:37 EXP_WaterTemperature 60 + +1 07:51 WaterVolume 0 +1 07:51 WaterTemperature 18 +1 07:51 EXP_WaterVolume 0 +1 07:51 EXP_WaterTemperature 18 +1 07:51 User Nobody + +1 08:30 EnvTemperature 23 + +1 13:14 EnvTemperature 29 + +1 21:15 EnvTemperature 18 + +### Wednesday ### + +2 07:12 EnvTemperature 14 +2 08:03 User Bruno +2 08:03 HeartRate Aerobic +2 08:03 BodyTemperature 37.5 + +2 08:03 WaterVolume 90 +2 08:03 WaterTemperature 20 +2 08:03 EXP_WaterVolume 90 +2 08:03 EXP_WaterTemperature 20 + +2 08:10 WaterVolume 0 +2 08:10 WaterTemperature 14 +2 08:10 EXP_WaterVolume 0 +2 08:10 EXP_WaterTemperature 14 +2 08:10 User Nobody + +2 08:30 EnvTemperature 20 + +2 12:00 EnvTemperature 23 + +2 21:00 EnvTemperature 25 + +### Thursday ### + +3 08:30 EnvTemperature 25 + +3 10:03 User Bruno +3 10:03 HeartRate Awake +3 10:03 BodyTemperature 37.4 + +3 10:03 WaterVolume 66 +3 10:03 WaterTemperature 63 +3 10:03 EXP_WaterVolume 66 +3 10:03 EXP_WaterTemperature 63 + +3 10:03 WaterTemperature 30 +3 10:03 EXP_WaterTemperature 30 + +3 10:20 WaterVolume 0 +3 10:20 WaterTemperature 14 +3 10:20 EXP_WaterVolume 0 +3 10:20 EXP_WaterTemperature 14 +3 10:20 User Nobody + +3 12:15 EnvTemperature 34 + +3 19:00 EnvTemperature 27 + +### Friday ### + +4 07:12 EnvTemperature 8 + +4 08:12 User Bruno +4 08:12 HeartRate Awake +4 08:12 BodyTemperature 37.0 + +4 08:12 WaterVolume 60 +4 08:12 WaterTemperature 80 +4 08:12 EXP_WaterVolume 60 +4 08:12 EXP_WaterTemperature 80 + +4 08:30 WaterVolume 0 +4 08:30 WaterTemperature 8 +4 08:30 EXP_WaterVolume 0 +4 08:30 EXP_WaterTemperature 8 +4 08:30 User Nobody + +4 08:40 EnvTemperature 13 + +4 12:00 EnvTemperature 15 + +4 17:00 EnvTemperature 12 + +### Saturday ### + +5 07:24 EnvTemperature 18 +5 11:48 EnvTemperature 23 +5 15:07 EnvTemperature 28 +5 19:12 EnvTemperature 20 +5 23:33 EnvTemperature 12 + +### Sunday ### + +6 08:19 EnvTemperature 20 +6 13:10 EnvTemperature 31 +6 16:22 EnvTemperature 27 +6 21:00 EnvTemperature 21 + +### Monday ### + +7 07:30 EnvTemperature 22 +7 07:45 User Bruno +7 07:46 HeartRate Awake +7 07:46 BodyTemperature 37.4 + +7 07:47 BEGIN_EXPECTATIONS +7 07:47 WaterVolume 60 +7 07:47 WaterTemperature 55 +7 07:47 EXP_WaterVolume 60 +7 07:47 EXP_WaterTemperature 55 +7 07:47 END_EXPECTATIONS + +7 08:00 EnvTemperature 25 + +7 08:10 WaterVolume 0 +7 08:10 WaterTemperature 22 +7 08:10 EXP_WaterVolume 0 +7 08:10 EXP_WaterTemperature 22 +7 08:10 User Nobody + +7 12:00 EnvTemperature 32 + +7 21:00 EnvTemperature 17 + +### Tuesday ### + +8 07:12 EnvTemperature 18 +8 07:35 User Bruno +8 07:36 HeartRate Awake +8 07:36 BodyTemperature 37.2 + +8 07:37 BEGIN_EXPECTATIONS +8 07:37 WaterVolume 65 +8 07:37 WaterTemperature 60 +8 07:37 EXP_WaterVolume 65 +8 07:37 EXP_WaterTemperature 60 +8 07:37 END_EXPECTATIONS + +8 07:51 WaterVolume 0 +8 07:51 WaterTemperature 18 +8 07:51 EXP_WaterVolume 0 +8 07:51 EXP_WaterTemperature 18 +8 07:51 User Nobody + +8 08:30 EnvTemperature 23 + +8 13:14 EnvTemperature 29 + +8 21:15 EnvTemperature 18 + +### Wednesday ### + +9 07:12 EnvTemperature 14 +9 08:03 User Bruno +9 08:03 HeartRate Aerobic +9 08:03 BodyTemperature 37.5 + +9 08:03 BEGIN_EXPECTATIONS +9 08:03 WaterVolume nan +9 08:03 WaterTemperature nan +9 08:03 EXP_WaterVolume 90 +9 08:03 EXP_WaterTemperature 20 +9 08:03 END_EXPECTATIONS + +9 08:10 WaterVolume 0 +9 08:10 WaterTemperature 14 +9 08:10 EXP_WaterVolume 0 +9 08:10 EXP_WaterTemperature 14 +9 08:10 User Nobody + +9 08:30 EnvTemperature 20 + +9 12:00 EnvTemperature 23 + +9 21:00 EnvTemperature 25 + +### Thursday ### + +10 08:30 EnvTemperature 25 + +10 10:03 User Bruno +10 10:03 HeartRate Awake +10 10:03 BodyTemperature 37.4 + +10 10:03 BEGIN_EXPECTATIONS +10 10:03 WaterVolume nan +10 10:03 WaterTemperature nan +10 10:03 EXP_WaterVolume 66 +10 10:03 EXP_WaterTemperature 63 +10 10:03 END_EXPECTATIONS + +10 10:03 WaterTemperature 30 +10 10:03 EXP_WaterTemperature 30 + +10 10:20 WaterVolume 0 +10 10:20 WaterTemperature 14 +10 10:20 EXP_WaterVolume 0 +10 10:20 EXP_WaterTemperature 14 +10 10:20 User Nobody + +10 12:15 EnvTemperature 34 + +10 19:00 EnvTemperature 27 + +### Friday ### + +11 07:12 EnvTemperature 8 + +11 08:12 User Bruno +11 08:12 HeartRate Anaerobic +11 08:12 BodyTemperature 37.0 + +11 08:12 BEGIN_EXPECTATIONS +11 08:12 WaterVolume nan +11 08:12 WaterTemperature nan +11 08:12 EXP_WaterVolume 90 +11 08:12 EXP_WaterTemperature 25 +11 08:12 END_EXPECTATIONS + +11 08:30 WaterVolume 0 +11 08:30 WaterTemperature 8 +11 08:30 EXP_WaterVolume 0 +11 08:30 EXP_WaterTemperature 8 +11 08:30 User Nobody + +11 08:40 EnvTemperature 13 + +11 12:00 EnvTemperature 15 + +11 17:00 EnvTemperature 12 + +### Saturday ### + +12 07:24 EnvTemperature 18 +12 11:48 EnvTemperature 23 +12 15:07 EnvTemperature 28 +12 19:12 EnvTemperature 20 +12 23:33 EnvTemperature 12 + +### Sunday ### + +13 08:19 EnvTemperature 20 +13 13:10 EnvTemperature 31 +13 16:22 EnvTemperature 27 +13 21:00 EnvTemperature 21 diff --git a/simulator/simulations/simple_office.conf b/simulator/simulations/simple_office.conf new file mode 100644 index 0000000..0ac0c12 --- /dev/null +++ b/simulator/simulations/simple_office.conf @@ -0,0 +1,57 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config + +# a day will be splited in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 14 + +# Inputs +# Block times per day and weekdays are created by default + +INPUT EnvLight 0 100 +TERM Night 0 10 +TERM Cloudy 5 30 +TERM PartlyCloudy 25 55 +TERM PartlySunny 50 80 +TERM Sunny 70 100 + +INPUT Presence 0 1 +TERM Absence 0 0 +TERM Presence 1 1 + +# Outputs +# Expectation variables are created by default with name EXP_Name + +OUTPUT Light 0 1 +TERM OFF 0 0 +TERM ON 1 1 diff --git a/simulator/simulations/simple_office.forget_lights_on.data b/simulator/simulations/simple_office.forget_lights_on.data new file mode 100644 index 0000000..c457cde --- /dev/null +++ b/simulator/simulations/simple_office.forget_lights_on.data @@ -0,0 +1,314 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Simulation: a single person working in a office +# She always let lights turned on while she is inside +# She wants to avoid forgotting lights on +# +# It simulates the usage of a room for 2 weeks, usually used from 10:00 +# to 18:00 on work days (Mon to Fri) with lunch between 13:00 and 14:00. +# It has a luminosity sensor, a presence sensor and a light bulb. +# User can change light state using a switcher, but it won't be +# used as input. Time is used as input (hours and week days). + +# initial scenario - lights off +0 0:00 Light OFF +0 0:00 EnvLight Night +0 0:00 Presence Absence + +0 7:23 EnvLight PartlySunny + +# we expect to turn on as soon as she arrives +0 8:10 Presence Presence +0 8:12 Light ON + +0 12:00 Light OFF +0 12:02 Presence Absence + +0 12:40 EnvLight Sunny + +0 13:04 Presence Presence +0 13:06 Light ON + +0 18:00 Light OFF +0 18:02 Presence Absence + +0 18:30 EnvLight Cloudy + +0 20:04 EnvLight Night + +############## + +1 7:00 EnvLight PartlyCloudy + +1 8:20 Presence Presence +1 8:23 Light ON + +1 12:10 Light OFF +1 12:14 Presence Absence + +1 13:00 EnvLight Cloudy + +1 13:20 Presence Presence +1 13:22 Light ON + +1 18:05 Light OFF +1 18:07 Presence Absence + +1 20:18 EnvLight Night + +############## + +2 7:18 EnvLight Sunny + +2 8:25 Presence Presence +2 8:29 Light ON + +2 11:05 EnvLight PartlyCloudy + +2 12:20 Light OFF +2 12:21 Presence Absence + +2 13:00 EnvLight Cloudy + +2 13:18 Presence Presence +2 13:20 Light ON + +2 18:25 Light OFF +2 18:27 Presence Absence + +2 20:09 EnvLight Night + +############## + +3 7:22 EnvLight PartlySunny + +3 8:15 Presence Presence +3 8:19 Light ON + +3 12:10 Light OFF +3 12:11 Presence Absence + +3 13:12 Presence Presence +3 13:15 Light ON + +# she forgot the lights on +3 18:18 BEGIN_EXPECTATIONS forgot_lights_on +3 18:18 EXP_Light OFF +3 18:18 Presence Absence +3 18:18 END_EXPECTATIONS + +# sml should turn off Lights and keep it off during the night. +3 18:19 BEGIN_EXPECTATIONS lights_off_at_night +3 18:19 Light OFF +3 20:12 EnvLight Night + +############## + +# A regular day without any big issue +4 7:00 EnvLight Sunny + +4 8:30 END_EXPECTATIONS + +4 8:31 BEGIN_EXPECTATIONS regular_day +4 8:31 Presence Presence +4 8:31 EXP_Light ON +4 8:32 Light ON + +4 12:00 Light OFF +4 12:00 EXP_Light OFF +4 12:02 Presence Absence + +4 12:50 Presence Presence +4 12:50 EXP_Light ON +4 12:51 Light ON + +4 18:00 Light OFF +4 18:00 EXP_Light OFF +4 18:05 Presence Absence + +5 19:30 END_EXPECTATIONS + +4 19:31 BEGIN_EXPECTATIONS lights_off_weekend +4 20:04 EnvLight Night + +############## + +# she doesn't work at weekends +5 7:03 EnvLight PartlySunny +5 9:21 EnvLight Sunny +5 15:46 EnvLight PartlyCloudy +5 20:10 EnvLight Night + +############## + +6 7:12 EnvLight Sunny +6 12:29 EnvLight Cloudy +6 20:01 EnvLight Night + +############## + +# second week is just repeating the first week + + +7 7:23 EnvLight PartlySunny + +7 8:00 END_EXPECTATIONS +7 8:10 Presence Presence +7 8:10 EXP_Light ON +7 8:12 Light ON + +7 12:00 Light OFF +7 12:02 EXP_Light OFF +7 12:02 Presence Absence + +7 12:40 EnvLight Sunny + +7 13:04 Presence Presence +7 13:04 EXP_Light ON +7 13:06 Light ON + +7 18:00 Light OFF +7 18:02 EXP_Light OFF +7 18:02 Presence Absence + +7 18:30 EnvLight Cloudy + +7 20:04 EnvLight Night + +############## + +8 7:00 EnvLight PartlyCloudy + +8 8:20 Presence Presence +8 8:20 EXP_Light ON +8 8:23 Light ON + +8 12:10 Light OFF +8 12:10 EXP_Light OFF +8 12:14 Presence Absence + +8 13:00 EnvLight Cloudy + +8 13:20 Presence Presence +8 13:20 EXP_Light ON +8 13:22 Light ON + +8 18:05 Light OFF +8 18:07 EXP_Light OFF +8 18:07 Presence Absence + +8 20:18 EnvLight Night + +############## + +9 7:18 EnvLight Sunny + +9 8:25 Presence Presence +9 8:25 EXP_Light ON +9 8:29 Light ON + +9 11:05 EnvLight PartlyCloudy + +9 12:20 Light OFF +9 12:20 EXP_Light OFF +9 12:21 Presence Absence + +9 13:00 EnvLight Cloudy + +9 13:18 Presence Presence +9 13:18 EXP_Light ON +9 13:20 Light ON + +9 18:25 Light OFF +9 18:27 EXP_Light OFF +9 18:27 Presence Absence + +9 20:09 EnvLight Night + +############## + +10 0:00 BEGIN_EXPECTATIONS another_regular_day + +10 7:22 EnvLight PartlySunny + +10 8:15 Presence Presence +10 8:15 EXP_Light ON +10 8:16 Light ON + +10 12:10 Light OFF +10 12:10 EXP_Light OFF +10 12:15 Presence Absence + +10 13:12 Presence Presence +10 13:12 EXP_Light ON +10 13:13 Light ON + +10 18:18 EXP_Light OFF +10 18:18 Presence Absence +10 18:19 Light OFF + +10 20:12 EnvLight Night + +11 8:00 END_EXPECTATIONS + +############## + +11 7:00 EnvLight Sunny + +11 8:31 Presence Presence +11 8:32 Light ON + +11 12:00 Light OFF +11 12:02 Presence Absence + +11 12:50 Presence Presence +11 12:55 Light ON + +11 18:00 Light OFF +11 18:02 Presence Absence +11 18:00 EnvLight Night +11 18:00 EXP_Light OFF + +11 18:10 BEGIN_EXPECTATIONS another_weekend + +############## + +12 7:03 EnvLight PartlySunny +12 9:21 EnvLight Sunny +12 15:46 EnvLight PartlyCloudy +12 20:10 EnvLight Night + +############## + +13 7:12 EnvLight Sunny +13 12:29 EnvLight Cloudy +13 20:01 EnvLight Night +13 23:59 END_EXPECTATIONS diff --git a/simulator/simulations/unvalidated/delivery.conf b/simulator/simulations/unvalidated/delivery.conf new file mode 100644 index 0000000..174b377 --- /dev/null +++ b/simulator/simulations/unvalidated/delivery.conf @@ -0,0 +1,69 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config + +# a day will be splitted in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 14 + +# Inputs +# Block times per day and weekdays are created by default + +INPUT User 0 3 +TERM Nobody 0 0 +TERM Bruno 1 1 +TERM Guilherme 2 2 +TERM Otavio 3 3 + + +INPUT MindState 0 5 +TERM Sad 0 1.5 +TERM Annoyed 1 2.5 +TERM Neutral 2 3.5 +TERM Happy 3 5 + +INPUT BodyState 0 3 +TERM Healthy 0 0 +TERM Tired 1 1 +TERM Exhausted 2 2 +TERM Ill 3 3 + +INPUT PeopleQuantity 1 10 + +OUTPUT Order 0 5 +TERM None 0 0 +TERM Pizza 1 1 +TERM Hamburger 2 2 +TERM Temaki 3 3 +TERM Arab 4 4 +TERM Chinese 5 5 + diff --git a/simulator/simulations/unvalidated/delivery.data b/simulator/simulations/unvalidated/delivery.data new file mode 100644 index 0000000..eebf3ca --- /dev/null +++ b/simulator/simulations/unvalidated/delivery.data @@ -0,0 +1,212 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# initial state +0 0:00 User Nobody +0 0:00 MindState Neutral +0 0:00 BodyState Healthy +0 0:00 PeopleQuantity 0 +0 0:00 Order None +0 0:00 EXP_Order None + +# # # Monday # # # +0 20:13 User Bruno +0 20:13 PeopleQuantity 1 +0 20:15 MindState Neutral +0 20:16 BodyState Tired + +0 20:18 Order Arab +0 20:18 EXP_Order Arab + +# # # Tuesday # # # +1 7:11 User Nobody +1 7:11 Order None +1 7:12 MindState Neutral +1 7:12 BodyState Healthy +1 7:15 PeopleQuantity 0 + +1 20:40 User Bruno +1 20:42 PeopleQuantity 1 +1 20:15 MindState Neutral +1 20:16 BodyState Tired + +# # # Wednesday # # # +2 7:08 User Nobody +2 7:09 MindState Annoyed +2 7:09 BodyState Ill +2 7:10 PeopleQuantity 0 + +2 21:02 User Bruno +2 21:03 PeopleQuantity 4 +2 21:04 MindState Annoyed +2 21:05 BodyState Ill + +2 21:28 Order Pizza +2 21:28 EXP_Order Pizza + +2 23:05 PeopleQuantity 1 + +# # # Thursday # # # +3 8:00 User Nobody +3 8:00 Order None +3 8:02 MindState Happy +3 8:03 BodyState Tired +3 8:04 PeopleQuantity 0 + +3 19:45 User Bruno +3 19:46 PeopleQuantity 1 +3 19:47 MindState Neutral +3 19:47 BodyState Tired + +# # # Friday # # # +4 7:23 User Nobody +4 7:23 Order None +4 7:25 MindState Neutral +4 7:25 BodyState Healthy +4 7:28 PeopleQuantity 0 + +4 21:22 User Bruno +4 21:23 PeopleQuantity 2 +4 21:24 MindState Happy +4 21:24 BodyState Tired + +4 21:40 Order Hamburger +4 21:40 EXP_Order Hamburger + +# # # Saturday # # # +5 10:34 User Nobody +5 10:34 Order None +5 10:35 MindState Neutral +5 10:35 BodyState Healthy +5 10:41 PeopleQuantity 0 + +5 23:07 User Bruno +5 23:08 PeopleQuantity 2 +5 23:09 MindState Happy +5 23:09 BodyState Tired + +# # # Sunday # # # +6 19:47 MindState Annoyed +6 19:48 BodyState Healthy +6 19:50 PeopleQuantity 1 + +6 19:53 BEGIN_EXPECTATIONS +6 19:53 Order nan +6 19:53 EXP_Order Arab +6 19:53 END_EXPECTATIONS +6 19:54 Order Arab + +# # # Monday # # # +7 7:31 User Nobody +7 7:31 Order None +7 7:33 MindState Neutral +7 7:33 BodyState Healthy +7 7:33 PeopleQuantity 0 + +7 20:24 User Bruno +7 20:24 PeopleQuantity 1 +7 20:25 MindState Annoyed +7 20:26 BodyState Tired + +7 21:08 Order Temaki +7 21:08 EXP_Order Temaki + +# # # Tuesday # # # +8 6:49 User Nobody +8 6:49 Order None +8 6:49 MindState Sad +8 6:51 BodyState Tired +8 6:51 PeopleQuantity 0 + +8 18:37 User Bruno +8 18:37 PeopleQuantity 1 +8 18:40 MindState Sad +8 18:45 BodyState Tired + +# # # Wednesday # # # +9 7:21 User Nobody +9 7:21 Order None +9 7:22 MindState Annoyed +9 7:22 BodyState Ill +9 7:25 PeopleQuantity 0 + +9 21:06 User Bruno +9 21:06 PeopleQuantity 3 +9 21:07 MindState Annoyed +9 21:08 BodyState Ill + +9 21:47 BEGIN_EXPECTATIONS +9 21:47 Order nan +9 21:47 EXP_Order Pizza +9 21:47 END_EXPECTATIONS +9 21:48 Order Pizza + +9 22:46 PeopleQuantity 1 + +# # # Thursday # # # +10 7:24 User Nobody +10 7:24 Order None +10 7:24 MindState Neutral +10 7:26 BodyState Exhausted +10 7:26 PeopleQuantity 0 + +10 19:23 User Bruno +10 19:23 PeopleQuantity 1 +10 19:25 MindState Annoyed +10 19:26 BodyState Exhausted + +10 19:37 BEGIN_EXPECTATIONS +10 19:37 Order nan +10 19:37 EXP_Order Hamburger +10 19:37 END_EXPECTATIONS +10 19:38 Order Hamburger + +# # # Friday # # # +11 8:02 User Nobody +11 8:02 Order None +11 8:05 MindState Neutral +11 8:05 BodyState Ill +11 8:08 PeopleQuantity 0 + +# # # Saturday # # # +12 21:07 User Bruno +12 21:08 PeopleQuantity 2 +12 21:09 MindState Happy +12 21:09 BodyState Tired + +# # # Sunday # # # +13 19:15 MindState Annoyed +13 19:15 BodyState Healthy + +13 20:23 BEGIN_EXPECTATIONS +13 20:23 Order nan +13 20:23 EXP_Order Temaki +13 20:23 END_EXPECTATIONS +13 20:24 Order Temaki diff --git a/simulator/simulations/unvalidated/home_precense.conf b/simulator/simulations/unvalidated/home_precense.conf new file mode 100644 index 0000000..d033d98 --- /dev/null +++ b/simulator/simulations/unvalidated/home_precense.conf @@ -0,0 +1,51 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config + +# a day will be splitted in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 14 + +# Inputs +# Block times per day and weekdays are created by default + +INPUT User 0 4 +TERM Nobody 0 0 +TERM Bruno 1 1 +TERM Guilherme 2 2 +TERM Otavio 3 3 + +OUTPUT UserActivity 0 2 +TERM None 0 0 +TERM WayIn 1 1 +TERM WayOut 2 2 + diff --git a/simulator/simulations/unvalidated/home_precense.data b/simulator/simulations/unvalidated/home_precense.data new file mode 100644 index 0000000..a1b4fcc --- /dev/null +++ b/simulator/simulations/unvalidated/home_precense.data @@ -0,0 +1,155 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Initial State +0 0:00 BEGIN_EXPECTATIONS +0 0:00 User Nobody +0 0:00 UserActivity None +0 0:00 EXP_UserActivity None + +# Guilherme usually goes to work at 8:30 +# and comes back home around 8:30 pm + +### Monday ### +0 6:30 User Guilherme +0 6:32 UserActivity WayOut +0 6:32 EXP_UserActivity WayOut + +0 20:07 User Guilherme +0 20:08 UserActivity WayIn +0 20:08 EXP_UserActivity WayIn + +### Tuesday ### +1 8:35 User Guilherme +1 8:36 UserActivity WayOut +1 8:36 EXP_UserActivity WayOut + +1 20:23 User Guilherme +1 20:24 UserActivity WayIn +1 20:24 EXP_UserActivity WayIn + +### Wednesday ### +2 6:23 User Guilherme +2 6:24 UserActivity WayOut +2 6:24 EXP_UserActivity WayOut + +2 20:45 User Guilherme +2 20:47 UserActivity WayIn +2 20:47 EXP_UserActivity Wayin + +### Thursday ### +3 8:43 User Guilherme +3 8:44 UserActivity WayOut +3 8:44 EXP_UserActivity WayOut + +### Friday ### +4 0:03 User Guilherme +4 0:04 UserActivity WayIn +4 0:04 EXP_UserActivity None + +4 9:01 User Guilherme +4 9:02 UserActivity WayOut +4 9:02 EXP_UserActivity WayOut +### Saturday ### +5 3:11 User Guilherme +5 3:12 UserActivity WayIn +5 3:12 EXP_UserActivity None + +5 13:01 User Guilherme +5 13:02 UserActivity WayOut +5 13:02 EXP_UserActivity WayOut + +### Saturday ### +6 5:07 User Guilherme +6 5:08 UserActivity WayIn +6 5:08 EXP_UserActivity None + +### Sunday ### + +### Monday ### +7 6:24 User Guilherme +7 6:25 UserActivity WayOut +7 6:25 EXP_UserActivity WayOut + +7 20:18 User Guilherme +7 20:19 UserActivity WayIn +7 20:19 EXP_UserActivity WayIn + +### Tuesday ### +8 8:40 User Guilherme +8 8:41 UserActivity WayOut +8 8:41 EXP_UserActivity WayOut + +8 20:33 User Guilherme +8 20:34 UserActivity WayIn +8 20:34 EXP_UserActivity WayIn + +### Wednesday ### +9 6:38 User Guilherme +9 6:39 UserActivity WayOut +9 6:39 EXP_UserActivity WayOut + +9 21:10 User Guilherme +9 21:11 UserActivity WayIn +9 21:11 EXP_UserActivity WayIn + +### Thursday ### +10 8:29 User Guilherme +10 8:44 UserActivity WayOut +10 8:44 EXP_UserActivity WayOut + +10 23:48 User Guilherme +10 23:49 UserActivity WayIn +10 23:49 EXP_UserActivity WayIn + +### Friday ### +11 8:42 User Guilherme +11 8:43 UserActivity WayOut +11 8:43 EXP_UserActivity WayOut + +### Saturday ### +12 1:27 User Guilherme +12 1:28 UserActivity WayIn +12 1:28 EXP_UserActivity WayIn + +12 17:19 User Guilherme +12 17:20 UserActivity WayOut +12 17:20 EXP_UserActivity WayOut + +### Sunday ### +13 13:16 User Guilherme +13 13:17 UserActivity WayIn +13 13:17 EXP_UserActivity WayIn + +13 19:43 User Guilherme +13 19:44 UserActivity WayOut +13 19:44 EXP_UserActivity WayOut + +13 23:59 END_EXPECTATIONS diff --git a/simulator/simulations/unvalidated/tv_content.conf b/simulator/simulations/unvalidated/tv_content.conf new file mode 100644 index 0000000..0996c3b --- /dev/null +++ b/simulator/simulations/unvalidated/tv_content.conf @@ -0,0 +1,85 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config + +# a day will be splitted in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 3 +DAYS 14 + +# Inputs +# Block times per day and weekdays are created by default + +INPUT EnvTemperature -30 60 + +INPUT User 0 3 +TERM Nobody 0 0 +TERM Bruno 1 1 +TERM Guilherme 2 2 +TERM Otavio 3 3 + +INPUT MindState 0 5 +TERM Sad 0 1.5 +TERM Annoyed 1 2.5 +TERM Neutral 2 3.5 +TERM Happy 3 5 + +INPUT BodyState 0 4 +TERM Healthy 0 1 +TERM Tired 1 2 +TERM Exhausted 2 3 +TERM Ill 3 4 + +OUTPUT ProgramType 0 9 +TERM None 0 0 +TERM Movie 1 1 +TERM Series 2 2 +TERM News 3 3 +TERM Documentary 4 4 +TERM Cartoon 5 5 +TERM Show 6 6 +TERM Sports 7 7 +TERM TalkShow 8 9 +TERM SoapOpera 9 9 + +OUTPUT ProgramGenre 0 9 +TERM None 0 0 +TERM Drama 1 1 +TERM Comedy 2 2 +TERM Terror 3 3 +TERM Thriller 4 4 +TERM Romance 5 5 +TERM Adventure 6 6 +TERM Fantasy 7 7 +TERM Animation 8 8 +TERM SciFi 9 9 + + diff --git a/simulator/simulations/unvalidated/tv_content.data b/simulator/simulations/unvalidated/tv_content.data new file mode 100644 index 0000000..cf26175 --- /dev/null +++ b/simulator/simulations/unvalidated/tv_content.data @@ -0,0 +1,571 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# initial state +0 0:00 BEGIN_EXPECTATIONS +0 0:00 EnvTemperature 21 +0 0:00 User Nobody +0 0:00 MindState Annoyed +0 0:00 BodyState Healthy + +0 0:00 ProgramType None +0 0:00 EXP_ProgramType None +0 0:00 ProgramGenre None +0 0:00 EXP_ProgramGenre None + +### Monday ### + +# Bruno watches the news every weekday at breakfast time +# and when he returns home from work. +# Sometimes he also watches something like movies or games before +# going to bed +0 8:00 EnvTemperature 21 +0 8:00 User Bruno +0 8:05 MindState Neutral +0 8:08 BodyState Healthy + +0 8:15 ProgramType Cartoon +0 8:15 EXP_ProgramType News +0 8:15 ProgramGenre None +0 8:15 EXP_ProgramGenre None + +0 8:30 EnvTemperature 25 + +0 8:30 User Nobody +0 8:30 ProgramType None +0 8:30 EXP_ProgramType None +0 8:30 ProgramGenre None +0 8:30 EXP_ProgramGenre None + +0 12:00 EnvTemperature 32 + +0 19:30 EnvTemperature 20 + +0 19:45 User Bruno +0 19:48 MindState Sad +0 19:50 BodyState Tired + +0 19:57 ProgramType News +0 19:57 EXP_ProgramType News +0 19:57 ProgramGenre None +0 19:57 EXP_ProgramGenre None + +0 20:30 ProgramType Movie +0 20:30 EXP_ProgramType Movie +0 20:30 ProgramGenre Terror +0 20:30 EXP_ProgramGenre Terror + +0 21:47 ProgramType Series +0 21:47 EXP_ProgramType Series +0 21:47 ProgramGenre Thriller +0 21:47 EXP_ProgramGenre Thriller + +0 23:00 EnvTemperature 18 + +0 23:05 User Nobody +0 23:05 ProgramType None +0 23:05 EXP_ProgramType None +0 23:05 ProgramGenre None +0 23:05 EXP_ProgramGenre None + +### Tuesday ### +1 8:00 EnvTemperature 19 +1 8:07 User Bruno +1 8:11 MindState Annoyed +1 8:11 BodyState Healthy + +1 8:15 ProgramType Series +1 8:15 EXP_ProgramType Cartoon +1 8:15 ProgramGenre Thriller +1 8:15 EXP_ProgramGenre None + +1 8:30 EnvTemperature 21 + +1 8:30 User Nobody +1 8:30 ProgramType None +1 8:30 EXP_ProgramType None +1 8:30 ProgramGenre None +1 8:30 EXP_ProgramGenre None + +1 12:00 EnvTemperature 22 + +1 19:30 EnvTemperature 17 + +1 19:52 User Bruno +1 19:54 MindState Sad +1 19:54 BodyState Exhausted + +1 20:13 ProgramType Cartoon +1 20:13 EXP_ProgramType News +1 20:13 ProgramGenre None +1 20:13 EXP_ProgramGenre None + +1 20:30 ProgramType Sports +1 20:30 EXP_ProgramType Sports +1 20:30 ProgramGenre None +1 20:30 EXP_ProgramGenre None + +1 21:30 EnvTemperature 15 + +1 22:05 User Nobody +1 22:05 ProgramType None +1 22:05 EXP_ProgramType None +1 22:05 ProgramGenre None +1 22:05 EXP_ProgramGenre None + +### Wednesday ### +2 8:00 EnvTemperature 19 +2 8:03 User Bruno +2 8:05 MindState Neutral +2 8:07 BodyState Healthy + +2 8:10 ProgramType Sports +2 8:10 EXP_ProgramType News +2 8:10 ProgramGenre None +2 8:10 EXP_ProgramGenre None + +2 8:30 EnvTemperature 21 + +2 8:30 User Nobody +2 8:30 ProgramType None +2 8:30 EXP_ProgramType None +2 8:30 ProgramGenre None +2 8:30 EXP_ProgramGenre None + +2 12:00 EnvTemperature 24 + +2 19:30 EnvTemperature 20 + +2 19:39 User Bruno +2 19:41 MindState Sad +2 19:41 BodyState Exhausted + +2 19:45 ProgramType News +2 19:45 EXP_ProgramType News +2 19:45 ProgramGenre None +2 19:45 EXP_ProgramGenre None + +2 20:30 User Nobody +2 20:30 ProgramType None +2 20:30 EXP_ProgramType None +2 20:30 ProgramGenre None +2 20:30 EXP_ProgramGenre None + +2 21:00 EnvTemperature 18 + +### Thursday ### +3 7:30 EnvTemperature 17 +3 7:35 User Bruno +3 7:37 MindState Neutral +3 7:38 BodyState Healthy + +3 7:43 ProgramType News +3 7:43 EXP_ProgramType News +3 7:43 ProgramGenre None +3 7:43 EXP_ProgramGenre None + +3 8:00 EnvTemperature 18 + +3 8:05 User Nobody +3 8:05 ProgramType None +3 8:05 EXP_ProgramType None +3 8:05 ProgramGenre None +3 8:05 EXP_ProgramGenre None + +3 12:00 EnvTemperature 23 + +3 19:00 EnvTemperature 20 + +3 19:15 User Bruno +3 19:15 MindState Sad +3 19:15 BodyState Exhausted + +3 20:00 ProgramType News +3 20:00 EXP_ProgramType News +3 20:00 ProgramGenre None +3 20:00 EXP_ProgramGenre None + +3 20:30 User Nobody +3 20:30 ProgramType None +3 20:30 EXP_ProgramType None +3 20:30 ProgramGenre None +3 20:30 EXP_ProgramGenre None + +3 21:00 EnvTemperature 17 + +### Friday ### +4 8:00 EnvTemperature 19 +4 8:02 User Bruno +4 8:04 MindState Annoyed +4 8:05 BodyState Healthy + +4 8:43 ProgramType News +4 8:43 EXP_ProgramType News +4 8:43 ProgramGenre None +4 8:43 EXP_ProgramGenre None + +4 9:00 EnvTemperature 18 + +4 9:05 User Nobody +4 9:05 ProgramType None +4 9:05 EXP_ProgramType None +4 9:05 ProgramGenre None +4 9:05 EXP_ProgramGenre None + +4 12:00 EnvTemperature 23 + +4 19:00 EnvTemperature 16 + +4 20:15 User Bruno +4 20:15 MindState Happy +4 20:15 BodyState Exhausted + +4 20:30 ProgramType News +4 20:30 EXP_ProgramType Series +4 20:30 ProgramGenre None +4 20:30 EXP_ProgramGenre Thriller + +4 21:30 User Nobody +4 21:30 ProgramType None +4 21:30 EXP_ProgramType None +4 21:30 ProgramGenre None +4 21:30 EXP_ProgramGenre None + +### Saturday ### +5 8:00 EnvTemperature 14 + +5 10:02 User Bruno +5 10:04 MindState Annoyed +5 10:05 BodyState Healthy + +5 11:43 ProgramType Series +5 11:43 EXP_ProgramType Series +5 11:43 ProgramGenre Drama +5 11:43 EXP_ProgramGenre Drama + +5 12:00 EnvTemperature 18 + +5 17:00 EnvTemperature 17 + +5 18:30 ProgramType None +5 18:30 EXP_ProgramType None +5 18:30 ProgramGenre None +5 18:30 EXP_ProgramGenre None + +### Sunday ### +6 8:00 EnvTemperature 15 + +6 15:02 User Bruno +6 15:04 MindState Annoyed +6 15:05 BodyState Healthy + +6 10:00 EnvTemperature 18 + +6 12:00 EnvTemperature 20 + +6 15:30 ProgramType Series +6 15:30 EXP_ProgramType Sports +6 15:30 ProgramGenre Drama +6 15:30 EXP_ProgramGenre None + +6 17:00 EnvTemperature 18 + +6 17:30 User Nobody +6 17:30 ProgramType None +6 17:30 EXP_ProgramType None +6 17:30 ProgramGenre None +6 17:30 EXP_ProgramGenre None + +### Monday ### +7 8:00 EnvTemperature 21 +7 8:00 User Bruno +7 8:05 MindState Neutral +7 8:08 BodyState Healthy + +7 8:15 ProgramType Sports +7 8:15 EXP_ProgramType News +7 8:15 ProgramGenre None +7 8:15 EXP_ProgramGenre None + +7 8:30 EnvTemperature 25 + +7 8:30 User Nobody +7 8:30 ProgramType None +7 8:30 EXP_ProgramType None +7 8:30 ProgramGenre None +7 8:30 EXP_ProgramGenre None + +7 12:00 EnvTemperature 32 + +7 19:30 EnvTemperature 20 + +7 19:45 User Bruno +7 19:48 MindState Sad +7 19:50 BodyState Tired + +7 19:57 ProgramType News +7 19:57 EXP_ProgramType News +7 19:57 ProgramGenre None +7 19:57 EXP_ProgramGenre None + +7 20:30 ProgramType Movie +7 20:30 EXP_ProgramType Movie +7 20:30 ProgramGenre Terror +7 20:30 EXP_ProgramGenre Terror + +7 21:47 ProgramType Series +7 21:47 EXP_ProgramType Series +7 21:47 ProgramGenre Thriller +7 21:47 EXP_ProgramGenre Thriller + +7 23:00 EnvTemperature 18 + +7 23:05 User Nobody +7 23:05 ProgramType Series +7 23:05 EXP_ProgramType News +7 23:05 ProgramGenre Thriller +7 23:05 EXP_ProgramGenre None + +### Tuesday ### +8 8:00 EnvTemperature 19 +8 8:07 User Bruno +8 8:11 MindState Annoyed +8 8:11 BodyState Healthy + +8 8:15 ProgramType News +8 8:15 EXP_ProgramType Cartoon +8 8:15 ProgramGenre None +8 8:15 EXP_ProgramGenre None + +8 8:30 EnvTemperature 21 + +8 8:30 User Nobody +8 8:30 ProgramType None +8 8:30 EXP_ProgramType None +8 8:30 ProgramGenre None +8 8:30 EXP_ProgramGenre None + +8 12:00 EnvTemperature 22 + +8 19:30 EnvTemperature 17 + +8 19:52 User Bruno +8 19:54 MindState Sad +8 19:54 BodyState Exhausted + +8 20:13 ProgramType Cartoon +8 20:13 EXP_ProgramType News +8 20:13 ProgramGenre None +8 20:13 EXP_ProgramGenre None + +8 20:30 ProgramType Movie +8 20:30 EXP_ProgramType Movie +8 20:30 ProgramGenre Romance +8 20:30 EXP_ProgramGenre Romance + +8 21:30 EnvTemperature 15 + +### Wednesday ### +9 02:05 User Nobody +9 02:05 ProgramType None +9 02:05 EXP_ProgramType None +9 02:05 ProgramGenre None +9 02:05 EXP_ProgramGenre None + +9 8:00 EnvTemperature 19 +9 8:03 User Bruno +9 8:05 MindState Neutral +9 8:07 BodyState Healthy + +9 8:10 ProgramType Movie +9 8:10 EXP_ProgramType News +9 8:10 ProgramGenre Romance +9 8:10 EXP_ProgramGenre None + +9 8:30 EnvTemperature 21 + +9 8:30 User Nobody +9 8:30 ProgramType None +9 8:30 EXP_ProgramType None +9 8:30 ProgramGenre None +9 8:30 EXP_ProgramGenre None + +9 12:00 EnvTemperature 24 + +9 19:30 EnvTemperature 20 + +9 19:39 User Bruno +9 19:41 MindState Sad +9 19:41 BodyState Exhausted + +9 19:45 ProgramType News +9 19:45 EXP_ProgramType News +9 19:45 ProgramGenre None +9 19:45 EXP_ProgramGenre None + +9 20:30 User Nobody +9 20:30 ProgramType None +9 20:30 EXP_ProgramType None +9 20:30 ProgramGenre None +9 20:30 EXP_ProgramGenre None + +9 21:00 EnvTemperature 18 + +### Thursday ### +10 7:30 EnvTemperature 17 +10 7:35 User Bruno +10 7:37 MindState Neutral +10 7:38 BodyState Healthy + +10 7:43 ProgramType News +10 7:43 EXP_ProgramType News +10 7:43 ProgramGenre None +10 7:43 EXP_ProgramGenre None + +10 8:00 EnvTemperature 18 + +10 8:05 User Nobody +10 8:05 ProgramType None +10 8:05 EXP_ProgramType None +10 8:05 ProgramGenre None +10 8:05 EXP_ProgramGenre None + +10 12:00 EnvTemperature 23 + +10 19:00 EnvTemperature 20 + +10 19:15 User Bruno +10 19:15 MindState Sad +10 19:15 BodyState Exhausted + +10 20:00 ProgramType News +10 20:00 EXP_ProgramType News +10 20:00 ProgramGenre None +10 20:00 EXP_ProgramGenre None + +10 21:00 ProgramType Movie +10 21:00 EXP_ProgramType Movie +10 21:00 ProgramGenre Comedy +10 21:00 EXP_ProgramGenre Comedy + +10 20:30 User Nobody +10 20:30 ProgramType None +10 20:30 EXP_ProgramType None +10 20:30 ProgramGenre None +10 20:30 EXP_ProgramGenre None + +10 21:00 EnvTemperature 17 + +### Friday ### +11 8:00 EnvTemperature 19 +11 8:02 User Bruno +11 8:04 MindState Annoyed +11 8:05 BodyState Healthy + +11 8:43 ProgramType Movie +11 8:43 EXP_ProgramType News +11 8:43 ProgramGenre Comedy +11 8:43 EXP_ProgramGenre None + +11 9:00 EnvTemperature 18 + +11 9:05 User Nobody +11 9:05 ProgramType None +11 9:05 EXP_ProgramType None +11 9:05 ProgramGenre None +11 9:05 EXP_ProgramGenre None + +11 12:00 EnvTemperature 23 + +11 19:00 EnvTemperature 16 + +11 20:15 User Bruno +11 20:15 MindState Happy +11 20:15 BodyState Exhausted + +11 21:30 ProgramType News +11 21:30 EXP_ProgramType Movie +11 21:30 ProgramGenre None +11 21:30 EXP_ProgramGenre Drama + +11 22:30 User Nobody +11 22:30 ProgramType None +11 22:30 EXP_ProgramType None +11 22:30 ProgramGenre None +11 22:30 EXP_ProgramGenre None + +### Saturday ### +12 8:00 EnvTemperature 16 + +12 12:00 EnvTemperature 22 + +12 16:00 EnvTemperature 18 + +12 20:00 EnvTemperature 17 + +12 21:02 User Bruno +12 21:04 MindState Annoyed +12 21:05 BodyState Healthy + +12 21:43 ProgramType Movie +12 21:43 EXP_ProgramType Series +12 21:43 ProgramGenre Drama +12 21:43 EXP_ProgramGenre Drama + +12 23:30 User Nobody +12 23:30 ProgramType None +12 23:30 EXP_ProgramType None +12 23:30 ProgramGenre None +12 23:30 EXP_ProgramGenre None + +### Sunday ### +13 8:00 EnvTemperature 15 +13 15:02 User Bruno +13 15:04 MindState Annoyed +13 15:05 BodyState Tired + +13 10:00 EnvTemperature 18 + +13 12:00 EnvTemperature 20 + +13 15:30 ProgramType Series +13 15:30 EXP_ProgramType Sports +13 15:30 ProgramGenre None +13 15:30 EXP_ProgramGenre None + +13 17:00 EnvTemperature 18 + +13 17:30 User Nobody +13 17:30 ProgramType None +13 17:30 EXP_ProgramType None +13 17:30 ProgramGenre None +13 17:30 EXP_ProgramGenre None + +13 23:59 END_EXPECTATIONS diff --git a/simulator/simulations/vacation.conf b/simulator/simulations/vacation.conf new file mode 100644 index 0000000..5770b85 --- /dev/null +++ b/simulator/simulations/vacation.conf @@ -0,0 +1,52 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# General config + +# a day will be splited in 48 blocks of 30 minutes +TIME_BLOCKS 48 +READ_FREQ 1 +DAYS 35 + +# Inputs +# Block times per day and weekdays are created by default + +INPUT EnvLight 0 10 +TERM Night 0 10 +TERM Cloudy 5 30 +TERM PartlyCloudy 25 55 +TERM PartlySunny 50 80 +TERM Sunny 70 100 + +# Outputs +# Expectation variables are created by default with name EXP_Name +OUTPUT Light 0 1 +TERM OFF 0 0 +TERM ON 1 1 diff --git a/simulator/simulations/vacation.data b/simulator/simulations/vacation.data new file mode 100644 index 0000000..16ff091 --- /dev/null +++ b/simulator/simulations/vacation.data @@ -0,0 +1,758 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Mon +0 0:00 EnvLight Night +0 0:00 Light ON +0 0:00 EXP_Light ON + +0 7:23 EnvLight PartlySunny +0 7:23 Light OFF +0 7:23 EXP_Light OFF + +0 9:00 EnvLight Cloudy +0 9:00 Light ON +0 9:00 EXP_Light ON + +0 13:00 EnvLight PartlyCloudy +0 13:00 Light OFF +0 13:00 EXP_Light OFF + +0 20:00 EnvLight Night +0 20:00 EXP_Light ON +0 20:00 Light ON + +#Tue +1 7:23 EnvLight PartlySunny +1 7:23 Light OFF +1 7:23 EXP_Light OFF + +1 9:00 EnvLight Cloudy +1 9:00 Light ON +1 9:00 EXP_Light ON + +1 13:00 EnvLight PartlyCloudy +1 13:00 Light OFF +1 13:00 EXP_Light OFF + +1 20:00 EnvLight Night +1 20:00 EXP_Light ON +1 20:00 Light ON + +#Wed +2 0:00 EnvLight Night +2 0:00 Light ON +2 0:00 EXP_Light ON + +2 7:23 EnvLight PartlySunny +2 7:23 Light OFF +2 7:23 EXP_Light OFF + +2 9:00 EnvLight Sunny +2 9:00 Light OFF +2 9:00 EXP_Light OFF + +2 13:00 EnvLight PartlyCloudy +2 13:00 Light OFF +2 13:00 EXP_Light OFF + +2 20:00 EnvLight Night +2 20:00 EXP_Light ON +2 20:00 Light ON + +#Thu +3 0:00 EnvLight Night +3 0:00 Light ON +3 0:00 EXP_Light ON + +3 7:23 EnvLight PartlySunny +3 7:23 Light OFF +3 7:23 EXP_Light OFF + +3 9:00 EnvLight Sunny +3 9:00 Light OFF +3 9:00 EXP_Light OFF + +3 13:00 EnvLight PartlyCloudy +3 13:00 Light OFF +3 13:00 EXP_Light OFF + +3 20:00 EnvLight Night +3 20:00 EXP_Light ON +3 20:00 Light ON + +#Fri +4 0:00 EnvLight Night +4 0:00 Light ON +4 0:00 EXP_Light ON + +4 7:23 EnvLight PartlySunny +4 7:23 Light OFF +4 7:23 EXP_Light OFF + +4 9:00 EnvLight Sunny +4 9:00 Light OFF +4 9:00 EXP_Light OFF + +4 13:00 EnvLight PartlyCloudy +4 13:00 Light OFF +4 13:00 EXP_Light OFF + +4 20:00 EnvLight Night +4 20:00 EXP_Light ON +4 20:00 Light ON + +#Sat +5 0:00 EnvLight Night +5 0:00 Light ON +5 0:00 EXP_Light ON + +5 7:23 EnvLight PartlySunny +5 7:23 Light OFF +5 7:23 EXP_Light OFF + +5 9:00 EnvLight Cloudy +5 9:00 Light ON +5 9:00 EXP_Light ON + +5 13:00 EnvLight PartlyCloudy +5 13:00 Light OFF +5 13:00 EXP_Light OFF + +5 20:00 EnvLight Night +5 20:00 EXP_Light ON +5 20:00 Light ON + +#Sun +6 0:00 EnvLight Night +6 0:00 Light ON +6 0:00 EXP_Light ON + +6 7:23 EnvLight PartlySunny +6 7:23 Light OFF +6 7:23 EXP_Light OFF + +6 9:00 EnvLight Sunny +6 9:00 Light OFF +6 9:00 EXP_Light OFF + +6 13:00 EnvLight PartlyCloudy +6 13:00 Light OFF +6 13:00 EXP_Light OFF + +6 20:00 EnvLight Night +6 20:00 EXP_Light ON +6 20:00 Light ON + +#Mon +7 0:00 EnvLight Night +7 0:00 Light ON +7 0:00 EXP_Light ON + +7 7:23 EnvLight PartlySunny +7 7:23 Light OFF +7 7:23 EXP_Light OFF + +7 9:00 EnvLight Cloudy +7 9:00 Light ON +7 9:00 EXP_Light ON + +7 13:00 EnvLight PartlyCloudy +7 13:00 Light OFF +7 13:00 EXP_Light OFF + +7 20:00 EnvLight Night +7 20:00 EXP_Light ON +7 20:00 Light ON + +#Tue +8 7:23 EnvLight PartlySunny +8 7:23 Light OFF +8 7:23 EXP_Light OFF + +8 9:00 EnvLight Cloudy +8 9:00 Light ON +8 9:00 EXP_Light ON + +8 13:00 EnvLight PartlyCloudy +8 13:00 Light OFF +8 13:00 EXP_Light OFF + +8 20:00 EnvLight Night +8 20:00 EXP_Light ON +8 20:00 Light ON + +#Wed +9 0:00 EnvLight Night +9 0:00 Light ON +9 0:00 EXP_Light ON + +9 7:23 EnvLight PartlySunny +9 7:23 Light OFF +9 7:23 EXP_Light OFF + +9 9:00 EnvLight Sunny +9 9:00 Light OFF +9 9:00 EXP_Light OFF + +9 13:00 EnvLight PartlyCloudy +9 13:00 Light OFF +9 13:00 EXP_Light OFF + +9 20:00 EnvLight Night +9 20:00 EXP_Light ON +9 20:00 Light ON + +#Thu +10 0:00 EnvLight Night +10 0:00 Light ON +10 0:00 EXP_Light ON + +10 7:23 EnvLight PartlySunny +10 7:23 Light OFF +10 7:23 EXP_Light OFF + +10 9:00 EnvLight Sunny +10 9:00 Light OFF +10 9:00 EXP_Light OFF + +10 13:00 EnvLight PartlyCloudy +10 13:00 Light OFF +10 13:00 EXP_Light OFF + +10 20:00 EnvLight Night +10 20:00 EXP_Light ON +10 20:00 Light ON + +#Fri +11 0:00 EnvLight Night +11 0:00 Light ON +11 0:00 EXP_Light ON + +11 7:23 EnvLight PartlySunny +11 7:23 Light OFF +11 7:23 EXP_Light OFF + +11 9:00 EnvLight Sunny +11 9:00 Light OFF +11 9:00 EXP_Light OFF + +11 13:00 EnvLight PartlyCloudy +11 13:00 Light OFF +11 13:00 EXP_Light OFF + +11 20:00 EnvLight Night +11 20:00 EXP_Light ON +11 20:00 Light ON + +#Sat +12 0:00 EnvLight Night +12 0:00 Light ON +12 0:00 EXP_Light ON + +12 7:23 EnvLight PartlySunny +12 7:23 Light OFF +12 7:23 EXP_Light OFF + +12 9:00 EnvLight Cloudy +12 9:00 Light ON +12 9:00 EXP_Light ON + +12 13:00 EnvLight PartlyCloudy +12 13:00 Light OFF +12 13:00 EXP_Light OFF + +12 20:00 EnvLight Night +12 20:00 EXP_Light ON +12 20:00 Light ON + +#Sun +13 0:00 BEGIN_EXPECTATIONS regular_day1 +13 0:00 Light nan +13 0:00 EnvLight Night +13 0:00 EXP_Light ON + +13 7:23 EnvLight PartlySunny +13 7:23 EXP_Light OFF + +13 9:00 EnvLight Sunny +13 9:00 EXP_Light OFF + +13 13:00 EnvLight PartlyCloudy +13 13:00 EXP_Light OFF + +13 20:00 EnvLight Night +13 20:00 EXP_Light ON +13 23:59 END_EXPECTATIONS + +#VACATION + +#Mon +14 0:00 BEGIN_EXPECTATIONS vacation_day1 +14 0:00 EnvLight Night +14 0:00 Light OFF +14 0:00 EXP_Light OFF + +14 7:23 EnvLight PartlySunny +14 7:23 Light OFF +14 7:23 EXP_Light OFF + +14 9:00 EnvLight Cloudy +14 9:00 Light OFF +14 9:00 EXP_Light OFF + +14 13:00 EnvLight PartlyCloudy +14 13:00 Light OFF +14 13:00 EXP_Light OFF + +14 20:00 EnvLight Night +14 20:00 EXP_Light OFF +14 20:00 Light OFF +14 23:59 END_EXPECTATIONS + +#Tue +15 0:00 BEGIN_EXPECTATIONS vacation_day2 +15 7:23 EnvLight PartlySunny +15 7:23 Light OFF +15 7:23 EXP_Light OFF + +15 9:00 EnvLight Cloudy +15 9:00 Light OFF +15 9:00 EXP_Light OFF + +15 13:00 EnvLight PartlyCloudy +15 13:00 Light OFF +15 13:00 EXP_Light OFF + +15 20:00 EnvLight Night +15 20:00 EXP_Light OFF +15 20:00 Light OFF +15 23:59 END_EXPECTATIONS + +#Wed +16 0:00 EnvLight Night +16 0:00 Light OFF +16 0:00 EXP_Light OFF + +16 7:23 EnvLight PartlySunny +16 7:23 Light OFF +16 7:23 EXP_Light OFF + +16 9:00 EnvLight Sunny +16 9:00 Light OFF +16 9:00 EXP_Light OFF + +16 13:00 EnvLight PartlyCloudy +16 13:00 Light OFF +16 13:00 EXP_Light OFF + +16 20:00 EnvLight Night +16 20:00 EXP_Light OFF +16 20:00 Light OFF + +#Thu +17 0:00 EnvLight Night +17 0:00 Light OFF +17 0:00 EXP_Light OFF + +17 7:23 EnvLight PartlySunny +17 7:23 Light OFF +17 7:23 EXP_Light OFF + +17 9:00 EnvLight Sunny +17 9:00 Light OFF +17 9:00 EXP_Light OFF + +17 13:00 EnvLight PartlyCloudy +17 13:00 Light OFF +17 13:00 EXP_Light OFF + +17 20:00 EnvLight Night +17 20:00 EXP_Light OFF +17 20:00 Light OFF + +#Fri +18 0:00 EnvLight Night +18 0:00 Light OFF +18 0:00 EXP_Light OFF + +18 7:23 EnvLight PartlySunny +18 7:23 Light OFF +18 7:23 EXP_Light OFF + +18 9:00 EnvLight Sunny +18 9:00 Light OFF +18 9:00 EXP_Light OFF + +18 13:00 EnvLight PartlyCloudy +18 13:00 Light OFF +18 13:00 EXP_Light OFF + +18 20:00 EnvLight Night +18 20:00 EXP_Light OFF +18 20:00 Light OFF + +#Sat +19 0:00 EnvLight Night +19 0:00 Light OFF +19 0:00 EXP_Light OFF + +19 7:23 EnvLight PartlySunny +19 7:23 Light OFF +19 7:23 EXP_Light OFF + +19 9:00 EnvLight Cloudy +19 9:00 Light OFF +19 9:00 EXP_Light OFF + +19 13:00 EnvLight PartlyCloudy +19 13:00 Light OFF +19 13:00 EXP_Light OFF + +19 20:00 EnvLight Night +19 20:00 EXP_Light OFF +19 20:00 Light OFF + +#Sun +20 0:00 EnvLight Night +20 0:00 Light OFF +20 0:00 EXP_Light OFF + +20 7:23 EnvLight PartlySunny +20 7:23 Light OFF +20 7:23 EXP_Light OFF + +20 9:00 EnvLight Sunny +20 9:00 Light OFF +20 9:00 EXP_Light OFF + +20 13:00 EnvLight PartlyCloudy +20 13:00 Light OFF +20 13:00 EXP_Light OFF + +20 20:00 EnvLight Night +20 20:00 Light OFF +20 20:00 Light OFF + +#Mon +21 0:00 EnvLight Night +21 0:00 Light OFF +21 0:00 EXP_Light OFF + +21 7:23 EnvLight PartlySunny +21 7:23 Light OFF +21 7:23 EXP_Light OFF + +21 9:00 EnvLight Cloudy +21 9:00 Light OFF +21 9:00 EXP_Light OFF + +21 13:00 EnvLight PartlyCloudy +21 13:00 Light OFF +21 13:00 EXP_Light OFF + +21 20:00 EnvLight Night +21 20:00 EXP_Light OFF +21 20:00 Light OFF + +#Tue +22 7:23 EnvLight PartlySunny +22 7:23 Light OFF +22 7:23 EXP_Light OFF + +22 9:00 EnvLight Cloudy +22 9:00 Light OFF +22 9:00 EXP_Light OFF + +22 13:00 EnvLight PartlyCloudy +22 13:00 Light OFF +22 13:00 EXP_Light OFF + +22 20:00 EnvLight Night +22 20:00 EXP_Light OFF +22 20:00 Light OFF + +#Wed +23 0:00 EnvLight Night +23 0:00 Light OFF +23 0:00 EXP_Light OFF + +23 7:23 EnvLight PartlySunny +23 7:23 Light OFF +23 7:23 EXP_Light OFF + +23 9:00 EnvLight Sunny +23 9:00 Light OFF +23 9:00 EXP_Light OFF + +23 13:00 EnvLight PartlyCloudy +23 13:00 Light OFF +23 13:00 EXP_Light OFF + +23 20:00 EnvLight Night +23 20:00 EXP_Light OFF +23 20:00 Light OFF + +#Thu +24 0:00 EnvLight Night +24 0:00 Light OFF +24 0:00 EXP_Light OFF + +24 7:23 EnvLight PartlySunny +24 7:23 Light OFF +24 7:23 EXP_Light OFF + +24 9:00 EnvLight Sunny +24 9:00 Light OFF +24 9:00 EXP_Light OFF + +24 13:00 EnvLight PartlyCloudy +24 13:00 Light OFF +24 13:00 EXP_Light OFF + +24 20:00 EnvLight Night +24 20:00 EXP_Light OFF +24 20:00 Light OFF + +#Fri +25 0:00 EnvLight Night +25 0:00 Light OFF +25 0:00 EXP_Light OFF + +25 7:23 EnvLight PartlySunny +25 7:23 Light OFF +25 7:23 EXP_Light OFF + +25 9:00 EnvLight Sunny +25 9:00 Light OFF +25 9:00 EXP_Light OFF + +25 13:00 EnvLight PartlyCloudy +25 13:00 Light OFF +25 13:00 EXP_Light OFF + +25 20:00 EnvLight Night +25 20:00 EXP_Light OFF +25 20:00 Light OFF + +#Sat +26 0:00 EnvLight Night +26 0:00 Light OFF +26 0:00 EXP_Light OFF + +26 7:23 EnvLight PartlySunny +26 7:23 Light OFF +26 7:23 EXP_Light OFF + +26 9:00 EnvLight Cloudy +26 9:00 Light OFF +26 9:00 EXP_Light OFF + +26 13:00 EnvLight PartlyCloudy +26 13:00 Light OFF +26 13:00 EXP_Light OFF + +26 20:00 EnvLight Night +26 20:00 EXP_Light OFF +26 20:00 Light OFF + +#Sun +27 0:00 BEGIN_EXPECTATIONS vacation_last_day +27 0:00 EnvLight Night +27 0:00 Light OFF +27 0:00 EXP_Light OFF + +27 7:23 EnvLight PartlySunny +27 7:23 Light OFF +27 7:23 EXP_Light OFF + +27 9:00 EnvLight Sunny +27 9:00 Light OFF +27 9:00 EXP_Light OFF + +27 13:00 EnvLight PartlyCloudy +27 13:00 Light OFF +27 13:00 EXP_Light OFF + +27 20:00 EnvLight Night +27 20:00 Light OFF +27 20:00 Light OFF +27 23:59 END_EXPECTATIONS + +#End vacation + +#Mon +28 0:00 BEGIN_EXPECTATIONS after_vacations +28 0:00 EnvLight Night +28 0:00 Light ON +28 0:00 EXP_Light ON + +28 7:23 EnvLight PartlySunny +28 7:23 Light OFF +28 7:23 EXP_Light OFF + +28 9:00 EnvLight Cloudy +28 9:00 Light ON +28 9:00 EXP_Light ON + +28 13:00 EnvLight PartlyCloudy +28 13:00 Light OFF +28 13:00 EXP_Light OFF + +28 20:00 EnvLight Night +28 20:00 EXP_Light ON +28 20:00 Light ON +28 23:59 END_EXPECTATIONS + +#Tue +29 0:00 BEGIN_EXPECTATIONS after_vacations2 +29 7:23 EnvLight PartlySunny +29 7:23 Light OFF +29 7:23 EXP_Light OFF + +29 9:00 EnvLight Cloudy +29 9:00 Light ON +29 9:00 EXP_Light ON + +29 13:00 EnvLight PartlyCloudy +29 13:00 Light OFF +29 13:00 EXP_Light OFF + +29 20:00 EnvLight Night +29 20:00 EXP_Light ON +29 20:00 Light ON +29 23:59 END_EXPECTATIONS + +#Wed +30 0:00 EnvLight Night +30 0:00 Light ON +30 0:00 EXP_Light ON + +30 7:23 EnvLight PartlySunny +30 7:23 Light OFF +30 7:23 EXP_Light OFF + +30 9:00 EnvLight Sunny +30 9:00 Light OFF +30 9:00 EXP_Light OFF + +30 13:00 EnvLight PartlyCloudy +30 13:00 Light OFF +30 13:00 EXP_Light OFF + +30 20:00 EnvLight Night +30 20:00 EXP_Light ON +30 20:00 Light ON + +#Thu +31 0:00 EnvLight Night +31 0:00 Light ON +31 0:00 EXP_Light ON + +31 7:23 EnvLight PartlySunny +31 7:23 Light OFF +31 7:23 EXP_Light OFF + +31 9:00 EnvLight Sunny +31 9:00 Light OFF +31 9:00 EXP_Light OFF + +31 13:00 EnvLight PartlyCloudy +31 13:00 Light OFF +31 13:00 EXP_Light OFF + +31 20:00 EnvLight Night +31 20:00 EXP_Light ON +31 20:00 Light ON + +#Fri +32 0:00 EnvLight Night +32 0:00 Light ON +32 0:00 EXP_Light ON + +32 7:23 EnvLight PartlySunny +32 7:23 Light OFF +32 7:23 EXP_Light OFF + +32 9:00 EnvLight Sunny +32 9:00 Light OFF +32 9:00 EXP_Light OFF + +32 13:00 EnvLight PartlyCloudy +32 13:00 Light OFF +32 13:00 EXP_Light OFF + +32 20:00 EnvLight Night +32 20:00 EXP_Light ON +32 20:00 Light ON + +#Sat +33 0:00 EnvLight Night +33 0:00 Light ON +33 0:00 EXP_Light ON + +33 7:23 EnvLight PartlySunny +33 7:23 Light OFF +33 7:23 EXP_Light OFF + +33 9:00 EnvLight Cloudy +33 9:00 Light ON +33 9:00 EXP_Light ON + +33 13:00 EnvLight PartlyCloudy +33 13:00 Light OFF +33 13:00 EXP_Light OFF + +33 20:00 EnvLight Night +33 20:00 EXP_Light ON +33 20:00 Light ON + +#Sun +34 0:00 BEGIN_EXPECTATIONS after_vacations3 +34 0:00 EnvLight Night +34 0:00 Light ON +34 0:00 EXP_Light ON + +34 7:23 EnvLight PartlySunny +34 7:23 Light OFF +34 7:23 EXP_Light OFF + +34 9:00 EnvLight Sunny +34 9:00 Light OFF +34 9:00 EXP_Light OFF + +34 13:00 EnvLight PartlyCloudy +34 13:00 Light OFF +34 13:00 EXP_Light OFF + +34 20:00 EnvLight Night +34 20:00 EXP_Light ON +34 20:00 Light ON +34 23:59 END_EXPECTATIONS diff --git a/simulator/sml_simulator.c b/simulator/sml_simulator.c new file mode 100644 index 0000000..c336ea9 --- /dev/null +++ b/simulator/sml_simulator.c @@ -0,0 +1,1354 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * All the inputs and outputs are handled directly with variables API. + * It works with both backends: neural newtworks and fuzzy. + * + * Config is read from a file with the following description: + * + * TIME_BLOCKS X + * READ_FREQ Y + * DAYS Z + * INPUT Input1 Min Max + * TERM Term1 Min Max + * TERM Term2 Min Max + * TERM Term3 Min Max + * INPUT Input2 Min Max + * TERM Term1 Min Max + * TERM Term2 Min Max + * OUTPUT Output1 Min Max + * TERM Term1 Min Max + * TERM Term2 Min Max + * ... + * + * Data is read from a file with the following description: + * DAY HH:MM [Input|Output|EXP_Output] STATE + */ + +#define TIME_BLOCKS (48) +#define READ_FREQ (2) +#define DAYS (14) + +#define TIME_STR ("Time") +#define WEEKDAY_STR ("Weekday") + +#define LINE_SIZE (256) +#define STR_PARSE_LEN 32 +#define NAME_SIZE 32 +#define EXP_NAME_SIZE (NAME_SIZE + 4) + +#define STR_FORMAT(WIDTH) "%" #WIDTH "s" +#define STR_FMT(W) STR_FORMAT(W) + +#define AUTOMATIC_TERMS (15) +#define DISABLED "[DISABLED]" +#define ENABLED "[ENABLED]" +#define BEGIN_EXPECTATIONS ("BEGIN_EXPECTATIONS") +#define END_EXPECTATIONS ("END_EXPECTATIONS") +#define FLOAT_THRESHOLD 0.01 +#define DISCRETE_THRESHOLD 0.45 +#define LAST_VALUE_DEVIATION (0.05) +#define DEFAULT_EXPECTATION_BLOCK_NAME "BLOCK_" + +#define FUZZY_ENGINE 0 +#define ANN_ENGINE 1 +#define NAIVE_ENGINE 2 +#define FUZZY_ENGINE_NO_SIMPLIFICATION 3 + +typedef struct { + float min; + float max; + char name[NAME_SIZE]; +} Term; + +typedef struct { + Term *term; + float value; + int time; +} Event; + +typedef struct { + bool enabled; + int time; +} Status_Event; + +typedef struct { + float guess_value; + float cur_value; + float min; + float max; + struct sml_variable *sml_var; + GList *terms; + GList *events; + GList *status_events; + Event *last_event; + int right_guesses; + int changes_counter; + int expectations_right_guesses; + int expectations_counter; + char name[NAME_SIZE]; +} Variable; + +typedef struct { + Variable *output; + GList *events; + Event *last_event; + char name[EXP_NAME_SIZE]; +} Expectation; + +typedef struct { + int begin; + int end; + char name[NAME_SIZE]; + bool error; +} Expectation_Block; + +typedef struct { + struct sml_object *sml; + struct sml_variable *weekday; + struct sml_variable *time; + GList *inputs; + GList *outputs; + GList *expectations; + GList *expectation_blocks; + GList *cur_expectation_block; + GRand *rand; + int time_blocks; + int days; + int reads; + int read_counter; + int read_freq; + double duration; + double max_iteration_duration; + bool debug; + bool enable_time_input; + bool enable_weekday_input; + int engine_type; +} Context; + +enum { + LINE_ERROR, + LINE_EMPTY, + LINE_OK +}; + +static const char *WEEKDAYS[] = +{ + "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" +}; + +static void +free_element(gpointer data) +{ + free(data); +} + +static void +free_variable(gpointer data) +{ + Variable *variable = data; + + g_list_free_full(variable->events, free_element); + g_list_free_full(variable->status_events, free_element); + g_list_free_full(variable->terms, free_element); + free(variable); +} + +static void +free_expectation(gpointer data) +{ + Expectation *expec = data; + + g_list_free_full(expec->events, free_element); + free(expec); +} + +static float +get_weekday(int reads, int read_freq) +{ + float weekday; + int day; + + day = reads / (24 * 60 / read_freq); + weekday = day % 7 + 0.5; + + return weekday; +} + +static float +get_time(Context *ctx) +{ + int total_blocks = ctx->read_counter / + (60 / ctx->read_freq * 24 / ctx->time_blocks); + + return total_blocks % ctx->time_blocks; +} + +static Event * +get_event(GList *events, int reads) +{ + Event *last_event = NULL; + GList *itr; + + for (itr = events; itr; itr = itr->next) { + Event *event = itr->data; + + // event->time >= last_event guarantees that guesses events + // will be considered even if it had an event in the same time + if ((event->time <= reads) && + ((!last_event) || (event->time >= last_event->time))) + last_event = event; + } + + if (!last_event) + fprintf(stderr, "Failed to find event for read %i\n", reads); + + return last_event; +} + +static Status_Event * +get_status_event(GList *status_events, int reads) +{ + GList *itr; + + for (itr = status_events; itr; itr = itr->next) { + Status_Event *status_event = itr->data; + if (status_event->time == reads) + return status_event; + } + + return NULL; +} + +static bool +term_is_discrete(Term *term) +{ + if (!term) + return false; + if (term->max - term->min < FLOAT_THRESHOLD) + return true; + return false; +} + +static bool +is_nan_event(Event *event) +{ + return !event->term && isnan(event->value); +} + +static float +event_get_value(Event *event, GRand *rand) +{ + gint32 rand_val; + float result; + Term *term = event->term; + + if (!term) + return event->value; + + if (term_is_discrete(term)) + return term->min; + + rand_val = g_rand_int_range(rand, term->min, term->max * 1000); + rand_val %= (gint32)((term->max - term->min) * 1000); + result = (float)rand_val * 0.0001 + term->min; + + return result; +} + +static void +print_term(Term *term) +{ + printf("Term: %p, Name: %s, Min: %f, Max: %f\n", + term, term->name, term->min, term->max); +} + +static void +print_event(Event *event) +{ + if (event->term) + printf("Event: %p, Term: %s, Time: %d\n", + event, event->term->name, event->time); + else + printf("Event: %p, Value: %f, Time: %d\n", + event, event->value, event->time); +} + +static void +print_status_event(Status_Event *status_event) +{ + printf("Event: %p, Enabled: %s, Time: %d\n", + status_event, status_event->enabled ? "true" : "false", + status_event->time); +} + +static void +print_variable(Variable *var) +{ + GList *itr; + + printf("= Variable: %s =\n", var->name); + + printf("struct sml_object Variable: %p\n", var->sml_var); + printf("Range %f - %f\n", var->min, var->max); + printf("Current value: %f\n", var->cur_value); + printf("Guess value: %f\n", var->guess_value); + printf("Last event: %p\n", var->last_event); + + printf("Terms:\n"); + for (itr = var->terms; itr; itr = itr->next) { + print_term(itr->data); + } + + printf("Events:\n"); + for (itr = var->events; itr; itr = itr->next) + print_event(itr->data); + + printf("Status Events:\n"); + for (itr = var->status_events; itr; itr = itr->next) + print_status_event(itr->data); + + printf("====================\n"); +} + +static void +print_expectation(Expectation *expec) +{ + GList *itr; + + printf("= Expectation: %s for %p =\n", expec->name, expec->output); + printf("Last event: %p\n", expec->last_event); + printf("Events:\n"); + for (itr = expec->events; itr; itr = itr->next) + print_event(itr->data); + printf("====================\n"); +} + +static void +print_scenario(Context *ctx) +{ + GList *itr; + + printf("=== Scenario ===\n"); + for (itr = ctx->inputs; itr; itr = itr->next) + print_variable(itr->data); + for (itr = ctx->outputs; itr; itr = itr->next) + print_variable(itr->data); + for (itr = ctx->expectations; itr; itr = itr->next) + print_expectation(itr->data); + printf("====================\n"); +} + +static float +event_get_value_with_deviation(GRand *rand, float last_value, Term *term, + Variable *var) +{ + float min, max; + + if (term_is_discrete(term) || isnan(last_value)) + return last_value; + + min = fabs(last_value - LAST_VALUE_DEVIATION); + max = last_value + LAST_VALUE_DEVIATION; + if (term) { + if (max > term->max) + max = term->max; + if (min < term->min) + min = term->min; + } else { + if (max > var->max) + max = var->max; + if (min < var->min) + min = var->min; + } + + float val; + val = (float)g_rand_double_range(rand, min, max); + return val; +} + +static void +variable_set_value(struct sml_object *sml, Variable *var, int reads, bool debug, + GRand *rand) +{ + Event *event; + Status_Event *status_event; + float value; + + event = get_event(var->events, reads); + if (!event) { + fprintf(stderr, "Failed to find event %s for reads: %d\n", var->name, + reads); + return; + } + if (!is_nan_event(event)) { + if (event == var->last_event) { + value = event_get_value_with_deviation(rand, var->cur_value, + event->term, var); + } else { + value = event_get_value(event, rand); + var->last_event = event; + } + if (!isnan(value)) + var->guess_value = var->cur_value = value; + } else + var->cur_value = var->guess_value; + + status_event = get_status_event(var->status_events, reads); + if (debug) { + printf("\tVar: %s %f", var->name, var->cur_value); + if (event->term) + printf(" - %s", event->term->name); + if (status_event) + printf(status_event->enabled ? " enabled" : " disabled"); + printf("\n"); + } + + sml_variable_set_value(sml, var->sml_var, var->cur_value); + if (status_event) + sml_variable_set_enabled(sml, var->sml_var, status_event->enabled); +} + +static bool +read_state_cb(struct sml_object *sml, void *data) +{ + float time, weekday; + Context *ctx = data; + GList *itr; + + time = get_time(ctx); + weekday = get_weekday(ctx->read_counter, ctx->read_freq); + + if (ctx->time) + sml_variable_set_value(sml, ctx->time, time); + if (ctx->weekday) + sml_variable_set_value(sml, ctx->weekday, weekday); + + if (ctx->debug) + printf("%i::READ(%i%%) - Weekday:%s, TB: %d\n", ctx->read_counter, + ctx->read_counter * 100 / ctx->reads, WEEKDAYS[(int)weekday], + (int)time); + + for (itr = ctx->inputs; itr; itr = itr->next) { + Variable *var = itr->data; + variable_set_value(sml, var, ctx->read_counter, ctx->debug, ctx->rand); + } + + for (itr = ctx->outputs; itr; itr = itr->next) { + Variable *var = itr->data; + variable_set_value(sml, var, ctx->read_counter, ctx->debug, ctx->rand); + } + + ctx->read_counter++; + + return true; +} + +static Event * +new_event(int time, Term *term, float value) +{ + Event *event = calloc(1, sizeof(Event)); + + event->time = time; + event->term = term; + event->value = value; + return event; +} + +static Expectation * +get_expectation(GList *expectations, Variable *output) +{ + Expectation *expec; + GList *itr; + + for (itr = expectations; itr; itr = itr->next) { + expec = itr->data; + if (expec->output == output) + return expec; + } + + fprintf(stderr, "Failed to find expectation %s\n", output->name); + return NULL; +} + +static GList * +get_terms(GList *terms, float value) +{ + GList *itr, *result = NULL; + Term *term; + + for (itr = terms; itr; itr = itr->next) { + term = itr->data; + if (term_is_discrete(term)) { + if (((int)round(value)) == ((int)round(term->min))) + result = g_list_append(result, term); + } else { + if ((value >= term->min) && (value <= term->max)) + result = g_list_append(result, term); + } + } + + return result; +} + +static void +_debug_guess(int read_counter, const char *name, float guess_value, + GList *terms, Event *event) +{ + GList *itr; + + printf("%i::GUESS %s %f - ", read_counter, name, guess_value); + + if (!terms) + printf("(null)"); + else if (!terms->next) + printf("%s", ((Term *)terms->data)->name); + else { + printf("("); + for (itr = terms; itr; itr = itr->next) { + printf("%s", ((Term *)itr->data)->name); + if (itr->next) + printf(", "); + } + printf(")"); + } + printf(", Expected: "); + + if (!event) + printf("(null). "); + else if (event->term) + printf("%s. ", event->term->name); + else + printf("%f. ", event->value); +} + +static bool +event_contains_guess(Event *event, GList *terms) +{ + GList *itr; + Term *term; + + if (event->term) { + for (itr = terms; itr; itr = itr->next) + if (event->term == itr->data) + return true; + return false; + } + + for (itr = terms; itr; itr = itr->next) { + term = itr->data; + if ((event->value >= term->min) && (event->value <= term->max)) + return true; + } + return false; +} + +static void +output_state_changed_cb(struct sml_object *sml, + struct sml_variables_list *changed, void *data) +{ + GList *itr; + Context *ctx = data; + float val; + + + if (ctx->debug) + printf("%i::output_state_changed_cb called.\n", ctx->read_counter - 1); + + for (itr = ctx->outputs; itr; itr = itr->next) { + Variable *var = itr->data; + val = sml_variable_get_value(sml, var->sml_var); + if (!isnan(val)) + var->guess_value = val; + } +} + +static int +set_time(Context *ctx, int day, int hour, int min) +{ + int total_min = (day * 24 + hour) * 60 + min; + + return total_min / ctx->read_freq; +} + +static int +parse_value(Context *ctx, const char *line, int *time, char *sensor, + char *state) +{ + int ret, day, hour, min; + + // empty or comment line + if ((line[0] == '\n') || (line[0] == '#')) + return LINE_EMPTY; + + ret = sscanf(line, "%d %d:%d " STR_FMT(STR_PARSE_LEN) " " + STR_FMT(STR_PARSE_LEN) " \n", &day, &hour, &min, sensor, state); + if (ret < 4) + return LINE_ERROR; + if (ret < 5) + state[0] = 0; //state is optional + + *time = set_time(ctx, day, hour, min); + + if (ctx->debug) + printf("READ: %d %02d:%02d %s %s\n", day, hour, min, sensor, state); + + return LINE_OK; +} + +static Variable * +parse_sensor(Context *ctx, const char *sensor) +{ + GList *itr; + + if (!sensor) { + fprintf(stderr, "Error: null sensor\n"); + return NULL; + } + + for (itr = ctx->inputs; itr; itr = itr->next) { + Variable *var = itr->data; + if (!strcmp(var->name, sensor)) + return var; + } + + for (itr = ctx->outputs; itr; itr = itr->next) { + Variable *var = itr->data; + if (!strcmp(var->name, sensor)) + return var; + } + + return NULL; +} + +static Expectation * +parse_expectation(Context *ctx, const char *sensor) +{ + GList *itr; + + if (!sensor) { + fprintf(stderr, "Error: null sensor\n"); + return NULL; + } + + for (itr = ctx->expectations; itr; itr = itr->next) { + Expectation *expec = itr->data; + if (!strcmp(expec->name, sensor)) + return expec; + } + + fprintf(stderr, "Error: unknown expectation %s\n", sensor); + return NULL; +} + +static Term * +parse_state(Variable *var, const char *state) +{ + GList *itr; + + if (!state) { + fprintf(stderr, "Error: null state\n"); + return NULL; + } + + for (itr = var->terms; itr; itr = itr->next) { + Term *term = itr->data; + if (!strcmp(term->name, state)) + return term; + } + + return NULL; +} + +static Status_Event * +parse_status_event(int time, const char *state) +{ + bool enabled; + + if (!strcmp(state, DISABLED)) + enabled = false; + else if (!strcmp(state, ENABLED)) + enabled = true; + else + return NULL; + + Status_Event *status = calloc(1, sizeof(Status_Event)); + status->enabled = enabled; + status->time = time; + return status; +} + +static Expectation_Block * +add_expectation_block(GList **list, char *name, int begin, int end) +{ + Expectation_Block *eblock = malloc(sizeof(Expectation_Block)); + + if (!eblock) + return NULL; + + eblock->begin = begin; + eblock->end = end; + eblock->error = false; + if (name && strlen(name)) + strncpy(eblock->name, name, NAME_SIZE); + else + snprintf(eblock->name, NAME_SIZE, "%s%d", + DEFAULT_EXPECTATION_BLOCK_NAME, g_list_length(*list)); + + *list = g_list_append(*list, eblock); + return eblock; +} + +static bool +read_values(const char *file_path, Context *ctx) +{ + FILE *f; + int line_num; + char line[LINE_SIZE]; + Expectation_Block *eblock = NULL; + + f = fopen(file_path, "r"); + if (!f) { + fprintf(stderr, "Failed to open %s\n", file_path); + return false; + } + + if (ctx->debug) + printf("=== Parsing ===\n"); + + line_num = 0; + // mark all events on values and expectations vectors + while (fgets(line, LINE_SIZE, f)) { + Variable *var; + Event *event; + Status_Event *status_event; + Term *term; + Expectation *expec = NULL; + int time, ret; + char sensor[STR_PARSE_LEN], state[STR_PARSE_LEN]; + float value = 0; + + ret = parse_value(ctx, line, &time, sensor, state); + if (ret == LINE_ERROR) { + fprintf(stderr, "Failed to read line %d: %s\n", line_num, line); + goto error; + } + + line_num++; + + if (ret == LINE_EMPTY) + continue; + + if (time >= ctx->reads) { + fprintf(stderr, "Time %d exceeds reads %d on line %d\n", + time, ctx->reads, line_num - 1); + goto error; + } + + if (!strcmp(sensor, BEGIN_EXPECTATIONS)) { + if (eblock) { + fprintf(stderr, "BEGIN_EXPECTATIONS block on line %d is inside" + " another BEGIN_EXPECTATIONS block\n", line_num - 1); + goto error; + } + eblock = add_expectation_block(&ctx->expectation_blocks, state, + time, 0); + continue; + } else if (!strcmp(sensor, END_EXPECTATIONS)) { + if (!eblock) { + fprintf(stderr, "Missing BEGIN_EXPECTATIONS block before " + "END_EXPECTATIONS block on line %d\n", line_num - 1); + goto error; + } + eblock->end = time; + eblock = NULL; + continue; + } + + var = parse_sensor(ctx, sensor); + if (!var) { + expec = parse_expectation(ctx, sensor); + if (expec) + var = expec->output; + else + goto error; + } + + status_event = parse_status_event(time, state); + if (status_event) { + if (expec) { + fprintf(stderr, "Error: EXP_%s is not suppose to have status " + "changes\n", var->name); + goto error; + } + var->status_events = g_list_append(var->status_events, + status_event); + } else { + term = parse_state(var, state); + if (!term) + value = atof(state); + + event = new_event(time, term, value); + + if (expec) + expec->events = g_list_append(expec->events, event); + else + var->events = g_list_append(var->events, event); + } + + } + + ctx->cur_expectation_block = ctx->expectation_blocks; + if (ctx->debug) + printf("=== Parsing concluded ===\n"); + + fclose(f); + return true; + +error: + fclose(f); + return false; +} + +static void +print_results(Context *ctx) +{ + GList *itr; + float hits; + int count = 0; + + printf("===============================\n"); + printf("Results\n"); + printf("Sensor reads: %d\n", ctx->read_counter); + printf("Right guesses:\n"); + + for (itr = ctx->outputs; itr; itr = itr->next) { + Variable *var = itr->data; + + if (var->expectations_counter != 0) + hits = (var->expectations_right_guesses * 100) / + (float)var->expectations_counter; + else + hits = 0.0; + + printf("\tVariable%d %s : %d of %d - %2.2f%% ( %f )\n", count++, + var->name, var->expectations_right_guesses, + var->expectations_counter, hits, (hits / 100)); + } + printf("Max Iteration Duration (in ms): %.2f\n", + ctx->max_iteration_duration * 1000); + printf("Average Duration (in ms): %.2f\n", + 1000 * ctx->duration / (float)ctx->reads); + printf("Expectation blocks with errors:\n"); + for (itr = ctx->expectation_blocks; itr; itr = itr->next) { + Expectation_Block *b = itr->data; + if (b->error) + printf("\t%s\n", b->name); + } + + printf("===============================\n"); +} + +static Variable * +add_input(Context *ctx, const char *name, float min, float max) +{ + Variable *var = calloc(1, sizeof(Variable)); + + strncpy(var->name, name, NAME_SIZE); + var->sml_var = sml_new_input(ctx->sml, name); + var->min = min; + var->max = max; + sml_variable_set_range(ctx->sml, var->sml_var, min, max); + ctx->inputs = g_list_append(ctx->inputs, var); + return var; +} + +static Variable * +add_output(Context *ctx, const char *name, float min, float max) +{ + Variable *var = calloc(1, sizeof(Variable)); + + strncpy(var->name, name, NAME_SIZE); + var->sml_var = sml_new_output(ctx->sml, name); + var->min = min; + var->max = max; + sml_variable_set_range(ctx->sml, var->sml_var, min, max); + ctx->outputs = g_list_append(ctx->outputs, var); + return var; +} + +static void +add_expectation(Context *ctx, Variable *output, const char *name) +{ + Expectation *expec = calloc(1, sizeof(Expectation)); + + snprintf(expec->name, EXP_NAME_SIZE, "EXP_%s", name); + expec->output = output; + ctx->expectations = g_list_append(ctx->expectations, expec); +} + +static void +add_term(Context *ctx, Variable *var, const char *name, float min, float max) +{ + Term *term = calloc(1, sizeof(Term)); + + strncpy(term->name, name, NAME_SIZE); + term->min = min; + term->max = max; + var->terms = g_list_append(var->terms, term); + + if (ctx->engine_type != FUZZY_ENGINE && + ctx->engine_type != FUZZY_ENGINE_NO_SIMPLIFICATION) + return; + + if (term_is_discrete(term)) { + if (fabs(var->min - min) < FLOAT_THRESHOLD) + sml_fuzzy_variable_add_term_ramp(ctx->sml, var->sml_var, name, + min + DISCRETE_THRESHOLD, min, 1); + else if (fabs(var->max - min) < FLOAT_THRESHOLD) + sml_fuzzy_variable_add_term_ramp(ctx->sml, var->sml_var, name, + min - DISCRETE_THRESHOLD, min, 1); + else + sml_fuzzy_variable_add_term_triangle(ctx->sml, var->sml_var, name, + min - DISCRETE_THRESHOLD, min, + min + DISCRETE_THRESHOLD, 1); + } else { + if (fabs(var->min - min) < FLOAT_THRESHOLD) + sml_fuzzy_variable_add_term_ramp(ctx->sml, var->sml_var, name, max, + min, 1); + else if (fabs(var->max - max) < FLOAT_THRESHOLD) + sml_fuzzy_variable_add_term_ramp(ctx->sml, var->sml_var, name, min, + max, 1); + else + sml_fuzzy_variable_add_term_triangle(ctx->sml, var->sml_var, name, + min, min + (max - min) / 2, max, 1); + } +} + +static void +variable_add_terms(Context *ctx, Variable *var) +{ + float step; + int i; + char name[NAME_SIZE]; + + step = (var->max - var->min) / AUTOMATIC_TERMS; + for (i = 0; i < AUTOMATIC_TERMS; i++) { + snprintf(name, NAME_SIZE, "t%d", i); + add_term(ctx, var, name, var->min + i * step, + var->min + (i + 1.5) * step); + } +} + +static bool +read_config(const char *file_path, Context *ctx) +{ + Variable *last_var = NULL; + GList *itr; + FILE *f; + char line[LINE_SIZE]; + char name[NAME_SIZE]; + int tmp; + + // default values + ctx->read_freq = READ_FREQ; + ctx->days = DAYS; + ctx->time_blocks = TIME_BLOCKS; + ctx->read_counter = 0; + ctx->enable_time_input = 1; + ctx->enable_weekday_input = 1; + ctx->inputs = NULL; + ctx->outputs = NULL; + ctx->expectations = NULL; + ctx->expectation_blocks = NULL; + ctx->time = NULL; + ctx->weekday = NULL; + + f = fopen(file_path, "r"); + if (!f) { + fprintf(stderr, "Failed to open %s\n", file_path); + return false; + } + + while (fgets(line, LINE_SIZE, f)) { + float min = 0, max = 0; + int ret; + + // empty or comment line + if ((line[0] == '\n') || (line[0] == '#')) + continue; + + ret = sscanf(line, "TIME_BLOCKS %d\n", &ctx->time_blocks); + if (ret > 0) { + last_var = NULL; + continue; + } + + ret = sscanf(line, "DAYS %d\n", &ctx->days); + if (ret > 0) { + last_var = NULL; + continue; + } + + ret = sscanf(line, "READ_FREQ %d\n", &ctx->read_freq); + if (ret > 0) { + last_var = NULL; + continue; + } + + ret = sscanf(line, "ENABLE_TIME_INPUT %d\n", + &tmp); + if (ret > 0) { + ctx->enable_time_input = !!tmp; + last_var = NULL; + continue; + } + + ret = sscanf(line, "ENABLE_WEEKDAY_INPUT %d\n", + &tmp); + if (ret > 0) { + ctx->enable_weekday_input = !!tmp; + last_var = NULL; + continue; + } + + ret = sscanf(line, "INPUT " STR_FMT(NAME_SIZE) " %f %f\n", + name, &min, &max); + if (ret > 0) { + last_var = add_input(ctx, name, min, max); + continue; + } + + ret = sscanf(line, "OUTPUT " STR_FMT(NAME_SIZE) " %f %f\n", + name, &min, &max); + if (ret > 0) { + last_var = add_output(ctx, name, min, max); + add_expectation(ctx, last_var, name); + continue; + } + + ret = sscanf(line, "TERM " STR_FMT(NAME_SIZE) " %f %f\n", + name, &min, &max); + if (ret > 0) { + if (!last_var) { + fprintf(stderr, "Failed to find var for term %s\n", line); + return false; + } + add_term(ctx, last_var, name, min, max); + continue; + } + + fprintf(stderr, "Unknow configuration %s\n", line); + goto error; + } + + ctx->reads = 24 * 60 / ctx->read_freq * ctx->days; + + for (itr = ctx->inputs; itr; itr = itr->next) { + Variable *var = itr->data; + if (!var->terms) + variable_add_terms(ctx, var); + } + + for (itr = ctx->outputs; itr; itr = itr->next) { + Variable *var = itr->data; + if (!var->terms) + variable_add_terms(ctx, var); + } + + fclose(f); + return true; + +error: + fclose(f); + return false; +} + +static void +add_time_day(Context *ctx) +{ + int i; + char term_name[8]; + + if (ctx->enable_time_input && ctx->time_blocks) { + ctx->time = sml_new_input(ctx->sml, TIME_STR); + sml_variable_set_range(ctx->sml, ctx->time, 0, ctx->time_blocks); + } + + if (ctx->enable_weekday_input) { + /* Mon == 0; Sun == 6 */ + ctx->weekday = sml_new_input(ctx->sml, WEEKDAY_STR); + sml_variable_set_range(ctx->sml, ctx->weekday, 0, 7); + } + + if (ctx->engine_type != FUZZY_ENGINE && + ctx->engine_type != FUZZY_ENGINE_NO_SIMPLIFICATION) + return; + + //create fuzzy terms + if (ctx->time) { + snprintf(term_name, sizeof(term_name), "%d", 0); + sml_fuzzy_variable_add_term_ramp(ctx->sml, ctx->time, term_name, 1, 0, + 1); + for (i = 1; i < ctx->time_blocks - 1; i++) { + snprintf(term_name, sizeof(term_name), "%d", i); + sml_fuzzy_variable_add_term_triangle(ctx->sml, ctx->time, + term_name, i - 1, i, i + 1, 1); + } + snprintf(term_name, sizeof(term_name), "%d", i); + sml_fuzzy_variable_add_term_ramp(ctx->sml, ctx->time, term_name, i - 1, + i, 1); + } + + if (ctx->weekday) { + sml_fuzzy_variable_add_term_triangle(ctx->sml, ctx->weekday, + "Monday", 0, 0.5, 1, 1); + sml_fuzzy_variable_add_term_triangle(ctx->sml, ctx->weekday, + "Tuesday", 1, 1.5, 2, 1); + sml_fuzzy_variable_add_term_triangle(ctx->sml, ctx->weekday, + "Wednesday", 2, 2.5, 3, 1); + sml_fuzzy_variable_add_term_triangle(ctx->sml, ctx->weekday, + "Thursday", 3, 3.5, 4, 1); + sml_fuzzy_variable_add_term_triangle(ctx->sml, ctx->weekday, + "Friday", 4, 4.5, 5, 1); + sml_fuzzy_variable_add_term_triangle(ctx->sml, ctx->weekday, + "Saturday", 5, 5.5, 6, 1); + sml_fuzzy_variable_add_term_triangle(ctx->sml, ctx->weekday, + "Sunday", 6, 6.5, 7, 1); + } +} + +struct sml_object * +_sml_new(int id) +{ + switch (id) { + case FUZZY_ENGINE: + case FUZZY_ENGINE_NO_SIMPLIFICATION: + return sml_fuzzy_new(); + case ANN_ENGINE: + return sml_ann_new(); + case NAIVE_ENGINE: + return sml_naive_new(); + } + return NULL; +} + +static void +_process_results(Context *ctx, double duration) +{ + GList *itr, *terms; + int read_counter = ctx->read_counter - 1; // it was incremented on read_state_cb + Expectation_Block *eblock; + + if (ctx->max_iteration_duration < duration) + ctx->max_iteration_duration = duration; + + if (!ctx->cur_expectation_block) + return; + + eblock = ctx->cur_expectation_block->data; + if (read_counter < eblock->begin) + return; + + for (itr = ctx->outputs; itr; itr = itr->next) { + Variable *var = itr->data; + Event *event; + Expectation *expec; + + if (!sml_variable_is_enabled(ctx->sml, var->sml_var)) + continue; + + expec = get_expectation(ctx->expectations, var); + if (!expec) { + fprintf(stderr, "Failed to find expectation %s\n", var->name); + _debug_guess(read_counter, var->name, var->guess_value, + NULL, NULL); + printf("SML is wrong\n"); + continue; + } + + event = get_event(expec->events, read_counter); + //if event value is indifferent (nan), skip it + if (isnan(event->value)) + continue; + + var->changes_counter++; + terms = get_terms(var->terms, var->guess_value); + if (!terms) { + fprintf(stderr, "Failed to find term for %s and value %f\n", + var->name, var->guess_value); + if (ctx->debug) + _debug_guess(read_counter, var->name, var->guess_value, + NULL, event); + printf("SML is wrong\n"); + continue; + } + + if (ctx->debug) + _debug_guess(read_counter, var->name, var->guess_value, + terms, event); + + if (event_contains_guess(event, terms)) { + var->right_guesses++; + if (ctx->debug) + printf("SML is right\n"); + } else { + if (ctx->debug) + printf("SML is wrong\n"); + } + g_list_free(terms); + } + + if (read_counter >= eblock->end) { + ctx->cur_expectation_block = ctx->cur_expectation_block->next; + + for (itr = ctx->outputs; itr; itr = itr->next) { + Variable *var = itr->data; + if (var->changes_counter) { + if (var->right_guesses == var->changes_counter) + var->expectations_right_guesses++; + else + eblock->error = true; + var->expectations_counter++; + } + var->right_guesses = var->changes_counter = 0; + } + } +} + +int +main(int argc, char *argv[]) +{ + Context ctx; + int i, tic, toc, total_toc, total_tic; + double duration; + int error; + + if (argc < 6) { + fprintf(stderr, "%s TEST.conf TEST.data SEED_VAL DEBUG_VAL " + "ENGINE_TYPE(0 fuzzy, 1 ann, 2 naive, " + "3 fuzzy_no_simplification) [MAX_MEMORY_FOR_OBSERVATION] " + "[ANN_CACHE_SIZE] [ANN_PSEUDO_REHEARSAL_STRATETY (1 for true, 0 for false)]\n", + argv[0]); + fprintf(stderr, + "Eg: %s simple_office.conf simple_office.forget_lights_on.data " + "30 1 1\n", + argv[0]); + return 1; + } + + ctx.rand = g_rand_new_with_seed(atoi(argv[3])); + ctx.debug = !!atoi(argv[4]); + + ctx.engine_type = atoi(argv[5]); + ctx.sml = _sml_new(ctx.engine_type); + if (!ctx.sml) { + fprintf(stderr, "Failed to create sml\n"); + return 2; + } + + if (!read_config(argv[1], &ctx)) { + fprintf(stderr, "Failed to read configuration: %s\n", argv[1]); + return 3; + } + + if (!read_values(argv[2], &ctx)) { + fprintf(stderr, "Failed to read data: %s\n", argv[2]); + return 4; + } + + add_time_day(&ctx); + + sml_set_read_state_callback(ctx.sml, read_state_cb, &ctx); + sml_set_output_state_changed_callback(ctx.sml, output_state_changed_cb, + &ctx); + sml_set_stabilization_hits(ctx.sml, 0); + if (ctx.engine_type == FUZZY_ENGINE_NO_SIMPLIFICATION) + sml_fuzzy_set_simplification_disabled(ctx.sml, true); + + if (argc >= 7) + sml_set_max_memory_for_observations(ctx.sml, atoi(argv[6])); + + if (ctx.engine_type == ANN_ENGINE) { + if (argc >= 8) + sml_ann_set_cache_max_size(ctx.sml, atoi(argv[7])); + if (argc >= 9) + sml_ann_use_pseudorehearsal_strategy(ctx.sml, atoi(argv[8]) != 0); + } + + if (ctx.debug) + print_scenario(&ctx); + + ctx.max_iteration_duration = -1; + total_tic = clock(); + for (i = 0; i < ctx.reads; i++) { + tic = clock(); + if ((error = sml_process(ctx.sml))) { + fprintf(stderr, "=== Unexpected error in simulation. " + "Error code: %d ===\n", error); + break; + } + toc = clock(); + duration = ((double)toc - tic) / CLOCKS_PER_SEC; + _process_results(&ctx, duration); + } + total_toc = clock(); + ctx.duration = ((double)total_toc - total_tic) / CLOCKS_PER_SEC; + + // scenario may changes thanks to new events created automatically + if (ctx.debug) { + print_scenario(&ctx); + sml_print_debug(ctx.sml, true); + } + print_results(&ctx); + + sml_free(ctx.sml); + + g_list_free_full(ctx.inputs, free_variable); + g_list_free_full(ctx.outputs, free_variable); + g_list_free_full(ctx.expectations, free_expectation); + g_list_free_full(ctx.expectation_blocks, free_element); + g_rand_free(ctx.rand); + + return 0; +} diff --git a/sml/CMakeLists.txt b/sml/CMakeLists.txt new file mode 100644 index 0000000..c1d4c45 --- /dev/null +++ b/sml/CMakeLists.txt @@ -0,0 +1,130 @@ +cmake_minimum_required(VERSION 2.8) + +project(sml) + +set(SML_VERSION 1.0) + +if (NOT CMAKE_INSTALL_LIBDIR) + set(SML_LIB_PREFIX lib) +else() + set(SML_LIB_PREFIX ${CMAKE_INSTALL_LIBDIR}) +endif() + +set(SML_LIB_DIR ${CMAKE_INSTALL_PREFIX}/${SML_LIB_PREFIX}) + +if (ANN_ENGINE) + set(SML_ANN_FILES + ${SML_INCLUDE_DIR}/sml_ann.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_ann/src/sml_ann_bridge.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_ann/src/sml_ann_bridge.c + ${CMAKE_CURRENT_SOURCE_DIR}/sml_ann/src/sml_ann_variable_list.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_ann/src/sml_ann_variable_list.c + ${CMAKE_CURRENT_SOURCE_DIR}/sml_ann/src/sml_ann.c) +else() + set(SML_ANN_FILES + ${SML_INCLUDE_DIR}/sml_ann.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_ann/src/sml_ann_support.c) +endif() + +if (FUZZY_ENGINE) + set(SML_FUZZY_FILES + ${SML_INCLUDE_DIR}/sml_fuzzy.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_bit_array.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_bit_array.c + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_fuzzy.c + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_fuzzy_bridge.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_fuzzy_bridge.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_measure.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_measure.c + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_observation.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_observation.c + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_observation_controller.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_observation_controller.c + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_observation_group.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_observation_group.c + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_rule_group.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_rule_group.c + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_terms_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_terms_manager.c) +else() + set(SML_FUZZY_FILES + ${SML_INCLUDE_DIR}/sml_fuzzy.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_fuzzy/src/sml_fuzzy_support.c) +endif() + +if (NAIVE_ENGINE) + set(SML_NAIVE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/sml_naive/include/sml_naive.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_naive/src/sml_naive.c) +else() + set(SML_NAIVE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/sml_naive/include/sml_naive.h + ${CMAKE_CURRENT_SOURCE_DIR}/sml_naive/src/sml_naive_support.c) +endif() + +if (MAINLOOP) + set (SML_MAINLOOP_FILES + ${SML_INCLUDE_DIR}/sml_main_loop.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/src/sml_main_loop.c) +endif() + +set(SML_COMMON_FILES + ${SML_INCLUDE_DIR}/sml.h + ${SML_INCLUDE_DIR}/sml_log.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/include/macros.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/include/sml_string.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/include/sml_util.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/include/sml_cache.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/include/sml_matrix.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/include/macros.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/src/sml_cache.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/src/sml_matrix.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/src/sml_util.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/src/sml_engine.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/src/sml_log.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/src/sml_string.c) + +include_directories(${GLIB_INCLUDE_DIRS} + ${SOLETTA_INCLUDE_DIRS} + ${FANN_INCLUDE_DIRS} + ${FUZZY_LITE_INCLUDE_DIRS} + ${SML_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/sml_naive/include/ + ${CMAKE_CURRENT_SOURCE_DIR}/common/include) + +link_directories(${GLIB_LIBRARY_DIRS} + ${SOLETTA_LIBRARY_DIRS} + ${FANN_LIBRARY_DIRS} + ${FUZZY_LITE_LIBRARY_DIRS}) + +add_library(sml_libs SHARED + ${SML_COMMON_FILES} + ${SML_MAINLOOP_FILES} + ${SML_ANN_FILES} + ${SML_FUZZY_FILES}) + +target_link_libraries(sml_libs + ${SOLETTA_LIBRARIES} + ${GLIB_LIBRARIES} + ${FANN_LIBRARIES} + ${FUZZY_LITE_LIBRARIES} + m) + +add_library(naive_engine_libs SHARED + ${SML_NAIVE_FILES}) + +target_link_libraries(naive_engine_libs + sml_libs + ${SOLETTA_LIBRARIES}) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/common/include/config.h.in + ${CMAKE_CURRENT_SOURCE_DIR}/common/include/config.h) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sml.pc.in ${CMAKE_CURRENT_SOURCE_DIR}/sml.pc @ONLY) + +install(TARGETS sml_libs + LIBRARY DESTINATION ${SML_LIB_PREFIX} + ARCHIVE DESTINATION ${SML_LIB_PREFIX}/static) + +install(DIRECTORY ${SML_INCLUDE_DIR}/ DESTINATION include) +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/sml.pc DESTINATION ${SML_LIB_PREFIX}/pkgconfig) diff --git a/sml/common/include/config.h.in b/sml/common/include/config.h.in new file mode 100644 index 0000000..e88363a --- /dev/null +++ b/sml/common/include/config.h.in @@ -0,0 +1,6 @@ +#pragma once + +#define @CMAKE_BUILD_TYPE@ +#cmakedefine FUZZY_ENGINE +#cmakedefine ANN_ENGINE +#cmakedefine NAIVE_ENGINE diff --git a/sml/common/include/macros.h b/sml/common/include/macros.h new file mode 100644 index 0000000..4a36604 --- /dev/null +++ b/sml/common/include/macros.h @@ -0,0 +1,50 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#define ON_NULL_RETURN_VAL(var, val) do { \ + if (var == NULL) { \ + return val; \ + } \ +} while (0) + +#define ON_NULL_RETURN_NULL(var) ON_NULL_RETURN_VAL(var, NULL) + +#define ON_NULL_RETURN(var) do { \ + if (var == NULL) { \ + return; \ + } \ +} while (0) + +#define API_EXPORT __attribute__((visibility("default"))) +#define VARIABLE_MEMBERSHIP_THRESHOLD (0.05) diff --git a/sml/common/include/sml_cache.h b/sml/common/include/sml_cache.h new file mode 100644 index 0000000..9dca33b --- /dev/null +++ b/sml/common/include/sml_cache.h @@ -0,0 +1,59 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +struct sml_cache; +typedef void (*sml_cache_element_free_cb)(void *element, void *data); +struct sml_cache *sml_cache_new(uint16_t max_elements, sml_cache_element_free_cb free_cb, void *free_cb_data); +bool sml_cache_put(struct sml_cache *cache, void *data); +struct sol_ptr_vector *sml_cache_get_elements(struct sml_cache *cache); +bool sml_cache_hit(struct sml_cache *cache, void *data); +bool sml_cache_remove(struct sml_cache *cache, void *data); +uint16_t sml_cache_get_size(struct sml_cache *cache); +void sml_cache_free(struct sml_cache *cache); +void sml_cache_clear(struct sml_cache *cache); +unsigned int sml_cache_get_total_elements_inserted(struct sml_cache *cache); +bool sml_cache_set_max_size(struct sml_cache *cache, uint16_t max_elements); +bool sml_cache_remove_by_id(struct sml_cache *cache, uint16_t elem); +void *sml_cache_get_element(struct sml_cache *cache, uint16_t elem); + +#ifdef __cplusplus +} +#endif diff --git a/sml/common/include/sml_engine.h b/sml/common/include/sml_engine.h new file mode 100644 index 0000000..37141d9 --- /dev/null +++ b/sml/common/include/sml_engine.h @@ -0,0 +1,112 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +struct sml_engine; +typedef bool (*sml_engine_load_file)(struct sml_engine *engine, const char *filename); +typedef void (*sml_engine_free)(struct sml_engine *engine); +typedef int (*sml_engine_process)(struct sml_engine *engine); +typedef bool (*sml_engine_predict)(struct sml_engine *engine); +typedef bool (*sml_engine_save)(struct sml_engine *engine, const char *path); +typedef bool (*sml_engine_load)(struct sml_engine *engine, const char *path); +typedef struct sml_variables_list *(*sml_engine_get_input_list)(struct sml_engine *engine); +typedef struct sml_variables_list *(*sml_engine_get_output_list)(struct sml_engine *engine); +typedef struct sml_variable *(*sml_engine_new_input)(struct sml_engine *engine, const char *name); +typedef struct sml_variable *(*sml_engine_new_output)(struct sml_engine *engine, const char *name); +typedef struct sml_variable *(*sml_engine_get_input)(struct sml_engine *engine, const char *name); +typedef struct sml_variable *(*sml_engine_get_output)(struct sml_engine *engine, const char *name); +typedef bool (*sml_engine_variable_set_value)(struct sml_variable *sml_variable, float value); +typedef float (*sml_engine_variable_get_value)(struct sml_variable *sml_variable); +typedef const char *(*sml_engine_variable_get_name)(struct sml_variable *sml_variable); +typedef int (*sml_engine_variable_set_enabled)(struct sml_engine *engine, struct sml_variable *variable, bool enabled); +typedef bool (*sml_engine_variable_is_enabled)(struct sml_variable *variable); +typedef bool (*sml_engine_remove_variable)(struct sml_engine *engine, struct sml_variable *variable); +typedef uint16_t (*sml_engine_variables_list_get_length)(struct sml_variables_list *list); +typedef struct sml_variable *(*sml_engine_variables_list_index)(struct sml_variables_list *list, unsigned int index); +typedef bool (*sml_engine_variable_set_range)(struct sml_variable *sml_variable, float min, float max); +typedef bool (*sml_engine_variable_get_range)(struct sml_variable *sml_variable, float *min, float *max); +typedef void (*sml_engine_print_debug)(struct sml_engine *engine, bool full); + +struct sml_engine { + /* General API */ + sml_engine_load_file load_file; + sml_engine_free free; + sml_engine_process process; + sml_engine_predict predict; + sml_engine_save save; + sml_engine_load load; + + /* Variables API */ + sml_engine_get_input_list get_input_list; + sml_engine_get_output_list get_output_list; + sml_engine_new_input new_input; + sml_engine_new_output new_output; + sml_engine_get_input get_input; + sml_engine_get_output get_output; + sml_engine_variable_get_name get_name; + sml_engine_variable_set_value set_value; + sml_engine_variable_get_value get_value; + sml_engine_variable_set_enabled variable_set_enabled; + sml_engine_variable_is_enabled variable_is_enabled; + sml_engine_remove_variable remove_variable; + sml_engine_variables_list_get_length variables_list_get_length; + sml_engine_variables_list_index variables_list_index; + sml_engine_variable_set_range variable_set_range; + sml_engine_variable_get_range variable_get_range; + + /* Debug API */ + sml_engine_print_debug print_debug; + + uint32_t magic_number; + sml_read_state_cb read_state_cb; + void *read_state_cb_data; + sml_change_cb output_state_changed_cb; + void *output_state_changed_cb_data; + bool learn_disabled; + bool output_state_changed_called; + uint16_t stabilization_hits; + uint16_t hits; + unsigned int obs_max_size; +}; + +#ifdef __cplusplus +} +#endif diff --git a/sml/common/include/sml_matrix.h b/sml/common/include/sml_matrix.h new file mode 100644 index 0000000..6814fe9 --- /dev/null +++ b/sml/common/include/sml_matrix.h @@ -0,0 +1,88 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#include +#include +#include "stdio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct sml_matrix { + uint16_t elem_size; + struct sol_vector data; +}; + +typedef bool (*sml_cmp_cb) (void *a, void *b); +typedef void (*sml_matrix_convert_cb) (char *buf, uint16_t buf_len, void *val); + +void sml_matrix_init(struct sml_matrix *m, uint16_t elem_size); +void sml_matrix_clear(struct sml_matrix *m); +void *sml_matrix_insert(struct sml_matrix *m, uint16_t i, uint16_t j); +void *sml_matrix_get(struct sml_matrix *m, uint16_t i, uint16_t j); +bool sml_matrix_equals(struct sml_matrix *m1, struct sml_matrix *m2, struct sol_vector *changed, sml_cmp_cb cmp_cb); +uint16_t sml_matrix_lines(struct sml_matrix *m); +uint16_t sml_matrix_cols(struct sml_matrix *m, uint16_t i); +void sml_matrix_remove_line(struct sml_matrix *m, uint16_t line_num); +void sml_matrix_remove_col(struct sml_matrix *m, uint16_t line_num, uint16_t col_num); +void sml_matrix_debug(struct sml_matrix *m, sml_matrix_convert_cb convert); + +#define sml_matrix_cast_get(m, i, j, tmp, type) \ + ( tmp = sml_matrix_get(m, i, j), \ + tmp ? *((type *)tmp) : 0 ) + +#define SML_MATRIX_FOREACH_IDX(matrix, itr_i, itr_j, i, j) \ + SOL_VECTOR_FOREACH_IDX (&matrix->data, itr_i, i) \ + SOL_VECTOR_FOREACH_IDX ((struct sol_vector *)itr_i, itr_j, j) + +#define MATRIX_CONVERT(type, format) \ + static inline void sml_matrix_ ## type ## _convert(char *buf, \ + uint16_t buf_len, void *val) \ + { \ + type *tmp = (type *)val; \ + snprintf(buf, buf_len, format, tmp ? *tmp : 0); \ + } \ + static inline void sml_matrix_debug_ ## type(struct sml_matrix *m) \ + { \ + sml_matrix_debug(m, sml_matrix_ ## type ## _convert); \ + } + +MATRIX_CONVERT(float, "%f") +MATRIX_CONVERT(uint16_t, "%d") +MATRIX_CONVERT(uint8_t, "%d") + +#undef MATRIX_CONVERT +#ifdef __cplusplus +} +#endif diff --git a/sml/common/include/sml_string.h b/sml/common/include/sml_string.h new file mode 100644 index 0000000..c6066f6 --- /dev/null +++ b/sml/common/include/sml_string.h @@ -0,0 +1,55 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct sml_string; + +struct sml_string *sml_string_new(const char *str); +bool sml_string_append_printf(struct sml_string *sml_string, const char *format, ...); +bool sml_string_append(struct sml_string *sml_string, const char *str); +bool sml_string_append_vprintf(struct sml_string *sml_string, const char *format, va_list ap); +size_t sml_string_length(struct sml_string *sml_string); +const char *sml_string_get_string(struct sml_string *sml_string); +void sml_string_free(struct sml_string *sml_string); + +#ifdef __cplusplus +} +#endif diff --git a/sml/common/include/sml_util.h b/sml/common/include/sml_util.h new file mode 100644 index 0000000..43cdce1 --- /dev/null +++ b/sml/common/include/sml_util.h @@ -0,0 +1,48 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif +#define SML_PATH_MAX (4096) + +bool is_file(const char *path); +bool is_dir(const char *path); +bool clean_dir(const char *path, const char *prefix); +bool delete_file(const char *path); + +#ifdef __cplusplus +} +#endif diff --git a/sml/common/src/sml_cache.c b/sml/common/src/sml_cache.c new file mode 100644 index 0000000..2aa94c5 --- /dev/null +++ b/sml/common/src/sml_cache.c @@ -0,0 +1,218 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sml_cache.h" +#include +#include +#include + +struct sml_cache { +#ifdef Debug + unsigned int total; +#endif + uint16_t max_elements; + struct sol_ptr_vector elements; + sml_cache_element_free_cb free_cb; + void *free_cb_data; +}; + +unsigned int +sml_cache_get_total_elements_inserted(struct sml_cache *cache) +{ +#ifdef Debug + return cache->total; +#else + sml_warning("sml_cache_get_total_elements_inserted is not available under " + "releasemode"); + return 0; +#endif +} + +static bool +_sml_cache_find_index_by_data(struct sol_ptr_vector *elements, void *data, + uint16_t *idx) +{ + uint16_t i; + void *v; + + SOL_PTR_VECTOR_FOREACH_IDX (elements, v, i) { + if (v == data) { + *idx = i; + return true; + } + } + return false; +} + +bool +sml_cache_set_max_size(struct sml_cache *cache, uint16_t max_elements) +{ + void *to_del; + + if (!max_elements || cache->max_elements == max_elements) + return true; + + cache->max_elements = max_elements; + while (sol_ptr_vector_get_len(&cache->elements) > max_elements) { + to_del = sol_ptr_vector_take(&cache->elements, 0); + if (!to_del) { + sml_critical("Could not remove an element from the cache!"); + return false; + } + cache->free_cb(to_del, cache->free_cb_data); + } + return true; +} + +struct sml_cache * +sml_cache_new(uint16_t max_elements, sml_cache_element_free_cb free_cb, + void *free_cb_data) +{ + struct sml_cache *cache; + + cache = calloc(1, sizeof(struct sml_cache)); + if (!cache) { + sml_critical("Could not create the cache"); + return NULL; + } + sol_ptr_vector_init(&cache->elements); + cache->max_elements = max_elements; + cache->free_cb = free_cb; + cache->free_cb_data = free_cb_data; + return cache; +} + +bool +sml_cache_put(struct sml_cache *cache, void *data) +{ + uint16_t count = sol_ptr_vector_get_len(&cache->elements); + void *to_del; + + if (cache->max_elements && count == cache->max_elements) { + to_del = sol_ptr_vector_take(&cache->elements, 0); + if (!to_del) { + sml_critical("Could not remove the oldest element in the cache"); + return false; + } + cache->free_cb(to_del, cache->free_cb_data); + } + + if (sol_ptr_vector_append(&cache->elements, data)) { + sml_critical("Could not add element to the cache"); + return false; + } +#ifdef Debug + cache->total++; +#endif + return true; +} + +bool +sml_cache_hit(struct sml_cache *cache, void *data) +{ + uint16_t i; + + if (!_sml_cache_find_index_by_data(&cache->elements, data, &i)) + return false; + + if (sol_ptr_vector_del(&cache->elements, i) || + sol_ptr_vector_append(&cache->elements, data)) { + sml_critical("Could not relocate the element in the cache"); + return false; + } + return true; +} + +bool +sml_cache_remove(struct sml_cache *cache, void *data) +{ + uint16_t i; + + if (!_sml_cache_find_index_by_data(&cache->elements, data, &i)) { + sml_critical("Could not find the index for data: %p", data); + return false; + } + + sol_ptr_vector_del(&cache->elements, i); + cache->free_cb(data, cache->free_cb_data); + return true; +} + +struct sol_ptr_vector * +sml_cache_get_elements(struct sml_cache *cache) +{ + return &cache->elements; +} + +uint16_t +sml_cache_get_size(struct sml_cache *cache) +{ + return sol_ptr_vector_get_len(&cache->elements); +} + +void +sml_cache_free(struct sml_cache *cache) +{ + sml_cache_clear(cache); + free(cache); +} + +void +sml_cache_clear(struct sml_cache *cache) +{ + uint16_t i; + void *v; + + SOL_PTR_VECTOR_FOREACH_IDX (&cache->elements, v, i) + cache->free_cb(v, cache->free_cb_data); + sol_ptr_vector_clear(&cache->elements); +} + +bool +sml_cache_remove_by_id(struct sml_cache *cache, uint16_t elem) +{ + void *to_del; + + to_del = sol_ptr_vector_take(&cache->elements, elem); + if (!to_del) { + sml_critical("Could not remove the oldest element in the cache"); + return false; + } + cache->free_cb(to_del, cache->free_cb_data); + return true; +} + +void * +sml_cache_get_element(struct sml_cache *cache, uint16_t elem) +{ + return sol_ptr_vector_get(&cache->elements, elem); +} diff --git a/sml/common/src/sml_engine.c b/sml/common/src/sml_engine.c new file mode 100644 index 0000000..2f19e36 --- /dev/null +++ b/sml/common/src/sml_engine.c @@ -0,0 +1,506 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LINE_SIZE (256) + +static bool +_default_load_fll_file(struct sml_object *engine, const char *filename) +{ + char line[LINE_SIZE]; + char *token, *saveptr; + FILE *f = fopen(filename, "r"); + uint16_t len; + struct sml_variable *last_var = NULL; + float min, max; + + if (!f) + return false; + + while (fgets(line, LINE_SIZE, f)) { + len = strlen(line); + if (len <= 1 || line[0] == '#') + continue; + line[len - 1] = '\0'; + + token = strtok_r(line, " \t", &saveptr); + if (!strncmp(token, "InputVariable:", 14)) + last_var = sml_new_input(engine, token + 15); + else if (!strncmp(token, "OutputVariable:", 15)) + last_var = sml_new_output(engine, token + 16); + else if (last_var) { + if (!strncmp(token, "enabled:", 8)) { + token = strtok_r(NULL, " \t", &saveptr); + if (!strncmp(token, "false", 5)) + sml_variable_set_enabled(engine, last_var, false); + else + sml_variable_set_enabled(engine, last_var, true); + } else if (!strncmp(token, "range:", 6)) { + token = strtok_r(NULL, " \t", &saveptr); + if (!token) + continue; + min = atof(token); + + token = strtok_r(NULL, " \t", &saveptr); + if (!token) + continue; + max = atof(token); + sml_variable_set_range(engine, last_var, min, max); + } + } + } + + fclose(f); + return true; +} + +API_EXPORT bool +sml_load_fll_file(struct sml_object *sml, const char *filename) +{ + ON_NULL_RETURN_VAL(sml, false); + ON_NULL_RETURN_VAL(filename, false); + struct sml_engine *engine = (struct sml_engine *)sml; + if (!engine->load_file) { + return _default_load_fll_file(sml, filename); + } + return engine->load_file(engine, filename); +} + +API_EXPORT void +sml_free(struct sml_object *sml) +{ + ON_NULL_RETURN(sml); + struct sml_engine *engine = (struct sml_engine *)sml; + if (!engine->free) { + sml_critical("Unexpected error. Implementation of function " + "sml_free is mandatory for engines."); + return; + } + engine->free(engine); +} + +API_EXPORT bool +sml_set_read_state_callback(struct sml_object *sml, + sml_read_state_cb read_state_cb, void *data) +{ + ON_NULL_RETURN_VAL(sml, false); + struct sml_engine *engine = (struct sml_engine *)sml; + + engine->read_state_cb = read_state_cb; + engine->read_state_cb_data = data; + + return true; +} + +API_EXPORT bool +sml_set_output_state_changed_callback(struct sml_object *sml, + sml_change_cb output_state_changed_cb, void *data) +{ + ON_NULL_RETURN_VAL(sml, false); + struct sml_engine *engine = (struct sml_engine *)sml; + + engine->output_state_changed_cb = output_state_changed_cb; + engine->output_state_changed_cb_data = data; + return true; +} + +API_EXPORT bool +sml_set_stabilization_hits(struct sml_object *sml, uint16_t hits) +{ + ON_NULL_RETURN_VAL(sml, false); + struct sml_engine *engine = (struct sml_engine *)sml; + engine->stabilization_hits = hits; + return true; +} + +API_EXPORT bool +sml_set_learn_disabled(struct sml_object *sml, bool disable) +{ + ON_NULL_RETURN_VAL(sml, false); + struct sml_engine *engine = (struct sml_engine *)sml; + engine->learn_disabled = disable; + return true; +} + +API_EXPORT int +sml_process(struct sml_object *sml) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml, -EINVAL); + if (!engine->process) { + sml_critical("Unexpected error. Implementation of function " + "sml_process is mandatory for engines."); + return false; + } + return engine->process(engine); +} + +API_EXPORT bool +sml_predict(struct sml_object *sml) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml, false); + if (!engine->predict) { + sml_critical("Unexpected error. Implementation of function " + "sml_predict is mandatory for engines."); + return false; + } + return engine->predict(engine); +} + +API_EXPORT bool +sml_save(struct sml_object *sml, const char *path) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml, false); + ON_NULL_RETURN_VAL(path, false); + if (!engine->save) { + sml_critical("Unexpected error. Implementation of function " + "sml_save is mandatory for engines."); + return false; + } + return engine->save(engine, path); +} + +API_EXPORT bool +sml_load(struct sml_object *sml, const char *path) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml, false); + ON_NULL_RETURN_VAL(path, false); + if (!engine->load) { + sml_critical("Unexpected error. Implementation of function " + "sml_load is mandatory for engines."); + return false; + } + return engine->load(engine, path); +} + +API_EXPORT struct sml_variables_list * +sml_get_input_list(struct sml_object *sml) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml, NULL); + if (!engine->get_input_list) { + sml_critical("Unexpected error. Implementation of function " + "sml_get_input_list is mandatory for engines."); + return false; + } + return engine->get_input_list(engine); +} + +API_EXPORT struct sml_variables_list * +sml_get_output_list(struct sml_object *sml) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml, NULL); + if (!engine->get_output_list) { + sml_critical("Unexpected error. Implementation of function " + "sml_get_output_list is mandatory for engines."); + return false; + } + return engine->get_output_list(engine); +} + +API_EXPORT struct sml_variable * +sml_new_input(struct sml_object *sml, const char *name) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml, NULL); + ON_NULL_RETURN_VAL(name, NULL); + if (!engine->new_input) { + sml_critical("Unexpected error. Implementation of function " + "sml_new_input is mandatory for engines."); + return false; + } + return engine->new_input(engine, name); +} + +API_EXPORT struct sml_variable * +sml_new_output(struct sml_object *sml, const char *name) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml, NULL); + ON_NULL_RETURN_VAL(name, NULL); + if (!engine->new_output) { + sml_critical("Unexpected error. Implementation of function " + "sml_new_output is mandatory for engines."); + return false; + } + return engine->new_output(engine, name); +} + +API_EXPORT struct sml_variable * +sml_get_input(struct sml_object *sml, const char *name) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml, NULL); + ON_NULL_RETURN_VAL(name, NULL); + if (!engine->get_input) { + sml_critical("Unexpected error. Implementation of function " + "sml_get_input is mandatory for engines."); + return false; + } + return engine->get_input(engine, name); +} + +API_EXPORT struct sml_variable * +sml_get_output(struct sml_object *sml, const char *name) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml, NULL); + ON_NULL_RETURN_VAL(name, NULL); + if (!engine->get_output) { + sml_critical("Unexpected error. Implementation of function " + "sml_get_output is mandatory for engines."); + return false; + } + return engine->get_output(engine, name); +} + +API_EXPORT bool +sml_variable_set_value(struct sml_object *sml, + struct sml_variable *sml_variable, float value) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml_variable, false); + ON_NULL_RETURN_VAL(sml, false); + if (!engine->set_value) { + sml_critical("Unexpected error. Implementation of function " + "sml_variable_set_value is mandatory for engines."); + return false; + } + return engine->set_value(sml_variable, value); +} + +API_EXPORT float +sml_variable_get_value(struct sml_object *sml, + struct sml_variable *sml_variable) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml_variable, NAN); + ON_NULL_RETURN_VAL(sml, NAN); + if (!engine->get_value) { + sml_critical("Unexpected error. Implementation of function " + "sml_variable_get_value is mandatory for engines."); + return false; + } + return engine->get_value(sml_variable); +} + +API_EXPORT const char * +sml_variable_get_name(struct sml_object *sml, struct sml_variable *sml_variable) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml_variable, NULL); + ON_NULL_RETURN_VAL(sml, NULL); + if (!engine->get_name) { + sml_critical("Unexpected error. Implementation of function " + "sml_variable_get_name is mandatory for engines."); + return false; + } + return engine->get_name(sml_variable); +} + +API_EXPORT int +sml_variable_set_enabled(struct sml_object *sml, + struct sml_variable *sml_variable, bool enabled) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml_variable, -EINVAL); + ON_NULL_RETURN_VAL(sml, -EINVAL); + if (!engine->variable_set_enabled) { + sml_critical("Unexpected error. Implementation of function " + "sml_variable_set_enabled is mandatory for engines."); + return false; + } + return engine->variable_set_enabled(engine, + sml_variable, enabled); +} + +API_EXPORT bool +sml_variable_is_enabled(struct sml_object *sml, + struct sml_variable *sml_variable) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml_variable, false); + ON_NULL_RETURN_VAL(sml, false); + if (!engine->variable_is_enabled) { + sml_critical("Unexpected error. Implementation of function " + "sml_variable_is_enabled is mandatory for engines."); + return false; + } + return engine->variable_is_enabled(sml_variable); +} + +API_EXPORT bool +sml_remove_variable(struct sml_object *sml, struct sml_variable *sml_variable) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml_variable, false); + ON_NULL_RETURN_VAL(sml, false); + if (!engine->remove_variable) { + sml_critical("Unexpected error. Implementation of function " + "sml_remove_variable is mandatory for engines."); + return false; + } + return engine->remove_variable(engine, sml_variable); +} + +API_EXPORT uint16_t +sml_variables_list_get_length(struct sml_object *sml, + struct sml_variables_list *list) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(list, 0); + ON_NULL_RETURN_VAL(sml, false); + if (!engine->variables_list_get_length) { + sml_critical("Unexpected error. Implementation of function " + "sml_variables_list_get_length is mandatory for engines."); + return 0; + } + return engine->variables_list_get_length(list); +} + +API_EXPORT bool +sml_variables_list_contains(struct sml_object *sml, + struct sml_variables_list *list, struct sml_variable *var) +{ + uint16_t i, len; + + ON_NULL_RETURN_VAL(sml, false); + ON_NULL_RETURN_VAL(list, false); + ON_NULL_RETURN_VAL(var, false); + + len = sml_variables_list_get_length(sml, list); + for (i = 0; i < len; i++) + if (sml_variables_list_index(sml, list, i) == var) + return true; + return false; + +} + +API_EXPORT struct sml_variable * +sml_variables_list_index(struct sml_object *sml, + struct sml_variables_list *list, uint16_t index) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(list, NULL); + ON_NULL_RETURN_VAL(sml, NULL); + if (!engine->variables_list_index) { + sml_critical("Unexpected error. Implementation of function " + "sml_variables_list_index is mandatory for engines."); + return false; + } + return engine->variables_list_index(list, index); +} + +API_EXPORT bool +sml_variable_set_range(struct sml_object *sml, + struct sml_variable *sml_variable, float min, float max) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml_variable, false); + ON_NULL_RETURN_VAL(sml, false); + if (!engine->variable_set_range) { + sml_critical("Unexpected error. Implementation of function " + "sml_variable_set_range is mandatory for engines."); + return false; + } + return engine->variable_set_range(sml_variable, min, max); +} + +API_EXPORT bool +sml_variable_get_range(struct sml_object *sml, + struct sml_variable *sml_variable, float *min, float *max) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN_VAL(sml_variable, false); + if (!engine->variable_get_range) { + sml_critical("Unexpected error. Implementation of function " + "sml_variable_get_range is mandatory for engines."); + return false; + } + return engine->variable_get_range(sml_variable, min, max); +} + +API_EXPORT void +sml_print_debug(struct sml_object *sml, bool full) +{ + struct sml_engine *engine = (struct sml_engine *)sml; + + ON_NULL_RETURN(sml); + if (!engine->print_debug) + return; + engine->print_debug(engine, full); +} + +API_EXPORT bool +sml_set_max_memory_for_observations(struct sml_object *sml, + unsigned int obs_max_size) +{ + ON_NULL_RETURN_VAL(sml, false); + struct sml_engine *engine = (struct sml_engine *)sml; + + engine->obs_max_size = obs_max_size; + return true; +} diff --git a/sml/common/src/sml_log.c b/sml/common/src/sml_log.c new file mode 100644 index 0000000..f0835b6 --- /dev/null +++ b/sml/common/src/sml_log.c @@ -0,0 +1,101 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +static void +_sml_log_default_handler(enum sml_log_level level, const char *msg, void *data) +{ + switch (level) { + case SML_LOG_LEVEL_DEBUG: + fprintf(stdout, "(**SML Debug**) %s\n", msg); + break; + case SML_LOG_LEVEL_WARNING: + fprintf(stdout, "(**SML Warning**) %s\n", msg); + break; + case SML_LOG_LEVEL_CRITICAL: + fprintf(stderr, "(**SML Critical**) %s\n", msg); + break; + default: + fprintf(stdout, "(**SML Unknown log level**) %s\n", msg); + } +} + +static sml_log_handler_cb _handler_cb = _sml_log_default_handler; +static void *_handler_data = NULL; +static enum sml_log_level _log_levels = SML_LOG_LEVEL_ALL; + +API_EXPORT void +sml_log_set_log_handler(enum sml_log_level levels, sml_log_handler_cb cb, + void *data) +{ + _handler_cb = cb; + _handler_data = data; + _log_levels = levels; +} + +API_EXPORT void +sml_log_print(enum sml_log_level level, const char *format, ...) +{ + struct sml_string *str; + va_list ap; + + if (!_handler_cb) + return; + +#ifndef Debug + if ((level & SML_LOG_LEVEL_DEBUG)) + return; +#endif + + if (!(_log_levels & level)) + return; + + str = sml_string_new(NULL); + + if (!str) + return; + + va_start(ap, format); + + if (sml_string_append_vprintf(str, format, ap)) + _handler_cb(level, sml_string_get_string(str), _handler_data); + + sml_string_free(str); + va_end(ap); +} diff --git a/sml/common/src/sml_main_loop.c b/sml/common/src/sml_main_loop.c new file mode 100644 index 0000000..6ebd39e --- /dev/null +++ b/sml/common/src/sml_main_loop.c @@ -0,0 +1,148 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include +#include + +static GMainLoop *loop; +static int _init_count; + +static gboolean +_on_signal(gpointer ptr) +{ + sml_debug("Got signal, quit"); + sml_main_loop_quit(); + return true; +} + +API_EXPORT int +sml_main_loop_init(void) +{ + _init_count++; + if (_init_count > 1) + return 0; + + loop = g_main_loop_new(NULL, false); + if (!loop) { + sml_critical("Failed to create main loop"); + _init_count = 0; + return errno ? -errno : -ENOENT; + } + + g_unix_signal_add(SIGINT, _on_signal, loop); + g_unix_signal_add(SIGTERM, _on_signal, loop); + + sml_debug("Main loop initialized"); + return 0; +} + +API_EXPORT void +sml_main_loop_run(void) +{ + if (_init_count == 0) { + sml_critical("Init main loop first"); + return; + } + sml_debug("Run main loop"); + g_main_loop_run(loop); +} + +API_EXPORT void +sml_main_loop_quit(void) +{ + if (_init_count == 0) { + sml_critical("No main loop initialized"); + return; + } + g_main_loop_quit(loop); + sml_debug("Main loop quit"); +} + +API_EXPORT void +sml_main_loop_shutdown(void) +{ + if (_init_count == 0) { + sml_critical("Init main loop first"); + return; + } + if (--_init_count > 0) return; + + g_main_loop_unref(loop); + loop = NULL; + sml_debug("Main loop shutdown"); +} + +static gboolean +_process_timeout(gpointer data) +{ + struct sml_object *sml = data; + + if (sml_process(sml)) { + sml_critical("Failed to process, removing timer"); + return G_SOURCE_REMOVE; + } + return G_SOURCE_CONTINUE; +} + +API_EXPORT int +sml_main_loop_schedule_sml_process(struct sml_object *sml, unsigned int timeout) +{ + int timeout_id; + + if (!sml) { + sml_critical("No sml, no process scheduled"); + return -1; + } + + timeout_id = g_timeout_add(timeout, _process_timeout, sml); + + if (timeout_id > 0) { + sml_debug("Scheduled process timeout with id: %d", timeout_id); + return timeout_id; + } + + sml_critical("Could not schedule process timeout"); + return -1; +} + +API_EXPORT bool +sml_main_loop_unschedule_sml_process(int sml_timeout_id) +{ + sml_debug("Removing scheduled process timeout %d", sml_timeout_id); + return g_source_remove(sml_timeout_id); +} diff --git a/sml/common/src/sml_matrix.c b/sml/common/src/sml_matrix.c new file mode 100644 index 0000000..50f631b --- /dev/null +++ b/sml/common/src/sml_matrix.c @@ -0,0 +1,212 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sml_matrix.h" +#include "sml_log.h" +#include "sml_string.h" +#include +#define max(a, b) ( a > b ? a : b ) +#define BUF_LEN (50) + +inline static struct sol_vector * +_get_line(struct sol_vector *v, uint16_t pos, uint16_t elem_size) +{ + uint16_t i; + + for (i = v->len; i <= pos; i++) { + struct sol_vector *line = sol_vector_append(v); + sol_vector_init(line, elem_size); + } + return sol_vector_get(v, pos); +} + +inline static void * +_get_column(struct sol_vector *line, uint16_t pos, uint16_t elem_size) +{ + uint16_t i; + + for (i = line->len; i <= pos; i++) { + void *c = sol_vector_append(line); + if (!c) + return NULL; + memset(c, 0, elem_size); + } + return sol_vector_get(line, pos); +} + +void +sml_matrix_init(struct sml_matrix *m, uint16_t elem_size) +{ + sol_vector_init(&m->data, sizeof(struct sol_vector)); + m->elem_size = elem_size; +} + +void +sml_matrix_clear(struct sml_matrix *m) +{ + uint16_t i; + struct sol_vector *line; + + SOL_VECTOR_FOREACH_IDX (&m->data, line, i) + sol_vector_clear(line); + + sol_vector_clear(&m->data); +} + +void * +sml_matrix_insert(struct sml_matrix *m, uint16_t i, uint16_t j) +{ + struct sol_vector *line = _get_line(&m->data, i, m->elem_size); + + if (!line) + return NULL; + return _get_column(line, j, m->elem_size); +} + +void * +sml_matrix_get(struct sml_matrix *m, uint16_t i, uint16_t j) +{ + struct sol_vector *line = sol_vector_get(&m->data, i); + + if (!line) + return NULL; + return sol_vector_get(line, j); +} + +bool +sml_matrix_equals(struct sml_matrix *m1, struct sml_matrix *m2, struct + sol_vector *changed, + sml_cmp_cb cmp_cb) +{ + uint16_t i, j, len_i, len_j, *idx; + struct sol_vector *vec1, *vec2; + bool r = false; + + len_i = max(m1->data.len, m2->data.len); + for (i = 0; i < len_i; i++) { + vec1 = sol_vector_get(&m1->data, i); + vec2 = sol_vector_get(&m2->data, i); + len_j = max((vec1 ? vec1->len : 0), (vec2 ? vec2->len : 0)); + for (j = 0; j < len_j; j++) { + if (!cmp_cb(sol_vector_get(vec1, j), + sol_vector_get(vec2, j))) { + if (changed) { + idx = sol_vector_append(changed); + if (!idx) { + sml_critical("Could not append the index:%d to the" \ + " changed vector", i); + return false; + } + *idx = i; + } + r = true; + break; + } + } + } + + return r; +} + +uint16_t +sml_matrix_lines(struct sml_matrix *m) +{ + return m->data.len; +} + +uint16_t +sml_matrix_cols(struct sml_matrix *m, uint16_t i) +{ + struct sol_vector *line = sol_vector_get(&m->data, i); + + if (!line) + return 0; + + return line->len; +} + +void +sml_matrix_remove_line(struct sml_matrix *m, uint16_t line_num) +{ + struct sol_vector *line; + + line = sol_vector_get(&m->data, line_num); + if (!line) + return; + + sol_vector_clear(line); + sol_vector_del(&m->data, line_num); +} + +void +sml_matrix_remove_col(struct sml_matrix *m, uint16_t line_num, uint16_t col_num) +{ + struct sol_vector *line; + + line = sol_vector_get(&m->data, line_num); + if (!line) + return; + + sol_vector_del(line, col_num); +} + +void +sml_matrix_debug(struct sml_matrix *m, sml_matrix_convert_cb convert) +{ + struct sml_string *str = sml_string_new("\t"); + uint16_t i, len_i, j, len_j; + struct sol_vector *vec; + char buf[BUF_LEN]; + + sml_string_append(str, "{"); + len_i = m->data.len; + for (i = 0; i < len_i; i++) { + vec = sol_vector_get(&m->data, i); + if (i > 0) + sml_string_append(str, ", "); + + sml_string_append(str, "{"); + len_j = vec ? vec->len : 0; + for (j = 0; j < len_j; j++) { + if (j > 0) + sml_string_append(str, ", "); + + convert(buf, BUF_LEN, sml_matrix_get(m, i, j)); + sml_string_append_printf(str, "%s", buf); + } + sml_string_append(str, "}"); + } + sml_string_append(str, "}"); + sml_debug("%s", sml_string_get_string(str)); + + sml_string_free(str); +} diff --git a/sml/common/src/sml_string.c b/sml/common/src/sml_string.c new file mode 100644 index 0000000..10c91e5 --- /dev/null +++ b/sml/common/src/sml_string.c @@ -0,0 +1,186 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#define DEFAULT_SIZE (10) + +struct sml_string { + char *str; + size_t len; +}; + +struct sml_string * +sml_string_new(const char *str) +{ + struct sml_string *sml_string = calloc(1, sizeof(struct sml_string)); + + ON_NULL_RETURN_VAL(sml_string, NULL); + if (str) { + sml_string->str = strdup(str); + if (!sml_string->str) { + free(sml_string); + return NULL; + } + sml_string->len = strlen(str); + } + return sml_string; +} + +int +_sml_string_create_formatted_str(char **buf, const char *format, va_list ap) +{ + va_list aq; + char *new_buf; + int r, len; + + len = DEFAULT_SIZE; + *buf = NULL; + + for (;;) { + new_buf = realloc(*buf, sizeof(char) * len); + + if (!new_buf) + goto err_exit; + + *buf = new_buf; + + va_copy(aq, ap); + r = vsnprintf(*buf, len, format, aq); + va_end(aq); + + if (r < 0) + goto err_exit; + + if (r < len) + break; + len = r + 1; + } + + return strlen(*buf); + +err_exit: + free(*buf); + *buf = NULL; + return -1; +} + +bool +sml_string_append(struct sml_string *sml_string, const char *str) +{ + size_t len; + char *buf; + + ON_NULL_RETURN_VAL(sml_string, false); + ON_NULL_RETURN_VAL(str, false); + len = strlen(str); + + buf = realloc(sml_string->str, sizeof(char) * (len + sml_string->len + 1)); + if (!buf) + return false; + sml_string->str = buf; + memcpy(sml_string->str + sml_string->len, str, len + 1); + sml_string->len += len; + return true; +} + +bool +sml_string_append_printf(struct sml_string *sml_string, const char *format, ...) +{ + va_list ap; + bool r; + + ON_NULL_RETURN_VAL(sml_string, false); + ON_NULL_RETURN_VAL(format, false); + + va_start(ap, format); + r = sml_string_append_vprintf(sml_string, format, ap); + va_end(ap); + return r; +} + +bool +sml_string_append_vprintf(struct sml_string *sml_string, const char *format, + va_list ap) +{ + char *buf, *new_str; + int len; + bool r; + + ON_NULL_RETURN_VAL(sml_string, false); + ON_NULL_RETURN_VAL(format, false); + + r = false; + buf = NULL; + + len = _sml_string_create_formatted_str(&buf, format, ap); + + if (len < 0) + goto exit; + + new_str = realloc(sml_string->str, + sizeof(char) * (len + sml_string->len) + 1); + if (!new_str) + goto exit; + memcpy(new_str + sml_string->len, buf, len + 1); + sml_string->str = new_str; + sml_string->len += len; + r = true; +exit: + free(buf); + return r; +} + +size_t +sml_string_length(struct sml_string *sml_string) +{ + ON_NULL_RETURN_VAL(sml_string, 0); + return sml_string->len; +} + +const char * +sml_string_get_string(struct sml_string *sml_string) +{ + ON_NULL_RETURN_VAL(sml_string, NULL); + return sml_string->str; +} + +void +sml_string_free(struct sml_string *sml_string) +{ + ON_NULL_RETURN(sml_string); + free(sml_string->str); + free(sml_string); +} diff --git a/sml/common/src/sml_util.c b/sml/common/src/sml_util.c new file mode 100644 index 0000000..4a15aac --- /dev/null +++ b/sml/common/src/sml_util.c @@ -0,0 +1,95 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sml_util.h" +#include +#include +#include +#include +#include + +bool +is_file(const char *path) +{ + struct stat stat_result; + + if (!stat(path, &stat_result) && S_ISREG(stat_result.st_mode)) + return true; + + return false; +} + +bool +is_dir(const char *path) +{ + struct stat stat_result; + + if (!stat(path, &stat_result) && S_ISDIR(stat_result.st_mode)) + return true; + + return false; +} + +bool +clean_dir(const char *path, const char *prefix) +{ + DIR *dir; + struct dirent *file; + char buf[SML_PATH_MAX]; + int prefix_len = 0; + + dir = opendir(path); + if (!dir) + return false; + + if (prefix) + prefix_len = strlen(prefix); + + while ((file = readdir(dir))) { + if (strncmp(file->d_name, prefix, prefix_len)) + continue; + snprintf(buf, SML_PATH_MAX, "%s/%s", path, file->d_name); + if (remove(buf)) + return false; + } + + return true; +} + +bool +delete_file(const char *path) +{ + if (!remove(path)) + return true; + sml_critical("Could not remove the path:%s", path); + return false; +} diff --git a/sml/include/sml.h b/sml/include/sml.h new file mode 100644 index 0000000..916a56c --- /dev/null +++ b/sml/include/sml.h @@ -0,0 +1,607 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @mainpage Soletta Machine Learning Project Documentation + * + * Soletta Machine Learning (SML) is an open source machine learning library + * focused on development of IoT projects. + * + * It provides API to handle with client side AI and an easy to use + * flow-based Soletta module. Supports neural networks and fuzzy logic + * learning and can be easily extended to support others. + * + * SML is divided in the following groups: + * + * @li @ref Engine + * @li @ref Fuzzy_Engine + * @li @ref Log + * @li @ref Mainloop + * @li @ref Ann_Engine + * @li @ref Variables + */ + +/** + * @file + * @defgroup Engine Engine + * @brief The SML common functions. + * + * The functions here are common to all engines. + * They are used to free the engines, + * create variables, save/load SML state and more. + * + * The SML main flow consist in the following steps: + * - Choose an engine (ANN or Fuzzy). + * - Create the inputs and outputs variables. + * - Register the read callback. + * - Register the change callback. + * - Read the variable value, set it in SML and call process. + * + * As a simple example imagine that one wants to control an indoor light that + * turns on automatically if a person enters in the room and goes off if + * the person leaves. For that, this person has a presence sensor. + * + * Choosing engines and creating variables is straight-forward after + * the solution is modeled. Let's say fuzzy was the choosen one. + * Registering callbacks is simple as well: + * + * @dontinclude example_doc.c + * @skip main + * @until sml_set_output_state_changed_callback + * + * Terms are a way to split the values in the range in meaningful parts. + * Fuzzy supports some functions to describe them, as ramps, triangles + * and others. Since they're binary variables, using two ramps, + * one starting on 0 and other ending on 1, with a small overlap between them, + * seems good enough. This way, it will try to predict the output + * for any possible value being more certain about it on extremities. + * + * After everything is set up, it's time to trigger the processing. + * It will be done in a simple loop, making 150 sml_process() calls, + * but more elaborated ways to call process() can be implemented, + * using mainloops. + * + * @until } + * @until } + * + * Read and change callbacks implementation varies a lot depending + * on machine learning usage, since they're the interface with the + * rest of the world. + * + * Read callback is a function that will be called at each processing cycle + * to update variables values. + * + * So in this function the values of presence sensor and light must + * to be fetched. It could be done via GPIO, OIC, or any other way, + * depending in your product. It may be synchronous or asynchronous. + * + * To keep it simple, yet illustrative, we're going to simulate the values + * in a function read_state_cb() Variable sensor_state represents presense + * sensor reading, switch_state represents light state. + * + * This variable will be global since its going to be used by the callback + * of state changes (you could use a struct with this variable and pass them + * to callbacks). + * + * To simulate a daily based used, a day would be a cycle of 15 readings, + * user will be present on last 5 readings of each "day". + * When she leaves she remembers to turn lights off... most of the time. + * This is simulated by off_count . When she forgets lights on and leaves, + * machine learning should suggest to turn lights off. + * + * After states are "fetch", they're set on sml variables (input and output). + * + * @dontinclude example_doc.c + * @skip static int switch_state + * @until return true; + * @until } + * + * To fetch predicted output values, it's required to set a + * callback function using sml_set_output_state_changed_callback() + * + * This callback will be called when SML makes a prediction for at + * least one output variable. + * + * Change state callback only will be called on output value changes. + * But most of the time, this prediction should matches current state of + * output variable. On this case no action must to be taken. + * Also, sometimes SML doesn't have enough information to make a prediction, + * setting output variable value to NaN. + * + * So in change state callback we're going to check first if it was able + * to predict a value, then check if we need to act, in case prediction + * and current light state diverges. + * + * In this example we'll just print a message informing the light state + * should be changed. + * + * @skip static void + * @until printf("Light should be turned OFF.\n"); + * @until } + * @until } + * + * A few tips to obtain good predictions. + * - Do not try to control the whole world with one SML object. + * - If you want to control a light and an air-conditioning and they + * are independent of each other. Create two SML objects, + * one will control the light and another one the air-conditioning. + * - Try to avoid adding unnecessary inputs/outpus to SML (or forget + * to add relevant inputs/outputs), this may lead the poor + * predictions. + * - Test both engines and check which one has the best results + * for your problem. + * @{ + */ + +#define SML_INTERNAL_ERROR 3 /**< SML error code. Could not complete an operation */ + +/** + * @struct sml_object + * + * Instance of the choosen machine learning engine, it may be created with + * sml_fuzzy_new() or sml_ann_new() and shold be deleted after usage with + * sml_free(). + */ +struct sml_object; + +/** + * @struct sml_variable + * @ingroup Variables + * + * A input or output variable. + */ +struct sml_variable; + +/** + * @struct sml_variables_list + * @ingroup Variables + * + * A list of input or output variables (::sml_variable) + */ +struct sml_variables_list; + +/** + * @brief A user defined callback to read the variables values. + * + * @param sml The ::sml_object object + * @param data The user defined data + * @return @c true on success. + * @return @c false if no reads were done. + * @see ::sml_set_read_state_callback + */ +typedef bool (*sml_read_state_cb) (struct sml_object *sml, void *data); + +/** + * @brief Called everytime the SML made a prediction. + * @param sml The ::sml_object Object. + * @param changed A ::sml_variables_list with the predicted variables. + * @param data User defined data. + * @see ::sml_set_output_state_changed_callback + */ +typedef void (*sml_change_cb)(struct sml_object *sml, struct sml_variables_list *changed, void *data); + + +/** + * @brief Reads a FLL file. + * + * FLL stands for Fuzzylite language. It can be used to create/change the fuzzy terms/defuzzifiers + * without using the SML apis. + * + * @remarks If the function is used on an already running SML engine, all the previous + * knowledge will be lost! + * + * @param sml The ::sml_object object. + * @param filename A fll file path. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_load_fll_file(struct sml_object *sml, const char *filename); + +/** + * @brief Frees the SML engine. + * + * @param sml The engine to be freed. + */ +void sml_free(struct sml_object *sml); + +/** + * @brief Register a read calblack. + * + * It should be used to set a callback function to read variables + * values. This callback must return true if it was able to + * read all variables or false on error. If an error happens + * ::sml_process will be aborted, returning an error value. + * Otherwise, ::sml_process will proceed with updated variables values. + * + * @remarks If read_state_cb is null previous callback will be unset. + * @param sml The ::sml_object object. + * @param read_state_cb A ::sml_read_state_cb. + * @param data User data to ::sml_read_state_cb. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_set_read_state_callback(struct sml_object *sml, sml_read_state_cb read_state_cb, void *data); + +/** + * @brief Register a change callback + * + * It should be used to set a callback function to fetch the predicted + * output variables. This callback will be called when the SML makes a prediction + * for at least on output variable. + * + * @remarks If output_state_changed_cb is null previous callback will be unset. + * @param sml The ::sml_object object. + * @param output_state_changed_cb A ::sml_change_cb. + * @param data User data to ::sml_read_state_cb. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_set_output_state_changed_callback(struct sml_object *sml, sml_change_cb output_state_changed_cb, void *data); + + +/** + * @brief Disable the SML learning. + * + * All the reads will be ignore and they will not be used to learn new + * patterns. However predictions can still be made. + * + * @remark Learning is enabled by default. + * + * @param sml The ::sml_object object. + * @param disable @c true to disable learn, @c false otherwise + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_set_learn_disabled(struct sml_object *sml, bool disable); + +/** + * @brief Process variables and make predictions + * + * This function is used to read the variables via ::sml_read_state_cb, process them and + * call ::sml_change_cb if necessary. + * + * @remarks It's required to set a read callback. + * + * @param sml The ::sml_object object. + * @return ::0 on success + * @return other values on failure. + * @see ::sml_set_read_state_callback + */ +int sml_process(struct sml_object *sml); + +/** + * @brief Make a prediction based on the most recent observations. + * + * This is usefull for making predictions without the normal SML flow, + * without a mainloop and a registered ::sml_change_cb. Take a look + * in the following example: + * + * @code{.c} + * + * //A simple example that will turn the light on if someone is in the room. + * struct sml_variale PresenveVar, LightStateVar; + * struct sml_object struct smlobject; + * ARandomLightClass MyLight; + * + * ... + * + * sml_variable_set_value(struct smlobject, PresenceVar, 1.0); //User is present + * sml_predict(struct smlobject); + * if (sml_variable_get_value(struct smlobject, LightStateVar) == 1.0) //Should be on + * light_api_set_On(MyLight); + * else + * light_api_set_Off(MyLight); + * ... + * @endcode + * + * + * @remarks ::sml_change_cb and ::sml_read_state_cb won't be called ! + * @param sml The ::sml_object object. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_predict(struct sml_object *sml); + +/** + * @brief Set the stabilization hits. + * + * Amount of reads without input changes to consider input stable. Only stable + * inputs are used to run predictions or to train the SML engine. This is + * necessary to remove noises in read data that could lead to incorrect + * previsions. + * + * @remarks It's defined as 5 reads by default. If set as 0, the input is + * always considered stable. + * @param sml The ::sml_object object. + * @param hits The number of hits to be considered stable. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_set_stabilization_hits(struct sml_object *sml, uint16_t hits); + +/** + * @brief Save the SML state on the disk. + * + * @param sml The ::sml_object object. + * @param path A direcoty to save the engine files. + * @return @c true on success. + * @return @c false on failure. + * @see ::sml_load + */ +bool sml_save(struct sml_object *sml, const char *path); + +/** + * @brief Load the SML state from the disk. + * + * @param sml The ::sml_object object. + * @param path A direcoty to load the engine files. + * @return @c true on success. + * @return @c false on failure. + * @see ::sml_save + */ +bool sml_load(struct sml_object *sml, const char *path); + +/** + * @brief Prints SML debug information. + * + * @param sml The ::sml_object object. + * @param full @c true for full log, @c false otherwise. + */ +void sml_print_debug(struct sml_object *sml, bool full); + +/** + * @brief Set maximum memory that can be used to store observation history data. + * + * @remark max_size = 0 means infinite (it is also the default). + * @param sml The ::sml_object object. + * @param max_size Max memory size in bytes. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_set_max_memory_for_observations(struct sml_object *sml, unsigned int max_size); + +/** + * @} + */ +/** + * @defgroup Variables Variables + * + * @brief SML Variable operations. + * @{ + */ + +/** + * @brief Return the input variables list. + * + * @param sml The ::sml_object object. + * @return ::sml_variables_list on success. + * @return @c NULL on failure. + */ +struct sml_variables_list *sml_get_input_list(struct sml_object *sml); + +/** + * @brief Return the output variables list. + * + * @param sml The ::sml_object object. + * @return ::sml_variables_list on success. + * @return @c NULL on failure. + */ +struct sml_variables_list *sml_get_output_list(struct sml_object *sml); + +/** + * @brief Create a new input variable + * + * New input variables start with NAN set as value. + * + * @param sml The ::sml_object object. + * @param name The variable name. + * @return ::sml_variable on success. + * @return @c NULL on failure. + */ +struct sml_variable *sml_new_input(struct sml_object *sml, const char *name); + +/** + * @brief Create a new output variable + * + * If its value can't be calculated in a ::sml_process execution, + * the value set on NAN will be used. + * + * @param sml The ::sml_object object. + * @param name The variable name. + * @return ::sml_variable on success. + * @return @c NULL on failure. + */ +struct sml_variable *sml_new_output(struct sml_object *sml, const char *name); + +/** + * @brief Get input variable by name + * + * @param sml The ::sml_object object. + * @param name The variable name. + * @return ::sml_variable on success. + * @return @c NULL on failure. + */ +struct sml_variable *sml_get_input(struct sml_object *sml, const char *name); + +/** + * @brief Get input variable by name + * + * @param sml The ::sml_object object. + * @param name The variable name. + * @return ::sml_variable on success. + * @return @c NULL on failure. + */ +struct sml_variable *sml_get_output(struct sml_object *sml, const char *name); + +/** + * @brief Set the variable value. + * + * @param sml The ::sml_object object. + * @param sml_variable The ::sml_variable + * @param value The desired value. + * @return @c true on succcess. + * @return @c false on failure. + */ +bool sml_variable_set_value(struct sml_object *sml, struct sml_variable *sml_variable, float value); + +/** + * @brief Get the variable current value. + * + * @param sml The ::sml_object object. + * @param sml_variable The ::sml_variable + * @return @c true on succcess. + * @return @c false on failure. + */ +float sml_variable_get_value(struct sml_object *sml, struct sml_variable *sml_variable); + +/** + * @brief Get ::sml_variable name. + * + * @param sml The ::sml_object object. + * @param sml_variable The ::sml_variable. + * @return The variable's name on success. + * @return @c NULL on failure. + */ +const char *sml_variable_get_name(struct sml_object *sml, struct sml_variable *sml_variable); + +/** + * @brief Enable or disable a variable + * + * If a variable is disabled and is an input variable, its value will be ignored when trying to + * predict the values or training the engine. + * If it is an output variable, no prediction for this variable will be processed + * + * @remarks All variables are enabled by default. + * @param sml The ::sml_object object. + * @param variable The ::sml_variable. + * @param enabled @c true to enable, @c false to disable. + * @return @c true on success. + * @return @c false on failure. + */ +int sml_variable_set_enabled(struct sml_object *sml, struct sml_variable *variable, bool enabled); + +/** + * @brief Check if a ::sml_variable is enabled. + * + * @param sml The ::sml_object object. + * @param variable The ::sml_variable + * @return @c true on succcess. + * @return @c false on failure. + */ +bool sml_variable_is_enabled(struct sml_object *sml, struct sml_variable *variable); + +/** + * @brief Remove a variable from the engine. + * + * @remark Removing a variable from a running SML engine may + * make it loose all previous knowledge. For temporary removals, use + * ::sml_variable_set_enabled + * + * @param sml The ::sml_object object. + * @param variable The ::sml_variable to be removed + * @return @c true on succcess. + * @return @c false on failure. + */ +bool sml_remove_variable(struct sml_object *sml, struct sml_variable *variable); + +/** + * @brief Get the ::sml_variables_list size + * + * @param sml The ::sml_object Object. + * @param list The ::sml_variables_list. + * @return The list size + */ +uint16_t sml_variables_list_get_length(struct sml_object *sml, struct sml_variables_list *list); + +/** + * @brief Get ::sml_variable by index. + * + * @param sml The ::sml_object object. + * @param list The ::sml_variables_list. + * @param index The list index. + * @return ::sml_variable on success. + * @return @c NULL on faiulre.. + */ +struct sml_variable *sml_variables_list_index(struct sml_object *sml, struct sml_variables_list *list, uint16_t index); + +/** + * @brief Check if ::sml_variable is present in a ::sml_variables_list + * + * @param sml The ::sml_object object. + * @param list The ::sml_variables_list. + * @param var The ::sml_variable. + * @return @c true it is present. + * @return @c false is is not present. + */ +bool sml_variables_list_contains(struct sml_object *sml, struct sml_variables_list *list, struct sml_variable *var); + +/** + * @brief Set variable range. + * + * @remarks default value is FLT_MIN for min and FLT_MAX for max. + * + * @param sml The ::sml_object object. + * @param sml_variable The ::sml_variable. + * @param min Variable's min value. + * @param max Variable's max value + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_variable_set_range(struct sml_object *sml, struct sml_variable *sml_variable, float min, float max); + +/** + * @brief Get variable range. + * + * @param sml The ::sml_object object. + * @param sml_variable The ::sml_variable. + * @param min Variable where min value will be set. If @c NULL it is ignored. + * @param max Variable where max value will be set. If @c NULL it is ignored. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_variable_get_range(struct sml_object *sml, struct sml_variable *sml_variable, float *min, float *max); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif diff --git a/sml/include/sml_ann.h b/sml/include/sml_ann.h new file mode 100644 index 0000000..50783f7 --- /dev/null +++ b/sml/include/sml_ann.h @@ -0,0 +1,284 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @defgroup Ann_Engine Neural network engine + * @brief The SML neural network engine. + * + * \anchor Neural_Network_Engine_Introduction + * The SML neural network engine has two methods of operation, these methods try + * to reduce or eliminate a problem called catastrophic forgetting that affects neural + * networks. + * + * Basically catastrophic forgetting is a problem that the neural network may forget everything + * that has learnt in the past and only accumulate recent memory. This happens due the nature + * of their training. In order to reduce this problem the following methods were implemented. + * + * The first method is called pseudohearsal (the default one), in this method only one neural network is created + * and everytime it needs be retrained, random inputs are genereted and + * feed to the network. The corresponding outputs are stored and used to train the neural network + * with the new collected data. + * + * The second method of operation consists in creating N neural networks, + * that are very specific for each pattern that SML encounters and everytime the SML wants to make a prediction, + * it will choose which is the best neural network for the current situation. + * It is possible to set a limit of how many neural networks SML will have in memory, this limit + * can be set with ::sml_ann_set_cache_max_size. This cache implements the LRU algorithm so, + * neural networks that were not recent used will be deleted. + * + * + * To know more about catastrophic forgetting: https://en.wikipedia.org/wiki/Catastrophic_interference + * @{ + */ + +/** + * @enum sml_ann_training_algorithm + * @brief Algorithm types used to train a neural network. + * @see ::sml_ann_set_training_algorithm + */ +enum sml_ann_training_algorithm { + SML_ANN_TRAINING_ALGORITHM_QUICKPROP, /**< Faster than the standard backpropagation. + Uses the gradient information to update the weights; + It's based on the Newton's method. + */ + SML_ANN_TRAINING_ALGORITHM_RPROP /**< Uses the sign of the gradient to update the weights.*/ +}; /**< The neural networks training type. */ + + +/** + * @enum sml_ann_activation_function + * @brief The functions that are used by the neurons to produce an output. + * @see ::sml_ann_set_activation_function_candidates + */ +enum sml_ann_activation_function { + SML_ANN_ACTIVATION_FUNCTION_SIGMOID, /**< Sigmoid function. Defined for 0 < y < 1*/ + SML_ANN_ACTIVATION_FUNCTION_SIGMOID_SYMMETRIC, /**< Sigmoid function. Defined for -1 < y < 1*/ + SML_ANN_ACTIVATION_FUNCTION_GAUSSIAN, /**< Gaussian function. Defined for 0 < y < 1*/ + SML_ANN_ACTIVATION_FUNCTION_GAUSSIAN_SYMMETRIC, /**< Gaussian function. Defined for -1 < y < 1*/ + SML_ANN_ACTIVATION_FUNCTION_ELLIOT, /**< Elliot function. Defined for 0 < y < 1*/ + SML_ANN_ACTIVATION_FUNCTION_ELLIOT_SYMMETRIC, /**< Elliot function. Defined for -1 < y < 1*/ + SML_ANN_ACTIVATION_FUNCTION_COS, /**< Cosinus function. Defined for 0 <= y <= 1 */ + SML_ANN_ACTIVATION_FUNCTION_COS_SYMMETRIC, /**< Cosinus function. Defined for -1 <= y <= 1 */ + SML_ANN_ACTIVATION_FUNCTION_SIN, /**< Sinus function. Defined for 0 <= y <= 1 */ + SML_ANN_ACTIVATION_FUNCTION_SIN_SYMMETRIC /**< Sinus function. Defined for -1 <= y <= 1 */ +}; /**< The neuron activation functions */ + +/** + * @brief Creates a SML neural networks engine. + * + * @remark It must be freed with ::sml_free after usage is done. + * + * @return A ::sml_object object on success. + * @return @c NULL on failure. + * + * @see ::sml_free + * @see ::sml_object + */ +struct sml_object *sml_ann_new(void); + +/** + * @brief Check if the SML object is a neural network engine. + * + * @param sml The ::sml_object object. + * @return @c true If it is fuzzy. + * @return @c false If it is not fuzzy. + */ +bool sml_is_ann(struct sml_object *sml); + +/** + * @brief Check if SML was built with neural networks support support. + * + * @return @c true If it has neural network support. + * @return @c false If it is has not neural network support. + */ +bool sml_ann_supported(void); + +/** + * @brief Set the neural network training algorithm. + * + * @remark The default training algorithm is ::SML_ANN_TRAINING_ALGORITHM_QUICKPROP + * + * @param sml The ::sml_object object. + * @param algorithm The ::sml_ann_training_algorithm algorithm. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_ann_set_training_algorithm(struct sml_object *sml, enum sml_ann_training_algorithm algorithm); + +/** + * @brief Set the neural networks activation function candidates. + * + * Activation functions resides inside the neurons and they are responsible for producing the + * neuron output value. As choosing the correct activation functions may required a + * lot of trail and error tests, the SML uses an algorithm that tries to suit the best + * activiation functions for a given problem. + * + * @remark By default all ::sml_ann_activation_function are used as candidates. + * + * @param sml The ::sml_object object. + * @param functions The ::sml_ann_activation_function functions vector. + * @param size The size of the vector functions. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_ann_set_activation_function_candidates(struct sml_object *sml, enum sml_ann_activation_function *functions, unsigned int size); + + +/** + * @brief Set the maximum number of neurons in the network + * + * SML automatically add neurons to the hidden layers when training the neural network, + * you can prevent the neural network to grow too big by setting the max neurons. + * Larger networks are more difficult to train, thus required more time. However, + * smaller networks will have poor predictions. + * + * @remark The default max_neurons is 5 + * + * @param sml The ::sml_object object. + * @param max_neurons The maximum number of neurons in the neural network. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_ann_set_max_neurons(struct sml_object *sml, unsigned int max_neurons); + +/** + * @brief Set the number of neural network candidates + * + * During the training phase the SML will choose the network topology by itself. + * To do so, it will create (M * 4) neuron candidates (where M is + * the number of activation function candidates) and then N (where N is the number of candidate groups) + * candidate groups will be created, ending up with M*4*N candidate neurons. + * The only different beetwen these candidate groups is the initial weight values. + * + * @remark The default number of candidates is 6 + * + * @param sml The ::sml_object object. + * @param candidate_groups The number of candidate groups. + * @return @c true on success. + * @return @c false on failure. + * + * @see ::sml_ann_set_max_neurons + * @see ::sml_ann_set_activation_function_candidates + */ +bool sml_ann_set_candidate_groups(struct sml_object *sml, unsigned int candidate_groups); + +/** + * @brief Set the neral network train epochs + * + * The training epochs is used to know when to stop the training. + * If the desired error is never reached, the training phase will stop + * when it reaches the training_epochs value. + * + * @remark The default training epochs is 300 + * + * @param sml The ::sml_object object. + * @param training_epochs The number of training_epochs + * @return @c true on success. + * @return @c false on failure. + * + * @see ::sml_ann_set_desired_error + */ +bool sml_ann_set_training_epochs(struct sml_object *sml, unsigned int training_epochs); + +/** + * @brief Set the neural network desired error + * + * This is used as a shortcut to stop the training phase. If + * the neural network is equals or below desired_error the train can be stopped. + * + * @remark The default desired error is 0.001 + * + * @param sml The ::sml_object object. + * @param desired_error The desired error + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_ann_set_desired_error(struct sml_object *sml, float desired_error); + +/** + * @brief Set the maximum number of neural networks in the cache. + * + * @remark The default cache size is 30. + * @remark 0 means "infinite" cache size. + * + * @param sml The ::sml_object object. + * @param max_size The max cache size + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_ann_set_cache_max_size(struct sml_object *sml, unsigned int max_size); + +/** + * @brief Set the required number of observations to train the neural network. + * + * The SML will only train the neural network when the observation count reaches + * required_observation. However this number is only a hint to SML, because if SML detects + * that the provided number is not enough, the required_observations will grow. + * There is a way to control how much memory the SML will use to store observations, + * this memory cap can be set with ::sml_set_max_memory_for_observations + * + * @remark The default required observations is 2500 + * + * @param sml The ::sml_object object. + * @param required_observations The number of required observations + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_ann_set_initial_required_observations(struct sml_object *sml, unsigned int required_observations); + +/** + * @brief Set the pseudoreharsal strategy + * + * For more information about the pseudorehearsal strategy look at the + * \ref Neural_Network_Engine_Introduction + * @remark The default value for pseudorehearsal is @c true. + * + * @param sml The ::sml_object object. + * @param use_pseudorehearsal @c true to enable, @c false to disable + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_ann_use_pseudorehearsal_strategy(struct sml_object *sml, bool use_pseudorehearsal); +/** + * @} + */ +#ifdef __cplusplus +} +#endif diff --git a/sml/include/sml_fuzzy.h b/sml/include/sml_fuzzy.h new file mode 100644 index 0000000..4aeb449 --- /dev/null +++ b/sml/include/sml_fuzzy.h @@ -0,0 +1,419 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @defgroup Fuzzy_Engine Fuzzy engine + * @brief The SML naive fuzzy logic engine. + * + * The SML may use a modified fuzzy engine to predict values. The main difference + * from a normal fuzzy engine, is that the SML engine will create the fuzzy rules by + * itself. + * A good start to know more about fuzzy logic is visiting https://en.wikipedia.org/wiki/Fuzzy_logic + * @{ + */ + +/** + * @enum sml_fuzzy_snorm + * @brief SNorm rules are also known as disjuction. + * + * @see ::sml_fuzzy_disjunction_set + */ +enum sml_fuzzy_snorm { + SML_FUZZY_SNORM_NONE, /**< No SNorm rule will be applied */ + SML_FUZZY_SNORM_ALGEBRAIC_SUM, /**< A or B -> A+B - (A*B)*/ + SML_FUZZY_SNORM_BOUNDED_SUM, /**< A or B -> min(A+B,1) */ + SML_FUZZY_SNORM_DRASTIC_SUM, /**< A or B -> if A=0 then B else if B=0 then A else 0 */ + SML_FUZZY_SNORM_EINSTEIN_SUM, /**< A or B -> A+B/1+A*B */ + SML_FUZZY_SNORM_HAMACHER_SUM, /**< A or B -> if A=B=0 then 0 else A*B/A+B-A*B */ + SML_FUZZY_SNORM_MAXIMUM, /**< A or B -> max(A,B) */ + SML_FUZZY_SNORM_NILPOTENT_MAXIMUM, /**< A or B -> if A+B < 1 then max(A,B) else 1 */ + SML_FUZZY_SNORM_NORMALIZED_SUM, /**< A or B -> A+B/max(1, max(A,B))*/ +}; /**< A fuzzy TNorm type. */ + +/** + * @enum sml_fuzzy_tnorm + * @brief TNorm rules are also known as conjuntion. + * + * @see ::sml_fuzzy_conjunction_set + */ +enum sml_fuzzy_tnorm { + SML_FUZZY_TNORM_NONE, /**< No TNorm rule will be applied */ + SML_FUZZY_TNORM_ALGEBRAIC_PRODUCT, /**< A and B -> A*B */ + SML_FUZZY_TNORM_BOUNDED_DIFFERENCE, /**< A and B -> max(A+B-1, 0)*/ + SML_FUZZY_TNORM_DRASTIC_PRODUCT, /**< A and B -> if A=1 then B else if B=1 then A else 0*/ + SML_FUZZY_TNORM_EINSTEIN_PRODUCT, /**< A and B -> A*B/2-(A+B-A*B)*/ + SML_FUZZY_TNORM_HAMACHER_PRODUCT, /**< A and B -> A*B/A+B-A*B*/ + SML_FUZZY_TNORM_MINIMUM, /**< A and B -> min(A,B)*/ + SML_FUZZY_TNORM_NILPOTENT_MINIMUM, /**< A and B -> if A+B > 1 then min(A,B) else 0 */ +}; /**< A fuzzy TNorm type. */ + +/** + * @enum sml_fuzzy_defuzzifier + * + * @brief The types of defuzzifier + * + * @see ::sml_fuzzy_output_set_defuzzifier + */ +enum sml_fuzzy_defuzzifier { + SML_FUZZY_DEFUZZIFIER_BISECTOR, /**< The point that divide the curve into two equal sub-regions */ + SML_FUZZY_DEFUZZIFIER_CENTROID, /**< The center of the area under the curve */ + SML_FUZZY_DEFUZZIFIER_LARGEST_OF_MAXIMUM, /**< The largest value of the maximun degrees of membership */ + SML_FUZZY_DEFUZZIFIER_MEAN_OF_MAXIMUM, /**< The mean of the maximum degrees of membership */ + SML_FUZZY_DEFUZZIFIER_SMALLEST_OF_MAXIMUM, /**< The smallest value of the maximun degrees of membership */ + SML_FUZZY_DEFUZZIFIER_WEIGHTED_AVERAGE, /**< The avarage of the activation degrees multipled by a weight*/ + SML_FUZZY_DEFUZZIFIER_WEIGHTED_SUM, /**< The sum of the activation degrees multipled by a weight*/ +}; /**< A fuzzy Defuzzifier type. */ + +/** + * @struct sml_fuzzy_term + * + * In Fuzzy Logic Engine, fuzzy terms are created using mathematical functions. + * The membership of a fuzzy value to a term is defined by the function + * applied to that value. + * + * Fuzzy Logic Engine supports 5 different terms: + * + * @li Ramp + * @li Triangle + * @li Rectangle + * @li Cosine + * @li Gaussian + */ +struct sml_fuzzy_term; /**< A fuzzy term object. */ + +/** + * @brief Creates a SML fuzzy engine. + * + * @remark It must be freed with ::sml_free after usage is done. + * + * @return A ::sml_object object on success. + * @return @c NULL on failure. + * + * @see ::sml_free + * @see ::sml_object + */ +struct sml_object *sml_fuzzy_new(void); + +/** + * @brief Check if the SML object is a fuzzy engine. + * + * @param sml The ::sml_object object. + * @return @c true If it is fuzzy. + * @return @c false If it is not fuzzy. + */ +bool sml_is_fuzzy(struct sml_object *sml); + +/** + * @brief Check if SML was built with fuzzy support. + * + * @return @c true If it is supported. + * @return @c false If not supported. + */ +bool sml_fuzzy_supported(void); + +/** + * @brief Set the conjunction fuzzy rule. + * + * The conjuction rule is equivalent to the boolean and operation. + * Example: + * If the fuzzy engie encounters the following expression in a fuzzy rule, "... A and B ...". + * Given that A is 0.6 and B is 0.8 and the disjuction operator is ::SML_FUZZY_TNORM_MINIMUM, + * the result of the operation will be 0.6 + * + * @remark The default value is ::SML_FUZZY_TNORM_MINIMUM + * + * @param sml The ::sml_object object. + * @param norm The desired ::sml_fuzzy_tnorm. + * + * @return @c true on success. + * @return @c false on failure. + * + * @see ::sml_fuzzy_tnorm + */ +bool sml_fuzzy_conjunction_set(struct sml_object *sml, enum sml_fuzzy_tnorm norm); + +/** + * @brief Set the disjuction fuzzy rule. + * + * The disjunction rule is equivalent to the boolean or operation. + * Example: + * If the fuzzy engie encounters the following expression in a fuzzy rule, "... A or B ...". + * Given that A is 0.6 and B is 0.8 and the disjuction operator is ::SML_FUZZY_SNORM_MAXIMUM, + * the result of the operation will be 0.8 + * + * @remark The default value is ::SML_FUZZY_SNORM_MAXIMUM + * + * @param sml The ::sml_object object. + * @param norm The desired ::sml_fuzzy_snorm. + * + * @return @c true on success. + * @return @c false on failure. + * + * @see ::sml_fuzzy_snorm + */ +bool sml_fuzzy_disjunction_set(struct sml_object *sml, enum sml_fuzzy_snorm norm); + +/** + * @brief Rules below a given value will be ignored. + * + * Fuzzy rules may have weights associated with it, bigger weights + * means bigger the relevance. + * + * @remark The default weight treshold is 0.05 + * + * @param sml The ::sml_object object. + * @param weight_threshold The desired threshold. + * + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_set_rule_weight_threshold(struct sml_object *sml, float weight_threshold); + +/** + * @brief Set the defuzzifier for an output variable. + * + * Fuzzy defuzzifiers are used to convert degrees of membership to a crisp value (a real number) + * For example if from a given rule the fuzzy engine predict that the degrees of membership + * for a given variable for the term Hot is 10% and for the term Warm is 90%. Using the + * defuzzifier it will be possible the compute a real number to represent these degrees of membership. + * + * @remarks Defuzzifier only works for outputs variables, also the + * defuzzifier_resulution will be ignore if ::sml_fuzzy_defuzzifier is + * ::SML_FUZZY_DEFUZZIFIER_WEIGHTED_SUM or ::SML_FUZZY_DEFUZZIFIER_WEIGHTED_AVERAGE. + * The default defuzzifier is ::SML_FUZZY_DEFUZZIFIER_CENTROID. + * + * @param sml The ::sml_object object. + * @param sml_variable The ::sml_variable to use the given defuzzifier. + * @param defuzzifier The ::sml_fuzzy_defuzzifier object. + * @param defuzzifier_resolution A constant that will be used by the defuzzifier to obtain the crisp value. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_fuzzy_output_set_defuzzifier(struct sml_object *sml, struct sml_variable *sml_variable, enum sml_fuzzy_defuzzifier defuzzifier, int defuzzifier_resolution); + +/** + * @brief Set the output accumulation + * + * @remarks The default accumulation is ::SML_FUZZY_SNORM_MAXIMUM + * + * @param sml The ::sml_object object. + * @param sml_variable The ::sml_variable. + * @param accumulation The ::sml_fuzzy_snorm rule. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_fuzzy_output_set_accumulation(struct sml_object *sml, struct sml_variable *sml_variable, enum sml_fuzzy_snorm accumulation); + +/** + * @brief Add a rectangle term for a variable. + * + * A rectangle term uses a mathematical function defined by its start and end + * points and its height. For any X value from start to end, the function + * value will be height. For all other X values, the function value will be + * @c zero. + * + * @remark The term name can not contain spaces! + * @param sml The ::sml_object object. + * @param variable The ::sml_variable. + * @param name The term's name. + * @param start The point on the X axis that the term will start. + * @param end The point on the X axis that the term will end. + * @param height The term's height, usually 1.0. + * @return @c ::sml_fuzzy_term on success. + * @return @c NULL on failure. + */ +struct sml_fuzzy_term *sml_fuzzy_variable_add_term_rectangle(struct sml_object *sml, struct sml_variable *variable, const char *name, float start, float end, float height); + +/** + * @brief Add a tirangle term for a variable. + * + * A triangle term uses is a mathematical function defined by 3 vertex (a, b c) + * and its height. For X coordinates between vertex a and b, function value is + * obtained by the linear function connecting points (vertex_a; 0) to + * (vertex_b; height). In vertex_b, function value will be the maximum possible + * value (height) and from vertex_b to vertex_c, function value is obtained by + * the linear function connecting opints (vertex_b; height) to (vertex_c; 0). + * For all other X values, the function value will be @c zero. + * + * @remark The term name can not contain spaces! + * @param sml The ::sml_object object. + * @param variable The ::sml_variable. + * @param name The term's name. + * @param vertex_a The point on the X axis that the term will start. + * @param vertex_b The point on the X axis that will be the middle of the triangle. + * @param vertex_c the point on the X axis that the term will end. + * @param height The term's height, usually 1.0. + * @return @c ::sml_fuzzy_term on success. + * @return @c NULL on failure. + */ +struct sml_fuzzy_term *sml_fuzzy_variable_add_term_triangle(struct sml_object *sml, struct sml_variable *variable, const char *name, float vertex_a, float vertex_b, float vertex_c, float height); + +/** + * @brief Add a cosine term for a variable. + * + * Cosine term value is obtained by the function value from a cosine function + * centered in X coordinate center and with width defined by width paramenter. + * The maximum value (height) of the cosine function is in X coordinate center. + * + * @remark The term name can not contain spaces! + * @param sml The ::sml_object object. + * @param variable The ::sml_variable. + * @param name The term's name. + * @param center The center of the cosine curve. + * @param width The width of the cosine curve. + * @param height The term's height, usually 1.0. + * @return @c ::sml_fuzzy_term on success. + * @return @c NULL on failure. + */ +struct sml_fuzzy_term *sml_fuzzy_variable_add_term_cosine(struct sml_object *sml, struct sml_variable *variable, const char *name, float center, float width, float height); + +/** + * @brief Add a gaussian term for a variable. + * + * Gaussian term value is obtained by the function value from a gaussian + * function defined by the parametes mean, standard_deviation. The maximum + * value of the gaussian function is the value of height parameter. + * + * @remark The term name can not contain spaces! + * @param sml The ::sml_object object. + * @param variable The ::sml_variable. + * @param name The term's name. + * @param mean The mean of the gaussian curve. + * @param standard_deviation The standard deviation of the curve. + * @param height The term's height, usually 1.0. + * @return @c ::sml_fuzzy_term on success. + * @return @c NULL on failure. + */ +struct sml_fuzzy_term *sml_fuzzy_variable_add_term_gaussian(struct sml_object *sml, struct sml_variable *variable, const char *name, float mean, float standard_deviation, float height); + +/** + * @brief Add a ramp term for a variable. + * + * A ramp term uses a mathematical function defined by its start and end points + * and its height. Start parameters is the coordinate in X axis where the ramp + * is in its minimum value (@c zero). End parameter is the coordinate in Y axis + * where the ramp is in its maximum value (height). If start < end we will have + * a positive ramp. If end < start we will have a negative ramp. + *
For example: + * + * @code{.c} + * //this will create a ramp going up, connecting points (0.3; 0.0) and (0.7; 1.0). In X position 0.3, the ramp value will be 0.0. In X position 0.7, the ramp value will be 1.0 + * sml_fuzzy_variable_add_term_ramp (sml, var, "ramp_up", 0.3, 0.7, 1.0); + * + * //this will create a ramp going down, connecting points (0.3; 1.0) and (0.7; 0.0). In X position 0.3, the ramp value will be 1.0. In X position 0.7, the ramp value will be 0.0 + * sml_fuzzy_variable_add_term_ramp (sml, var, "ramp_up", 0.7, 0.3, 1.0); + * @endcode + * + * @remark The term name can not contain spaces! + * @param sml The ::sml_object object. + * @param variable The ::sml_variable. + * @param name The term's name. + * @param start The start of the ramp on the X axis. + * @param end The end of the ramp on the X axis. + * @param height The term's maximum value, usually 1.0. + * @return @c ::sml_fuzzy_term on success. + * @return @c NULL on failure. + */ +struct sml_fuzzy_term *sml_fuzzy_variable_add_term_ramp(struct sml_object *sml, struct sml_variable *variable, const char *name, float start, float end, float height); + +/** + * @brief Set terms autobalance + * + * Defining terms overlaps is a hard task, sometimes the user defined terms are not + * well suited for an application. If the term definitions are poor, the fuzzy engine + * the fuzzy predictions will be poor as well. If auto balance is enabled and if the + * fuzzy engine detects that the terms are not well set, it will recreate the terms. + * + * @remarks Terms auto balance is disabled by default + * + * @param sml The ::sml_object object. + * @param variable_terms_auto_balance @c true to enable, @c false to disable. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_fuzzy_set_variable_terms_auto_balance(struct sml_object *sml, bool variable_terms_auto_balance); + +/** + * @brief Remove a fuzzy term from the engine. + * + * @param sml The ::sml_object object. + * @param variable The ::sml_variable to remove the term. + * @param term The The ::sml_fuzzy_term to be removed. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_fuzzy_variable_remove_term(struct sml_object *sml, struct sml_variable *variable, struct sml_fuzzy_term *term); + +/** + * @brief Disable/Enable simplification. + * + * The rule simplification uses a heuristic to try to simplify the fuzzy rules. + * For example, if the fuzzy engine is controlling a a home Light using two variables + * (Weekday and TimeOfTheDay) we can ha ve the following rules: + *
+ * If Weekday is Sunday and TimeOfTheDay is Night then Light is On.
+ * If Weekday is Monday and TimeOfTheDay is Night then Light is On.
+ * ....
+ * If Weekday is Saturday and TimeOfTheDay is Night then Light is On.
+ *
+ * It is clear that the Weekday is not important, if TimeOfTheDay is Night then + * the Light should be On. Knowing that, the fuzzy engine will simplify those rules + * into one rule: + *
+ * If TimeOfTheDay is Night then Light is On. + *
+ * However if after the simplification a new rule is created that denies the + * simplificated rule, the simplification is undone. + * + * @remarks Rule simplification is enabled by default. + * + * @param sml The ::sml_object object. + * @param disabled @c true to disable, @c false to enable. + * @return @c true on success. + * @return @c false on failure. + */ +bool sml_fuzzy_set_simplification_disabled(struct sml_object *sml, bool disabled); + +/** + * @} + */ +#ifdef __cplusplus +} +#endif diff --git a/sml/include/sml_log.h b/sml/include/sml_log.h new file mode 100644 index 0000000..360bd05 --- /dev/null +++ b/sml/include/sml_log.h @@ -0,0 +1,127 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @defgroup Log Log + * @brief These functions and data types are responsible for logging the SML events. + * @{ + */ + +/** + * @enum sml_log_level + * @brief Log level types + */ +enum sml_log_level { + SML_LOG_LEVEL_DEBUG = 1 << 0, /**< Show debug messages. The debug messages will not be loged with SML is compiled in Release mode.*/ + SML_LOG_LEVEL_WARNING = 1 << 1, /**< Show warning messages */ + SML_LOG_LEVEL_CRITICAL = 1 << 2, /**< Show critical messages */ + SML_LOG_LEVEL_ALL = (SML_LOG_LEVEL_DEBUG | SML_LOG_LEVEL_WARNING | SML_LOG_LEVEL_CRITICAL) /**< Show all messages. */ +}; /**< The types of log levels */ + +/** + * @brief Log handler callback. + * + * This function is responsible for logging the message. + * It is called every time ::sml_log_print is called. + * + * @param level The message log level. + * @param msg The message itself. + * @param data User data that was set with ::sml_log_set_log_handler. + * + * @see ::sml_log_set_log_handler + */ +typedef void (*sml_log_handler_cb)(enum sml_log_level level, const char *msg, void *data); + +/** + * @brief Set a log handler. + * + * This function is usefull if one wants to log SML events in files + * or do not want to log ::SML_LOG_LEVEL_WARNING messages, for example. + * SML provides a default ::sml_log_handler_cb that is automatically set at + * startup, the log level is set to ::SML_LOG_LEVEL_ALL and all messages will be + * logged at stdout. + * + * @param levels The log levels that will be captured. + * @param cb A user defined callback to a log handler. + * @param data User data to cb. + * + * @see ::sml_log_handler_cb + */ +void sml_log_set_log_handler(enum sml_log_level levels, sml_log_handler_cb cb, void *data); + +/** + * @brief Prints a message with a desired log level. + * + * @param level The desired log level. + * @param format A formatted string. + * @param ... Contents of the formatted string. + */ +void sml_log_print(enum sml_log_level level, const char *format, ...); + +/** + * @brief Syntatic sugar to ::sml_log_print(SML_LOG_LEVEL_DEBUG, "debug message") + * + * @param ... A formatted message + * + * @see ::sml_log_print + */ +#define sml_debug(...) sml_log_print(SML_LOG_LEVEL_DEBUG, __VA_ARGS__) +/** + * @brief Syntatic sugar to ::sml_log_print(SML_LOG_LEVEL_WARNING, "warning message") + * + * @param ... A formatted message + * + * @see ::sml_log_print + */ +#define sml_warning(...) sml_log_print(SML_LOG_LEVEL_WARNING, __VA_ARGS__) +/** + * @brief Syntatic sugar to ::sml_log_print(SML_LOG_LEVEL_CRITICAL, "critical message") + * + * @param ... A formatted message + * + * @see ::sml_log_print + */ +#define sml_critical(...) sml_log_print(SML_LOG_LEVEL_CRITICAL, __VA_ARGS__) + +/** + * @} + */ +#ifdef __cplusplus +} +#endif diff --git a/sml/include/sml_main_loop.h b/sml/include/sml_main_loop.h new file mode 100644 index 0000000..8052b55 --- /dev/null +++ b/sml/include/sml_main_loop.h @@ -0,0 +1,119 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @defgroup Mainloop Mainloop + * @brief The sml_main_loop is responsible for providing a mainloop using glib's mainloop. + * It is also possible to schedule a timer to automatically call ::sml_process + * @{ + */ + +/** + * @brief Init the SML mainloop. + * + * @remark The SML mainloop is refcounted, so the number of calls to ::sml_main_loop_init + * must match the number of calls to ::sml_main_loop_shutdown + * + * @return @c 0 on success. + * @return @c A number < @c 0 on failure. + * + * @see ::sml_main_loop_shutdown + * @see ::sml_main_loop_run + */ +int sml_main_loop_init(void); + +/** + * @brief Start the SML mainloop. + * + * @see ::sml_main_loop_quit + */ +void sml_main_loop_run(void); + +/** + * @brief Stops the SML mainloop. + * + * @see ::sml_main_loop_run + * @see ::sml_main_loop_shutdown + */ +void sml_main_loop_quit(void); + +/** + * @brief Clean up the SML mainloop. + * + * @see ::sml_main_loop_init + */ +void sml_main_loop_shutdown(void); + +/** + * @brief Schedule a timer to call ::sml_process automatically + * + * @param sml The ::sml_object object. + * @param timeout The interval between ::sml_process calls (milliseconds). + * @return A timeout_id on success. + * @return -1 on error. + * + * @see ::sml_process + * @see ::sml_main_loop_unschedule_sml_process + * @see ::sml_object + */ +int sml_main_loop_schedule_sml_process(struct sml_object *sml, unsigned int timeout); + +/** + * @brief Unschedule the SML mainloop. + * + * This function will unschedule the ::sml_process calls. + * + * @param sml_timeout_id The timeout_id returned by ::sml_main_loop_schedule_sml_process. + * @return @c true on success. + * @return @c false on failure. + * + * @see ::sml_main_loop_schedule_sml_process + * @see ::sml_process + */ +bool sml_main_loop_unschedule_sml_process(int sml_timeout_id); + +/** + * @} + */ +#ifdef __cplusplus +} +#endif diff --git a/sml/sml.pc.in b/sml/sml.pc.in new file mode 100644 index 0000000..24c7a4c --- /dev/null +++ b/sml/sml.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +includedir=${exec_prefix}/include +libdir=@SML_LIB_DIR@ + +Name: SML +Description: Soletta machine learning library. +Version: @SML_VERSION@ +Libs: -L${libdir} -lsml_libs +Cflags: -I${includedir} diff --git a/sml/sml_ann/src/sml_ann.c b/sml/sml_ann/src/sml_ann.c new file mode 100644 index 0000000..53628b0 --- /dev/null +++ b/sml/sml_ann/src/sml_ann.c @@ -0,0 +1,1298 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "sml_ann_variable_list.h" +#include +#include +#include +#include "sml_cache.h" +#include +#include +#include +#include +#include +#include +#include "sml_ann_bridge.h" +#include "sml_util.h" +#include +#include + +#define DEFAULT_EPOCHS (300) +#define DEFAULT_CANDIDATE_GROUPS (6) +#define DEFAULT_DESIRED_ERROR (0.01) +#define MIN_TRESHOLD (0.5) +#define INITIAL_REQUIRED_OBSERVATIONS (2500) +#define DEFAULT_CACHE_SIZE (30) +#define ANN_FILE_PREFIX "ann_" +#define ANN_FILE_EXTENSION "net" +#define CI_FILE_PREFIX "ann_ci_" +#define CI_FILE_EXTENSION "ci" +#define ANN_PSEUDOREHEARSAL_PREFIX "pseudo_rehearsal_ann" +#define CFG_FILE_PREFIX "ann_cfg_" +#define CFG_FILE_EXTENSION "cfg" +#define ANN_MAGIC (0xa22) +#define EXPAND_FACTOR (3) + +struct sml_ann_engine { + struct sml_engine engine; + + struct sml_variables_list *inputs; + struct sml_variables_list *outputs; + bool first_run; + bool use_pseudorehearsal; + + unsigned int required_observations; + unsigned int train_epochs; + float train_error; + unsigned int max_neurons; + unsigned int candidate_groups; + + enum sml_ann_training_algorithm train_algorithm; + + struct sol_ptr_vector pending_add; + struct sol_ptr_vector pending_remove; + struct sol_vector activation_functions; + + struct sml_cache *anns_cache; +}; + +//FIXME: Is this a good approuch? +static struct sml_variables_list * +_sml_ann_output_has_significant_changes(struct sml_variables_list *outputs) +{ + uint16_t i, size; + struct sml_variable *var; + float neural_value, read_value; + struct sml_variables_list *changed = sml_ann_variable_list_new(); + + if (!changed) { + sml_critical("Could not alloc the output changed list !"); + return NULL; + } + + size = sml_ann_variables_list_get_length(outputs); + for (i = 0; i < size; i++) { + var = sml_ann_variables_list_index(outputs, i); + + neural_value = sml_ann_variable_get_value(var); + read_value = sml_ann_variable_get_previous_value(var); + /* Neural value will never be NAN at this point! */ + if (isnan(read_value) || + fabs(read_value - neural_value) >= MIN_TRESHOLD) { + if (sml_ann_variable_list_add_variable(changed, var)) { + sml_ann_variable_list_free(changed, false); + sml_critical("Could not add a variable to the changed list!"); + return NULL; + } + } else /* If no significant changes happened, set the old value. */ + sml_ann_variable_set_value(var, read_value); + } + sml_debug("Changed list size:%d", + sml_ann_variables_list_get_length(changed)); + return changed; +} + +//FIXME: Is this a good approuch? +static bool +_sml_ann_variable_list_has_significant_changes( + struct sml_variables_list *inputs) +{ + + uint16_t i, size; + struct sml_variable *var; + float last, stable; + + size = sml_ann_variables_list_get_length(inputs); + for (i = 0; i < size; i++) { + var = sml_ann_variables_list_index(inputs, i); + last = sml_ann_variable_get_value(var); + stable = sml_ann_variable_get_last_stable_value(var); + + if (!isnan(stable) && !isnan(last)) { + if (fabs(last - stable) >= MIN_TRESHOLD) + return true; + } else if (!(isnan(stable) && isnan(last))) + return true; + } + return false; +} + +static unsigned int +_sml_ann_get_observations_length(struct sml_ann_engine *ann_engine) +{ + struct sml_variable *var; + + var = sml_ann_variables_list_index(ann_engine->inputs, 0); + + if (!var) + return 0; + return sml_ann_variable_get_observations_length(var); +} + +static bool +_sml_ann_can_alloc_memory_for_observations(unsigned int total_variables, + unsigned int observations_size, + unsigned int max_memory_size) +{ + if (!max_memory_size) + return true; + + unsigned int final_size = observations_size * + sizeof(float) * total_variables; + return final_size <= max_memory_size; +} + +static int +_sml_ann_train(struct sml_ann_engine *ann_engine, struct sml_ann_bridge *iann, + unsigned int observations_size) +{ + int error; + unsigned int required_observations_suggestion; + bool retrain, can_realloc; + uint16_t in_size, out_size, pending_size, i; + struct sml_variable *var; + + error = sml_ann_bridge_train(iann, ann_engine->inputs, ann_engine->outputs, + ann_engine->train_error, + observations_size, + ann_engine->max_neurons, + &required_observations_suggestion, + ann_engine->use_pseudorehearsal); + if (error) + return error; + + can_realloc = true; + retrain = false; + if (required_observations_suggestion > ann_engine->required_observations) { + in_size = sml_ann_variables_list_get_length(ann_engine->inputs); + out_size = sml_ann_variables_list_get_length(ann_engine->outputs); + pending_size = sol_ptr_vector_get_len(&ann_engine->pending_add); + if (!_sml_ann_can_alloc_memory_for_observations( + in_size + out_size + pending_size, + required_observations_suggestion, + ann_engine->engine.obs_max_size)) { + sml_warning("Can not alloc more memory for observations," \ + "obs_max_size has been reached." \ + "Considering the network trained"); + can_realloc = false; + error = sml_ann_bridge_consider_trained(iann, ann_engine->inputs, + ann_engine->required_observations, + ann_engine->use_pseudorehearsal); + } + } else if (required_observations_suggestion < + ann_engine->required_observations) + retrain = true; + else + can_realloc = false; + + if (!sml_ann_bridge_is_trained(iann)) { + if (can_realloc) { + ann_engine->required_observations = + required_observations_suggestion; + if ((error = sml_ann_variables_list_realloc_observations_array( + ann_engine->inputs, ann_engine->required_observations))) + return error; + if ((error = sml_ann_variables_list_realloc_observations_array( + ann_engine->outputs, ann_engine->required_observations))) + return error; + SOL_PTR_VECTOR_FOREACH_IDX (&ann_engine->pending_add, var, i) { + if ((error = sml_ann_variable_realloc_observation_array( + var, ann_engine->required_observations))) + return error; + } + } + if (retrain) { + error = sml_ann_bridge_train(iann, ann_engine->inputs, + ann_engine->outputs, + ann_engine->train_error, + ann_engine->required_observations, + ann_engine->max_neurons, + NULL, + ann_engine->use_pseudorehearsal); + } + } + return error; +} + +static bool +_sml_ann_remove_variable_from_sml(struct sml_ann_engine *ann_engine, + struct sml_variable *var_to_remove, bool input) +{ + struct sml_variable *var; + struct sml_variables_list *list; + uint16_t i, size; + + if (input) + list = ann_engine->inputs; + else + list = ann_engine->outputs; + + size = sml_ann_variables_list_get_length(list); + for (i = 0; i < size; i++) { + var = sml_ann_variables_list_index(list, i); + if (var == var_to_remove) { + sml_ann_variable_list_remove(list, i); + return true; + } + } + return false; +} + +static struct sml_variable * +_sml_ann_find_variable_by_name(struct sml_ann_engine *ann_engine, + const char *name, bool input) +{ + struct sml_variables_list *list; + struct sml_variable *var; + uint16_t i, size; + + if (input) + list = ann_engine->inputs; + else + list = ann_engine->outputs; + + size = sml_ann_variables_list_get_length(list); + for (i = 0; i < size; i++) { + var = sml_ann_variables_list_index(list, i); + if (!strcmp(name, sml_ann_variable_get_name(var))) + return var; + } + return NULL; +} + +static bool +_sml_ann_remove_variable_from_lists(struct sml_ann_engine *ann_engine, + struct sml_variable *var) +{ + if (!_sml_ann_remove_variable_from_sml(ann_engine, var, true)) + return _sml_ann_remove_variable_from_sml(ann_engine, var, false); + return true; +} + +static struct sml_variable * +_sml_ann_add_variable(struct sml_ann_engine *ann_engine, const char *name, + bool input) +{ + struct sml_variable *var; + struct sml_variables_list *list; + unsigned int total; + + if (input) + list = ann_engine->inputs; + else + list = ann_engine->outputs; + + var = sml_ann_variable_new(name, input); + + if (!var) + return NULL; + + total = sml_ann_variables_list_get_length(ann_engine->inputs) + + sml_ann_variables_list_get_length(ann_engine->outputs) + + sol_ptr_vector_get_len(&ann_engine->pending_add) + 1; + if (!_sml_ann_can_alloc_memory_for_observations(total, + ann_engine->required_observations, + ann_engine->engine.obs_max_size) || + sml_ann_variable_realloc_observation_array(var, + ann_engine->required_observations)) { + sml_critical("Could not alloc the observation array!"); + goto err_exit; + } + sml_ann_variable_set_observations_array_index(var, + _sml_ann_get_observations_length(ann_engine)); + + if (!sml_cache_get_size(ann_engine->anns_cache) && + sml_ann_variable_list_add_variable(list, var)) { + sml_critical("Could not add the variable to the list"); + goto err_exit; + } else if (sml_cache_get_size(ann_engine->anns_cache) && + sol_ptr_vector_append(&ann_engine->pending_add, var)) { + sml_critical("Could not add the variable to the add pending list"); + goto err_exit; + } + + return var; +err_exit: + sml_ann_variable_free(var); + return NULL; +} + +static struct sml_ann_bridge * +_sml_ann_new(struct sml_ann_engine *ann_engine, int *error_code) +{ + + if (ann_engine->use_pseudorehearsal && + sml_cache_get_size(ann_engine->anns_cache) == 1) { + sml_debug("Returning previous created ANN - pseudorehearsal"); + return sml_cache_get_element(ann_engine->anns_cache, 0); + } + + sml_debug("Creating a new ANN!"); + struct sml_ann_bridge *iann = sml_ann_bridge_new( + sml_ann_variables_list_get_length(ann_engine->inputs), + sml_ann_variables_list_get_length(ann_engine->outputs), + ann_engine->candidate_groups, + ann_engine->train_epochs, + ann_engine->train_algorithm, + &ann_engine->activation_functions, error_code); + + if (!iann) + return NULL; + + if (!sml_cache_put(ann_engine->anns_cache, iann)) { + sml_ann_bridge_free(iann); + if (error_code) + *error_code = -ENOMEM; + return NULL; + } + return iann; +} + +static int +_sml_ann_change_ann_layout_if_needed(struct sml_ann_engine *ann_engine) +{ + struct sml_ann_bridge *iann; + struct sml_variable *var; + struct sml_variables_list *list; + unsigned int inputs, outputs; + uint16_t i; + bool changed = false; + int error; + + if (!sol_ptr_vector_get_len(&ann_engine->pending_add) && + !sol_ptr_vector_get_len(&ann_engine->pending_remove)) + return 0; + + inputs = sml_ann_variables_list_get_length(ann_engine->inputs); + outputs = sml_ann_variables_list_get_length(ann_engine->outputs); + + /* Check the new number of inputs/outputs */ + SOL_PTR_VECTOR_FOREACH_IDX (&ann_engine->pending_add, var, i) { + if (sml_ann_variable_is_input(var)) { + inputs++; + list = ann_engine->inputs; + sml_debug("Adding input variable"); + } else { + outputs++; + list = ann_engine->outputs; + sml_debug("Adding output variable"); + } + changed = true; + sml_ann_variable_list_add_variable(list, var); + } + + SOL_PTR_VECTOR_FOREACH_IDX (&ann_engine->pending_remove, var, i) { + if (sml_ann_variable_is_input(var)) { + if (inputs > 0) + inputs--; + sml_debug("Removing input variable"); + } else { + if (outputs > 0) + outputs--; + sml_debug("Removing output variable"); + } + changed = true; + _sml_ann_remove_variable_from_lists(ann_engine, var); + } + + sol_ptr_vector_clear(&ann_engine->pending_remove); + sol_ptr_vector_clear(&ann_engine->pending_add); + + if (changed) { + sml_cache_clear(ann_engine->anns_cache); + iann = _sml_ann_new(ann_engine, &error); + if (!iann) { + sml_critical("Could not create a new ANN"); + return error; + } + ann_engine->max_neurons = 0; + if ((error = _sml_ann_train(ann_engine, iann, + ann_engine->required_observations))) + return error; + sml_ann_variables_list_reset_observations(ann_engine->inputs); + sml_ann_variables_list_reset_observations(ann_engine->outputs); + } + return 0; +} + +static int +_sml_ann_alloc_arrays_if_needed(struct sml_ann_engine *ann_engine) +{ + unsigned int inputs, outputs; + int error; + + /* Already allocated */ + if (!ann_engine->first_run) + return 0; + + inputs = sml_ann_variables_list_get_length(ann_engine->inputs); + outputs = sml_ann_variables_list_get_length(ann_engine->outputs); + + while (!_sml_ann_can_alloc_memory_for_observations(inputs + outputs, + ann_engine->required_observations, + ann_engine->engine.obs_max_size)) + ann_engine->required_observations /= 2; + + if (!ann_engine->required_observations) { + sml_critical("Can not alloc %d bytes for observations", + ann_engine->engine.obs_max_size); + return -ENOMEM; + } + + error = sml_ann_variables_list_realloc_observations_array( + ann_engine->inputs, ann_engine->required_observations); + if (error) { + sml_critical("Could not alloc the input observation arrays"); + return error; + } + + error = sml_ann_variables_list_realloc_observations_array( + ann_engine->outputs, ann_engine->required_observations); + if (error) { + sml_critical("Could not alloc the output observation arrays"); + return error; + } + + return 0; +} + +static struct sml_ann_bridge * +_sml_ann_get_best_ann_for_latest_observations(struct sml_ann_engine *ann_engine) +{ + struct sol_ptr_vector *anns; + struct sml_ann_bridge *iann, *best_ann; + unsigned int i; + float sum_iann, sum_best, distance, min; + + anns = sml_cache_get_elements(ann_engine->anns_cache); + best_ann = NULL; + min = FLT_MAX; + sum_best = FLT_MAX; + + sml_debug("Selecting best ANN. Neural networks size: %d", + sol_ptr_vector_get_len(anns)); + + SOL_PTR_VECTOR_FOREACH_IDX (anns, iann, i) { + sml_debug("Neural network:%d", i); + if (!sml_ann_bridge_is_trained(iann)) { + sml_debug("ANN is not trained, skip"); + continue; + } + distance = sml_ann_bridge_confidence_intervals_distance_sum(iann, + ann_engine->inputs); + sml_debug("ANN:%d distance:%f", i, distance); + if (distance < min) { + min = distance; + best_ann = iann; + sum_best = sml_ann_bridge_get_confidence_interval_sum(iann); + } else if (distance == min) { + sum_iann = sml_ann_bridge_get_confidence_interval_sum(iann); + if (sum_iann < sum_best) { + best_ann = iann; + sum_best = sum_iann; + } + } + } + + if (best_ann) + sml_cache_hit(ann_engine->anns_cache, best_ann); + return best_ann; +} + +static void +_sml_ann_engine_free(struct sml_engine *engine) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + uint16_t i; + struct sml_variable *var; + + sml_ann_variable_list_free(ann_engine->inputs, true); + sml_ann_variable_list_free(ann_engine->outputs, true); + + sml_cache_free(ann_engine->anns_cache); + sol_ptr_vector_clear(&ann_engine->pending_remove); + + SOL_PTR_VECTOR_FOREACH_IDX (&ann_engine->pending_add, var, i) + sml_ann_variable_free(var); + + sol_ptr_vector_clear(&ann_engine->pending_add); + sol_vector_clear(&ann_engine->activation_functions); + free(ann_engine); +} + +API_EXPORT bool +sml_ann_set_training_algorithm(struct sml_object *sml, + enum sml_ann_training_algorithm algorithm) +{ + if (!sml_is_ann(sml)) + return false; + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)sml;; + + ann_engine->train_algorithm = algorithm; + return true; +} + +API_EXPORT bool +sml_ann_set_training_epochs(struct sml_object *sml, + unsigned int training_epochs) +{ + if (!sml_is_ann(sml)) + return false; + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)sml;; + + ann_engine->train_epochs = training_epochs; + return true; +} + +API_EXPORT bool +sml_ann_set_desired_error(struct sml_object *sml, float desired_error) +{ + if (!sml_is_ann(sml)) + return false; + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)sml;; + + ann_engine->train_error = desired_error; + return true; +} + +static int +_sml_ann_pseudorehearsal_train(struct sml_ann_engine *ann_engine, + struct sml_ann_bridge *iann) +{ + + int r; + unsigned int total_size, diff, i, j, len, old_size; + struct sml_variable *var; + + len = sml_ann_variables_list_get_length(ann_engine->inputs); + old_size = ann_engine->required_observations; + total_size = ann_engine->required_observations * EXPAND_FACTOR; + diff = total_size - ann_engine->required_observations; + + if (!sml_ann_bridge_is_trained(iann)) { + sml_debug("ANN is not trained yet, training with the usual way"); + return _sml_ann_train(ann_engine, iann, + ann_engine->required_observations); + } + + if (sml_ann_bridge_get_error(iann, ann_engine->inputs, ann_engine->outputs, + ann_engine->required_observations) <= ann_engine->train_error) { + sml_debug("Not retraining the ANN. Error is good enought"); + return 0; + } + + if ((r = sml_ann_variables_list_realloc_observations_array( + ann_engine->inputs, total_size))) { + sml_debug("Could not expand the input array"); + return r; + } + + if ((r = sml_ann_variables_list_realloc_observations_array( + ann_engine->outputs, total_size))) { + sml_debug("Could not expand the output array"); + return r; + } + + //Generate inputs + for (i = 0; i < len; i++) { + var = sml_ann_variables_list_index(ann_engine->inputs, i); + sml_ann_variable_fill_with_random_values(var, diff); + } + + //Predict the outputs + for (i = 0, j = ann_engine->required_observations; i < diff; i++, j++) { + sml_ann_bridge_predict_output_by_index(iann, ann_engine->inputs, + ann_engine->outputs, j); + } + + //Now train! + if ((r = _sml_ann_train(ann_engine, iann, total_size))) { + sml_debug("Could not retrain the ANN!"); + return r; + } + + len = sml_ann_variables_list_get_length(ann_engine->inputs); + for (i = 0; i < len; i++) { + var = sml_ann_variables_list_index(ann_engine->inputs, i); + sml_ann_variable_set_observations_array_index(var, old_size); + } + + //reset values + sml_ann_variables_list_realloc_observations_array(ann_engine->inputs, + old_size); + sml_ann_variables_list_realloc_observations_array(ann_engine->outputs, + old_size); + return 0; +} + +static int +_sml_ann_store_observations(struct sml_ann_engine *ann_engine) +{ + struct sol_ptr_vector *anns; + struct sml_ann_bridge *iann, *to_train; + unsigned int hits, i, input_len; + int r; + bool use_common_pool; + + if (ann_engine->engine.learn_disabled) { + sml_debug("Learn is disabled, not storing values"); + return 0; + } + + use_common_pool = true; + to_train = NULL; + if (!ann_engine->use_pseudorehearsal) { + anns = sml_cache_get_elements(ann_engine->anns_cache); + input_len = sml_ann_variables_list_get_length(ann_engine->inputs); + sml_debug("Total ANNS:%d", sol_ptr_vector_get_len(anns)); + SOL_PTR_VECTOR_FOREACH_IDX (anns, iann, i) { + if (!sml_ann_bridge_is_trained(iann)) { + sml_debug("ANN is not trained, skip"); + to_train = iann; + continue; + } + hits = sml_ann_bridge_inputs_in_confidence_interval_hits(iann, + ann_engine->inputs); + if (hits == input_len) { + use_common_pool = false; + sml_ann_bridge_add_observation(iann, ann_engine->inputs, + ann_engine->outputs); + sml_debug("Adding current observation to ANN:%d", i); + } + } + } + + if (use_common_pool) { + sml_debug("Storing observation in the common pool %d", + _sml_ann_get_observations_length(ann_engine)); + sml_ann_variables_list_add_last_value_to_observation( + ann_engine->inputs); + sml_ann_variables_list_add_last_value_to_observation( + ann_engine->outputs); + + if (_sml_ann_get_observations_length(ann_engine) == + ann_engine->required_observations) { + if (!to_train) { + iann = _sml_ann_new(ann_engine, &r); + if (!iann) { + sml_critical("Could not create a new neural network"); + return r; + } + } else { + iann = to_train; + sml_debug("Trying to train a previous created ANN."); + } + + if (!ann_engine->use_pseudorehearsal) { + if ((r = _sml_ann_train(ann_engine, iann, + ann_engine->required_observations))) { + sml_critical("Could not train the neural network"); + sml_cache_remove(ann_engine->anns_cache, iann); + return r; + } + } else { + if ((r = _sml_ann_pseudorehearsal_train(ann_engine, iann))) { + sml_critical("Could not train the neural network"); + return r; + } + } + + if (sml_ann_bridge_is_trained(iann)) { + sml_debug("ANN is trained, reseting variable observations."); + sml_ann_variables_list_reset_observations(ann_engine->inputs); + sml_ann_variables_list_reset_observations(ann_engine->outputs); + } + } + } + return 0; +} + +static int +_sml_ann_process(struct sml_engine *engine) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + bool r, significant_changes, should_act; + int error = 0; + struct sml_ann_bridge *iann; + struct sml_variables_list *changed; + + if (!ann_engine->engine.read_state_cb) { + sml_critical("There is not read callback registered"); + return -EINVAL; + } + + if ((error = _sml_ann_alloc_arrays_if_needed(ann_engine))) { + sml_critical("Could not alloc observation arrays123! %d", error); + return error; + } + + /* Changes the ANN layout if variables were added/removed */ + if ((error = _sml_ann_change_ann_layout_if_needed(ann_engine))) { + sml_critical("Could not change the ANN layout"); + return error; + } + + if (!ann_engine->engine.read_state_cb( + (struct sml_object *)&ann_engine->engine, + ann_engine->engine.read_state_cb_data)) { + sml_debug("Read cb returned false"); + return -EAGAIN; + } + + should_act = false; + if (ann_engine->first_run) { + sml_ann_variables_list_set_current_value_as_stable( + ann_engine->inputs); + sml_ann_variables_list_set_current_value_as_stable( + ann_engine->outputs); + ann_engine->first_run = false; + } else { + significant_changes = + _sml_ann_variable_list_has_significant_changes(ann_engine->inputs); + if (significant_changes) + ann_engine->engine.output_state_changed_called = false; + significant_changes |= + _sml_ann_variable_list_has_significant_changes(ann_engine->outputs); + if (significant_changes) { + ann_engine->engine.hits = 0; + sml_ann_variables_list_set_current_value_as_stable( + ann_engine->inputs); + sml_ann_variables_list_set_current_value_as_stable( + ann_engine->outputs); + } + } + + if (ann_engine->engine.hits == ann_engine->engine.stabilization_hits) { + ann_engine->engine.hits = 0; + should_act = true; + _sml_ann_store_observations(ann_engine); + sml_debug("Reads are stabilized!"); + } else + ann_engine->engine.hits++; + + if (ann_engine->engine.output_state_changed_cb && + should_act && !ann_engine->engine.output_state_changed_called) { + + if (!ann_engine->use_pseudorehearsal) + iann = _sml_ann_get_best_ann_for_latest_observations(ann_engine); + else + iann = sml_cache_get_element(ann_engine->anns_cache, 0); + + if (iann && sml_ann_bridge_is_trained(iann)) { + sml_debug("Trying to predict output"); + r = sml_ann_bridge_predict_output(iann, ann_engine->inputs, + ann_engine->outputs); + if (r) { + changed = _sml_ann_output_has_significant_changes( + ann_engine->outputs); + if (changed && sml_ann_variables_list_get_length(changed)) { + ann_engine->engine.output_state_changed_cb( + (struct sml_object *)&ann_engine->engine, changed, + ann_engine->engine.output_state_changed_cb_data); + if (should_act) + ann_engine->engine.output_state_changed_called = true; + } else + sml_debug("Not calling changed cb."); + if (changed) + sml_ann_variable_list_free(changed, false); + } else + sml_critical("Could not predict the output"); + } else + sml_critical("Could not select the best ann"); + } + + return error; +} + +static bool +_sml_ann_predict(struct sml_engine *engine) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + struct sml_ann_bridge *iann; + + if (!ann_engine->use_pseudorehearsal) + iann = _sml_ann_get_best_ann_for_latest_observations(ann_engine); + else + iann = sml_cache_get_element(ann_engine->anns_cache, 0); + + if (!iann || !sml_ann_bridge_is_trained(iann)) { + sml_critical("Could not select the best ann"); + return false; + } + + if (!sml_ann_bridge_predict_output(iann, ann_engine->inputs, + ann_engine->outputs)) { + sml_critical("Could not predict the output"); + return false; + } + + return true; +} + +static bool +_sml_ann_save(struct sml_engine *engine, const char *path) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + struct sml_ann_bridge *iann; + char ann_path[SML_PATH_MAX], cfg_path[SML_PATH_MAX]; + struct sol_ptr_vector *anns; + uint16_t i, ann_idx; + + if (!sml_cache_get_size(ann_engine->anns_cache)) { + sml_critical("Could not save the neural network." \ + "The neural network is NULL"); + return false; + } + + if (!is_dir(path)) { + sml_critical("Failed to save sml: %s is not a directory\n", path); + return false; + } + + if (!clean_dir(path, ANN_FILE_PREFIX) || + !clean_dir(path, CFG_FILE_PREFIX)) { + sml_critical("Failed to clearn %s to save sml\n", path); + return false; + } + + if (ann_engine->use_pseudorehearsal) { + snprintf(ann_path, sizeof(ann_path), "%s/%s.%s", path, + ANN_PSEUDOREHEARSAL_PREFIX, ANN_FILE_EXTENSION); + iann = sml_cache_get_element(ann_engine->anns_cache, 0); + if (iann && sml_ann_bridge_is_trained(iann)) { + if (!sml_ann_bridge_save_with_no_cfg(iann, ann_path)) { + sml_critical("Could not save the ANN at:%s", ann_path); + return false; + } + } else + sml_debug("Not saving ANN. Not trained or does not exist yet."); + } else { + anns = sml_cache_get_elements(ann_engine->anns_cache); + ann_idx = 0; + SOL_PTR_VECTOR_FOREACH_IDX (anns, iann, i) { + if (!sml_ann_bridge_is_trained(iann)) { + sml_debug("Not saving untrained ANN."); + continue; + } + snprintf(ann_path, sizeof(ann_path), "%s/%s%d.%s", + path, ANN_FILE_PREFIX, ann_idx, ANN_FILE_EXTENSION); + snprintf(cfg_path, sizeof(cfg_path), "%s/%s%d.%s", + path, CFG_FILE_PREFIX, ann_idx, CFG_FILE_EXTENSION); + ann_idx++; + if (!sml_ann_bridge_save(iann, ann_path, cfg_path)) { + sml_critical("Could not save the neural network at:%s", path); + continue; + } + } + } + sml_debug("Neural network saved at:%s", path); + return true; +} + +API_EXPORT bool +sml_ann_set_activation_function_candidates(struct sml_object *sml, + enum sml_ann_activation_function *functions, + unsigned int size) +{ + if (!sml_is_ann(sml)) + return false; + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)sml;; + unsigned int i; + enum sml_ann_activation_function *func; + + for (i = 0; i < size; i++) { + func = sol_vector_append(&ann_engine->activation_functions); + if (!func) { + sml_critical("Could append an activation function"); + continue; + } + *func = functions[i]; + } + return true; +} + +API_EXPORT bool +sml_ann_set_max_neurons(struct sml_object *sml, unsigned int max_neurons) +{ + if (!sml_is_ann(sml)) + return false; + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)sml;; + + ann_engine->max_neurons = max_neurons; + return true; +} + +API_EXPORT bool +sml_ann_set_candidate_groups(struct sml_object *sml, + unsigned int candidate_groups) +{ + if (!sml_is_ann(sml)) + return false; + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)sml;; + + ann_engine->candidate_groups = candidate_groups; + return true; +} + +static bool +_sml_ann_load(struct sml_engine *engine, const char *path) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + struct sml_ann_bridge *iann; + char ann_path[SML_PATH_MAX], cfg_path[SML_PATH_MAX]; + unsigned int i = 0; + + if (sml_cache_get_size(ann_engine->anns_cache)) { + sml_cache_clear(ann_engine->anns_cache); + sml_warning("Destroying a previously created neural network"); + } + + if (!is_dir(path)) { + sml_critical("Failed to load sml in directory %s\n", path); + return false; + } + + if (ann_engine->use_pseudorehearsal) { + snprintf(ann_path, sizeof(ann_path), "%s/%s.%s", path, + ANN_PSEUDOREHEARSAL_PREFIX, ANN_FILE_EXTENSION); + iann = sml_ann_bridge_load_from_file_with_no_cfg(ann_path); + if (!iann) { + sml_critical("Could not load the ann at:%s", ann_path); + return false; + } + if (!sml_cache_put(ann_engine->anns_cache, iann)) { + sml_critical( + "Could not add the struct sml_ann_bridge to the cache"); + sml_ann_bridge_free(iann); + return false; + } + } else { + while (1) { + snprintf(ann_path, sizeof(ann_path), "%s/%s%d.%s", path, + ANN_FILE_PREFIX, i, ANN_FILE_EXTENSION); + snprintf(cfg_path, sizeof(cfg_path), "%s/%s%d.%s", + path, CFG_FILE_PREFIX, i, CFG_FILE_EXTENSION); + if (!is_file(ann_path)) { + sml_warning("The path:%s is not an ANN file", ann_path); + break; + } else if (!is_file(cfg_path)) { + sml_warning("The path:%s is not a cfg file", + cfg_path); + break; + } + + iann = sml_ann_bridge_load_from_file(ann_path, cfg_path); + if (!iann) + break; + if (!sml_cache_put(ann_engine->anns_cache, iann)) { + sml_ann_bridge_free(iann); + sml_cache_clear(ann_engine->anns_cache); + return false; + } + i++; + } + } + sml_debug("Neural network loaded"); + return true; +} + +static struct sml_variable * +_sml_ann_new_input(struct sml_engine *engine, const char *name) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + + return _sml_ann_add_variable(ann_engine, name, true); +} + +static struct sml_variable * +_sml_ann_new_output(struct sml_engine *engine, const char *name) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + + return _sml_ann_add_variable(ann_engine, name, false); +} + +static bool +_sml_ann_remove_variable(struct sml_engine *engine, struct sml_variable *var) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + + if (sml_cache_get_size(ann_engine->anns_cache)) { + if (sol_ptr_vector_append(&ann_engine->pending_remove, var)) { + sml_critical("Could not add the variable to the pending remove" \ + " list"); + return false; + } + return true; + } + return _sml_ann_remove_variable_from_lists(ann_engine, var); +} + +static struct sml_variable * +_sml_ann_get_input(struct sml_engine *engine, const char *name) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + + return _sml_ann_find_variable_by_name(ann_engine, name, true); +} + +static struct sml_variable * +_sml_ann_get_output(struct sml_engine *engine, const char *name) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + + return _sml_ann_find_variable_by_name(ann_engine, name, false); +} + +static struct sml_variables_list * +_sml_ann_get_input_list(struct sml_engine *engine) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + + return ann_engine->inputs; +} + +static struct sml_variables_list * +_sml_ann_get_output_list(struct sml_engine *engine) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + + return ann_engine->outputs; +} + +static int +_sml_ann_variable_set_enabled(struct sml_engine *engine, + struct sml_variable *var, bool enabled) +{ + return sml_ann_variable_set_enabled(var, enabled); +} + +static void +_sml_ann_print_variables_list(struct sml_variables_list *list) +{ + uint16_t i, len; + struct sml_variable *var; + + len = sml_ann_variables_list_get_length(list); + for (i = 0; i < len; i++) { + var = sml_ann_variables_list_index(list, i); + sml_debug("\t%s: %g", sml_ann_variable_get_name(var), + sml_ann_variable_get_value(var)); + } +} + +static void +_sml_ann_print_debug(struct sml_engine *engine, bool full) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)engine; + struct sol_ptr_vector *elems; + struct sml_ann_bridge *ann; + uint16_t i; + + sml_debug("Inputs (%d) {", + sml_ann_variables_list_get_length(ann_engine->inputs)); + _sml_ann_print_variables_list(ann_engine->inputs); + sml_debug("}"); + sml_debug("Outputs (%d) {", + sml_ann_variables_list_get_length(ann_engine->outputs)); + _sml_ann_print_variables_list(ann_engine->outputs); + sml_debug("}"); + + if (full) { + sml_debug("Required observations: %d", + ann_engine->required_observations); + sml_debug("Train epochs: %d", ann_engine->train_epochs); + sml_debug("Train error: %g", ann_engine->train_error); + sml_debug("Max neurons: %d", ann_engine->max_neurons); + sml_debug("Candidate groups: %d", ann_engine->candidate_groups); + sml_debug("Observations max size: %d", + ann_engine->engine.obs_max_size); + + sml_debug("ANNs (%d) {", + sml_cache_get_size(ann_engine->anns_cache)); + elems = sml_cache_get_elements(ann_engine->anns_cache); + SOL_PTR_VECTOR_FOREACH_IDX (elems, ann, i) { + sml_debug("{"); + sml_ann_bridge_print_debug(ann); + sml_debug("}"); + } + sml_debug("}"); +#ifdef Debug + sml_debug("Total ANNs created: (%d)", + sml_cache_get_total_elements_inserted(ann_engine->anns_cache)); +#endif + } +} + +static void +_sml_ann_cache_element_free(void *element, void *data) +{ + sml_ann_bridge_free(element); +} + +API_EXPORT struct sml_object * +sml_ann_new(void) +{ + struct sml_ann_engine *ann_engine = calloc(1, + sizeof(struct sml_ann_engine)); + + if (!ann_engine) { + sml_critical("Could not create a sml"); + return NULL; + } + ann_engine->inputs = sml_ann_variable_list_new(); + + if (!ann_engine->inputs) { + sml_critical("Could not create the input variable list"); + goto err_inputs; + } + ann_engine->outputs = sml_ann_variable_list_new(); + if (!ann_engine->outputs) { + sml_critical("Could not create the output variable list"); + goto err_outputs; + } + + ann_engine->anns_cache = sml_cache_new(DEFAULT_CACHE_SIZE, + _sml_ann_cache_element_free, NULL); + + if (!ann_engine->anns_cache) { + sml_critical("Could not create the ANN cache"); + goto err_cache; + } + + ann_engine->train_algorithm = SML_ANN_TRAINING_ALGORITHM_QUICKPROP; + ann_engine->train_epochs = DEFAULT_EPOCHS; + ann_engine->train_error = DEFAULT_DESIRED_ERROR; + ann_engine->candidate_groups = DEFAULT_CANDIDATE_GROUPS; + ann_engine->required_observations = INITIAL_REQUIRED_OBSERVATIONS; + ann_engine->first_run = true; + ann_engine->use_pseudorehearsal = true; + sol_vector_init(&ann_engine->activation_functions, + sizeof(enum sml_ann_activation_function)); + sol_ptr_vector_init(&ann_engine->pending_remove); + sol_ptr_vector_init(&ann_engine->pending_add); + + ann_engine->engine.free = _sml_ann_engine_free; + ann_engine->engine.process = _sml_ann_process; + ann_engine->engine.predict = _sml_ann_predict; + ann_engine->engine.save = _sml_ann_save; + ann_engine->engine.load = _sml_ann_load; + ann_engine->engine.get_input_list = _sml_ann_get_input_list; + ann_engine->engine.get_output_list = _sml_ann_get_output_list; + ann_engine->engine.new_input = _sml_ann_new_input; + ann_engine->engine.new_output = _sml_ann_new_output; + ann_engine->engine.get_input = _sml_ann_get_input; + ann_engine->engine.get_output = _sml_ann_get_output; + ann_engine->engine.get_name = sml_ann_variable_get_name; + ann_engine->engine.set_value = sml_ann_variable_set_value; + ann_engine->engine.get_value = sml_ann_variable_get_value; + ann_engine->engine.variable_set_enabled = _sml_ann_variable_set_enabled; + ann_engine->engine.variable_is_enabled = sml_ann_variable_is_enabled; + ann_engine->engine.remove_variable = _sml_ann_remove_variable; + ann_engine->engine.variables_list_get_length = + sml_ann_variables_list_get_length; + ann_engine->engine.variables_list_index = sml_ann_variables_list_index; + ann_engine->engine.variable_set_range = sml_ann_variable_set_range; + ann_engine->engine.variable_get_range = sml_ann_variable_get_range; + ann_engine->engine.print_debug = _sml_ann_print_debug; + ann_engine->engine.magic_number = ANN_MAGIC; + + return (struct sml_object *)&ann_engine->engine; +err_cache: + sml_ann_variable_list_free(ann_engine->outputs, true); +err_outputs: + sml_ann_variable_list_free(ann_engine->inputs, true); +err_inputs: + free(ann_engine); + return NULL; +} + +API_EXPORT bool +sml_is_ann(struct sml_object *sml) +{ + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)sml; + + ON_NULL_RETURN_VAL(sml, false); + return ann_engine->engine.magic_number == ANN_MAGIC; +} + +API_EXPORT bool +sml_ann_supported(void) +{ + return true; +} + +API_EXPORT bool +sml_ann_set_cache_max_size(struct sml_object *sml, unsigned int max_size) +{ + if (!sml_is_ann(sml)) + return false; + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)sml; + sml_debug("Setting ann cache to max size:%d", max_size); + return sml_cache_set_max_size(ann_engine->anns_cache, max_size); +} + +API_EXPORT bool +sml_ann_set_initial_required_observations(struct sml_object *sml, + unsigned int required_observations) +{ + if (!sml_is_ann(sml)) + return false; + + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)sml; + if (!ann_engine->first_run) { + sml_warning("Initial required observation must be set before first call" + " of sml_process"); + return false; + } + ann_engine->required_observations = required_observations; + return true; +} + +API_EXPORT bool +sml_ann_use_pseudorehearsal_strategy(struct sml_object *sml, + bool use_pseudorehearsal) +{ + if (!sml_is_ann(sml)) + return false; + + struct sml_ann_engine *ann_engine = (struct sml_ann_engine *)sml; + if (!ann_engine->first_run) { + sml_warning("Pseudorehearsal strategy can only be set before the first" + " call of sml_process"); + return false; + } + ann_engine->use_pseudorehearsal = use_pseudorehearsal; + return true; +} diff --git a/sml/sml_ann/src/sml_ann_bridge.c b/sml/sml_ann/src/sml_ann_bridge.c new file mode 100644 index 0000000..75f0502 --- /dev/null +++ b/sml/sml_ann/src/sml_ann_bridge.c @@ -0,0 +1,849 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sml_ann_bridge.h" +#include "sml_ann_variable_list.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define REPORTS_BETWEEN_EPOCHS (100) +#define MAX_NEURONS_MULTIPLIER (5) +#define MAX_EPOCHS (500) + +struct sml_ann_bridge { + bool trained; + float last_train_error; + struct fann *ann; + struct sol_vector confidence_intervals; + struct fann_train_data *observations; + unsigned int required_observations; + unsigned int observation_idx; + unsigned int max_neurons; + + float ci_length_sum; +}; + +typedef struct _Confidence_Interval { + float lower_limit; + float upper_limit; +} Confidence_Interval; + +static struct sml_ann_bridge * +_sml_ann_bridge_new(struct fann *ann, bool trained) +{ + struct sml_ann_bridge *iann = calloc(1, sizeof(struct sml_ann_bridge)); + + if (!iann) { + sml_critical("Could not create an struct sml_ann_bridge"); + return NULL; + } + sol_vector_init(&iann->confidence_intervals, sizeof(Confidence_Interval)); + iann->ann = ann; + iann->trained = trained; + iann->last_train_error = NAN; + return iann; +} + +static float +_sml_ann_bridge_get_variable_value(struct sml_variables_list *list, + uint16_t i, bool scale) +{ + struct sml_variable *var = sml_ann_variables_list_index(list, i); + float v = sml_ann_variable_get_value(var); + + if (isnan(v)) + sml_ann_variable_get_range(var, &v, NULL); + if (scale) + return sml_ann_variable_scale_value(var, v); + return v; +} + +static bool +_sml_ann_bridge_calculate_confidence_interval(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs, + unsigned int observations) +{ + unsigned int i, j, inputs_len; + float mean, sd, value; + struct sml_variable *var; + Confidence_Interval *ci; + + sml_debug("Calculating confidence interval"); + inputs_len = sml_ann_variables_list_get_length(inputs); + for (i = 0; i < inputs_len; i++) { + mean = sd = 0.0; + var = sml_ann_variables_list_index(inputs, i); + ci = sol_vector_append(&iann->confidence_intervals); + if (!ci) { + sml_critical("Could not alloc the Confidence_Interval"); + goto err_exit; + } + + for (j = 0; j < observations; j++) { + value = sml_ann_variable_get_value_by_index(var, j); + if (isnan(value)) + sml_ann_variable_get_range(var, &value, NULL); + mean += value; + } + mean /= observations; + + //Now the standard deviation + for (j = 0; j < observations; j++) { + value = sml_ann_variable_get_value_by_index(var, j); + if (isnan(value)) + sml_ann_variable_get_range(var, &value, NULL); + sd += pow(value - mean, 2.0); + } + sd /= observations; + sd = sqrt(sd); + + //Confidence interval of 95% + ci->lower_limit = mean - (1.96 * (sd / sqrt(observations))); + ci->upper_limit = mean + (1.96 * (sd / sqrt(observations))); + iann->ci_length_sum += (ci->upper_limit - ci->lower_limit); + sml_debug("Variable:%s mean:%f sd:%f lower:%f upper:%f", + sml_ann_variable_get_name(var), mean, sd, ci->lower_limit, + ci->upper_limit); + } + + return true; +err_exit: + sol_vector_clear(&iann->confidence_intervals); + return false; +} + +static enum fann_activationfunc_enum +_sml_ann_bridge_translate_to_fann_activation_func( + enum sml_ann_activation_function activation) +{ + switch (activation) { + case SML_ANN_ACTIVATION_FUNCTION_SIGMOID: + return FANN_SIGMOID; + case SML_ANN_ACTIVATION_FUNCTION_SIGMOID_SYMMETRIC: + return FANN_SIGMOID_SYMMETRIC; + case SML_ANN_ACTIVATION_FUNCTION_GAUSSIAN: + return FANN_GAUSSIAN; + case SML_ANN_ACTIVATION_FUNCTION_GAUSSIAN_SYMMETRIC: + return FANN_GAUSSIAN_SYMMETRIC; + case SML_ANN_ACTIVATION_FUNCTION_ELLIOT: + return FANN_ELLIOT; + case SML_ANN_ACTIVATION_FUNCTION_ELLIOT_SYMMETRIC: + return FANN_ELLIOT_SYMMETRIC; + case SML_ANN_ACTIVATION_FUNCTION_COS: + return FANN_COS; + case SML_ANN_ACTIVATION_FUNCTION_COS_SYMMETRIC: + return FANN_COS_SYMMETRIC; + case SML_ANN_ACTIVATION_FUNCTION_SIN: + return FANN_SIN; + default: + return FANN_SIN_SYMMETRIC; + } +} + +static enum fann_train_enum +_sml_ann_bridge_translate_to_fann_train_enum( + enum sml_ann_training_algorithm train) +{ + switch (train) { + case SML_ANN_TRAINING_ALGORITHM_QUICKPROP: + return FANN_TRAIN_QUICKPROP; + default: + return FANN_TRAIN_RPROP; + } +} + +static bool +_sml_ann_bridge_translate_to_fann_activation_vector( + struct sol_vector *sml_funcs, struct sol_vector *fann_funcs) +{ + uint16_t i; + enum sml_ann_activation_function *sml_func; + enum fann_activationfunc_enum *fann_func; + + SOL_VECTOR_FOREACH_IDX (sml_funcs, sml_func, i) { + fann_func = sol_vector_append(fann_funcs); + if (!fann_func) + return false; + *fann_func = _sml_ann_bridge_translate_to_fann_activation_func( + *sml_func); + } + return true; +} + +static void +_sml_ann_bridge_fill_train_data_array(struct sml_variables_list *inputs, + struct sml_variables_list *outputs, + struct fann_train_data *train_data, + unsigned int observations) +{ + uint16_t i, j, size; + struct sml_variable *var; + float value, min; + + size = sml_ann_variables_list_get_length(inputs); + for (i = 0; i < size; i++) { + var = sml_ann_variables_list_index(inputs, i); + for (j = 0; j < observations; j++) { + value = sml_ann_variable_get_value_by_index(var, j); + if (isnan(value) || !sml_ann_variable_is_enabled(var)) { + sml_ann_variable_get_range(var, &min, NULL); + value = min; + } + train_data->input[j][i] = + sml_ann_variable_scale_value(var, value); + } + } + + size = sml_ann_variables_list_get_length(outputs); + for (i = 0; i < size; i++) { + var = sml_ann_variables_list_index(outputs, i); + for (j = 0; j < observations; j++) { + value = sml_ann_variable_get_value_by_index(var, j); + if (isnan(value) || !sml_ann_variable_is_enabled(var)) { + sml_ann_variable_get_range(var, &min, NULL); + value = min; + } + train_data->output[j][i] = + sml_ann_variable_scale_value(var, value); + } + } +} + +static int +_sml_really_train(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs, + struct sml_variables_list *outputs, + float *err, unsigned int required_observations, + unsigned int max_neurons, + float desired_train_error) +{ + + struct fann_train_data *train_data; + unsigned int in_size, out_size; + float train_error; + + fann_randomize_weights(iann->ann, -0.2, 0.2); + + in_size = sml_ann_variables_list_get_length(inputs); + out_size = sml_ann_variables_list_get_length(outputs); + + train_data = fann_create_train(required_observations, in_size, + out_size); + if (!train_data) { + sml_critical("Could not create the train data"); + return -ENOMEM; + } + + _sml_ann_bridge_fill_train_data_array(inputs, outputs, train_data, + required_observations); + + sml_debug("Observations size: %d", required_observations); + + if (!max_neurons) + max_neurons = (in_size + out_size) + + ((in_size + out_size) * MAX_NEURONS_MULTIPLIER); + iann->max_neurons = max_neurons; + fann_shuffle_train_data(train_data); + if (!iann->trained) { + fann_cascadetrain_on_data(iann->ann, train_data, + max_neurons, + REPORTS_BETWEEN_EPOCHS, desired_train_error); + } else { + fann_set_training_algorithm(iann->ann, FANN_TRAIN_INCREMENTAL); + fann_train_on_data(iann->ann, train_data, MAX_EPOCHS, + REPORTS_BETWEEN_EPOCHS, desired_train_error); + } + + train_error = fann_get_MSE(iann->ann); + sml_debug("MSE error on test data: %f\n", train_error); + fann_destroy_train(train_data); + *err = train_error; + return 0; +} + +static int +_sml_ann_bridge_setup_ci_and_observations(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs, + unsigned int required_observations, + bool use_pseudorehearsal) +{ + if (use_pseudorehearsal) + return 0; + + if (!_sml_ann_bridge_calculate_confidence_interval(iann, inputs, + required_observations)) + return -ENOMEM; + + iann->required_observations = required_observations; + iann->observations = + fann_create_train(iann->required_observations, + fann_get_num_input(iann->ann), + fann_get_num_output(iann->ann)); + if (!iann->observations) { + sml_critical("Could not create the observations array for" \ + " retraining"); + return -ENOMEM; + } + return 0; +} + +int +sml_ann_bridge_train(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs, + struct sml_variables_list *outputs, float desired_train_error, + unsigned int required_observations, + unsigned int max_neurons, + unsigned int *required_observations_suggestion, + bool use_pseudorehearsal) +{ + float train_error; + int error; + + if ((error = _sml_really_train(iann, inputs, outputs, &train_error, + required_observations, max_neurons, + desired_train_error))) + return error; + + if (train_error <= desired_train_error) { + iann->trained = true; + sml_debug("Error is good enough. Desired:%f current error:%f", + desired_train_error, train_error); + } else if (!isnan(iann->last_train_error) && + iann->last_train_error < train_error) { + /* Less data gave us better results, stop trying to increase + the required number of observations. */ + required_observations /= 2; + iann->trained = true; + sml_debug("Decreasing the observations data set. Current error:%f" \ + " last error:%f", train_error, + iann->last_train_error); + } else { + required_observations *= 2; + sml_debug("We still need more that to train the ann. Current" \ + " error:%f desired error:%f", train_error, + desired_train_error); + + } + iann->last_train_error = train_error; + + if (required_observations_suggestion) + *required_observations_suggestion = required_observations; + if (iann->trained) + error = _sml_ann_bridge_setup_ci_and_observations(iann, inputs, + required_observations, + use_pseudorehearsal); + return error; +} + +unsigned int +sml_ann_bridge_inputs_in_confidence_interval_hits(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs) +{ + unsigned int hits = 0; + uint16_t i, len; + Confidence_Interval *ci; + float v; + + len = sml_ann_variables_list_get_length(inputs); + for (i = 0; i < len; i++) { + v = _sml_ann_bridge_get_variable_value(inputs, i, false); + ci = sol_vector_get(&iann->confidence_intervals, i); + if (!ci) { + sml_debug("Confidence interval for idx:%d is NULL!", i); + continue; + } + sml_debug("variable:%s value:%f lower:%f upper:%f", + sml_ann_variable_get_name( + sml_ann_variables_list_index(inputs, i)), + v, ci->lower_limit, ci->upper_limit); + if (v >= ci->lower_limit && v <= ci->upper_limit) + hits++; + } + return hits; +} + +float +sml_ann_bridge_confidence_intervals_distance_sum(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs) +{ + Confidence_Interval *ci; + uint16_t i, len; + float v, distance = 0.0; + + len = sml_ann_variables_list_get_length(inputs); + for (i = 0; i < len; i++) { + v = _sml_ann_bridge_get_variable_value(inputs, i, false); + ci = sol_vector_get(&iann->confidence_intervals, i); + if (v < ci->lower_limit) + distance += fabsf(ci->lower_limit - v); + else if (v > ci->upper_limit) + distance += fabsf(ci->upper_limit - v); + sml_debug("variable:%s value:%f lower:%f upper:%f distance:%f", + sml_ann_variable_get_name( + sml_ann_variables_list_index(inputs, i)), + v, ci->lower_limit, ci->upper_limit, distance); + } + return distance; +} + +void +sml_ann_bridge_add_observation(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs, + struct sml_variables_list *outputs) +{ + uint16_t i, len; + + if (!iann->observations) { + sml_warning("The bridge observation vector is not created"); + return; + } + + len = sml_ann_variables_list_get_length(inputs); + for (i = 0; i < len; i++) + iann->observations->input[iann->observation_idx][i] = + _sml_ann_bridge_get_variable_value(inputs, i, true); + + len = sml_ann_variables_list_get_length(outputs); + for (i = 0; i < len; i++) + iann->observations->output[iann->observation_idx][i] = + _sml_ann_bridge_get_variable_value(outputs, i, true); + + iann->observation_idx++; + sml_debug("ANN:%p observation_idx:%d", iann, iann->observation_idx); + if (iann->observation_idx == iann->required_observations) { + sml_debug("Retraining the ANN !"); + fann_cascadetrain_on_data(iann->ann, iann->observations, + iann->max_neurons, + REPORTS_BETWEEN_EPOCHS, + iann->last_train_error); + iann->observation_idx = 0; + } +} + +float +sml_ann_bridge_get_confidence_interval_sum(struct sml_ann_bridge *iann) +{ + return iann->ci_length_sum; +} + +int +sml_ann_bridge_consider_trained(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs, + unsigned int observations, + bool use_pseudorehearsal) +{ + int error = _sml_ann_bridge_setup_ci_and_observations(iann, inputs, + observations, + use_pseudorehearsal); + + if (error != 0) + return error; + iann->trained = true; + return 0; +} + +static bool +_sml_ann_bridge_really_predict_output(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs, + struct sml_variables_list *outputs, + unsigned int idx, + bool set_current_value) +{ + uint16_t size, i; + fann_type *out, *in; + struct sml_variable *var; + float value; + bool r = false; + + size = sml_ann_variables_list_get_length(inputs); + in = malloc(sizeof(fann_type) * size); + + if (!in) { + sml_critical("Could not alloc fann input vector"); + return r; + } + + for (i = 0; i < size; i++) { + var = sml_ann_variables_list_index(inputs, i); + if (!set_current_value) + value = sml_ann_variable_get_value_by_index(var, idx); + else //the last observation + value = sml_ann_variable_get_value(var); + if (isnan(value)) + sml_ann_variable_get_range(var, &value, NULL); + in[i] = sml_ann_variable_scale_value(var, value); + } + + out = fann_run(iann->ann, in); + + if (out) { + size = sml_ann_variables_list_get_length(outputs); + + for (i = 0; i < size; i++) { + var = sml_ann_variables_list_index(outputs, i); + + if (isnan(out[i])) + sml_ann_variable_get_range(var, &value, NULL); + else + value = sml_ann_variable_descale_value(var, out[i]); + + if (!set_current_value) + sml_ann_variable_set_value_by_index(var, value, idx); + else + sml_ann_variable_set_value(var, value); + sml_debug("Predicted value:%f current value:%f variable:%s", value, + sml_ann_variable_get_previous_value(var), + sml_ann_variable_get_name(var)); + } + r = true; + } else + sml_critical("fann_run() returned NULL!"); + free(in); + return r; +} + +bool +sml_ann_bridge_predict_output_by_index(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs, + struct sml_variables_list *outputs, + unsigned int idx) +{ + return _sml_ann_bridge_really_predict_output(iann, inputs, outputs, idx, + false); +} + +bool +sml_ann_bridge_predict_output(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs, struct sml_variables_list *outputs) +{ + return _sml_ann_bridge_really_predict_output(iann, inputs, outputs, 0, + true); +} + +void +sml_ann_bridge_free(struct sml_ann_bridge *iann) +{ + fann_destroy_train(iann->observations); + fann_destroy(iann->ann); + sol_vector_clear(&iann->confidence_intervals); + free(iann); +} + +bool +sml_ann_bridge_is_trained(struct sml_ann_bridge *iann) +{ + return iann->trained; +} + +struct sml_ann_bridge * +sml_ann_bridge_new(unsigned int inputs, unsigned int outputs, + unsigned int candidate_groups, unsigned int epochs, + enum sml_ann_training_algorithm train_algorithm, + struct sol_vector *activation_functions, int *error_code) +{ + struct fann *ann; + struct sml_ann_bridge *iann; + struct sol_vector fann_funcs; + bool err; + + if (!inputs || !outputs) { + sml_critical("Inputs/Outputs size. Inputs:%d Outputs:%d", inputs, + outputs); + if (error_code) + *error_code = -EINVAL; + return NULL; + } + + ann = fann_create_shortcut(2, inputs, outputs); + + if (!ann) { + sml_critical("Could not create the neural network"); + if (error_code) + *error_code = -ENOMEM; + return NULL; + } + + /* These activation functions might change during the cascade training. */ + fann_set_activation_function_hidden(ann, FANN_SIGMOID_SYMMETRIC); + fann_set_activation_function_output(ann, FANN_SIGMOID_SYMMETRIC); + fann_set_training_algorithm(ann, + _sml_ann_bridge_translate_to_fann_train_enum( + train_algorithm)); + fann_set_train_error_function(ann, FANN_ERRORFUNC_LINEAR); + + if (activation_functions->len) { + sol_vector_init(&fann_funcs, sizeof(enum fann_activationfunc_enum)); + err = _sml_ann_bridge_translate_to_fann_activation_vector( + activation_functions, &fann_funcs); + if (!err) { + sml_critical("Could not convert to activation functions to " \ + "fann enum"); + goto err_exit; + } + fann_set_cascade_activation_functions(ann, + fann_funcs.data, + fann_funcs.len); + sol_vector_clear(&fann_funcs); + } + + fann_set_cascade_max_cand_epochs(ann, epochs); + fann_set_cascade_max_out_epochs(ann, epochs); + fann_set_cascade_num_candidate_groups(ann, candidate_groups); + + iann = _sml_ann_bridge_new(ann, false); + if (!iann) + goto err_exit; + return iann; +err_exit: + fann_destroy(ann); + if (error_code) + *error_code = ENOMEM; + return NULL; +} + +bool +sml_ann_bridge_save_with_no_cfg(struct sml_ann_bridge *iann, + const char *ann_path) +{ + sml_debug("Saving ann at:%s", ann_path); + if (fann_save(iann->ann, ann_path) < 0) { + sml_critical("Could not save the ANN at:%s", ann_path); + return false; + } + return true; +} + +struct sml_ann_bridge * +sml_ann_bridge_load_from_file_with_no_cfg(const char *ann_path) +{ + struct fann *ann; + struct sml_ann_bridge *iann; + + ann = fann_create_from_file(ann_path); + + if (!ann) { + sml_critical("Could not load the ann from path:%s", ann_path); + return NULL; + } + + iann = _sml_ann_bridge_new(ann, true); + if (!iann) { + sml_critical("Could not create an struct sml_ann_bridge"); + fann_destroy(ann); + return NULL; + } + return iann; +} + +bool +sml_ann_bridge_save(struct sml_ann_bridge *iann, const char *ann_path, + const char *cfg_path) +{ + uint16_t i; + Confidence_Interval *ci; + FILE *f; + bool r = false; + + sml_debug("Saving ann at:%s and CFGs at:%s", ann_path, cfg_path); + if (fann_save(iann->ann, ann_path) < 0) + return false; + + f = fopen(cfg_path, "wb"); + if (!f) { + sml_critical("Could not create the confidence intervals file"); + return false; + } + + if (fwrite(&iann->confidence_intervals.len, sizeof(uint16_t), 1, f) < 1) { + sml_critical("Could not write the confidence intervals len"); + goto exit; + } + + SOL_VECTOR_FOREACH_IDX (&iann->confidence_intervals, ci, i) { + if (fwrite(&ci->lower_limit, sizeof(float), 1, f) < 1) { + sml_critical("Could not save the lower limit"); + goto exit; + } + if (fwrite(&ci->upper_limit, sizeof(float), 1, f) < 1) { + sml_critical("Could not save the upper limit"); + goto exit; + } + } + + if (fwrite(&iann->max_neurons, sizeof(unsigned int), 1, f) < 1) { + sml_critical("Could not save the max neurons"); + goto exit; + } + + if (fwrite(&iann->required_observations, sizeof(unsigned int), 1, f) < 1) { + sml_critical("Could not save the required observations"); + goto exit; + } + + r = true; +exit: + if (fclose(f) == EOF) { + sml_critical("Could not correctly close the confidence intervals file"); + r = false; + } + if (!r) { + delete_file(ann_path); + delete_file(cfg_path); + } + return r; +} + +struct sml_ann_bridge * +sml_ann_bridge_load_from_file(const char *ann_path, const char *cfg_path) +{ + struct fann *ann; + struct sml_ann_bridge *iann; + Confidence_Interval *ci; + uint16_t count, i; + FILE *f; + + sml_debug("Load ann:%s and CI:%s", ann_path, cfg_path); + + ann = fann_create_from_file(ann_path); + if (!ann) + return NULL; + + iann = _sml_ann_bridge_new(ann, true); + if (!iann) { + fann_destroy(ann); + return NULL; + } + + f = fopen(cfg_path, "rb"); + if (!f) { + sml_critical("Could not open file:%s", cfg_path); + goto err_exit; + } + + if (fread(&count, sizeof(uint16_t), 1, f) < 1) { + sml_critical("Could not read the confidence interval len"); + goto err_close_file; + } + + for (i = 0; i < count; i++) { + ci = sol_vector_append(&iann->confidence_intervals); + if (!ci) { + sml_critical("Could not alloc the confidence interval"); + goto err_close_file; + } + if (fread(&ci->lower_limit, sizeof(float), 1, f) < 1) { + sml_critical("Could not read the lower limit"); + goto err_close_file; + } + if (fread(&ci->upper_limit, sizeof(float), 1, f) < 1) { + sml_critical("Could not read the upper limit"); + goto err_close_file; + } + iann->ci_length_sum += (ci->upper_limit - ci->lower_limit); + } + + if (fread(&iann->max_neurons, sizeof(unsigned int), 1, f) < 1) { + sml_critical("Could not read the max neurons"); + goto err_close_file; + } + + if (fread(&iann->required_observations, sizeof(unsigned int), 1, f) < 1) { + sml_critical("Could not read the required observations"); + goto err_close_file; + } + + iann->observations = fann_create_train(iann->required_observations, + fann_get_num_input(iann->ann), + fann_get_num_output(iann->ann)); + if (!iann->observations) { + sml_critical("Could not alloc observations array"); + goto err_close_file; + } + + if (fclose(f) == EOF) { + sml_critical("Could not correctly close the CI file"); + goto err_exit; + } + + return iann; +err_close_file: + fclose(f); +err_exit: + sml_ann_bridge_free(iann); + return NULL; +} + +void +sml_ann_bridge_print_debug(struct sml_ann_bridge *ann) +{ + uint16_t i; + Confidence_Interval *interval; + + sml_debug("\ttrained: %s", ann->trained ? "true" : "false"); + sml_debug("\tlast_train_error: %g", ann->last_train_error); + sml_debug("\tConfidence Intervals (%d) {", ann->confidence_intervals.len); + SOL_VECTOR_FOREACH_IDX (&ann->confidence_intervals, interval, i) { + sml_debug("\t\t{%g - %g}", interval->lower_limit, + interval->upper_limit); + } + sml_debug("\t}"); +} + +float +sml_ann_bridge_get_error(struct sml_ann_bridge *iann, + struct sml_variables_list *input, struct sml_variables_list *output, + unsigned int observations) +{ + struct fann_train_data *test_data; + float err = NAN; + + test_data = fann_create_train(observations, + sml_ann_variables_list_get_length(input), + sml_ann_variables_list_get_length(output)); + if (!test_data) { + sml_critical("Could not create the test data"); + return err; + } + + _sml_ann_bridge_fill_train_data_array(input, output, test_data, + observations); + err = fann_test_data(iann->ann, test_data); + sml_debug("ANN current error:%f", err); + fann_destroy_train(test_data); + return err; +} diff --git a/sml/sml_ann/src/sml_ann_bridge.h b/sml/sml_ann/src/sml_ann_bridge.h new file mode 100644 index 0000000..7880062 --- /dev/null +++ b/sml/sml_ann/src/sml_ann_bridge.h @@ -0,0 +1,85 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +struct sml_ann_bridge; + +struct sml_ann_bridge *sml_ann_bridge_new(unsigned int inputs, + unsigned int outputs, + unsigned int candidate_groups, + unsigned int epochs, + enum sml_ann_training_algorithm train_algorithm, + struct sol_vector *activation_functions, + int *error_code); + +void sml_ann_bridge_free(struct sml_ann_bridge *iann); +bool sml_ann_bridge_predict_output(struct sml_ann_bridge *iann, struct sml_variables_list *inputs, + struct sml_variables_list *outputs); +bool sml_ann_bridge_is_trained(struct sml_ann_bridge *iann); +int sml_ann_bridge_train(struct sml_ann_bridge *iann, struct sml_variables_list *inputs, + struct sml_variables_list *outputs, float desired_train_error, + unsigned int required_observations, + unsigned int max_neurons, + unsigned int *required_observations_suggestion, + bool use_pseudorehearsal); +bool sml_ann_bridge_save(struct sml_ann_bridge *iann, const char *ann_path, const char *cfg_path); +struct sml_ann_bridge *sml_ann_bridge_load_from_file(const char *ann_path, const char *cfg_path); +int sml_ann_bridge_consider_trained(struct sml_ann_bridge *iann, struct sml_variables_list *inputs, + unsigned int observations, bool use_pseudorehearsal); +unsigned int sml_ann_bridge_inputs_in_confidence_interval_hits(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs); +void sml_ann_bridge_add_observation(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs, + struct sml_variables_list *outputs); +void sml_ann_bridge_print_debug(struct sml_ann_bridge *ann); +float sml_ann_bridge_get_confidence_interval_sum(struct sml_ann_bridge *iann); +float sml_ann_bridge_confidence_intervals_distance_sum(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs); +bool sml_ann_bridge_predict_output_by_index(struct sml_ann_bridge *iann, + struct sml_variables_list *inputs, + struct sml_variables_list *outputs, + unsigned int idx); +float sml_ann_bridge_get_error(struct sml_ann_bridge *iann, struct sml_variables_list *input, + struct sml_variables_list *output, + unsigned int observations); +bool sml_ann_bridge_save_with_no_cfg(struct sml_ann_bridge *iann, const char *ann_path); +struct sml_ann_bridge *sml_ann_bridge_load_from_file_with_no_cfg(const char *ann_path); +#ifdef __cplusplus +} +#endif diff --git a/sml/sml_ann/src/sml_ann_support.c b/sml/sml_ann/src/sml_ann_support.c new file mode 100644 index 0000000..0500f4c --- /dev/null +++ b/sml/sml_ann/src/sml_ann_support.c @@ -0,0 +1,122 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "macros.h" +#include "sml_log.h" + +API_EXPORT bool +sml_ann_set_training_algorithm(struct sml_object *sml, + enum sml_ann_training_algorithm algorithm) +{ + sml_critical("Ann engine not supported."); + return false; +} + +API_EXPORT bool +sml_ann_set_training_epochs(struct sml_object *sml, + unsigned int training_epochs) +{ + sml_critical("Ann engine not supported."); + return false; +} + +API_EXPORT bool +sml_ann_set_desired_error(struct sml_object *sml, float desired_error) +{ + sml_critical("Ann engine not supported."); + return false; +} + +API_EXPORT bool +sml_ann_set_max_neurons(struct sml_object *sml, unsigned int max_neurons) +{ + sml_critical("Ann engine not supported."); + return false; +} + +API_EXPORT bool +sml_ann_set_candidate_groups(struct sml_object *sml, + unsigned int candidate_groups) +{ + sml_critical("Ann engine not supported."); + return false; +} + +API_EXPORT bool +sml_ann_set_max_memory_for_observations(struct sml_object *sml, + unsigned int max_size) +{ + sml_critical("Ann engine not supported."); + return false; +} + +API_EXPORT struct sml_object * +sml_ann_new(void) +{ + sml_critical("Ann engine not supported."); + return NULL; +} + +API_EXPORT bool +sml_is_ann(struct sml_object *sml) +{ + sml_critical("Ann engine not supported."); + return false; +} + +API_EXPORT bool +sml_ann_supported(void) +{ + return false; +} + +API_EXPORT bool +sml_ann_set_cache_max_size(struct sml_object *sml, unsigned int max_size) +{ + return false; +} + +API_EXPORT bool +sml_ann_use_pseudorehearsal_strategy(struct sml_object *sml, + bool use_pseudorehearsal) +{ + return false; +} + +API_EXPORT bool +sml_ann_set_initial_required_observations(struct sml_object *sml, + unsigned int required_observations) +{ + return false; +} diff --git a/sml/sml_ann/src/sml_ann_variable_list.c b/sml/sml_ann/src/sml_ann_variable_list.c new file mode 100644 index 0000000..5c0b4da --- /dev/null +++ b/sml/sml_ann/src/sml_ann_variable_list.c @@ -0,0 +1,414 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "sml_ann_variable_list.h" +#include +#include +#include +#include +#include +#include +#include + +struct sml_variable_impl { + char *name; + unsigned int observations_idx; + /* Keep this as plain C-Array, it's easier to resize + and preallocate the data */ + float *observations; + + float current_value; + float previous_value; + float last_stable_value; + float min_value; + float max_value; + + bool enabled; + bool input; +}; + +struct sml_variables_list_impl { + struct sol_ptr_vector variables; +}; + +void +sml_ann_variable_fill_with_random_values(struct sml_variable *var, + unsigned int total) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + unsigned int i; + + for (i = 0; i < total; i++) { + impl->observations[impl->observations_idx++] = + impl->min_value + rand() / + (RAND_MAX / (impl->max_value - impl->min_value)); + } +} + +void +sml_ann_variable_set_value_by_index(struct sml_variable *var, float value, + unsigned int idx) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + impl->observations[idx] = value; +} + +void +sml_ann_variables_list_add_last_value_to_observation( + struct sml_variables_list *list) +{ + struct sml_variables_list_impl *impl = + (struct sml_variables_list_impl *)list; + struct sml_variable_impl *var; + uint16_t i; + + SOL_PTR_VECTOR_FOREACH_IDX (&impl->variables, var, i) + var->observations[var->observations_idx++] = var->current_value; +} + +void +sml_ann_variables_list_reset_observations(struct sml_variables_list *list) +{ + struct sml_variables_list_impl *impl = + (struct sml_variables_list_impl *)list; + struct sml_variable_impl *var; + uint16_t i; + + SOL_PTR_VECTOR_FOREACH_IDX (&impl->variables, var, i) + var->observations_idx = 0; +} + +void +sml_ann_variables_list_set_current_value_as_stable( + struct sml_variables_list *list) +{ + struct sml_variables_list_impl *impl = + (struct sml_variables_list_impl *)list; + struct sml_variable_impl *var; + uint16_t i; + + SOL_PTR_VECTOR_FOREACH_IDX (&impl->variables, var, i) + var->last_stable_value = var->current_value; +} + +int +sml_ann_variable_realloc_observation_array(struct sml_variable *var, + unsigned int size) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + float *observations; + unsigned int i; + + observations = realloc(impl->observations, sizeof(float) * size); + if (!observations) { + sml_critical("Could not realloc the variable %s observations array" \ + " to %d", impl->name, size); + return -errno; + } + + impl->observations = observations; + + if (size < impl->observations_idx) + impl->observations_idx = size; + else { + for (i = impl->observations_idx; i < size; i++) + impl->observations[i] = NAN; + } + return 0; +} + +int +sml_ann_variables_list_realloc_observations_array( + struct sml_variables_list *list, unsigned int size) +{ + struct sml_variables_list_impl *impl = + (struct sml_variables_list_impl *)list; + struct sml_variable_impl *var; + uint16_t i; + int r; + + SOL_PTR_VECTOR_FOREACH_IDX (&impl->variables, var, i) { + r = sml_ann_variable_realloc_observation_array( + (struct sml_variable *)var, size); + if (r < 0) + return r; + } + return 0; +} + +void +sml_ann_variable_free(struct sml_variable *var) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + free(impl->observations); + free(impl->name); + free(impl); +} + +struct sml_variable * +sml_ann_variable_new(const char *name, bool input) +{ + struct sml_variable_impl *var = calloc(1, sizeof(struct sml_variable_impl)); + + ON_NULL_RETURN_VAL(var, NULL); + var->name = strdup(name); + if (!var->name) { + free(var); + return NULL; + } + + var->current_value = NAN; + var->previous_value = NAN; + var->last_stable_value = NAN; + var->min_value = FLT_MIN; + var->max_value = FLT_MAX; + var->enabled = true; + var->input = input; + + return (struct sml_variable *)var; +} + +void +sml_ann_variable_set_observations_array_index(struct sml_variable *var, + unsigned int idx) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + impl->observations_idx = idx; +} + +float +sml_ann_variable_get_last_stable_value(struct sml_variable *var) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + return impl->last_stable_value; +} + +struct sml_variables_list * +sml_ann_variable_list_new() +{ + struct sml_variables_list_impl *list = + malloc(sizeof(struct sml_variables_list_impl)); + + ON_NULL_RETURN_VAL(list, NULL); + sol_ptr_vector_init(&list->variables); + return (struct sml_variables_list *)list; +} + +float +sml_ann_variable_scale_value(struct sml_variable *var, float value) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + float midrange = (impl->max_value + impl->min_value) / 2.0; + + return (value - midrange) / ((impl->max_value - impl->min_value) / 2.0); +} + +float +sml_ann_variable_descale_value(struct sml_variable *var, float value) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + float midrange = (impl->max_value + impl->min_value) / 2.0; + + return (((impl->max_value - impl->min_value) / 2.0) * value) + midrange; +} + +void +sml_ann_variable_list_free(struct sml_variables_list *list, bool free_var) +{ + struct sml_variables_list_impl *impl = + (struct sml_variables_list_impl *)list; + struct sml_variable *var; + uint16_t i; + + if (free_var) { + SOL_PTR_VECTOR_FOREACH_IDX (&impl->variables, var, i) + sml_ann_variable_free(var); + } + sol_ptr_vector_clear(&impl->variables); + free(impl); +} + +int +sml_ann_variable_list_add_variable(struct sml_variables_list *list, + struct sml_variable *var) +{ + struct sml_variables_list_impl *impl = + (struct sml_variables_list_impl *)list; + + return sol_ptr_vector_append(&impl->variables, var); +} + +float +sml_ann_variable_get_value_by_index(struct sml_variable *var, + unsigned int index) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + return impl->observations[index]; +} + +unsigned int +sml_ann_variable_get_observations_length(struct sml_variable *var) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + return impl->observations_idx; +} + +bool +sml_ann_variable_list_remove(struct sml_variables_list *list, uint16_t index) +{ + struct sml_variables_list_impl *impl = + (struct sml_variables_list_impl *)list; + struct sml_variable *var = sol_ptr_vector_take(&impl->variables, index); + + if (!var) { + sml_critical("Could not remove the index %d", index); + return false; + } + sml_ann_variable_free(var); + return true; +} + +float +sml_ann_variable_get_previous_value(struct sml_variable *var) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + return impl->previous_value; +} + +bool +sml_ann_variable_is_input(struct sml_variable *var) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + return impl->input; +} + +float +sml_ann_variable_get_value(struct sml_variable *var) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + ON_NULL_RETURN_VAL(var, NAN); + return impl->current_value; +} + +bool +sml_ann_variable_set_value(struct sml_variable *var, float value) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + ON_NULL_RETURN_VAL(var, false); + impl->previous_value = impl->current_value; + impl->current_value = value; + return true; +} + +struct sml_variable * +sml_ann_variables_list_index(struct sml_variables_list *list, + unsigned int index) +{ + struct sml_variables_list_impl *impl = + (struct sml_variables_list_impl *)list; + + ON_NULL_RETURN_VAL(list, NULL); + return sol_ptr_vector_get(&impl->variables, index); +} + +uint16_t +sml_ann_variables_list_get_length(struct sml_variables_list *list) +{ + struct sml_variables_list_impl *impl = + (struct sml_variables_list_impl *)list; + + ON_NULL_RETURN_VAL(list, 0); + return sol_ptr_vector_get_len(&impl->variables); +} + +const char * +sml_ann_variable_get_name(struct sml_variable *var) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + ON_NULL_RETURN_VAL(var, NULL); + return impl->name; +} + +bool +sml_ann_variable_set_range(struct sml_variable *var, float min, float max) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + ON_NULL_RETURN_VAL(var, false); + impl->min_value = min; + impl->max_value = max; + return true; +} + +bool +sml_ann_variable_get_range(struct sml_variable *var, float *min, float *max) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + ON_NULL_RETURN_VAL(var, false); + if (min) + *min = impl->min_value; + if (max) + *max = impl->max_value; + return true; +} + +int +sml_ann_variable_set_enabled(struct sml_variable *var, bool enabled) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + impl->enabled = enabled; + + return 0; +} + +bool +sml_ann_variable_is_enabled(struct sml_variable *var) +{ + struct sml_variable_impl *impl = (struct sml_variable_impl *)var; + + ON_NULL_RETURN_VAL(var, false); + return impl->enabled; +} diff --git a/sml/sml_ann/src/sml_ann_variable_list.h b/sml/sml_ann/src/sml_ann_variable_list.h new file mode 100644 index 0000000..f584e9a --- /dev/null +++ b/sml/sml_ann/src/sml_ann_variable_list.h @@ -0,0 +1,84 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +int sml_ann_variable_list_add_variable(struct sml_variables_list *list, struct sml_variable *var); +float sml_ann_variable_get_value_by_index(struct sml_variable *var, unsigned int index); + +struct sml_variable *sml_ann_variable_new(const char *name, bool input); +void sml_ann_variable_set_observations_array_index(struct sml_variable *var, unsigned int idx); +bool sml_ann_variable_is_input(struct sml_variable *var); +void sml_ann_variable_free(struct sml_variable *var); +struct sml_variables_list *sml_ann_variable_list_new(); +void sml_ann_variable_list_free(struct sml_variables_list *list, bool free_var); +bool sml_ann_variable_list_remove(struct sml_variables_list *list, uint16_t index); + +unsigned int sml_ann_variable_get_observations_length(struct sml_variable *var); + +float sml_ann_variable_scale_value(struct sml_variable *var, float value); +float sml_ann_variable_descale_value(struct sml_variable *var, float value); + +int sml_ann_variable_realloc_observation_array(struct sml_variable *var, unsigned int size); +float sml_ann_variable_get_previous_value(struct sml_variable *var); + +float sml_ann_variable_get_last_stable_value(struct sml_variable *var); +void sml_ann_variable_set_last_stable_value(struct sml_variable *var, float value); + +float sml_ann_variable_get_value(struct sml_variable *var); +bool sml_ann_variable_set_value(struct sml_variable *var, float value); +void sml_ann_variable_set_value_by_index(struct sml_variable *var, float value, unsigned int idx); + +struct sml_variable *sml_ann_variables_list_index(struct sml_variables_list *list, unsigned int index); +uint16_t sml_ann_variables_list_get_length(struct sml_variables_list *list); +const char *sml_ann_variable_get_name(struct sml_variable *var); +bool sml_ann_variable_set_range(struct sml_variable *var, float min, float max); +bool sml_ann_variable_get_range(struct sml_variable *var, float *min, float *max); +int sml_ann_variable_set_enabled(struct sml_variable *var, bool enabled); +bool sml_ann_variable_is_enabled(struct sml_variable *var); + +void sml_ann_variables_list_add_last_value_to_observation(struct sml_variables_list *list); +void sml_ann_variables_list_reset_observations(struct sml_variables_list *list); +void sml_ann_variables_list_set_current_value_as_stable(struct sml_variables_list *list); +int sml_ann_variables_list_realloc_observations_array(struct sml_variables_list *list, unsigned int size); +void sml_ann_variable_fill_with_random_values(struct sml_variable *var, unsigned int total); + +#ifdef __cplusplus +} +#endif diff --git a/sml/sml_fuzzy/src/sml_bit_array.c b/sml/sml_fuzzy/src/sml_bit_array.c new file mode 100644 index 0000000..a21391d --- /dev/null +++ b/sml/sml_fuzzy/src/sml_bit_array.c @@ -0,0 +1,156 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "sml_bit_array.h" +#include "sml.h" + +//Change this constants to change the size of the bit array element. +#define BITS 1 +#define ITEMS_IN_BYTE 8 //(8/BITS) +#define MASK 1 //(11b) + +static uint16_t +_calc_data_size(uint16_t size) +{ + uint16_t input_data_size = size / ITEMS_IN_BYTE; + + if (size % ITEMS_IN_BYTE) + input_data_size++; + return input_data_size; +} + +void +sml_bit_array_init(struct sml_bit_array *array) +{ + array->size = 0; + array->data = NULL; +} + +bool +sml_bit_array_set(struct sml_bit_array *array, uint16_t pos, uint8_t value) +{ + uint16_t real_pos; + uint8_t mask, shift; + + real_pos = pos / ITEMS_IN_BYTE; + if (real_pos >= array->size) + return false; + + shift = (pos % ITEMS_IN_BYTE) * BITS; + mask = MASK << shift; + value = value << shift; + array->data[real_pos] = (array->data[real_pos] & ~mask) | value; + + return true; +} + +uint8_t +sml_bit_array_get(struct sml_bit_array *array, uint16_t pos) +{ + uint16_t real_pos; + uint8_t input_terms_membership, shift; + + if (pos >= array->size) + return 0; + + real_pos = pos / ITEMS_IN_BYTE; + shift = (pos % ITEMS_IN_BYTE) * BITS; + input_terms_membership = array->data[real_pos]; + input_terms_membership = input_terms_membership & (MASK << shift); + return input_terms_membership >> shift; +} + +void +sml_bit_array_clear(struct sml_bit_array *array) +{ + array->size = 0; + free(array->data); + array->data = NULL; +} + +int +sml_bit_array_size_set(struct sml_bit_array *array, uint16_t new_size, + uint8_t initial_value) +{ + uint8_t *tmp_output; + uint16_t new_real_size, old_size; + + if (new_size == 0) { + sml_bit_array_clear(array); + return 0; + } + + new_real_size = _calc_data_size(new_size); + tmp_output = realloc(array->data, new_real_size); + if (tmp_output == NULL) + return -errno; + array->data = tmp_output; + old_size = array->size; + array->size = new_size; + + if (new_size > old_size) { + uint16_t i; + for (i = old_size; i < new_size; i++) + sml_bit_array_set(array, i, initial_value); + } + + return 0; +} + +uint16_t +sml_bit_array_size_get(struct sml_bit_array *array) +{ + return array->size; +} + +unsigned int +sml_bit_array_byte_size_get(struct sml_bit_array *array) +{ + return _calc_data_size(array->size); +} + +int +sml_bit_array_remove(struct sml_bit_array *array, uint16_t pos) +{ + uint16_t i; + + if (pos >= array->size) + return -EINVAL; + for (i = pos; i < array->size - 1; i++) + sml_bit_array_set(array, i, sml_bit_array_get(array, i + 1)); + + return sml_bit_array_size_set(array, array->size - 1, 0); +} diff --git a/sml/sml_fuzzy/src/sml_bit_array.h b/sml/sml_fuzzy/src/sml_bit_array.h new file mode 100644 index 0000000..e36fd0c --- /dev/null +++ b/sml/sml_fuzzy/src/sml_bit_array.h @@ -0,0 +1,61 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include + +#define UNSET 0 +#define SET 1 + +#ifdef __cplusplus +extern "C" { +#endif + +struct sml_bit_array { + uint16_t size; + uint8_t *data; +}; + +bool sml_bit_array_set(struct sml_bit_array *array, uint16_t pos, uint8_t value); +uint8_t sml_bit_array_get(struct sml_bit_array *array, uint16_t pos); +void sml_bit_array_clear(struct sml_bit_array *array); +int sml_bit_array_size_set(struct sml_bit_array *array, uint16_t new_size, uint8_t initial_value); +uint16_t sml_bit_array_size_get(struct sml_bit_array *array); +void sml_bit_array_init(struct sml_bit_array *array); +unsigned int sml_bit_array_byte_size_get(struct sml_bit_array *array); +int sml_bit_array_remove(struct sml_bit_array *array, uint16_t pos); + +#ifdef __cplusplus +} +#endif diff --git a/sml/sml_fuzzy/src/sml_fuzzy.c b/sml/sml_fuzzy/src/sml_fuzzy.c new file mode 100644 index 0000000..cf40b6e --- /dev/null +++ b/sml/sml_fuzzy/src/sml_fuzzy.c @@ -0,0 +1,965 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "sml_fuzzy_bridge.h" +#include "sml_observation_controller.h" +#include "sml_util.h" +#include "sml_matrix.h" +#include "sml_terms_manager.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define FUZZY_FILE_PREFIX "fuzzy" +#define DEFAULT_FLL "fuzzy_description.fll" +#define FUZZY_MAGIC (0xf0022ee) + +struct sml_term_to_remove { + struct sml_variable *var; + struct sml_fuzzy_term *term; + bool is_input; +}; + +struct sml_fuzzy_engine { + struct sml_engine engine; + + bool output_state_changed_called; + bool variable_terms_auto_balance; + + struct sml_measure *last_stable_measure; + + struct sml_fuzzy *fuzzy; + struct sml_observation_controller *observation_controller; + struct sml_terms_manager terms_manager; + struct sol_ptr_vector inputs_to_be_removed; + struct sol_ptr_vector outputs_to_be_removed; + struct sol_vector terms_to_be_removed; +}; + +struct sml_fuzzy * +sml_get_fuzzy(struct sml_engine *engine) +{ + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + + return fuzzy_engine->fuzzy; +} + +static void +_fill_variables(struct sml_variables_list *list, + struct sol_ptr_vector *remove_list, bool *to_remove) +{ + struct sml_variable *var; + uint16_t i, pos; + + SOL_PTR_VECTOR_FOREACH_IDX (remove_list, var, i) { + if (sml_fuzzy_find_variable(list, var, &pos)) + to_remove[pos] = 1; + } +} + +static bool +_sml_load_fll_file(struct sml_engine *engine, const char *filename) +{ + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + + if (!sml_fuzzy_load_file(fuzzy_engine->fuzzy, filename)) + return false; + + sml_observation_controller_clear(fuzzy_engine->observation_controller); + sml_terms_manager_clear(&fuzzy_engine->terms_manager); + sol_ptr_vector_clear(&fuzzy_engine->inputs_to_be_removed); + sol_vector_clear(&fuzzy_engine->terms_to_be_removed); + sol_ptr_vector_clear(&fuzzy_engine->outputs_to_be_removed); + + return true; +} + +static bool +_float_equals(void *v1, void *v2) +{ + float a = 0, b = 0; + + if (v1) + a = *((float *)v1); + if (v2) + b = *((float *)v2); + + if (isnan(a) && isnan(b)) + return true; + + if (isnan(a) || isnan(b)) + return false; + + return fabs(a - b) <= VARIABLE_MEMBERSHIP_THRESHOLD; +} + +static bool +_matrix_has_significant_changes(struct sml_matrix *old, struct sml_matrix *new, + struct sol_vector *changed) +{ + return sml_matrix_equals(old, new, changed, _float_equals); +} + +static bool +_measure_has_significant_changes(struct sml_measure *old_measure, + struct sml_measure *new_measure, bool *input_changed) +{ + //First run. + if (!old_measure) { + if (input_changed) + *input_changed = true; + return true; + } + + if (_matrix_has_significant_changes(&old_measure->inputs, + &new_measure->inputs, NULL)) { + if (input_changed) + *input_changed = true; + return true; + } + + if (input_changed) + *input_changed = false; + + if (_matrix_has_significant_changes(&old_measure->outputs, + &new_measure->outputs, NULL)) + return true; + + return false; +} + +API_EXPORT bool +sml_fuzzy_set_variable_terms_auto_balance(struct sml_object *sml, + bool variable_terms_auto_balance) +{ + if (!sml_is_fuzzy(sml)) + return false; + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)sml; + + if (!variable_terms_auto_balance && + fuzzy_engine->variable_terms_auto_balance) + sml_terms_manager_clear(&fuzzy_engine->terms_manager); + fuzzy_engine->variable_terms_auto_balance = variable_terms_auto_balance; + + return true; +} + +static int +_read_variables(struct sml_fuzzy_engine *fuzzy_engine) +{ + if (!fuzzy_engine->engine.read_state_cb) { + sml_critical("It's required to set a read_state_cb to read"); + return -EINVAL; + } + + if (!fuzzy_engine->engine.read_state_cb( + (struct sml_object *)&fuzzy_engine->engine, + fuzzy_engine->engine.read_state_cb_data)) + return -EAGAIN; + + return 0; +} + +static bool +_pre_process(struct sml_fuzzy_engine *fuzzy_engine, bool *should_act, + bool *should_learn) +{ + struct sml_measure *new_measure; + bool input_changed; + + if (!fuzzy_engine->fuzzy->input_terms_count || + !fuzzy_engine->fuzzy->output_terms_count) + return true; + + new_measure = sml_fuzzy_get_membership_values(fuzzy_engine->fuzzy); + if (!new_measure) + return false; + + if (_measure_has_significant_changes(fuzzy_engine->last_stable_measure, + new_measure, &input_changed)) { + sml_measure_free(fuzzy_engine->last_stable_measure); + fuzzy_engine->last_stable_measure = new_measure; + fuzzy_engine->engine.hits = 0; + new_measure = NULL; + + //if input has changed + if (input_changed) + fuzzy_engine->engine.output_state_changed_called = false; + } + + //measures didn't have significant changes in the defined number of hits + if (fuzzy_engine->engine.hits == fuzzy_engine->engine.stabilization_hits) { + sml_debug("Input is stable, saving state"); + if (new_measure) { + sml_measure_free(fuzzy_engine->last_stable_measure); + fuzzy_engine->last_stable_measure = new_measure; + fuzzy_engine->engine.hits = 0; + new_measure = NULL; + } + + //If we called output_state_changed_cb before and there are no significative + //changes in inputs, or we don't have enough rules, then + //We won't act and we will learn this scenario + if (fuzzy_engine->engine.output_state_changed_called || + sml_fuzzy_is_rule_block_empty(fuzzy_engine->fuzzy)) + *should_learn = true; + else + *should_act = true; + } else { + sml_measure_free(new_measure); + fuzzy_engine->engine.hits++; + } + return true; +} + +static int +_act(struct sml_fuzzy_engine *fuzzy_engine, bool *should_learn) +{ + struct sml_matrix output_membership; + struct sol_vector changed_idx = SOL_VECTOR_INIT(uint16_t); + struct sml_variables_list *changed; + struct sml_variable *variable; + int error; + + //predict outputs + if ((error = sml_fuzzy_process_output(fuzzy_engine->fuzzy))) + return error; + +#ifdef Debug + sml_debug("Fuzzy output values"); + uint16_t i, len; + struct sml_variables_list *outputs; + outputs = fuzzy_engine->fuzzy->output_list; + len = sml_fuzzy_variables_list_get_length(outputs); + for (i = 0; i < len; i++) { + variable = sml_fuzzy_variables_list_index(outputs, i); + sml_debug("%s\t%g", sml_fuzzy_variable_get_name(variable), + sml_fuzzy_variable_get_value(variable)); + } +#endif + + if (!fuzzy_engine->engine.output_state_changed_cb) { + *should_learn = true; + return 0; + } + + sml_matrix_init(&output_membership, sizeof(float)); + if ((error = sml_fuzzy_get_membership_values_output(fuzzy_engine->fuzzy, + &output_membership))) + return error; + + //If output_has_significative_changes + //or we are forced to call output_state_changed_cb + if (_matrix_has_significant_changes( + &fuzzy_engine->last_stable_measure->outputs, + &output_membership, &changed_idx)) { + changed = sml_fuzzy_variables_list_new(fuzzy_engine->fuzzy, + &changed_idx); + if (!changed) { + sml_critical("Could not create the changed variables list"); + } else { + sml_debug("Calling user's change state callback!"); + //If variable is not present in the changed list, the read values + //should be set as its value. + sml_fuzzy_set_read_values(fuzzy_engine->fuzzy, changed); + fuzzy_engine->engine.output_state_changed_cb( + (struct sml_object *)&fuzzy_engine->engine, changed, + fuzzy_engine->engine.output_state_changed_cb_data); + fuzzy_engine->engine.output_state_changed_called = true; + sml_fuzzy_variables_list_free(changed); + } + } + + sol_vector_clear(&changed_idx); + sml_matrix_clear(&output_membership); + *should_learn = true; + return 0; +} + +static int +_remove_variables(struct sml_fuzzy_engine *fuzzy_engine, bool *removed) +{ + int error; + struct sml_variable *var; + uint16_t i, pos; + bool *inputs_to_remove_bool = NULL; + bool *outputs_to_remove_bool = NULL; + + *removed = false; + if (sol_ptr_vector_get_len(&fuzzy_engine->inputs_to_be_removed)) { + inputs_to_remove_bool = calloc(sml_fuzzy_variables_list_get_length( + fuzzy_engine->fuzzy->input_list), sizeof(bool)); + _fill_variables(fuzzy_engine->fuzzy->input_list, + &fuzzy_engine->inputs_to_be_removed, + inputs_to_remove_bool); + } + + if (sol_ptr_vector_get_len(&fuzzy_engine->outputs_to_be_removed)) { + outputs_to_remove_bool = calloc(sml_fuzzy_variables_list_get_length( + fuzzy_engine->fuzzy->output_list), sizeof(bool)); + _fill_variables(fuzzy_engine->fuzzy->output_list, + &fuzzy_engine->outputs_to_be_removed, + outputs_to_remove_bool); + } + + if (!inputs_to_remove_bool && !outputs_to_remove_bool) + return 0; + + if ((error = sml_observation_controller_remove_variables( + fuzzy_engine->observation_controller, + inputs_to_remove_bool, outputs_to_remove_bool))) + return error; + + if ((error = sml_terms_manager_remove_variables( + &fuzzy_engine->terms_manager, + inputs_to_remove_bool, outputs_to_remove_bool))) + return error; + + SOL_PTR_VECTOR_FOREACH_IDX (&fuzzy_engine->inputs_to_be_removed, var, i) { + if (!sml_fuzzy_find_variable(fuzzy_engine->fuzzy->input_list, var, + &pos)) + continue; + if (!sml_fuzzy_remove_variable(fuzzy_engine->fuzzy, var)) + continue; + if (fuzzy_engine->last_stable_measure) + sml_measure_remove_input_variable( + fuzzy_engine->last_stable_measure, pos); + } + + SOL_PTR_VECTOR_FOREACH_IDX (&fuzzy_engine->outputs_to_be_removed, var, i) { + if (!sml_fuzzy_find_variable(fuzzy_engine->fuzzy->output_list, var, + &pos)) + continue; + if (!sml_fuzzy_remove_variable(fuzzy_engine->fuzzy, var)) + continue; + if (fuzzy_engine->last_stable_measure) + sml_measure_remove_output_variable( + fuzzy_engine->last_stable_measure, pos); + } + + sol_ptr_vector_clear(&fuzzy_engine->inputs_to_be_removed); + sol_ptr_vector_clear(&fuzzy_engine->outputs_to_be_removed); + + *removed = true; + return 0; +} + +static int +_remove_terms(struct sml_fuzzy_engine *fuzzy_engine, bool *removed) +{ + int error = 0; + uint16_t i, var_num, term_num; + bool terms_removed = false; + struct sml_term_to_remove *to_remove; + + SOL_VECTOR_FOREACH_IDX (&fuzzy_engine->terms_to_be_removed, to_remove, i) { + if (to_remove->is_input) { + if (!sml_fuzzy_find_variable(fuzzy_engine->fuzzy->input_list, + to_remove->var, &var_num)) + continue; + } else { + if (!sml_fuzzy_find_variable(fuzzy_engine->fuzzy->output_list, + to_remove->var, &var_num)) + continue; + } + + if (!sml_fuzzy_variable_find_term(to_remove->var, to_remove->term, + &term_num)) + continue; + + //Will remove term + if ((error = sml_observation_controller_remove_term( + fuzzy_engine->observation_controller, + var_num, term_num, to_remove->is_input))) + goto _remove_terms_end; + + if ((error = sml_fuzzy_bridge_variable_remove_term(to_remove->var, + term_num))) + goto _remove_terms_end; + + sml_terms_manager_remove_term(&fuzzy_engine->terms_manager, var_num, + term_num, to_remove->is_input); + + terms_removed = true; + } + sol_vector_clear(&fuzzy_engine->terms_to_be_removed); + +_remove_terms_end: + *removed = terms_removed; + return error; +} + +static int +_handle_removals(struct sml_fuzzy_engine *fuzzy_engine) +{ + int error; + bool removed_terms = false, removed_variables = false; + + if ((error = _remove_variables(fuzzy_engine, &removed_variables))) + return error; + + if ((error = _remove_terms(fuzzy_engine, &removed_terms))) + return error; + + if (removed_terms || removed_variables) + error = sml_observation_controller_post_remove_variables( + fuzzy_engine->observation_controller); + + return error; +} + +static void +_print_rule(const char *str, void *data) +{ + uint16_t *counter = (uint16_t *)data; + + *counter = *counter + 1; + sml_debug("\t%s", str); +} + +static int +_initialize_terms_list(struct sml_fuzzy *fuzzy, struct sml_variables_list *list) +{ + int error; + uint16_t len, i; + + len = sml_fuzzy_variables_list_get_length(list); + for (i = 0; i < len; i++) { + struct sml_variable *var = sml_fuzzy_variables_list_index(list, i); + if (!sml_fuzzy_variable_terms_count(var)) + if ((error = sml_terms_manager_initialize_variable(fuzzy, var))) + return error; + } + + return 0; +} + +static int +_sml_process(struct sml_engine *engine) +{ + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + bool should_learn = false, should_act = false; + int error; + + if (!sml_observation_controller_update_cache_size( + fuzzy_engine->observation_controller, + fuzzy_engine->engine.obs_max_size)) + return -ENOMEM; + + if ((error = _handle_removals(fuzzy_engine))) + return error; + + if (fuzzy_engine->variable_terms_auto_balance && + ((error = _initialize_terms_list(fuzzy_engine->fuzzy, + fuzzy_engine->fuzzy->input_list)) || + (error = _initialize_terms_list(fuzzy_engine->fuzzy, + fuzzy_engine->fuzzy->output_list)))) + return error; + + if ((error = _read_variables(fuzzy_engine))) + return error; + + if (!_pre_process(fuzzy_engine, &should_act, &should_learn)) + return -ENOMEM; + + if (should_act && (error = _act(fuzzy_engine, &should_learn))) + return error; + + if (should_learn && !fuzzy_engine->engine.learn_disabled && + (error = sml_observation_controller_observation_hit( + fuzzy_engine->observation_controller, + fuzzy_engine->last_stable_measure))) + return error; + + if (fuzzy_engine->variable_terms_auto_balance && + (error = sml_terms_manager_hit(&fuzzy_engine->terms_manager, + fuzzy_engine->fuzzy, + fuzzy_engine->observation_controller, + fuzzy_engine->last_stable_measure))) + return error; + + return 0; +} + +static bool +_sml_predict(struct sml_engine *engine) +{ + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + + if (!fuzzy_engine->fuzzy->input_terms_count || + !fuzzy_engine->fuzzy->output_terms_count) + return false; + + return sml_fuzzy_process_output(fuzzy_engine->fuzzy) == 0; +} + +static bool +_sml_save(struct sml_engine *engine, const char *path) +{ + char buf[SML_PATH_MAX]; + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + + if (!is_dir(path)) { + sml_critical("Failed to save sml: %s is not a directory\n", path); + return false; + } + + if (!clean_dir(path, FUZZY_FILE_PREFIX)) { + sml_critical("Failed to clearn %s to save sml\n", path); + return false; + } + + snprintf(buf, sizeof(buf), "%s/%s", path, DEFAULT_FLL); + if (!sml_fuzzy_save_file(fuzzy_engine->fuzzy, buf)) + return false; + + return sml_observation_controller_save_state( + fuzzy_engine->observation_controller, path); +} + +static bool +_sml_load(struct sml_engine *engine, const char *path) +{ + char buf[SML_PATH_MAX]; + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + + if (!is_dir(path)) { + sml_critical("Failed to load sml in directory %s\n", path); + return false; + } + + snprintf(buf, sizeof(buf), "%s/%s", path, DEFAULT_FLL); + if (!_sml_load_fll_file(engine, buf)) + return false; + + return sml_observation_controller_load_state( + fuzzy_engine->observation_controller, path); +} + +static void +_sml_free(struct sml_engine *engine) +{ + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + + sml_measure_free(fuzzy_engine->last_stable_measure); + sml_observation_controller_free(fuzzy_engine->observation_controller); + sml_terms_manager_clear(&fuzzy_engine->terms_manager); + sol_ptr_vector_clear(&fuzzy_engine->inputs_to_be_removed); + sol_vector_clear(&fuzzy_engine->terms_to_be_removed); + sol_ptr_vector_clear(&fuzzy_engine->outputs_to_be_removed); + sml_fuzzy_destroy(fuzzy_engine->fuzzy); + free(fuzzy_engine); +} + +API_EXPORT bool +sml_fuzzy_set_rule_weight_threshold(struct sml_object *sml, + float weight_threshold) +{ + if (!sml_is_fuzzy(sml)) + return false; + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)sml; + + sml_observation_controller_set_weight_threshold( + fuzzy_engine->observation_controller, + weight_threshold); + return true; +} + +API_EXPORT bool +sml_fuzzy_conjunction_set(struct sml_object *sml, enum sml_fuzzy_tnorm norm) +{ + if (!sml_is_fuzzy(sml)) + return false; + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)sml; + + return sml_fuzzy_bridge_conjunction_set(fuzzy_engine->fuzzy, norm); +} + +API_EXPORT bool +sml_fuzzy_disjunction_set(struct sml_object *sml, enum sml_fuzzy_snorm norm) +{ + if (!sml_is_fuzzy(sml)) + return false; + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)sml; + + return sml_fuzzy_bridge_disjunction_set(fuzzy_engine->fuzzy, norm); +} + +static void +_sml_print_debug(struct sml_engine *engine, bool full) +{ + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + uint16_t counter = 0; + + if (full) { + sml_observation_controller_debug(fuzzy_engine->observation_controller); + sml_terms_manager_debug(&fuzzy_engine->terms_manager); + sml_debug("Last Stable Measure:"); + if (fuzzy_engine->last_stable_measure) + sml_measure_debug(fuzzy_engine->last_stable_measure, + sml_matrix_float_convert); + else + sml_debug("\tNULL"); + sml_fuzzy_debug(fuzzy_engine->fuzzy); + } + + sml_debug("Rules:"); + sml_observation_controller_rule_generate( + fuzzy_engine->observation_controller, _print_rule, &counter); + sml_debug("Total: %d\n", counter); +} + +static struct sml_variables_list * +_sml_get_input_list(struct sml_engine *engine) +{ + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + + return (struct sml_variables_list *)fuzzy_engine->fuzzy->input_list; +} + +static struct sml_variables_list * +_sml_get_output_list(struct sml_engine *engine) +{ + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + + return (struct sml_variables_list *)fuzzy_engine->fuzzy->output_list; +} + +static bool +_sml_remove_variable(struct sml_engine *engine, struct sml_variable *variable) +{ + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + + if (sml_fuzzy_is_input(fuzzy_engine->fuzzy, variable)) { + if (sol_ptr_vector_append(&fuzzy_engine->inputs_to_be_removed, + variable)) { + sml_critical("Could not add input variable to the remove list"); + return false; + } + return true; + } + if (sml_fuzzy_is_output(fuzzy_engine->fuzzy, variable)) { + if (sol_ptr_vector_append(&fuzzy_engine->outputs_to_be_removed, + variable)) { + sml_critical("Could not add output variable to the remove list"); + return false; + } + return true; + } + + sml_critical("Failed to remove. Variable not in fuzzy engine."); + return false; +} + +API_EXPORT bool +sml_fuzzy_variable_remove_term(struct sml_object *sml, struct sml_variable *var, + struct sml_fuzzy_term *term) +{ + if (!sml_is_fuzzy(sml)) + return false; + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)sml; + bool is_input; + struct sml_term_to_remove *to_remove; + + if (sml_fuzzy_is_input(fuzzy_engine->fuzzy, var)) + is_input = true; + else if (sml_fuzzy_is_output(fuzzy_engine->fuzzy, var)) + is_input = false; + else { + sml_critical("Failed to remove term. Variable not in fuzzy engine."); + return false; + } + + if (!sml_fuzzy_variable_find_term(var, term, NULL)) { + sml_critical("Failed to remove term. Term not in Variable."); + return false; + } + + to_remove = sol_vector_append(&fuzzy_engine->terms_to_be_removed); + to_remove->is_input = is_input; + to_remove->term = term; + to_remove->var = var; + + return true; +} + + +static int +_sml_variable_set_enabled(struct sml_engine *engine, + struct sml_variable *variable, bool enabled) +{ + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)engine; + + if (enabled == sml_fuzzy_variable_is_enabled(variable)) + return 0; + + sml_fuzzy_variable_set_enabled(variable, enabled); + return sml_observation_controller_variable_set_enabled( + fuzzy_engine->observation_controller, enabled); +} + + +static struct sml_variable * +_sml_get_input(struct sml_engine *engine, const char *name) +{ + return sml_fuzzy_get_input(sml_get_fuzzy(engine), name); +} + +static struct sml_variable * +_sml_get_output(struct sml_engine *engine, const char *name) +{ + return sml_fuzzy_get_output(sml_get_fuzzy(engine), name); +} + +static struct sml_variable * +_sml_new_input(struct sml_engine *engine, const char *name) +{ + return sml_fuzzy_new_input(sml_get_fuzzy(engine), name); +} + +static struct sml_variable * +_sml_new_output(struct sml_engine *engine, const char *name) +{ + struct sml_variable *variable; + + variable = sml_fuzzy_new_output(sml_get_fuzzy(engine), name); + return variable; +} + +static bool +_sml_variable_set_value(struct sml_variable *sml_variable, float value) +{ + if (!sml_fuzzy_variable_is_enabled(sml_variable)) + sml_warning("Trying to set a value in a disabled variable: %s.", + sml_fuzzy_variable_get_name(sml_variable)); + sml_fuzzy_variable_set_value(sml_variable, value); + return true; +} + +API_EXPORT struct sml_fuzzy_term * +sml_fuzzy_variable_add_term_rectangle(struct sml_object *sml, + struct sml_variable *variable, const char *name, float start, float end, + float height) +{ + ON_NULL_RETURN_VAL(variable, false); + if (!sml_is_fuzzy(sml)) + return false; + + return sml_fuzzy_bridge_variable_add_term_rectangle( + sml_get_fuzzy((struct sml_engine *)sml), + variable, name, start, end, height); +} + +API_EXPORT struct sml_fuzzy_term * +sml_fuzzy_variable_add_term_triangle(struct sml_object *sml, + struct sml_variable *variable, const char *name, float vertex_a, + float vertex_b, float vertex_c, float height) +{ + ON_NULL_RETURN_VAL(variable, false); + if (!sml_is_fuzzy(sml)) + return false; + + return sml_fuzzy_bridge_variable_add_term_triangle( + sml_get_fuzzy((struct sml_engine *)sml), + variable, name, vertex_a, vertex_b, vertex_c, height); +} + +API_EXPORT struct sml_fuzzy_term * +sml_fuzzy_variable_add_term_cosine(struct sml_object *sml, + struct sml_variable *variable, const char *name, float center, float width, + float height) +{ + ON_NULL_RETURN_VAL(variable, false); + if (!sml_is_fuzzy(sml)) + return false; + + return sml_fuzzy_bridge_variable_add_term_cosine( + sml_get_fuzzy((struct sml_engine *)sml), + variable, name, center, width, height); +} + +API_EXPORT struct sml_fuzzy_term * +sml_fuzzy_variable_add_term_gaussian(struct sml_object *sml, + struct sml_variable *variable, const char *name, float mean, + float standard_deviation, float height) +{ + ON_NULL_RETURN_VAL(variable, false); + if (!sml_is_fuzzy(sml)) + return false; + + return sml_fuzzy_bridge_variable_add_term_gaussian( + sml_get_fuzzy((struct sml_engine *)sml), + variable, name, mean, standard_deviation, height); +} + +API_EXPORT struct sml_fuzzy_term * +sml_fuzzy_variable_add_term_ramp(struct sml_object *sml, + struct sml_variable *variable, const char *name, float start, float end, + float height) +{ + ON_NULL_RETURN_VAL(variable, false); + if (!sml_is_fuzzy(sml)) + return false; + + return sml_fuzzy_bridge_variable_add_term_ramp( + sml_get_fuzzy((struct sml_engine *)sml), variable, + name, start, end, height); +} + +static struct sml_variable * +_fuzzy_variables_list_index(struct sml_variables_list *list, unsigned int index) +{ + if (index > UINT16_MAX) + return NULL; + + return sml_fuzzy_variables_list_index(list, index); +} + +API_EXPORT bool +sml_fuzzy_set_simplification_disabled(struct sml_object *sml, bool disabled) +{ + if (!sml_is_fuzzy(sml)) + return false; + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)sml; + + sml_observation_controller_set_simplification_disabled( + fuzzy_engine->observation_controller, disabled); + return true; +} + +API_EXPORT struct sml_object * +sml_fuzzy_new(void) +{ + struct sml_fuzzy_engine *fuzzy_engine = calloc(1, + sizeof(struct sml_fuzzy_engine)); + + if (!fuzzy_engine) + goto error_sml; + + fuzzy_engine->fuzzy = sml_fuzzy_bridge_new(); + if (!fuzzy_engine->fuzzy) + goto error_fuzzy; + + fuzzy_engine->observation_controller = + sml_observation_controller_new(fuzzy_engine->fuzzy); + if (!fuzzy_engine->observation_controller) + goto error_observation_controller; + + sml_terms_manager_init(&fuzzy_engine->terms_manager); + sol_ptr_vector_init(&fuzzy_engine->inputs_to_be_removed); + sol_vector_init(&fuzzy_engine->terms_to_be_removed, + sizeof(struct sml_term_to_remove)); + sol_ptr_vector_init(&fuzzy_engine->outputs_to_be_removed); + fuzzy_engine->last_stable_measure = NULL; + + fuzzy_engine->engine.load_file = _sml_load_fll_file; + fuzzy_engine->engine.free = _sml_free; + fuzzy_engine->engine.process = _sml_process; + fuzzy_engine->engine.predict = _sml_predict; + fuzzy_engine->engine.save = _sml_save; + fuzzy_engine->engine.load = _sml_load; + fuzzy_engine->engine.get_input_list = _sml_get_input_list; + fuzzy_engine->engine.get_output_list = _sml_get_output_list; + fuzzy_engine->engine.new_input = _sml_new_input; + fuzzy_engine->engine.new_output = _sml_new_output; + fuzzy_engine->engine.get_input = _sml_get_input; + fuzzy_engine->engine.get_output = _sml_get_output; + fuzzy_engine->engine.get_name = sml_fuzzy_variable_get_name; + fuzzy_engine->engine.set_value = _sml_variable_set_value; + fuzzy_engine->engine.get_value = sml_fuzzy_variable_get_value; + fuzzy_engine->engine.variable_set_enabled = _sml_variable_set_enabled; + fuzzy_engine->engine.variable_is_enabled = sml_fuzzy_variable_is_enabled; + fuzzy_engine->engine.remove_variable = _sml_remove_variable; + fuzzy_engine->engine.variables_list_get_length = + sml_fuzzy_variables_list_get_length; + fuzzy_engine->engine.variables_list_index = _fuzzy_variables_list_index; + fuzzy_engine->engine.variable_set_range = sml_fuzzy_variable_set_range; + fuzzy_engine->engine.variable_get_range = sml_fuzzy_variable_get_range; + fuzzy_engine->engine.print_debug = _sml_print_debug; + fuzzy_engine->engine.magic_number = FUZZY_MAGIC; + + return (struct sml_object *)&fuzzy_engine->engine; + +error_observation_controller: + sml_fuzzy_destroy(fuzzy_engine->fuzzy); +error_fuzzy: + free(fuzzy_engine); +error_sml: + sml_critical("Failed to create struct sml"); + return NULL; +} + +API_EXPORT bool +sml_is_fuzzy(struct sml_object *sml) +{ + struct sml_fuzzy_engine *fuzzy_engine = (struct sml_fuzzy_engine *)sml; + + ON_NULL_RETURN_VAL(sml, false); + return fuzzy_engine->engine.magic_number == FUZZY_MAGIC; +} + +API_EXPORT bool +sml_fuzzy_output_set_defuzzifier(struct sml_object *sml, + struct sml_variable *var, enum sml_fuzzy_defuzzifier defuzzifier, + int defuzzifier_resolution) +{ + ON_NULL_RETURN_VAL(var, false); + if (!sml_is_fuzzy(sml)) + return false; + + return sml_fuzzy_bridge_output_set_defuzzifier(var, defuzzifier, + defuzzifier_resolution); +} + +API_EXPORT bool +sml_fuzzy_output_set_accumulation(struct sml_object *sml, + struct sml_variable *var, enum sml_fuzzy_snorm accumulation) +{ + ON_NULL_RETURN_VAL(var, false); + if (!sml_is_fuzzy(sml)) + return false; + + return sml_fuzzy_bridge_output_set_accumulation(var, accumulation); +} + +API_EXPORT bool +sml_fuzzy_supported(void) +{ + return true; +} diff --git a/sml/sml_fuzzy/src/sml_fuzzy_bridge.cpp b/sml/sml_fuzzy/src/sml_fuzzy_bridge.cpp new file mode 100644 index 0000000..edccdc6 --- /dev/null +++ b/sml/sml_fuzzy/src/sml_fuzzy_bridge.cpp @@ -0,0 +1,1204 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "sml_fuzzy_bridge.h" +#include "sml_measure.h" +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_MIN (0) +#define DEFAULT_MAX (1) +#define DEFAULT_ACCUMULATION (SML_FUZZY_SNORM_MAXIMUM) + +template +static uint16_t +_calc_terms_count(const std::vector &vec) +{ + uint16_t i, count = 0; + for (i = 0; i < vec.size(); i++) + count += vec[i]->numberOfTerms(); + return count; +} + +/* remove all the rules from the first rule block + and remove all the other ruleblocks, since + all the rules we'll be added on the first one */ +static void +_remove_rule_blocks(fl::Engine *engine) +{ + uint16_t rule_blocks_size, rules_size, i; + fl::RuleBlock *rule_block; + + sml_debug("Removing rules"); + + rule_blocks_size = engine->numberOfRuleBlocks(); + if (rule_blocks_size == 0) + return; + + rule_block = engine->getRuleBlock(0); + rules_size = rule_block->numberOfRules(); + for (i = 0; i < rules_size; i++) + delete rule_block->removeRule(0); + + for (i = 1; i < rule_blocks_size; i++) + delete engine->removeRuleBlock(1); +} + +static bool +_is_in_list(struct sml_variables_list *list, fl::Variable *var) +{ + std::vector *variables = + static_cast *>((void *)list); + for (std::vector::const_iterator it = + variables->begin(); + it != variables->end(); ++it) { + if (*it == var) + return true; + } + return false; +} + +/* only create rule block if it doesn't exists */ +static bool +_create_rule_block(fl::Engine *engine) +{ + fl::RuleBlock *rule_block; + fl::SNorm *snorm; + fl::TNorm *tnorm; + fl::TNorm *activation; + + if (engine->numberOfRuleBlocks() > 0) + return true; + + rule_block = new (std::nothrow) fl::RuleBlock(); + + if (!rule_block) + return false; + + tnorm = new (std::nothrow) fl::Minimum(); + if (!tnorm) + goto err_tnorm; + + snorm = new (std::nothrow) fl::Maximum(); + if (!snorm) + goto err_snorm; + + activation = new (std::nothrow) fl::Minimum(); + if (!activation) + goto err_activation; + + rule_block->setEnabled(true); + rule_block->setName(""); + rule_block->setConjunction(tnorm); + rule_block->setDisjunction(snorm); + rule_block->setActivation(activation); + + engine->addRuleBlock(rule_block); + return true; + +err_activation: + delete snorm; +err_snorm: + delete tnorm; +err_tnorm: + delete rule_block; + return false; +} + +struct sml_fuzzy * +sml_fuzzy_bridge_new(void) +{ + struct sml_fuzzy *fuzzy = (struct sml_fuzzy *) calloc(1, sizeof(struct sml_fuzzy)); + fl::Engine *engine = NULL; + + if (!fuzzy) { + sml_critical("Failed to create fuzzy"); + return NULL; + } + + engine = new (std::nothrow) fl::Engine(); + if (!engine) + goto new_error; + + if (!_create_rule_block(engine)) { + sml_critical("Could not alloc the rule block"); + goto new_error; + } + + engine->setName("EngineDefault"); + fuzzy->engine = engine; + fuzzy->input_list = (struct sml_variables_list*)&(engine->inputVariables()); + fuzzy->output_list = (struct sml_variables_list*)&(engine->outputVariables()); + + return fuzzy; + +new_error: + free(fuzzy); + delete engine; + return NULL; +} + +bool +sml_fuzzy_save_file(struct sml_fuzzy *fuzzy, const char *filename) +{ + fl::FllExporter exporter; + fl::RuleBlock *block, *new_block; + fl::Engine *engine = (fl::Engine *) fuzzy->engine; + FILE *f; + + if (!engine) + return false; + + f = fopen(filename, "w"); + if (!f) { + fprintf(stderr, "Failed to open %s\n", filename); + return false; + } + + block = engine->removeRuleBlock(0); + new_block = new fl::RuleBlock(); + + new_block->setActivation(block->getActivation()->clone()); + new_block->setConjunction(block->getConjunction()->clone()); + new_block->setDisjunction(block->getDisjunction()->clone()); + engine->addRuleBlock(new_block); + fprintf(f, "%s\n", exporter.toString(engine).c_str()); + if (fclose(f)) + return false; + + delete engine->removeRuleBlock(0); + engine->addRuleBlock(block); + return true; +} + +bool +sml_fuzzy_load_file(struct sml_fuzzy *fuzzy, const char *filename) +{ + fl::Engine *engine; + + try { + fl::FllImporter importer; + engine = importer.fromFile(filename); + + } catch (fl::Exception e) { + sml_critical("%s", e.getWhat().c_str()); + return false; + } + + if (engine->numberOfInputVariables() == 0 || + engine->numberOfOutputVariables() == 0) { + sml_critical("Input and output variables must be provided!"); + goto error; + } + + if (engine->numberOfRuleBlocks() == 0) { + sml_critical("Rule blocks must be provided!"); + goto error; + } + + + if (fuzzy->engine) + delete (fl::Engine*) fuzzy->engine; + + fuzzy->engine = engine; + fuzzy->input_list = (struct sml_variables_list*)&(engine->inputVariables()); + fuzzy->output_list = (struct sml_variables_list*)&(engine->outputVariables()); + fuzzy->input_terms_count = _calc_terms_count(engine->inputVariables()); + fuzzy->output_terms_count = _calc_terms_count(engine->outputVariables()); + _remove_rule_blocks(engine); + + return true; + +error: + delete engine; + return false; +} + +static int +_sml_fuzzy_fill_membership_values(struct sml_matrix *variables, + struct sml_variables_list *list) +{ + uint16_t i, j, len; + float f, *ptr; + + len = sml_fuzzy_variables_list_get_length(list); + try { + for (i = 0; i < len; i++) { + struct sml_variable *variable = sml_fuzzy_variables_list_index(list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(variable); + for (j = 0; j < terms_len; j++) { + fl::Term *term = (fl::Term *) + sml_fuzzy_variable_get_term(variable, j); + f = term->membership(sml_fuzzy_variable_get_value(variable)); + ptr = (float*) sml_matrix_insert(variables, i, j); + if (!ptr) { + sml_critical("Could not fill membership to variable"); + return -ENOMEM; + } + *ptr = f; + } + } + } catch (fl::Exception e) { + sml_critical("%s", e.getWhat().c_str()); + return SML_INTERNAL_ERROR; + } + return 0; +} + +struct sml_measure * +sml_fuzzy_get_membership_values(struct sml_fuzzy *fuzzy) +{ + struct sml_measure *measure = sml_measure_new(sizeof(float), sizeof(float)); + if (!measure) + return NULL; + + if (_sml_fuzzy_fill_membership_values(&measure->inputs, + fuzzy->input_list)) + goto membership_error; + + if (_sml_fuzzy_fill_membership_values(&measure->outputs, + fuzzy->output_list)) + goto membership_error; + + return measure; + +membership_error: + sml_measure_free(measure); + return NULL; +} + +int +sml_fuzzy_get_membership_values_output(struct sml_fuzzy *fuzzy, + struct sml_matrix *output_membership) +{ + int error; + if ((error = _sml_fuzzy_fill_membership_values(output_membership, + fuzzy->output_list))) { + sml_matrix_clear(output_membership); + return error; + } + return 0; +} + +int +sml_fuzzy_process_output(struct sml_fuzzy *fuzzy) +{ + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + + try { + engine->process(); + } catch (fl::Exception e) { + sml_critical("%s", e.getWhat().c_str()); + return SML_INTERNAL_ERROR; + } + + return 0; +} + +void +sml_fuzzy_destroy(struct sml_fuzzy *fuzzy) +{ + delete (fl::Engine*) fuzzy->engine; + free(fuzzy); +} + +static fl::TNorm * +_get_tnorm(enum sml_fuzzy_tnorm norm) { + fl::TNorm *fl_norm; + + switch (norm) { + case SML_FUZZY_TNORM_NONE: + sml_debug("Conjunction set to none"); + return NULL; + case SML_FUZZY_TNORM_ALGEBRAIC_PRODUCT: + sml_debug("Conjunction set to algebraic product"); + fl_norm = new (std::nothrow) fl::AlgebraicProduct(); + break; + case SML_FUZZY_TNORM_BOUNDED_DIFFERENCE: + sml_debug("Conjunction set to bounded difference"); + fl_norm = new (std::nothrow) fl::BoundedDifference(); + break; + case SML_FUZZY_TNORM_DRASTIC_PRODUCT: + sml_debug("Conjunction set to drastic product"); + fl_norm = new (std::nothrow) fl::DrasticProduct(); + break; + case SML_FUZZY_TNORM_EINSTEIN_PRODUCT: + sml_debug("Conjunction set to einstein product"); + fl_norm = new (std::nothrow) fl::EinsteinProduct(); + break; + case SML_FUZZY_TNORM_HAMACHER_PRODUCT: + sml_debug("Conjunction set to hamacher product"); + fl_norm = new (std::nothrow) fl::HamacherProduct(); + break; + case SML_FUZZY_TNORM_MINIMUM: + sml_debug("Conjunction set to minimum"); + fl_norm = new (std::nothrow) fl::Minimum(); + break; + case SML_FUZZY_TNORM_NILPOTENT_MINIMUM: + sml_debug("Conjunction set to nilpotent minimum"); + fl_norm = new (std::nothrow) fl::NilpotentMinimum(); + break; + default: + sml_critical("Unknown TNorm %d", norm); + return NULL; + } + + if (!fl_norm) + sml_critical("Could not alloc the tnorm"); + + return fl_norm; +} + +bool +sml_fuzzy_bridge_conjunction_set(struct sml_fuzzy *fuzzy, enum sml_fuzzy_tnorm norm) +{ + fl::TNorm *fl_norm = _get_tnorm(norm); + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + if (!fl_norm) + return false; + + if (!_create_rule_block(engine)) { + sml_critical("Could not alloc the rule block"); + return false; + } + + engine->getRuleBlock(0)->setConjunction(fl_norm); + return true; +} + +static fl::SNorm * +_get_snorm(enum sml_fuzzy_snorm norm) +{ + fl::SNorm *fl_norm; + + switch (norm) { + case SML_FUZZY_SNORM_NONE: + sml_debug("SNorm is none"); + return NULL; + case SML_FUZZY_SNORM_ALGEBRAIC_SUM: + sml_debug("SNorm is algebraic sum"); + fl_norm = new (std::nothrow) fl::AlgebraicSum(); + break; + case SML_FUZZY_SNORM_BOUNDED_SUM: + sml_debug("SNorm is bounded sum"); + fl_norm = new (std::nothrow) fl::BoundedSum(); + break; + case SML_FUZZY_SNORM_DRASTIC_SUM: + sml_debug("SNorm is drastic sum"); + fl_norm = new (std::nothrow) fl::DrasticSum(); + break; + case SML_FUZZY_SNORM_EINSTEIN_SUM: + sml_debug("SNorm is einstein sum"); + fl_norm = new (std::nothrow) fl::EinsteinSum(); + break; + case SML_FUZZY_SNORM_HAMACHER_SUM: + sml_debug("SNorm is hamacher sum"); + fl_norm = new (std::nothrow) fl::HamacherSum(); + break; + case SML_FUZZY_SNORM_MAXIMUM: + sml_debug("SNorm is maximum"); + fl_norm = new (std::nothrow) fl::Maximum(); + break; + case SML_FUZZY_SNORM_NILPOTENT_MAXIMUM: + sml_debug("SNorm is nilpotent maximum"); + fl_norm = new (std::nothrow) fl::NilpotentMaximum(); + break; + case SML_FUZZY_SNORM_NORMALIZED_SUM: + sml_debug("SNorm is normalized sum"); + fl_norm = new (std::nothrow) fl::NormalizedSum(); + break; + default: + sml_critical("Unknown SNorm %d", norm); + return NULL; + } + + if (!fl_norm) + sml_critical("Could not alloc the snorm"); + + return fl_norm; +} + +bool +sml_fuzzy_bridge_disjunction_set(struct sml_fuzzy *fuzzy, enum sml_fuzzy_snorm norm) +{ + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + fl::SNorm *fl_norm = _get_snorm(norm); + if (!fl_norm) + return false; + + if (!_create_rule_block(engine)) { + sml_critical("Could not alloc the rule block"); + return false; + } + engine->getRuleBlock(0)->setDisjunction(fl_norm); + + return true; +} + +uint16_t +sml_fuzzy_variables_list_get_length(struct sml_variables_list *list) +{ + std::vector *variables = + static_cast *>((void *)list); + return variables->size(); +} + +struct sml_variable * +sml_fuzzy_variables_list_index(struct sml_variables_list *list, uint16_t index) +{ + std::vector *variables = + static_cast *>((void *)list); + return (struct sml_variable *) variables->at(index); +} + +const char * +sml_fuzzy_variable_get_name(struct sml_variable *variable) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + return fl_var->getName().c_str(); +} + +uint16_t +sml_fuzzy_variable_terms_count(struct sml_variable *variable) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + return fl_var->numberOfTerms(); +} + +struct sml_fuzzy_term * +sml_fuzzy_variable_get_term(struct sml_variable *variable, uint16_t index) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + return (struct sml_fuzzy_term *)fl_var->getTerm(index); +} + +const char * +sml_fuzzy_term_get_name(struct sml_fuzzy_term *term) +{ + fl::Term *fl_term = (fl::Term*) term; + return fl_term->getName().c_str(); +} + +static float +_var_get_val_in_range(fl::Variable *fl_var, float value) +{ + if (value < fl_var->getMinimum()) + return fl_var->getMinimum(); + if (value > fl_var->getMaximum()) + return fl_var->getMaximum(); + + return value; +} + +float +sml_fuzzy_variable_get_value(struct sml_variable *variable) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl::OutputVariable *output_var; + fl::InputVariable *input_var; + + input_var = dynamic_cast(fl_var); + if (input_var) + return _var_get_val_in_range(fl_var, input_var->getInputValue()); + + output_var = dynamic_cast(fl_var); + if (output_var) + return _var_get_val_in_range(fl_var, output_var->getOutputValue()); + + sml_warning("Trying to use unkown class of variable"); + return NAN; +} + +void +sml_fuzzy_variable_set_value(struct sml_variable *variable, float value) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl::OutputVariable *output_var; + fl::InputVariable *input_var; + + input_var = dynamic_cast(fl_var); + if (input_var) { + input_var->setInputValue(value); + return; + } + + output_var = dynamic_cast(fl_var); + if (output_var) { + output_var->setOutputValue(value); + return; + } + + sml_warning("Trying to use unkown class of variable"); +} + +struct sml_variable * +sml_fuzzy_new_input(struct sml_fuzzy *fuzzy, const char *name) +{ + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + + if (engine->hasInputVariable(name)) + return NULL; + + fl::InputVariable *variable = new (std::nothrow) fl::InputVariable(); + if (!variable) + return NULL; + + variable->setEnabled(true); + variable->setName(name); + variable->setRange(DEFAULT_MIN, DEFAULT_MAX); + engine->addInputVariable(variable); + + return (struct sml_variable *)variable; +} + +struct sml_variable * +sml_fuzzy_new_output(struct sml_fuzzy *fuzzy, const char *name) +{ + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + + if (engine->hasOutputVariable(name)) + return NULL; + + fl::OutputVariable *variable = new (std::nothrow) fl::OutputVariable(); + fl::Defuzzifier *fl_defuzzifier = + new (std::nothrow) fl::Centroid(); + + if (!variable) return NULL; + + if (!fl_defuzzifier) { + delete variable; + return NULL; + } + + variable->setEnabled(true); + variable->setName(name); + variable->setRange(DEFAULT_MIN, DEFAULT_MAX); + variable->setDefaultValue(NAN); + variable->setDefuzzifier(fl_defuzzifier); + variable->fuzzyOutput()->setAccumulation(_get_snorm(DEFAULT_ACCUMULATION)); + engine->addOutputVariable(variable); + + return (struct sml_variable *)variable; +} + +struct sml_variable * +sml_fuzzy_get_input(struct sml_fuzzy *fuzzy, const char *name) +{ + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + fl::Variable *variable = engine->getInputVariable(name); + return (struct sml_variable *)variable; +} + +struct sml_variable * +sml_fuzzy_get_output(struct sml_fuzzy *fuzzy, const char *name) +{ + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + fl::Variable *variable = engine->getOutputVariable(name); + return (struct sml_variable *)variable; +} + +void +sml_fuzzy_variable_set_enabled(struct sml_variable *variable, bool enabled) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl_var->setEnabled(enabled); + sml_debug("Variable %s %s", fl_var->getName().c_str(), + enabled ? "enabled" : "disabled"); +} + +bool +sml_fuzzy_variable_is_enabled(struct sml_variable *variable) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + return fl_var->isEnabled(); +} + +bool +sml_fuzzy_bridge_output_set_defuzzifier(struct sml_variable *variable, + enum sml_fuzzy_defuzzifier defuzzifier, + int defuzzifier_resolution) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl::Defuzzifier *fl_defuzzifier = NULL; + fl::OutputVariable *output_var = dynamic_cast(fl_var); + if (!output_var) { + sml_critical("Not a output variable!"); + return false; + } + + switch (defuzzifier) { + case SML_FUZZY_DEFUZZIFIER_BISECTOR: + fl_defuzzifier = + new (std::nothrow) fl::Bisector(defuzzifier_resolution); + break; + case SML_FUZZY_DEFUZZIFIER_CENTROID: + fl_defuzzifier = + new (std::nothrow) fl::Centroid(defuzzifier_resolution); + break; + case SML_FUZZY_DEFUZZIFIER_LARGEST_OF_MAXIMUM: + fl_defuzzifier = + new (std::nothrow) fl::LargestOfMaximum(defuzzifier_resolution); + break; + case SML_FUZZY_DEFUZZIFIER_MEAN_OF_MAXIMUM: + fl_defuzzifier = + new (std::nothrow) fl::MeanOfMaximum(defuzzifier_resolution); + break; + case SML_FUZZY_DEFUZZIFIER_SMALLEST_OF_MAXIMUM: + fl_defuzzifier = + new (std::nothrow) fl::SmallestOfMaximum(defuzzifier_resolution); + break; + case SML_FUZZY_DEFUZZIFIER_WEIGHTED_AVERAGE: + fl_defuzzifier = new (std::nothrow) fl::WeightedAverage(); + break; + case SML_FUZZY_DEFUZZIFIER_WEIGHTED_SUM: + fl_defuzzifier = new (std::nothrow) fl::WeightedSum(); + break; + default: + sml_critical("Unknown defuzzifier %d", defuzzifier); + } + + if (!fl_defuzzifier) { + sml_critical("Failed to create defuzzifier"); + return false; + } + output_var->setDefuzzifier(fl_defuzzifier); + return true; +} + +bool +sml_fuzzy_bridge_output_set_accumulation(struct sml_variable *variable, + enum sml_fuzzy_snorm accumulation) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl::OutputVariable *output_var = dynamic_cast(fl_var); + if (!output_var) { + sml_critical("Not a output variable!"); + return false; + } + + output_var->fuzzyOutput()->setAccumulation(_get_snorm(accumulation)); + + return true; +} + +bool +sml_fuzzy_variable_set_range(struct sml_variable *variable, float min, float max) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl_var->setRange(min, max); + + return true; +} + +bool +sml_fuzzy_variable_get_range(struct sml_variable *variable, float *min, float *max) { + fl::Variable *fl_var = (fl::Variable*) variable; + if (min) + *min = fl_var->getMinimum(); + if (max) + *max = fl_var->getMaximum(); + return true; +} + +static bool +_find_variable(std::vector *list, fl::Variable *var, + uint16_t *index) +{ + uint16_t len, i; + len = list->size(); + for (i = 0; i < len; i++) + if (list->at(i) == var) { + if (index) + *index = i; + return true; + } + return false; +} + +static void +_debug_variables(struct sml_variables_list *list) +{ + uint16_t i, len, j, len_j; + struct sml_variable *var; + struct sml_fuzzy_term *term; + float val; + + len = sml_fuzzy_variables_list_get_length(list); + for (i = 0; i < len; i++) { + var = sml_fuzzy_variables_list_index(list, i); + val = sml_fuzzy_variable_get_value(var); + sml_debug("\t\t%s: %g", sml_fuzzy_variable_get_name(var), val); + len_j = sml_fuzzy_variable_terms_count(var); + for (j = 0; j < len_j; j++) { + term = sml_fuzzy_variable_get_term(var, j); + sml_debug("\t\t\t%s: %g", sml_fuzzy_term_get_name(term), + ((fl::Term *)term)->membership(val)); + } + } +} + +bool +sml_fuzzy_remove_variable(struct sml_fuzzy *fuzzy, struct sml_variable *variable) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl::Variable *removed_var = NULL; + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + uint16_t index; + + if (_find_variable((std::vector *) fuzzy->input_list, + fl_var, &index)) { + removed_var = engine->removeInputVariable(index); + fuzzy->input_terms_count -= removed_var->numberOfTerms(); + } else if (_find_variable((std::vector *) + fuzzy->output_list, fl_var, &index)) { + removed_var = engine->removeOutputVariable(index); + fuzzy->output_terms_count -= removed_var->numberOfTerms(); + } else { + sml_critical("Variable is not a valid input or output"); + return false; + } + + delete removed_var; + return true; +} + +bool +sml_fuzzy_find_variable(struct sml_variables_list *list, struct sml_variable *var, + uint16_t *index) +{ + return _find_variable((std::vector *) list, + (fl::Variable*) var, index); +} + +bool +sml_fuzzy_variable_find_term(struct sml_variable *var, struct sml_fuzzy_term *term, + uint16_t *index) +{ + uint16_t i, len; + + len = sml_fuzzy_variable_terms_count(var); + for (i = 0; i < len; i++) + if (sml_fuzzy_variable_get_term(var, i) == term) { + if (index) + *index = i; + return true; + } + + return false; +} + +struct sml_fuzzy_term* +sml_fuzzy_bridge_variable_add_term_rectangle(struct sml_fuzzy *fuzzy, + struct sml_variable *variable, + const char *name, float start, + float end, float height) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl::Term *term; + + term = new (std::nothrow) fl::Rectangle(name, start, end, height); + + if (!term) { + sml_critical("Failed to create term"); + return NULL; + } + + if (sml_fuzzy_is_input(fuzzy, variable)) + fuzzy->input_terms_count++; + else if (sml_fuzzy_is_output(fuzzy, variable)) + fuzzy->output_terms_count++; + else { + delete term; + return NULL; + } + + fl_var->addTerm(term); + return (struct sml_fuzzy_term*) term; +} + +struct sml_fuzzy_term* +sml_fuzzy_bridge_variable_add_term_triangle(struct sml_fuzzy *fuzzy, + struct sml_variable *variable, + const char *name, float vertex_a, + float vertex_b, float vertex_c, + float height) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl::Term *term; + + term = new (std::nothrow) fl::Triangle(name, vertex_a, vertex_b, vertex_c, + height); + + if (!term) { + sml_critical("Failed to create term"); + return NULL; + } + + if (sml_fuzzy_is_input(fuzzy, variable)) + fuzzy->input_terms_count++; + else if (sml_fuzzy_is_output(fuzzy, variable)) + fuzzy->output_terms_count++; + else { + delete term; + return NULL; + } + + fl_var->addTerm(term); + return (struct sml_fuzzy_term *) term; +} + +struct sml_fuzzy_term* +sml_fuzzy_bridge_variable_add_term_cosine(struct sml_fuzzy *fuzzy, + struct sml_variable *variable, + const char *name, float center, + float width, float height) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl::Term *term; + + term = new (std::nothrow) fl::Cosine(name, center, width, height); + if (!term) { + sml_critical("Failed to create term"); + return NULL; + } + + if (sml_fuzzy_is_input(fuzzy, variable)) + fuzzy->input_terms_count++; + else if (sml_fuzzy_is_output(fuzzy, variable)) + fuzzy->output_terms_count++; + else { + delete term; + return NULL; + } + + fl_var->addTerm(term); + return (struct sml_fuzzy_term *) term; +} + +struct sml_fuzzy_term* +sml_fuzzy_bridge_variable_add_term_gaussian(struct sml_fuzzy *fuzzy, + struct sml_variable *variable, + const char *name, float mean, + float standard_deviation, + float height) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl::Term *term; + + term = new (std::nothrow) fl::Gaussian(name, mean, standard_deviation, + height); + if (!term) { + sml_critical("Failed to create term"); + return NULL; + } + + if (sml_fuzzy_is_input(fuzzy, variable)) + fuzzy->input_terms_count++; + else if (sml_fuzzy_is_output(fuzzy, variable)) + fuzzy->output_terms_count++; + else { + delete term; + return NULL; + } + + fl_var->addTerm(term); + return (struct sml_fuzzy_term *) term; +} + +struct sml_fuzzy_term* +sml_fuzzy_bridge_variable_add_term_ramp(struct sml_fuzzy *fuzzy, + struct sml_variable *variable, + const char *name, float start, + float end, float height) +{ + fl::Variable *fl_var = (fl::Variable*) variable; + fl::Term *term; + + term = new (std::nothrow) fl::Ramp(name, start, end, height); + if (!term) { + sml_critical("Failed to create term"); + return NULL; + } + + if (sml_fuzzy_is_input(fuzzy, variable)) + fuzzy->input_terms_count++; + else if (sml_fuzzy_is_output(fuzzy, variable)) + fuzzy->output_terms_count++; + else { + delete term; + return NULL; + } + + fl_var->addTerm(term); + return (struct sml_fuzzy_term *) term; +} + +bool +sml_fuzzy_is_input(struct sml_fuzzy *fuzzy, struct sml_variable *variable) +{ + fl::InputVariable *input_var; + + input_var = dynamic_cast((fl::Variable*) variable); + if (!input_var) + return false; + + return _is_in_list(fuzzy->input_list, input_var); +} + +bool +sml_fuzzy_is_output(struct sml_fuzzy *fuzzy, struct sml_variable *variable) +{ + fl::OutputVariable *output_var; + + output_var = dynamic_cast((fl::Variable*) variable); + if (!output_var) + return false; + + return _is_in_list(fuzzy->output_list, output_var); + +} + +bool +sml_fuzzy_is_rule_block_empty(struct sml_fuzzy *fuzzy) +{ + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + + if (engine->numberOfRuleBlocks() == 0) + return true; + + return engine->getRuleBlock(0)->numberOfRules() == 0; +} + +struct sml_fuzzy_rule * +sml_fuzzy_rule_add(struct sml_fuzzy *fuzzy, const char *rule) +{ + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + fl::RuleBlock *block = engine->getRuleBlock(0); + fl::Rule *rule_obj; + + try { + rule_obj = fl::Rule::parse(rule, engine); + block->addRule(rule_obj); + } catch (fl::Exception e) { + sml_critical("%s", e.getWhat().c_str()); + return NULL; + } + + return (struct sml_fuzzy_rule *) rule_obj; +} + +bool +sml_fuzzy_rule_free(struct sml_fuzzy *fuzzy, struct sml_fuzzy_rule *rule) +{ + uint16_t index = 0; + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + fl::RuleBlock *block = engine->getRuleBlock(0); + std::vector& rules = block->rules(); + + for (std::vector::const_iterator it = + rules.begin(); + it != rules.end(); ++it, index++) { + if (*it == (void *)rule) { + delete block->removeRule(index); + return true; + } + } + + return false; +} + +bool +sml_fuzzy_term_get_range(struct sml_fuzzy_term *term, float *min, float *max) { + fl::Term *fl_term = (fl::Term*) term; + fl::Rectangle *rect; + fl::Triangle *triangle; + fl::Ramp *ramp; + + rect = dynamic_cast(fl_term); + if (rect) { + if (min) + *min = rect->getStart(); + if (max) + *max = rect->getEnd(); + return true; + } + + triangle = dynamic_cast(fl_term); + if (triangle) { + if (min) + *min = triangle->getVertexA(); + if (max) + *max = triangle->getVertexC(); + return true; + } + + ramp = dynamic_cast(fl_term); + if (ramp) { + if (min) + *min = fmin(ramp->getStart(), ramp->getEnd()); + if (max) + *max = fmax(ramp->getStart(), ramp->getEnd()); + return true; + } + + return false; +} + +bool +sml_fuzzy_term_set_range(struct sml_fuzzy_term *term, float min, float max) { + fl::Term *fl_term = (fl::Term*) term; + fl::Rectangle *rect; + fl::Triangle *triangle; + fl::Ramp *ramp; + + rect = dynamic_cast(fl_term); + if (rect) { + rect->setStart(min); + rect->setEnd(max); + return true; + } + + triangle = dynamic_cast(fl_term); + if (triangle) { + triangle->setVertexA(min); + triangle->setVertexB((min + max) / 2); + triangle->setVertexC(max); + return true; + } + + ramp = dynamic_cast(fl_term); + if (ramp) { + if (ramp->direction() == fl::Ramp::POSITIVE) { + ramp->setStart(min); + ramp->setEnd(max); + } else { + ramp->setStart(max); + ramp->setEnd(min); + } + return true; + } + + return false; +} + +int +sml_fuzzy_bridge_variable_remove_term(struct sml_variable *variable, + uint16_t term_num) +{ + fl::Term *term; + fl::Variable *fl_var = (fl::Variable*) variable; + + term = fl_var->removeTerm(term_num); + if (term) { + delete term; + return true; + } + + return -EINVAL; +} + +void +sml_fuzzy_debug(struct sml_fuzzy *fuzzy) +{ + sml_debug("Fuzzy Bridge:"); + sml_debug("\tInputs(%d) {", + sml_fuzzy_variables_list_get_length(fuzzy->input_list)); + _debug_variables(fuzzy->input_list); + sml_debug("\t}"); + sml_debug("\tOutputs(%d) {", + sml_fuzzy_variables_list_get_length(fuzzy->output_list)); + _debug_variables(fuzzy->output_list); + sml_debug("\t}"); + +} + +struct sml_variables_list * +sml_fuzzy_variables_list_new(struct sml_fuzzy *fuzzy, struct sol_vector *indexes) +{ + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + uint16_t i, *idx; + void *v; + std::vector *changed = + new (std::nothrow) std::vector(); + + if (!changed) { + sml_critical("Could not alloc the variables list!"); + return NULL; + } + + if (indexes) { + try { + SOL_VECTOR_FOREACH_IDX(indexes, v, i) { + idx = (uint16_t *)v; + changed->push_back(engine->getOutputVariable(*idx)); + } + } catch (const std::out_of_range &oor) { + sml_critical("Array out of bounds. error:%s", oor.what()); + goto err_exit; + } + } + return (struct sml_variables_list *)changed; + +err_exit: + delete changed; + return NULL; +} + +void +sml_fuzzy_variables_list_free(struct sml_variables_list *list) { + std::vector *vector = + (std::vector *)list; + delete vector; +} + +bool +sml_fuzzy_set_read_values(struct sml_fuzzy *fuzzy, struct sml_variables_list *outputs) { + fl::Engine *engine = (fl::Engine*)fuzzy->engine; + std::vector *vector = + (std::vector *)outputs; + std::vector all_outputs = engine->outputVariables(); + + for (std::vector::const_iterator it = + all_outputs.begin(); it != all_outputs.end(); ++it) { + if (std::find(vector->begin(), vector->end(), *it) == vector->end()) + (*it)->setOutputValue((*it)->getPreviousOutputValue()); + } + return true; +} diff --git a/sml/sml_fuzzy/src/sml_fuzzy_bridge.h b/sml/sml_fuzzy/src/sml_fuzzy_bridge.h new file mode 100644 index 0000000..1cf8352 --- /dev/null +++ b/sml/sml_fuzzy/src/sml_fuzzy_bridge.h @@ -0,0 +1,115 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#include +#include +#include "sml_measure.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct sml_fuzzy_term; +struct sml_fuzzy_rule; + +struct sml_fuzzy { + void *engine; + struct sml_variables_list *input_list; + struct sml_variables_list *output_list; + uint16_t input_terms_count; + uint16_t output_terms_count; +}; + +struct sml_fuzzy *sml_get_fuzzy(struct sml_engine *sml); +struct sml_fuzzy *sml_fuzzy_bridge_new(void); + +struct sml_measure *sml_fuzzy_get_membership_values(struct sml_fuzzy *fuzzy); +int sml_fuzzy_get_membership_values_output(struct sml_fuzzy *fuzzy, struct sml_matrix *output_membership); +int sml_fuzzy_process_output(struct sml_fuzzy *fuzzy); +bool sml_fuzzy_load_file(struct sml_fuzzy *fuzzy, const char *filename); +bool sml_fuzzy_save_file(struct sml_fuzzy *fuzzy, const char *filename); +void sml_fuzzy_destroy(struct sml_fuzzy *fuzzy); + +bool sml_fuzzy_bridge_conjunction_set(struct sml_fuzzy *fuzzy, enum sml_fuzzy_tnorm norm); +bool sml_fuzzy_bridge_disjunction_set(struct sml_fuzzy *fuzzy, enum sml_fuzzy_snorm norm); + +uint16_t sml_fuzzy_variables_list_get_length(struct sml_variables_list *list); +struct sml_variable *sml_fuzzy_variables_list_index(struct sml_variables_list *list, uint16_t index); + +struct sml_variable *sml_fuzzy_new_input(struct sml_fuzzy *fuzzy, const char *name); +struct sml_variable *sml_fuzzy_new_output(struct sml_fuzzy *fuzzy, const char *name); +struct sml_variable *sml_fuzzy_get_input(struct sml_fuzzy *fuzzy, const char *name); +struct sml_variable *sml_fuzzy_get_output(struct sml_fuzzy *fuzzy, const char *name); +const char *sml_fuzzy_variable_get_name(struct sml_variable *variable); +float sml_fuzzy_variable_get_value(struct sml_variable *variable); +void sml_fuzzy_variable_set_value(struct sml_variable *variable, float value); +uint16_t sml_fuzzy_variable_terms_count(struct sml_variable *variable); +void sml_fuzzy_variable_set_enabled(struct sml_variable *variable, bool enabled); +bool sml_fuzzy_variable_is_enabled(struct sml_variable *variable); +bool sml_fuzzy_remove_variable(struct sml_fuzzy *fuzzy, struct sml_variable *variable); + +bool sml_fuzzy_variable_set_range(struct sml_variable *variable, float min, float max); +bool sml_fuzzy_bridge_output_set_defuzzifier(struct sml_variable *variable, enum sml_fuzzy_defuzzifier defuzzifier, int defuzzifier_resolution); +bool sml_fuzzy_bridge_output_set_accumulation(struct sml_variable *variable, enum sml_fuzzy_snorm accumulation); +bool sml_fuzzy_bridge_output_set_default_value(struct sml_variable *variable, float default_value); + +bool sml_fuzzy_variable_get_range(struct sml_variable *variable, float *min, float *max); +struct sml_fuzzy_term *sml_fuzzy_bridge_variable_add_term_rectangle(struct sml_fuzzy *fuzzy, struct sml_variable *variable, const char *name, float start, float end, float height); +struct sml_fuzzy_term *sml_fuzzy_bridge_variable_add_term_triangle(struct sml_fuzzy *fuzzy, struct sml_variable *variable, const char *name, float vertex_a, float vertex_b, float vertex_c, float height); +struct sml_fuzzy_term *sml_fuzzy_bridge_variable_add_term_cosine(struct sml_fuzzy *fuzzy, struct sml_variable *variable, const char *name, float center, float width, float height); +struct sml_fuzzy_term *sml_fuzzy_bridge_variable_add_term_gaussian(struct sml_fuzzy *fuzzy, struct sml_variable *variable, const char *name, float mean, float standard_deviation, float height); +struct sml_fuzzy_term *sml_fuzzy_bridge_variable_add_term_ramp(struct sml_fuzzy *fuzzy, struct sml_variable *variable, const char *name, float start, float end, float height); +int sml_fuzzy_bridge_variable_remove_term(struct sml_variable *variable, uint16_t term_num); +struct sml_fuzzy_term *sml_fuzzy_variable_get_term(struct sml_variable *variable, uint16_t index); +const char *sml_fuzzy_term_get_name(struct sml_fuzzy_term *term); +bool sml_fuzzy_term_get_range(struct sml_fuzzy_term *term, float *min, float *max); +bool sml_fuzzy_term_set_range(struct sml_fuzzy_term *term, float min, float max); + +bool sml_fuzzy_is_input(struct sml_fuzzy *fuzzy, struct sml_variable *variable); +bool sml_fuzzy_is_output(struct sml_fuzzy *fuzzy, struct sml_variable *variable); +bool sml_fuzzy_is_rule_block_empty(struct sml_fuzzy *fuzzy); +struct sml_fuzzy_rule *sml_fuzzy_rule_add(struct sml_fuzzy *fuzzy, const char *rule); +bool sml_fuzzy_rule_free(struct sml_fuzzy *fuzzy, struct sml_fuzzy_rule *rule); +bool sml_fuzzy_find_variable(struct sml_variables_list *list, struct sml_variable *var, uint16_t *index); +void sml_fuzzy_update_terms_count(struct sml_fuzzy *fuzzy); +bool sml_fuzzy_variable_find_term(struct sml_variable *var, struct sml_fuzzy_term *term, uint16_t *index); +void sml_fuzzy_debug(struct sml_fuzzy *fuzzy); +struct sml_variables_list *sml_fuzzy_variables_list_new(struct sml_fuzzy *fuzzy, struct sol_vector *indexes); +void sml_fuzzy_variables_list_free(struct sml_variables_list *list); +bool sml_fuzzy_set_read_values(struct sml_fuzzy *fuzzy, struct sml_variables_list *outputs); + +#ifdef __cplusplus +} +#endif diff --git a/sml/sml_fuzzy/src/sml_fuzzy_support.c b/sml/sml_fuzzy/src/sml_fuzzy_support.c new file mode 100644 index 0000000..d757c9e --- /dev/null +++ b/sml/sml_fuzzy/src/sml_fuzzy_support.c @@ -0,0 +1,180 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "macros.h" +#include "sml_log.h" + +API_EXPORT bool +sml_fuzzy_set_variable_terms_auto_balance(struct sml_object *sml, + bool variable_terms_auto_balance) +{ + sml_critical("Fuzzy engine not supported."); + return false; +} + +API_EXPORT bool +sml_fuzzy_set_rule_weight_threshold(struct sml_object *sml, float + weight_threshold) +{ + sml_critical("Fuzzy engine not supported."); + return false; +} + +API_EXPORT bool +sml_fuzzy_conjunction_set(struct sml_object *sml, enum sml_fuzzy_tnorm norm) +{ + sml_critical("Fuzzy engine not supported."); + return false; +} + +API_EXPORT bool +sml_fuzzy_disjunction_set(struct sml_object *sml, enum sml_fuzzy_snorm norm) +{ + sml_critical("Fuzzy engine not supported."); + return false; +} + +API_EXPORT bool +sml_fuzzy_variable_remove_term(struct sml_object *sml, struct sml_variable *var, + struct sml_fuzzy_term *term) +{ + sml_critical("Fuzzy engine not supported."); + return false; +} + +API_EXPORT struct sml_fuzzy_term * +sml_fuzzy_variable_add_term_rectangle(struct sml_object *sml, struct + sml_variable *variable, + const char *name, float start, float end, + float height) +{ + sml_critical("Fuzzy engine not supported."); + return NULL; +} + +API_EXPORT struct sml_fuzzy_term * +sml_fuzzy_variable_add_term_triangle(struct sml_object *sml, struct + sml_variable *variable, + const char *name, float vertex_a, + float vertex_b, float vertex_c, + float height) +{ + sml_critical("Fuzzy engine not supported."); + return NULL; +} + +API_EXPORT struct sml_fuzzy_term * +sml_fuzzy_variable_add_term_cosine(struct sml_object *sml, struct + sml_variable *variable, + const char *name, float center, float width, + float height) +{ + sml_critical("Fuzzy engine not supported."); + return NULL; +} + +API_EXPORT struct sml_fuzzy_term * +sml_fuzzy_variable_add_term_gaussian(struct sml_object *sml, struct + sml_variable *variable, + const char *name, float mean, + float standard_deviation, float height) +{ + sml_critical("Fuzzy engine not supported."); + return NULL; +} + +API_EXPORT struct sml_fuzzy_term * +sml_fuzzy_variable_add_term_ramp(struct sml_object *sml, struct + sml_variable *variable, + const char *name, float start, float end, + float height) +{ + sml_critical("Fuzzy engine not supported."); + return NULL; +} + +API_EXPORT bool +sml_fuzzy_set_simplification_disabled(struct sml_object *sml, bool disabled) +{ + sml_critical("Fuzzy engine not supported."); + return false; +} + +API_EXPORT struct sml_object * +sml_fuzzy_new(void) +{ + sml_critical("Fuzzy engine not supported."); + return NULL; +} + +API_EXPORT bool +sml_is_fuzzy(struct sml_object *sml) +{ + sml_critical("Fuzzy engine not supported."); + return false; +} + +API_EXPORT bool +sml_fuzzy_output_set_defuzzifier(struct sml_object *sml, struct + sml_variable *var, + enum sml_fuzzy_defuzzifier defuzzifier, + int defuzzifier_resolution) +{ + sml_critical("Fuzzy engine not supported."); + return false; +} + +API_EXPORT bool +sml_fuzzy_output_set_default_value(struct sml_object *sml, struct + sml_variable *var, + float default_value) +{ + sml_critical("Fuzzy engine not supported."); + return false; +} + +API_EXPORT bool +sml_fuzzy_output_set_accumulation(struct sml_object *sml, struct + sml_variable *var, + enum sml_fuzzy_snorm accumulation) +{ + sml_critical("Fuzzy engine not supported."); + return false; +} + +API_EXPORT bool +sml_fuzzy_supported(void) +{ + return false; +} diff --git a/sml/sml_fuzzy/src/sml_measure.c b/sml/sml_fuzzy/src/sml_measure.c new file mode 100644 index 0000000..beb7518 --- /dev/null +++ b/sml/sml_fuzzy/src/sml_measure.c @@ -0,0 +1,92 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sml_measure.h" +#include "sml_log.h" +#include + +struct sml_measure * +sml_measure_new(uint16_t input_elem_size, uint16_t output_elem_size) +{ + struct sml_measure *measure = malloc(sizeof(struct sml_measure)); + + if (!measure) + return NULL; + sml_measure_init(measure, input_elem_size, output_elem_size); + return measure; +} + +void +sml_measure_free(struct sml_measure *measure) +{ + if (!measure) + return; + sml_measure_clear(measure); + free(measure); +} + + +void +sml_measure_init(struct sml_measure *measure, uint16_t input_elem_size, + uint16_t output_elem_size) +{ + sml_matrix_init(&measure->inputs, input_elem_size); + sml_matrix_init(&measure->outputs, output_elem_size); +} + +void +sml_measure_clear(struct sml_measure *measure) +{ + sml_matrix_clear(&measure->inputs); + sml_matrix_clear(&measure->outputs); +} + +void +sml_measure_debug(struct sml_measure *measure, sml_matrix_convert_cb convert) +{ + sml_debug("\tInputs:"); + sml_matrix_debug(&measure->inputs, convert); + sml_debug("\tOutputs:"); + sml_matrix_debug(&measure->outputs, convert); +} + +void +sml_measure_remove_input_variable(struct sml_measure *measure, uint16_t pos) +{ + sml_matrix_remove_line(&measure->inputs, pos); +} + +void +sml_measure_remove_output_variable(struct sml_measure *measure, uint16_t pos) +{ + sml_matrix_remove_line(&measure->outputs, pos); +} diff --git a/sml/sml_fuzzy/src/sml_measure.h b/sml/sml_fuzzy/src/sml_measure.h new file mode 100644 index 0000000..5aef8dd --- /dev/null +++ b/sml/sml_fuzzy/src/sml_measure.h @@ -0,0 +1,56 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#include +#include "sml_matrix.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct sml_measure { + struct sml_matrix inputs; + struct sml_matrix outputs; +}; + +struct sml_measure *sml_measure_new(uint16_t input_elem_size, uint16_t output_elem_size); +void sml_measure_free(struct sml_measure *measure); +void sml_measure_remove_input_variable(struct sml_measure *measure, uint16_t pos); +void sml_measure_remove_output_variable(struct sml_measure *measure, uint16_t pos); +void sml_measure_debug(struct sml_measure *measure, sml_matrix_convert_cb convert); +void sml_measure_init(struct sml_measure *measure, uint16_t input_elem_size, uint16_t output_elem_size); +void sml_measure_clear(struct sml_measure *measure); + +#ifdef __cplusplus +} +#endif diff --git a/sml/sml_fuzzy/src/sml_observation.c b/sml/sml_fuzzy/src/sml_observation.c new file mode 100644 index 0000000..a3f5892 --- /dev/null +++ b/sml/sml_fuzzy/src/sml_observation.c @@ -0,0 +1,929 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sml_observation.h" +#include "sml_fuzzy_bridge.h" +#include "sml_bit_array.h" +#include +#include +#include + +#include +#include +#include +#include + +#define RULE_WEIGHT 1 +#define WEIGHT_THRESHOLD (0.1) +#define FLOAT_THRESHOLD (0.01) + +struct sml_observation { + //Replace this structure with a struct sml_matrix + struct sol_vector output_weights; + struct sol_vector input_membership; +}; + +static void +_input_set(struct sml_observation *observation, uint16_t input, uint16_t term, + uint8_t value) +{ + struct sml_bit_array *array; + + array = sol_vector_get(&observation->input_membership, input); + if (!array) + return; + + sml_bit_array_set(array, term, value); +} + + +static int +_input_membership_initialize(struct sml_fuzzy *fuzzy, + struct sml_observation *obs) +{ + uint16_t len, i, terms_len; + struct sml_bit_array *array; + struct sml_variable *var; + int error; + + len = sml_fuzzy_variables_list_get_length(fuzzy->input_list); + for (i = 0; i < len; i++) { + if (i >= obs->input_membership.len) { + array = sol_vector_append(&obs->input_membership); + if (!array) + return -ENOMEM; + sml_bit_array_init(array); + } else + array = sol_vector_get(&obs->input_membership, i); + + var = sml_fuzzy_variables_list_index(fuzzy->input_list, i); + terms_len = sml_fuzzy_variable_terms_count(var); + error = sml_bit_array_size_set(array, terms_len, 0); + if (error != 0) + return error; + } + + return 0; +} + +static int +_output_weights_initialize(struct sml_fuzzy *fuzzy, struct sml_observation *obs) +{ + uint16_t len, i, j, terms_len; + uint8_t *val; + struct sol_vector *vector; + struct sml_variable *var; + + len = sml_fuzzy_variables_list_get_length(fuzzy->output_list); + for (i = 0; i < len; i++) { + if (i >= obs->output_weights.len) { + vector = sol_vector_append(&obs->output_weights); + if (!vector) + return -ENOMEM; + sol_vector_init(vector, sizeof(uint8_t)); + } else + vector = sol_vector_get(&obs->output_weights, i); + + var = sml_fuzzy_variables_list_index(fuzzy->output_list, i); + terms_len = sml_fuzzy_variable_terms_count(var); + for (j = vector->len; j < terms_len; j++) { + val = sol_vector_append(vector); + *val = 0; + } + } + return 0; +} + +static void +_input_membership_free(struct sml_observation *observation) +{ + uint16_t i; + + for (i = 0; i < observation->input_membership.len; i++) + sml_bit_array_clear(sol_vector_get(&observation->input_membership, i)); + sol_vector_clear(&observation->input_membership); +} + +static void +_output_weights_free(struct sml_observation *observation) +{ + uint16_t i; + + for (i = 0; i < observation->output_weights.len; i++) + sol_vector_clear(sol_vector_get(&observation->output_weights, i)); + sol_vector_clear(&observation->output_weights); +} + +static int +_output_set(struct sml_fuzzy *fuzzy, struct sml_observation *obs, uint16_t + output, + uint16_t term, uint8_t data) +{ + struct sol_vector *vector; + uint8_t *val; + int error; + + if (output >= obs->output_weights.len || + term >= *((uint8_t *)sol_vector_get(&obs->output_weights, output))) { + if ((error = _output_weights_initialize(fuzzy, obs))) + return error; + } + + vector = sol_vector_get(&obs->output_weights, output); + if (!vector) + return -ENODATA; + + val = sol_vector_get(vector, term); + if (!val) + return -ENODATA; + + *val = data; + return 0; +} + +static uint8_t +_output_get(struct sml_observation *observation, uint16_t output, uint16_t term) +{ + struct sol_vector *terms; + uint8_t *val; + + if (output >= observation->output_weights.len) + return 0; + + terms = sol_vector_get(&observation->output_weights, output); + if (term >= terms->len) + return 0; + + val = sol_vector_get(terms, term); + if (!val) + return 0; + return *val; +} + +static struct sml_observation * +_observation_alloc(struct sml_fuzzy *fuzzy) +{ + struct sml_observation *observation = malloc( + sizeof(struct sml_observation)); + + if (!observation) + return NULL; + + sol_vector_init(&observation->output_weights, sizeof(struct sol_vector)); + if (_output_weights_initialize(fuzzy, observation)) + goto alloc_error; + + sol_vector_init(&observation->input_membership, + sizeof(struct sml_bit_array)); + if (_input_membership_initialize(fuzzy, observation) != 0) + goto alloc_error; + + return observation; + +alloc_error: + _output_weights_free(observation); + _input_membership_free(observation); + free(observation); + return NULL; +} + +static bool +_set_input_observations_values(struct sml_observation *observation, + struct sml_variables_list *list, struct sml_matrix *values) +{ + uint16_t len, i, j; + float *tmp, val; + bool set = false; + + len = sml_fuzzy_variables_list_get_length(list); + for (i = 0; i < len; i++) { + struct sml_variable *variable = sml_fuzzy_variables_list_index(list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(variable); + if (sml_fuzzy_variable_is_enabled(variable)) { + for (j = 0; j < terms_len; j++) { + val = sml_matrix_cast_get(values, i, j, tmp, float); + if (val > VARIABLE_MEMBERSHIP_THRESHOLD) { + _input_set(observation, i, j, SET); + set = true; + } else + _input_set(observation, i, j, UNSET); + } + } + } + + return set; +} + +uint8_t +sml_observation_input_term_get(struct sml_observation *obs, uint16_t input, + uint16_t term) +{ + struct sml_bit_array *array; + + array = sol_vector_get(&obs->input_membership, input); + if (!array) + return 0; + + return sml_bit_array_get(array, term); +} + +void +sml_observation_free(struct sml_observation *observation) +{ + _output_weights_free(observation); + _input_membership_free(observation); + free(observation); +} + +int +sml_observation_new(struct sml_fuzzy *fuzzy, struct sml_measure *measure, + struct sml_observation **observation) +{ + struct sml_observation *tmp_obs; + + if (!observation) + return -EINVAL; + + if (!fuzzy->output_terms_count || !fuzzy->input_terms_count) { + *observation = NULL; + return 0; + } + + tmp_obs = _observation_alloc(fuzzy); + if (!tmp_obs) { + sml_critical("Failed to create new tmp_obs"); + return -errno; + } + + if (!_set_input_observations_values(tmp_obs, fuzzy->input_list, + &measure->inputs)) { + sml_observation_free(tmp_obs); + *observation = NULL; + return 0; + } + + *observation = tmp_obs; + return 0; +} + +bool +sml_observation_enabled_input_values_equals(struct sml_fuzzy *fuzzy, + struct sml_observation *observation, + struct sml_measure *measure) +{ + uint16_t i, j, len; + float val, *tmp; + struct sml_variable *var; + + len = sml_fuzzy_variables_list_get_length(fuzzy->input_list); + for (i = 0; i < len; i++) { + var = sml_fuzzy_variables_list_index(fuzzy->input_list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(var); + if (sml_fuzzy_variable_is_enabled(var)) { + for (j = 0; j < terms_len; j++) { + val = sml_matrix_cast_get(&measure->inputs, i, j, tmp, float); + uint8_t set = val > VARIABLE_MEMBERSHIP_THRESHOLD; + if (sml_observation_input_term_get(observation, i, j) != set) + return false; + } + } + } + + return true; +} + +bool +sml_observation_enabled_input_equals(struct sml_fuzzy *fuzzy, + struct sml_observation *obs1, + struct sml_observation *obs2) +{ + uint16_t i, j, len; + struct sml_variable *var; + + len = sml_fuzzy_variables_list_get_length(fuzzy->input_list); + for (i = 0; i < len; i++) { + var = sml_fuzzy_variables_list_index(fuzzy->input_list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(var); + if (sml_fuzzy_variable_is_enabled(var)) { + for (j = 0; j < terms_len; j++) { + if (sml_observation_input_term_get(obs1, i, j) != + sml_observation_input_term_get(obs2, i, j)) + return false; + } + } + } + + return true; +} + +bool +sml_observation_output_equals(struct sml_fuzzy *fuzzy, + struct sml_observation *obs1, struct sml_observation *obs2, + uint16_t output_number) +{ + uint16_t i, terms_len, total_weight1 = 0, total_weight2 = 0; + struct sml_variable *var; + + var = sml_fuzzy_variables_list_index(fuzzy->output_list, output_number); + terms_len = sml_fuzzy_variable_terms_count(var); + for (i = 0; i < terms_len; i++) { + total_weight1 += _output_get(obs1, output_number, i); + total_weight2 += _output_get(obs2, output_number, i); + } + if (total_weight1 == 0 && total_weight2 == 0) + return true; + + if (total_weight1 == 0 || total_weight2 == 0) + return false; + + for (i = 0; i < terms_len; i++) + if (fabs((_output_get(obs1, output_number, i) / total_weight1) - + (_output_get(obs2, output_number, i) / total_weight2)) > + WEIGHT_THRESHOLD) + return false; + + return true; +} + +bool +sml_observation_input_equals(struct sml_fuzzy *fuzzy, + struct sml_observation *obs1, struct sml_observation *obs2) +{ + uint16_t i, j, len; + struct sml_variable *var; + + len = sml_fuzzy_variables_list_get_length(fuzzy->input_list); + for (i = 0; i < len; i++) { + var = sml_fuzzy_variables_list_index(fuzzy->input_list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(var); + for (j = 0; j < terms_len; j++) { + if (sml_observation_input_term_get(obs1, i, j) != + sml_observation_input_term_get(obs2, i, j)) + return false; + } + } + + return true; +} + +int +sml_observation_hit(struct sml_fuzzy *fuzzy, + struct sml_observation *observation, struct sml_measure *measure, bool *hit) +{ + uint16_t len, i, j, index = 0; + int error; + float val, *tmp; + bool tmp_hit = false; + struct sml_variable *variable; + + len = sml_fuzzy_variables_list_get_length(fuzzy->output_list); + for (i = 0; i < len; i++) { + variable = sml_fuzzy_variables_list_index(fuzzy->output_list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(variable); + bool reduce_weight = false; + + for (j = 0; j < terms_len; j++) { + val = sml_matrix_cast_get(&measure->outputs, i, j, tmp, float); + uint16_t output_weight = _output_get(observation, i, j); + + if (val >= VARIABLE_MEMBERSHIP_THRESHOLD) { + if (output_weight >= UINT8_MAX - RULE_WEIGHT) { + output_weight = UINT8_MAX; + reduce_weight = true; + } else + output_weight += RULE_WEIGHT; + if ((error = _output_set(fuzzy, observation, i, j, + output_weight))) + return error; + tmp_hit = true; + } else if (output_weight > 0 && + val < VARIABLE_MEMBERSHIP_THRESHOLD) { + if (output_weight < RULE_WEIGHT) + output_weight = 0; + else + output_weight -= RULE_WEIGHT; + if ((error = _output_set(fuzzy, observation, i, j, + output_weight))) + return error; + tmp_hit = true; + } + index++; + } + + if (reduce_weight) + for (j = 0; j < terms_len; j++) + _output_set(fuzzy, observation, i, j, + _output_get(observation, i, j)); + } + + if (hit) + *hit = tmp_hit; + return 0; +} + +static bool +_is_input_relevant(struct sml_bit_array *relevant_inputs, uint16_t i) +{ + if (!relevant_inputs) + return true; + return sml_bit_array_get(relevant_inputs, i) == SET; +} + +static bool +_observation_input_rule_generate(struct sml_variables_list *list, + struct sml_bit_array *relevant_inputs, + struct sml_observation *observation, struct sml_string *str) +{ + uint16_t len, i, j; + bool is_first = true, r; + struct sml_variable *variable; + struct sml_fuzzy_term *term; + + len = sml_fuzzy_variables_list_get_length(list); + for (i = 0; i < len; i++) { + variable = sml_fuzzy_variables_list_index(list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(variable); + if (sml_fuzzy_variable_is_enabled(variable) && + _is_input_relevant(relevant_inputs, i)) { + for (j = 0; j < terms_len; j++) { + term = sml_fuzzy_variable_get_term(variable, j); + uint8_t val = sml_observation_input_term_get(observation, + i, j); + if (val == SET) { + if (is_first) + is_first = false; + else { + r = sml_string_append(str, " and "); + if (!r) { + sml_critical("Could not append \"and\" to the " \ + "string"); + return false; + } + } + r = sml_string_append_printf(str, "%s is %s", + sml_fuzzy_variable_get_name(variable), + sml_fuzzy_term_get_name(term)); + if (!r) { + sml_critical("Could not append the variable name " \ + "and term to the string"); + return false; + } + } + } + } + } + return !is_first; +} + +static void +_observation_output_rule_generate(struct sml_variables_list *list, + float *output_weights, + struct sml_string *prefix, + float weight_threshold, + uint16_t output_number, + sml_process_str_cb process_cb, void *data) +{ + uint16_t i, j, len, index = 0; + bool r; + + len = sml_fuzzy_variables_list_get_length(list); + for (i = 0; i < len; i++) { + struct sml_variable *v = sml_fuzzy_variables_list_index(list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(v); + if (i != output_number) { + index += terms_len; + continue; + } + + for (j = 0; j < terms_len; j++) { + struct sml_fuzzy_term *term = sml_fuzzy_variable_get_term(v, j); + float output_weight = output_weights[index]; + if (output_weight > weight_threshold) { + struct sml_string *str_observation = + sml_string_new(sml_string_get_string(prefix)); + if (!str_observation) { + sml_critical("Could not alloc the sml string"); + continue; + } + r = sml_string_append_printf(str_observation, "%s is %s", + sml_fuzzy_variable_get_name(v), + sml_fuzzy_term_get_name(term)); + if (r) { + if (output_weight < (1 - FLOAT_THRESHOLD)) + r = sml_string_append_printf( + str_observation, " with %f", output_weight); + if (r) + process_cb(sml_string_get_string(str_observation), + data); + else + sml_critical("Couild not append the rule weight"); + } else + sml_critical("Could not append the variable name and term"); + + sml_string_free(str_observation); + } + index++; + } + break; + } +} + +void +sml_observation_rule_generate(struct sml_fuzzy *fuzzy, + struct sol_ptr_vector *observation_list, + float weight_threshold, + struct sml_bit_array *relevant_inputs, + float *output_weights, + uint16_t output_number, + sml_process_str_cb process_cb, void *data) +{ + struct sml_observation *first_observation = + sol_ptr_vector_get(observation_list, 0); + bool success; + struct sml_string *str = sml_string_new("if "); + + if (!str) { + sml_critical("Could not alloc the sml string"); + return; + } + + success = _observation_input_rule_generate(fuzzy->input_list, + relevant_inputs, + first_observation, str); + if (!success) { + sml_critical("Generating observation string failed"); + goto error; + } + + if (!sml_string_append(str, " then ")) { + sml_critical("Could not append to \"then\" to the string"); + goto error; + } + + _observation_output_rule_generate(fuzzy->output_list, + output_weights, str, weight_threshold, + output_number, + process_cb, data); +error: + sml_string_free(str); +} + +void +sml_observation_debug(struct sml_observation *observation) +{ + uint16_t i, j; + struct sml_string *str = sml_string_new("\t"); + struct sol_vector *term_weights; + struct sml_bit_array *term_membership; + uint8_t *val; + + sml_string_append_printf(str, "Observation {"); + sml_string_append_printf(str, "Inputs (%d) {", + observation->input_membership.len); + SOL_VECTOR_FOREACH_IDX (&observation->input_membership, term_membership, + i) { + if (i > 0) + sml_string_append(str, ", "); + sml_string_append_printf(str, "{"); + for (j = 0; j < term_membership->size; j++) { + if ( j > 0) + sml_string_append(str, ", "); + sml_string_append_printf(str, "%d", + sml_bit_array_get(term_membership, j)); + } + sml_string_append(str, "}"); + } + sml_string_append(str, "}"); + + sml_string_append_printf(str, ", Outputs (%d) {", + observation->output_weights.len); + + SOL_VECTOR_FOREACH_IDX (&observation->output_weights, term_weights, i) { + if (i > 0) + sml_string_append(str, ", "); + sml_string_append_printf(str, "{"); + SOL_VECTOR_FOREACH_IDX (term_weights, val, j) { + if ( j > 0) + sml_string_append(str, ", "); + sml_string_append_printf(str, "%d", *val); + } + sml_string_append(str, "}"); + } + + sml_string_append(str, "}"); + sml_string_append(str, "}"); + sml_debug("%s", sml_string_get_string(str)); + + sml_string_free(str); +} + +int +sml_observation_remove_variables(struct sml_observation *observation, + bool *inputs_to_remove, + bool *outputs_to_remove) +{ + uint16_t i, removed, len; + + if (inputs_to_remove) { + removed = 0; + len = observation->input_membership.len; + for (i = 0; i < len; i++) { + if (inputs_to_remove[i]) { + sml_bit_array_clear(sol_vector_get( + &observation->input_membership, i - removed)); + sol_vector_del(&observation->input_membership, i - removed); + removed++; + } + } + } + + if (outputs_to_remove) { + removed = 0; + len = observation->output_weights.len; + for (i = 0; i < len; i++) { + if (outputs_to_remove[i]) { + sol_vector_clear(sol_vector_get(&observation->output_weights, + i - removed)); + sol_vector_del(&observation->output_weights, i - removed); + removed++; + } + } + } + + return 0; +} + +bool +sml_observation_is_empty(struct sml_observation *observation) +{ + return !observation->output_weights.len || + !observation->input_membership.len; +} + +int +sml_observation_merge_output(struct sml_fuzzy *fuzzy, + struct sml_observation *observation1, struct sml_observation *observation2) +{ + uint16_t i, j; + struct sol_vector *term_weights; + uint8_t *val; + int error; + + if ((error = _output_weights_initialize(fuzzy, observation1))) + return error; + + SOL_VECTOR_FOREACH_IDX (&observation1->output_weights, term_weights, i) { + SOL_VECTOR_FOREACH_IDX (term_weights, val, j) + *val = *val + _output_get(observation2, i, j); + } + + return 0; +} + +bool +sml_observation_is_base(struct sml_fuzzy *fuzzy, + struct sml_observation *observation) +{ + uint16_t i, j, len; + struct sml_variable *var; + + len = sml_fuzzy_variables_list_get_length(fuzzy->input_list); + for (i = 0; i < len; i++) { + var = sml_fuzzy_variables_list_index(fuzzy->input_list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(var); + if (!sml_fuzzy_variable_is_enabled(var)) { + for (j = 0; j < terms_len; j++) { + if (sml_observation_input_term_get(observation, i, j)) + return false; + } + } + } + + return true; +} + +void +sml_observation_fill_output_weights(struct sml_fuzzy *fuzzy, + struct sml_observation *obs, uint16_t *output_weights) +{ + uint16_t index, len, i, j, terms_len; + struct sml_variables_list *list; + + index = 0; + list = fuzzy->output_list; + len = sml_fuzzy_variables_list_get_length(list); + for (i = 0; i < len; i++) { + struct sml_variable *variable = sml_fuzzy_variables_list_index(list, i); + terms_len = sml_fuzzy_variable_terms_count(variable); + for (j = 0; j < terms_len; j++) + output_weights[index++] += _output_get(obs, i, j); + } +} + +bool +sml_observation_save(struct sml_observation *obs, FILE *f) +{ + uint16_t input_byte_size, i; + struct sol_vector *vector; + struct sml_bit_array *array; + + if (fwrite(&obs->output_weights.len, sizeof(uint16_t), 1, f) < 1) + return false; + + SOL_VECTOR_FOREACH_IDX (&obs->output_weights, vector, i) { + if (fwrite(&vector->len, sizeof(uint16_t), 1, f) < 1) + return false; + + if (fwrite(vector->data, sizeof(uint8_t), vector->len, f) < vector->len) + return false; + } + + if (fwrite(&obs->input_membership.len, sizeof(uint16_t), 1, f) < 1) + return false; + + SOL_VECTOR_FOREACH_IDX (&obs->input_membership, array, i) { + if (fwrite(&array->size, sizeof(uint16_t), 1, f) < 1) + return false; + + input_byte_size = sml_bit_array_byte_size_get(array); + if (fwrite(array->data, sizeof(uint8_t), input_byte_size, f) + < input_byte_size) + return false; + + } + + return true; +} + +struct sml_observation * +sml_observation_load(FILE *f) +{ + struct sml_observation *obs; + uint16_t i, j, input_size, output_size; + + obs = malloc(sizeof(struct sml_observation)); + + if (fread(&output_size, sizeof(uint16_t), 1, f) < 1) + goto error; + sol_vector_init(&obs->output_weights, sizeof(struct sol_vector)); + for (i = 0; i < output_size; i++) { + struct sol_vector *vector; + uint16_t terms_size; + + vector = sol_vector_append(&obs->output_weights); + sol_vector_init(vector, sizeof(uint8_t)); + + if (fread(&terms_size, sizeof(uint16_t), 1, f) < 1) + goto error; + for (j = 0; j < terms_size; j++) { + uint8_t *val = sol_vector_append(vector); + if (fread(val, sizeof(uint8_t), 1, f) < 1) + goto error; + } + } + + if (fread(&input_size, sizeof(uint16_t), 1, f) < 1) + goto error; + sol_vector_init(&obs->input_membership, sizeof(struct sml_bit_array)); + for (i = 0; i < input_size; i++) { + struct sml_bit_array *array; + uint16_t terms_size, input_byte_size; + + array = sol_vector_append(&obs->input_membership); + sml_bit_array_init(array); + + if (fread(&terms_size, sizeof(uint16_t), 1, f) < 1) + goto error; + if (sml_bit_array_size_set(array, terms_size, 0) != 0) + goto error; + input_byte_size = sml_bit_array_byte_size_get(array); + if (fread(array->data, sizeof(uint8_t), input_byte_size, f) + < input_byte_size) + goto error; + } + return obs; + +error: + sml_observation_free(obs); + return NULL; +} + +int +sml_observation_remove_term(struct sml_observation *obs, uint16_t var_num, + uint16_t term_num, bool input) +{ + struct sol_vector *vector; + struct sml_bit_array *array; + + if (input) { + array = sol_vector_get(&obs->input_membership, var_num); + return sml_bit_array_remove(array, term_num); + } + + vector = sol_vector_get(&obs->output_weights, var_num); + return sol_vector_del(vector, term_num); +} + +int +sml_observation_merge_terms(struct sml_observation *obs, uint16_t var_num, + uint16_t term1, uint16_t term2, bool input) +{ + struct sol_vector *vector; + struct sml_bit_array *array; + uint8_t val; + uint16_t *weight1, *weight2; + + if (input) { + array = sol_vector_get(&obs->input_membership, var_num); + val = sml_bit_array_get(array, term1) == SET || + sml_bit_array_get(array, term2) == SET ? SET : UNSET; + sml_bit_array_set(array, term1, val); + return sml_bit_array_remove(array, term2); + } + + vector = sol_vector_get(&obs->output_weights, var_num); + weight1 = sol_vector_get(vector, term1); + weight2 = sol_vector_get(vector, term2); + *weight1 = *weight1 + *weight2; + return sol_vector_del(vector, term2); +} + +int +sml_observation_split_terms(struct sml_fuzzy *fuzzy, + struct sml_observation *obs, uint16_t var_num, uint16_t term_num, + uint16_t term1, uint16_t term2, bool input) +{ + struct sol_vector *vector; + struct sml_bit_array *array; + struct sml_variable *var; + uint8_t val; + uint16_t weight, terms_len; + int error; + + if (input) { + array = sol_vector_get(&obs->input_membership, var_num); + var = sml_fuzzy_variables_list_index(fuzzy->input_list, var_num); + terms_len = sml_fuzzy_variable_terms_count(var); + if ((error = sml_bit_array_size_set(array, terms_len, 0))) + return error; + + val = sml_bit_array_get(array, term_num) == SET; + sml_bit_array_set(array, term1, val); + sml_bit_array_set(array, term2, val); + return sml_bit_array_remove(array, term_num); + } + + weight = _output_get(obs, var_num, term_num); + + if ((error = _output_set(fuzzy, obs, var_num, term1, weight))) + return error; + + if ((error = _output_set(fuzzy, obs, var_num, term2, weight))) + return error; + + vector = sol_vector_get(&obs->output_weights, var_num); + return sol_vector_del(vector, term_num); +} + +unsigned int +sml_observation_estimate_size(struct sml_fuzzy *fuzzy) +{ + unsigned int size = sizeof(struct sml_observation); + + size += (sml_fuzzy_variables_list_get_length(fuzzy->input_list) + + sml_fuzzy_variables_list_get_length(fuzzy->output_list)) * + sizeof(struct sol_vector); + size += (fuzzy->output_terms_count * sizeof(uint8_t)) + + (fuzzy->input_terms_count / 8 + 1); + return size; +} + diff --git a/sml/sml_fuzzy/src/sml_observation.h b/sml/sml_fuzzy/src/sml_observation.h new file mode 100644 index 0000000..779bb0f --- /dev/null +++ b/sml/sml_fuzzy/src/sml_observation.h @@ -0,0 +1,71 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "sml_fuzzy_bridge.h" +#include "sml_bit_array.h" +#include "sml_measure.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct sml_observation; +typedef void (*sml_process_str_cb) (const char *str, void *data); + +int sml_observation_new(struct sml_fuzzy *fuzzy, struct sml_measure *measure, struct sml_observation **observation); +void sml_observation_free(struct sml_observation *observation); +bool sml_observation_enabled_input_equals(struct sml_fuzzy *fuzzy, struct sml_observation *obs1, struct sml_observation *obs2); +bool sml_observation_input_equals(struct sml_fuzzy *fuzzy, struct sml_observation *obs1, struct sml_observation *obs2); +bool sml_observation_enabled_input_values_equals(struct sml_fuzzy *fuzzy, struct sml_observation *observation, struct sml_measure *measure); +void sml_observation_rule_generate(struct sml_fuzzy *fuzzy, struct sol_ptr_vector *observation_list, float weight_threshold, struct sml_bit_array *relevant_inputs, float *output_weights, uint16_t output_number, sml_process_str_cb process_cb, void *data); +int sml_observation_hit(struct sml_fuzzy *fuzzy, struct sml_observation *observation, struct sml_measure *measure, bool *hit); +void sml_observation_debug(struct sml_observation *observation); +int sml_observation_remove_variables(struct sml_observation *observation, bool *inputs_to_remove, bool *outputs_to_remove); +bool sml_observation_is_empty(struct sml_observation *observation); +int sml_observation_merge_output(struct sml_fuzzy *fuzzy, struct sml_observation *observation1, struct sml_observation *observation2); +bool sml_observation_is_base(struct sml_fuzzy *fuzzy, struct sml_observation *observation); +uint8_t sml_observation_input_term_get(struct sml_observation *observation, uint16_t input, uint16_t term); +bool sml_observation_output_equals(struct sml_fuzzy *fuzzy, struct sml_observation *obs1, struct sml_observation *obs2, uint16_t output_number); +void sml_observation_fill_output_weights(struct sml_fuzzy *fuzzy, struct sml_observation *obs, uint16_t *output_weights); +bool sml_observation_save(struct sml_observation *obs, FILE *f); +struct sml_observation *sml_observation_load(FILE *f); +int sml_observation_remove_term(struct sml_observation *obs, uint16_t var_num, uint16_t term_num, bool input); +int sml_observation_merge_terms(struct sml_observation *obs, uint16_t var_num, uint16_t term1, uint16_t term2, bool input); +int sml_observation_split_terms(struct sml_fuzzy *fuzzy, struct sml_observation *obs, uint16_t var_num, uint16_t term_num, uint16_t term1, uint16_t term2, bool input); +unsigned int sml_observation_estimate_size(struct sml_fuzzy *fuzzy); + +#ifdef __cplusplus +} +#endif diff --git a/sml/sml_fuzzy/src/sml_observation_controller.c b/sml/sml_fuzzy/src/sml_observation_controller.c new file mode 100644 index 0000000..02fe25b --- /dev/null +++ b/sml/sml_fuzzy/src/sml_observation_controller.c @@ -0,0 +1,623 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sml_observation_controller.h" +#include "sml_observation_group.h" +#include +#include +#include "sml_rule_group.h" +#include "sml_util.h" +#include +#include +#include +#include +#include + +#define DEFAULT_CACHE_SIZE (0) +#define WEIGHT_THRESHOLD (0.05) +#define DEFAULT_OBS_CONTROLLER_FILE "controller.dat" +#define VERSION 0x1 + +struct sml_observation_controller { + struct sml_cache *obs_group_cache; + //vector of ptr_vector of struct sml_rule_group + //The index of this vector indicates which output the rules are related to + struct sol_vector rule_group_map; //TODO: User Matrix + struct sml_fuzzy *fuzzy; + float weight_threshold; + bool simplification_disabled; +}; + +static int +_merge_obs_groups(struct sml_observation_controller *obs_controller) + +{ + int error; + uint16_t i, j; + uint16_t len; + struct sml_observation_group *item_i, *item_j; + struct sol_ptr_vector *obs_group_list; + + obs_group_list = sml_cache_get_elements(obs_controller->obs_group_cache); + len = sol_ptr_vector_get_len(obs_group_list); + for (i = 0; i < len; i++) + for (j = i + 1; j < len; j++) { + item_i = sol_ptr_vector_get(obs_group_list, i); + item_j = sol_ptr_vector_get(obs_group_list, j); + + if (sml_observation_group_enabled_input_equals( + obs_controller->fuzzy, item_i, item_j)) { + if ((error = sml_observation_group_merge(obs_controller->fuzzy, + item_i, item_j))) + return error; + sml_observation_group_free(item_j); + sol_ptr_vector_del(obs_group_list, j); + len--; + j--; + } + } + + return 0; +} + +static void +_initialize_rule_group_map(struct sml_observation_controller *obs_controller) +{ + uint16_t i, l; + + l = sml_fuzzy_variables_list_get_length(obs_controller->fuzzy->output_list); + for (i = obs_controller->rule_group_map.len; i < l; i++) + sol_ptr_vector_init(sol_vector_append(&obs_controller->rule_group_map)); + +} + +static void +_rule_group_map_clear(struct sml_observation_controller *obs_controller) +{ + uint16_t i, j; + struct sol_ptr_vector *rule_group_list; + struct sml_rule_group *rule_group; + + SOL_VECTOR_FOREACH_IDX (&obs_controller->rule_group_map, rule_group_list, + i) { + SOL_PTR_VECTOR_FOREACH_IDX (rule_group_list, rule_group, j) + sml_rule_group_free(obs_controller->fuzzy, rule_group); + sol_ptr_vector_clear(rule_group_list); + } + sol_vector_clear(&obs_controller->rule_group_map); +} + +static bool +_controller_append_observation( + struct sml_observation_controller *obs_controller, + struct sml_observation *obs) +{ + int error; + uint16_t i; + struct sml_observation_group *obs_group; + struct sol_ptr_vector *obs_group_list; + bool appended = false; + + obs_group_list = sml_cache_get_elements(obs_controller->obs_group_cache); + SOL_PTR_VECTOR_FOREACH_IDX (obs_group_list, obs_group, i) { + error = sml_observation_group_observation_append(obs_controller->fuzzy, + obs_group, obs, + &appended); + if (error || appended) + return error; + } + + //New observation + obs_group = sml_observation_group_new(); + if (!obs_group) + return -errno; + + error = sml_observation_group_observation_append(obs_controller->fuzzy, + obs_group, obs, &appended); + if (error || !appended) + goto append_error; + + sml_cache_put(obs_controller->obs_group_cache, obs_group); + return 0; + +append_error: + sml_observation_group_free(obs_group); + return error; +} + +static void +_cache_element_free(void *element, void *data) +{ + struct sml_observation_controller *obs_controller = data; + uint16_t i; + struct sol_ptr_vector *rule_group_list; + + SOL_VECTOR_FOREACH_IDX (&obs_controller->rule_group_map, + rule_group_list, i) + sml_rule_group_list_observation_remove(obs_controller->fuzzy, + rule_group_list, element, obs_controller->weight_threshold, i); + + sml_observation_group_free(element); +} + +struct sml_observation_controller * +sml_observation_controller_new(struct sml_fuzzy *fuzzy) +{ + struct sml_observation_controller *obs_controller = + malloc(sizeof(struct sml_observation_controller)); + + obs_controller->obs_group_cache = sml_cache_new(DEFAULT_CACHE_SIZE, + _cache_element_free, obs_controller); + sol_vector_init(&obs_controller->rule_group_map, + sizeof(struct sol_ptr_vector)); + obs_controller->fuzzy = fuzzy; + obs_controller->weight_threshold = WEIGHT_THRESHOLD; + obs_controller->simplification_disabled = false; + _initialize_rule_group_map(obs_controller); + return obs_controller; +} + +void +sml_observation_controller_clear( + struct sml_observation_controller *obs_controller) +{ + sml_cache_clear(obs_controller->obs_group_cache); + _rule_group_map_clear(obs_controller); +} + +void +sml_observation_controller_free( + struct sml_observation_controller *obs_controller) +{ + sml_observation_controller_clear(obs_controller); + sml_cache_free(obs_controller->obs_group_cache); + free(obs_controller); +} + +int +sml_observation_controller_observation_hit(struct sml_observation_controller * + obs_controller, struct sml_measure *measure) +{ + int error; + uint16_t i, j; + struct sml_observation_group *obs_group; + struct sol_ptr_vector *rule_group_list; + struct sol_ptr_vector *obs_group_list; + bool found; + + _initialize_rule_group_map(obs_controller); + + obs_group_list = sml_cache_get_elements(obs_controller->obs_group_cache); + SOL_PTR_VECTOR_FOREACH_IDX (obs_group_list, obs_group, i) { + error = sml_observation_group_observation_hit(obs_controller->fuzzy, + obs_group, measure, &found); + if (error) + return error; + + if (found) { + if (!obs_controller->simplification_disabled) + SOL_VECTOR_FOREACH_IDX (&obs_controller->rule_group_map, + rule_group_list, j) { + error = sml_rule_group_list_rebalance(obs_controller->fuzzy, + rule_group_list, obs_group, + obs_controller->weight_threshold, j); + if (error) + return error; + } + sml_cache_hit(obs_controller->obs_group_cache, obs_group); + return 0; + } + } + + //New observation + obs_group = sml_observation_group_new(); + if (!obs_group) + return -errno; + + if ((error = sml_observation_group_observation_hit(obs_controller->fuzzy, + obs_group, measure, &found))) + goto error_end; + + if (found) { + SOL_VECTOR_FOREACH_IDX (&obs_controller->rule_group_map, + rule_group_list, j) { + if ((error = sml_rule_group_list_observation_append( + obs_controller->fuzzy, rule_group_list, + obs_group, obs_controller->weight_threshold, + obs_controller->simplification_disabled, j))) + goto error_end; + } + + sml_cache_put(obs_controller->obs_group_cache, obs_group); + } else + sml_observation_group_free(obs_group); + return 0; + +error_end: + sml_observation_group_free(obs_group); + return error; +} + +void +sml_observation_controller_rule_generate(struct sml_observation_controller + *obs_controller, + sml_process_str_cb process_cb, + void *data) +{ + uint16_t i, j; + struct sml_rule_group *rule_group; + struct sol_ptr_vector *rule_group_list; + + _initialize_rule_group_map(obs_controller); + + SOL_VECTOR_FOREACH_IDX (&obs_controller->rule_group_map, + rule_group_list, i) { + SOL_PTR_VECTOR_FOREACH_IDX (rule_group_list, rule_group, j) + sml_rule_group_rule_generate(obs_controller->fuzzy, rule_group, + obs_controller->weight_threshold, i, + process_cb, data); + } +} + +void +sml_observation_controller_set_weight_threshold( + struct sml_observation_controller *obs_controller, float weight_threshold) +{ + obs_controller->weight_threshold = weight_threshold; +} + +void +sml_observation_controller_debug( + struct sml_observation_controller *obs_controller) +{ + uint16_t i; + struct sml_observation_group *obs_group; + struct sol_ptr_vector *obs_group_list; + + obs_group_list = sml_cache_get_elements(obs_controller->obs_group_cache); + sml_debug("Observation Controller (%d) {", + sol_ptr_vector_get_len(obs_group_list)); + SOL_PTR_VECTOR_FOREACH_IDX (obs_group_list, obs_group, i) + sml_observation_group_debug(obs_group); + sml_debug("}"); +} + +int +sml_observation_controller_variable_set_enabled( + struct sml_observation_controller *obs_controller, bool enabled) +{ + int error; + struct sol_ptr_vector *obs_group_list; + + _initialize_rule_group_map(obs_controller); + + if (enabled) { + uint16_t i; + struct sml_observation_group *item; + struct sol_ptr_vector split = SOL_PTR_VECTOR_INIT; + + //Split groups + obs_group_list = + sml_cache_get_elements(obs_controller->obs_group_cache); + SOL_PTR_VECTOR_FOREACH_IDX (obs_group_list, item, i) + sml_observation_group_split(obs_controller->fuzzy, item, &split); + sml_cache_clear(obs_controller->obs_group_cache); + SOL_PTR_VECTOR_FOREACH_IDX (&split, item, i) + sml_cache_put(obs_controller->obs_group_cache, item); + sol_ptr_vector_clear(&split); + } else { + if ((error = _merge_obs_groups(obs_controller))) + return error; + } + + if ((error = sml_observation_controller_rules_rebuild(obs_controller))) + return error; + + return 0; +} + +int +sml_observation_controller_remove_variables(struct sml_observation_controller + *obs_controller, + bool *inputs_to_remove, + bool *outputs_to_remove) +{ + struct sml_observation_group *obs_group; + uint16_t i; + int error = 0; + struct sol_ptr_vector *obs_group_list; + + obs_group_list = sml_cache_get_elements(obs_controller->obs_group_cache); + SOL_PTR_VECTOR_FOREACH_IDX (obs_group_list, obs_group, i) { + if ((error = sml_observation_group_remove_variables(obs_group, + inputs_to_remove, outputs_to_remove))) + goto exit; + + if (sml_observation_group_is_empty(obs_group)) { + if (!sml_cache_remove_by_id(obs_controller->obs_group_cache, i)) { + sml_critical("Could not remove the observation group"); + goto exit; + } + i--; + } + } + +exit: + free(inputs_to_remove); + free(outputs_to_remove); + return error; +} + +int +sml_observation_controller_post_remove_variables( + struct sml_observation_controller *obs_controller) +{ + int error; + + if ((error = _merge_obs_groups(obs_controller))) + return error; + + _rule_group_map_clear(obs_controller); + + if ((error = sml_observation_controller_rules_rebuild(obs_controller))) + return error; + + return 0; +} + +bool +sml_observation_controller_save_state(struct sml_observation_controller + *obs_controller, const char *path) +{ + char buf[SML_PATH_MAX]; + FILE *f; + uint16_t i, j, count = 0; + uint8_t version = VERSION; + struct sol_ptr_vector *obs_group; + struct sml_observation *obs; + struct sol_ptr_vector *obs_group_list; + + snprintf(buf, sizeof(buf), "%s/%s", path, DEFAULT_OBS_CONTROLLER_FILE); + if (!(f = fopen(buf, "wb"))) { + sml_critical("Failed to open file %s\n", buf); + return false; + } + + if (fwrite(&version, sizeof(uint8_t), 1, f) < 1) + goto save_state_false_end; + + obs_group_list = sml_cache_get_elements(obs_controller->obs_group_cache); + SOL_PTR_VECTOR_FOREACH_IDX (obs_group_list, obs_group, i) + count += sol_ptr_vector_get_len(obs_group); + + if (fwrite(&count, sizeof(uint16_t), 1, f) < 1) + goto save_state_false_end; + + SOL_PTR_VECTOR_FOREACH_IDX (obs_group_list, obs_group, i) { + SOL_PTR_VECTOR_FOREACH_IDX (obs_group, obs, j) { + if (!sml_observation_save(obs, f)) + goto save_state_false_end; + } + } + + return fclose(f) == 0; + +save_state_false_end: + fclose(f); + return false; +} + +bool +sml_observation_controller_load_state(struct sml_observation_controller + *obs_controller, const char *path) +{ + char buf[SML_PATH_MAX]; + FILE *f; + uint8_t version; + uint16_t count; + int error; + struct sml_observation *obs; + + snprintf(buf, sizeof(buf), "%s/%s", path, DEFAULT_OBS_CONTROLLER_FILE); + if (!(f = fopen(buf, "rb"))) { + sml_critical("Failed to open file %s\n", buf); + return false; + } + + if (fread(&version, sizeof(uint8_t), 1, f) < 1 || version != VERSION) + goto load_state_false_end; + + if (fread(&count, sizeof(uint16_t), 1, f) < 1) + goto load_state_false_end; + + while (count) { + obs = sml_observation_load(f); + if (!obs) + goto load_state_false_end; + + if (_controller_append_observation(obs_controller, obs) + != 0) { + free(obs); + goto load_state_false_end; + } + + count--; + } + + if ((error = sml_observation_controller_rules_rebuild(obs_controller))) + goto load_state_false_end; + + return fclose(f) == 0; + +load_state_false_end: + fclose(f); + return false; +} + +int +sml_observation_controller_rules_rebuild(struct sml_observation_controller + *obs_controller) +{ + int error; + struct sol_ptr_vector *rule_group_list; + uint16_t i; + struct sol_ptr_vector *obs_group_list; + + obs_group_list = sml_cache_get_elements(obs_controller->obs_group_cache); + _initialize_rule_group_map(obs_controller); + SOL_VECTOR_FOREACH_IDX (&obs_controller->rule_group_map, + rule_group_list, i) { + error = sml_rule_group_list_rebuild(obs_controller->fuzzy, + rule_group_list, obs_group_list, + obs_controller->weight_threshold, + obs_controller->simplification_disabled, i); + if (error) + return error; + } + + return 0; +} + +void +sml_observation_controller_set_simplification_disabled( + struct sml_observation_controller *obs_controller, bool disabled) +{ + if (obs_controller->simplification_disabled == disabled) + return; + + obs_controller->simplification_disabled = disabled; + sml_observation_controller_rules_rebuild(obs_controller); +} + +int +sml_observation_controller_remove_term(struct sml_observation_controller + *obs_controller, uint16_t var_num, + uint16_t term_num, bool input) +{ + struct sml_observation_group *obs_group; + uint16_t i; + int error = 0; + struct sol_ptr_vector *obs_group_list; + + obs_group_list = sml_cache_get_elements(obs_controller->obs_group_cache); + SOL_PTR_VECTOR_FOREACH_IDX (obs_group_list, obs_group, i) { + if ((error = sml_observation_group_remove_terms(obs_group, var_num, + term_num, input))) + return error; + + if (sml_observation_group_is_empty(obs_group)) { + if (!sml_cache_remove_by_id(obs_controller->obs_group_cache, i)) { + sml_critical("Could not remove the observation group"); + return error; + } + i--; + } + } + + return error; +} + +int +sml_observation_controller_merge_terms(struct sml_observation_controller + *obs_controller, uint16_t var_num, + uint16_t term1, uint16_t term2, + bool input) +{ + struct sml_observation_group *obs_group; + uint16_t i; + int error = 0; + struct sol_ptr_vector *obs_group_list; + + obs_group_list = sml_cache_get_elements(obs_controller->obs_group_cache); + SOL_PTR_VECTOR_FOREACH_IDX (obs_group_list, obs_group, i) { + if ((error = sml_observation_group_merge_terms(obs_group, var_num, + term1, term2, input))) + return error; + + if (sml_observation_group_is_empty(obs_group)) { + if (!sml_cache_remove_by_id(obs_controller->obs_group_cache, i)) { + sml_critical("Could not remove the observation group"); + return error; + } + i--; + } + } + + return error; +} + +int +sml_observation_controller_split_terms(struct sml_fuzzy *fuzzy, + struct sml_observation_controller + *obs_controller, uint16_t var_num, + uint16_t term_num, uint16_t term1, + uint16_t term2, bool input) +{ + struct sml_observation_group *obs_group; + uint16_t i; + int error = 0; + struct sol_ptr_vector *obs_group_list; + + obs_group_list = sml_cache_get_elements(obs_controller->obs_group_cache); + SOL_PTR_VECTOR_FOREACH_IDX (obs_group_list, obs_group, i) { + if ((error = sml_observation_group_split_terms(fuzzy, obs_group, + var_num, term_num, term1, term2, input))) + return error; + + if (sml_observation_group_is_empty(obs_group)) { + if (!sml_cache_remove_by_id(obs_controller->obs_group_cache, i)) { + sml_critical("Could not remove the observation group"); + return error; + } + i--; + } + } + + return error; +} + +bool +sml_observation_controller_update_cache_size(struct sml_observation_controller + *obs_controller, unsigned int max_memory_for_observation) +{ + unsigned int cache_size; + + if (!max_memory_for_observation) + return true; + + cache_size = max_memory_for_observation / + sml_observation_estimate_size(obs_controller->fuzzy); + if (!cache_size) + cache_size = 1; + + return sml_cache_set_max_size(obs_controller->obs_group_cache, cache_size); +} diff --git a/sml/sml_fuzzy/src/sml_observation_controller.h b/sml/sml_fuzzy/src/sml_observation_controller.h new file mode 100644 index 0000000..2df6673 --- /dev/null +++ b/sml/sml_fuzzy/src/sml_observation_controller.h @@ -0,0 +1,64 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "sml_observation.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct sml_observation_controller; + +struct sml_observation_controller *sml_observation_controller_new(struct sml_fuzzy *fuzzy); +void sml_observation_controller_free(struct sml_observation_controller *observation); +void sml_observation_controller_clear(struct sml_observation_controller *observation); +int sml_observation_controller_observation_hit(struct sml_observation_controller *obs_controller, struct sml_measure *measure); +void sml_observation_controller_rule_generate(struct sml_observation_controller *obs_controller, sml_process_str_cb process_cb, void *data); +void sml_observation_controller_set_weight_threshold(struct sml_observation_controller *list, float weight_threshold); +void sml_observation_controller_debug(struct sml_observation_controller *obs_controller); +int sml_observation_controller_remove_variables(struct sml_observation_controller *obs_controller, bool *inputs_to_remove, bool *outputs_to_remove); +int sml_observation_controller_variable_set_enabled(struct sml_observation_controller *obs_controller, bool enabled); +bool sml_observation_controller_save_state(struct sml_observation_controller *obs_controller, const char *path); +bool sml_observation_controller_load_state(struct sml_observation_controller *obs_controller, const char *path); +int sml_observation_controller_post_remove_variables(struct sml_observation_controller *obs_controller); +int sml_observation_controller_rules_rebuild(struct sml_observation_controller *obs_controller); +void sml_observation_controller_set_simplification_disabled(struct sml_observation_controller *obs_controller, bool disabled); +int sml_observation_controller_remove_term(struct sml_observation_controller *obs_controller, uint16_t var_num, uint16_t term_num, bool input); +int sml_observation_controller_merge_terms(struct sml_observation_controller *obs_controller, uint16_t var_num, uint16_t term1, uint16_t term2, bool input); +int sml_observation_controller_split_terms(struct sml_fuzzy *fuzzy, struct sml_observation_controller *obs_controller, uint16_t var_num, uint16_t term_num, uint16_t term1, uint16_t term2, bool input); +bool sml_observation_controller_update_cache_size(struct sml_observation_controller *obs_controller, unsigned int max_memory_for_observation); + +#ifdef __cplusplus +} +#endif diff --git a/sml/sml_fuzzy/src/sml_observation_group.c b/sml/sml_fuzzy/src/sml_observation_group.c new file mode 100644 index 0000000..3c46441 --- /dev/null +++ b/sml/sml_fuzzy/src/sml_observation_group.c @@ -0,0 +1,389 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "sml_observation_group.h" + +//Observation Group is a class to group all observation that have exactly same +//inputs for enabled inputs. i.e, if all inputs are enabled, only a single +//observation will belong to a group. + +struct sml_observation_group * +sml_observation_group_new() +{ + struct sml_observation_group *obs_group = calloc(1, + sizeof(struct sol_ptr_vector)); + + if (!obs_group) + return NULL; + + sol_ptr_vector_init((struct sol_ptr_vector *)obs_group); + return obs_group; +} + +struct sml_observation * +sml_observation_group_get_first_observation( + struct sml_observation_group *obs_group) +{ + if (!sol_ptr_vector_get_len((struct sol_ptr_vector *)obs_group)) + return NULL; + + return sol_ptr_vector_get((struct sol_ptr_vector *)obs_group, 0); +} + +int +sml_observation_group_observation_hit(struct sml_fuzzy *fuzzy, + struct sml_observation_group *obs_group, + struct sml_measure *measure, bool *found) +{ + int error; + bool obs_hit; + + if (found) + *found = false; + if (sol_ptr_vector_get_len((struct sol_ptr_vector *)obs_group)) { + uint16_t i; + struct sml_observation *obs; + struct sml_observation *first_observation = + sol_ptr_vector_get((struct sol_ptr_vector *)obs_group, 0); + + if (!sml_observation_enabled_input_values_equals(fuzzy, + first_observation, measure)) + return 0; + + SOL_PTR_VECTOR_FOREACH_IDX ((struct sol_ptr_vector *)obs_group, obs, i) + if (sml_observation_is_base(fuzzy, obs)) { + if (found) + *found = true; + return sml_observation_hit(fuzzy, obs, measure, NULL); + } + + } + + //New observation in this group + struct sml_observation *observation; + error = sml_observation_new(fuzzy, measure, &observation); + if (error || !observation) + return error; + + error = sml_observation_hit(fuzzy, observation, measure, &obs_hit); + if (error || !obs_hit) { + sml_observation_free(observation); + return error; + } + sol_ptr_vector_append((struct sol_ptr_vector *)obs_group, observation); + + if (found) + *found = true; + return 0; +} + +int +sml_observation_group_observation_append(struct sml_fuzzy *fuzzy, + struct sml_observation_group *obs_group, + struct sml_observation *obs, bool *appended) +{ + if (sol_ptr_vector_get_len((struct sol_ptr_vector *)obs_group)) { + struct sml_observation *first_observation = + sol_ptr_vector_get((struct sol_ptr_vector *)obs_group, 0); + + if (!sml_observation_enabled_input_equals(fuzzy, first_observation, + obs)) { + if (appended) + *appended = false; + return 0; + } + } + + sol_ptr_vector_append((struct sol_ptr_vector *)obs_group, obs); + + if (appended) + *appended = true; + return 0; +} + +int +sml_observation_group_merge(struct sml_fuzzy *fuzzy, + struct sml_observation_group *obs_group1, + struct sml_observation_group *obs_group2) +{ + int error; + uint16_t i, j; + struct sml_observation *obs, *obs_aux; + + SOL_PTR_VECTOR_FOREACH_IDX ((struct sol_ptr_vector *)obs_group2, obs, i) + sol_ptr_vector_append((struct sol_ptr_vector *)obs_group1, obs); + sol_ptr_vector_clear((struct sol_ptr_vector *)obs_group2); + + for (i = 0; i < sol_ptr_vector_get_len((struct sol_ptr_vector *)obs_group1); + i++) { + obs = sol_ptr_vector_get((struct sol_ptr_vector *)obs_group1, i); + for (j = i + 1; j < sol_ptr_vector_get_len( + (struct sol_ptr_vector *)obs_group1); j++) { + obs_aux = sol_ptr_vector_get((struct sol_ptr_vector *)obs_group1, + j); + if (sml_observation_input_equals(fuzzy, obs, obs_aux)) { + if ((error = sml_observation_merge_output(fuzzy, + obs, obs_aux))) + return error; + sml_observation_free(obs_aux); + sol_ptr_vector_del((struct sol_ptr_vector *)obs_group1, j); + j--; + } + } + } + + return 0; +} + +bool +sml_observation_group_enabled_input_equals(struct sml_fuzzy *fuzzy, + struct sml_observation_group *obs_group1, + struct sml_observation_group *obs_group2) +{ + struct sml_observation *f1, *f2; + + if (!sol_ptr_vector_get_len((struct sol_ptr_vector *)obs_group1) || + !sol_ptr_vector_get_len((struct sol_ptr_vector *)obs_group2)) + return false; + + f1 = sol_ptr_vector_get((struct sol_ptr_vector *)obs_group1, 0), + f2 = sol_ptr_vector_get((struct sol_ptr_vector *)obs_group2, 0); + return sml_observation_enabled_input_equals(fuzzy, f1, f2); +} + +void +sml_observation_group_free(struct sml_observation_group *obs_group) +{ + uint16_t i; + struct sml_observation *obs; + + SOL_PTR_VECTOR_FOREACH_IDX ((struct sol_ptr_vector *)obs_group, obs, i) + sml_observation_free(obs); + sol_ptr_vector_clear((struct sol_ptr_vector *)obs_group); + free(obs_group); +} + +void +sml_observation_group_rule_generate(struct sml_fuzzy *fuzzy, + struct sml_observation_group *obs_group, + float weight_threshold, + struct sml_bit_array *relevant_inputs, + float *output_weights, + uint16_t output_number, + sml_process_str_cb process_cb, + void *data) +{ + sml_observation_rule_generate(fuzzy, (struct sol_ptr_vector *)obs_group, + weight_threshold, relevant_inputs, output_weights, + output_number, process_cb, data); +} + +void +sml_observation_group_debug(struct sml_observation_group *obs_group) +{ + uint16_t i; + struct sml_observation *obs; + + sml_debug("Observation Group (%d) {", + sol_ptr_vector_get_len((struct sol_ptr_vector *)obs_group)); + SOL_PTR_VECTOR_FOREACH_IDX ((struct sol_ptr_vector *)obs_group, obs, i) + sml_observation_debug(obs); + sml_debug("}"); +} + +void +sml_observation_group_split(struct sml_fuzzy *fuzzy, + struct sml_observation_group *obs_group, struct sol_ptr_vector *split) +{ + uint16_t i, j, start; + struct sml_observation *item_i; + struct sml_observation_group *item_j; + struct sml_observation *first; + + start = sol_ptr_vector_get_len((struct sol_ptr_vector *)split); + SOL_PTR_VECTOR_FOREACH_IDX ((struct sol_ptr_vector *)obs_group, item_i, i) { + bool added = false; + for (j = start; j < sol_ptr_vector_get_len( + (struct sol_ptr_vector *)split); j++) { + item_j = sol_ptr_vector_get((struct sol_ptr_vector *)split, j); + first = sol_ptr_vector_get((struct sol_ptr_vector *)item_j, 0); + if (sml_observation_enabled_input_equals(fuzzy, item_i, first)) { + sol_ptr_vector_append((struct sol_ptr_vector *)item_j, item_i); + added = true; + break; + } + } + + if (!added) { + item_j = sml_observation_group_new(); + sol_ptr_vector_append((struct sol_ptr_vector *)item_j, item_i); + sol_ptr_vector_append((struct sol_ptr_vector *)split, item_j); + } + } + + sol_ptr_vector_clear((struct sol_ptr_vector *)obs_group); +} + +int +sml_observation_group_remove_variables(struct sml_observation_group *obs_group, + bool *inputs_to_remove, + bool *outputs_to_remove) +{ + struct sml_observation *obs; + uint16_t i; + int error; + + //Remove variables from observation structure and remove empty structs + SOL_PTR_VECTOR_FOREACH_IDX ((struct sol_ptr_vector *)obs_group, obs, i) { + if ((error = sml_observation_remove_variables(obs, inputs_to_remove, + outputs_to_remove))) + return error; + + if (sml_observation_is_empty(obs)) { + sml_observation_free(obs); + if ((error = sol_ptr_vector_del((struct sol_ptr_vector *)obs_group, + i))) { + sml_critical("Could not remove the observation from group"); + return error; + } + i--; + } + } + + return 0; +} + +bool +sml_observation_group_is_empty(struct sml_observation_group *obs_group) +{ + return !sol_ptr_vector_get_len((struct sol_ptr_vector *)obs_group); +} + +void +sml_observation_group_fill_output_weights(struct sml_fuzzy *fuzzy, + struct sml_observation_group *obs_group, + uint16_t *output_weights) +{ + uint16_t i; + struct sml_observation *obs; + + SOL_PTR_VECTOR_FOREACH_IDX ((struct sol_ptr_vector *)obs_group, obs, i) + sml_observation_fill_output_weights(fuzzy, obs, output_weights); +} + +int +sml_observation_group_remove_terms(struct sml_observation_group *obs_group, + uint16_t var_num, uint16_t term_num, + bool input) +{ + struct sml_observation *obs; + uint16_t i; + int error; + + SOL_PTR_VECTOR_FOREACH_IDX ((struct sol_ptr_vector *)obs_group, obs, i) { + if ((error = sml_observation_remove_term(obs, var_num, term_num, + input))) + return error; + + if (sml_observation_is_empty(obs)) { + sml_observation_free(obs); + if ((error = sol_ptr_vector_del((struct sol_ptr_vector *)obs_group, + i))) { + sml_critical("Could not remove the observation from group"); + return error; + } + i--; + } + } + + return 0; +} + +int +sml_observation_group_merge_terms(struct sml_observation_group *obs_group, + uint16_t var_num, uint16_t term1, + uint16_t term2, bool input) +{ + struct sml_observation *obs; + uint16_t i; + int error; + + SOL_PTR_VECTOR_FOREACH_IDX ((struct sol_ptr_vector *)obs_group, obs, i) { + if ((error = sml_observation_merge_terms(obs, var_num, term1, term2, + input))) + return error; + + if (sml_observation_is_empty(obs)) { + sml_observation_free(obs); + if ((error = sol_ptr_vector_del((struct sol_ptr_vector *)obs_group, + i))) { + sml_critical("Could not remove the observation from group"); + return error; + } + i--; + } + } + + return 0; +} + +int +sml_observation_group_split_terms(struct sml_fuzzy *fuzzy, + struct sml_observation_group *obs_group, + uint16_t var_num, uint16_t term_num, + int16_t term1, uint16_t term2, bool input) +{ + struct sml_observation *obs; + uint16_t i; + int error; + + SOL_PTR_VECTOR_FOREACH_IDX ((struct sol_ptr_vector *)obs_group, obs, i) { + if ((error = sml_observation_split_terms(fuzzy, obs, var_num, term_num, + term1, term2, input))) + return error; + + if (sml_observation_is_empty(obs)) { + sml_observation_free(obs); + if ((error = sol_ptr_vector_del((struct sol_ptr_vector *)obs_group, + i))) { + sml_critical("Could not remove the observation from group"); + return error; + } + i--; + } + } + + return 0; +} diff --git a/sml/sml_fuzzy/src/sml_observation_group.h b/sml/sml_fuzzy/src/sml_observation_group.h new file mode 100644 index 0000000..8380dc7 --- /dev/null +++ b/sml/sml_fuzzy/src/sml_observation_group.h @@ -0,0 +1,63 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "sml_fuzzy_bridge.h" +#include "sml_observation.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct sml_observation_group; + +struct sml_observation_group *sml_observation_group_new(); +int sml_observation_group_observation_hit(struct sml_fuzzy *fuzzy, struct sml_observation_group *obs_group, struct sml_measure *measure, bool *hit); +void sml_observation_group_free(struct sml_observation_group *obs_group); +void sml_observation_group_rule_generate(struct sml_fuzzy *fuzzy, struct sml_observation_group *obs_group, float weight_threshold, struct sml_bit_array *relevant_inputs, float *output_weights, uint16_t output_number, sml_process_str_cb process_cb, void *data); +void sml_observation_group_debug(struct sml_observation_group *obs_group); +int sml_observation_group_merge(struct sml_fuzzy *fuzzy, struct sml_observation_group *obs_group1, struct sml_observation_group *obs_group2); +bool sml_observation_group_enabled_input_equals(struct sml_fuzzy *fuzzy, struct sml_observation_group *obs_group1, struct sml_observation_group *obs_group2); +void sml_observation_group_split(struct sml_fuzzy *fuzzy, struct sml_observation_group *obs_group, struct sol_ptr_vector *split); +int sml_observation_group_remove_variables(struct sml_observation_group *obs_group, bool *inputs_to_remove, bool *outputs_to_remove); +struct sml_observation *sml_observation_group_get_first_observation(struct sml_observation_group *obs_group); +void sml_observation_group_fill_output_weights(struct sml_fuzzy *fuzzy, struct sml_observation_group *obs_group, uint16_t *output_weights); +bool sml_observation_group_is_empty(struct sml_observation_group *obs_group); +int sml_observation_group_remove_terms(struct sml_observation_group *obs_group, uint16_t var_num, uint16_t term_num, bool input); +int sml_observation_group_merge_terms(struct sml_observation_group *obs_group, uint16_t var_num, uint16_t term1, uint16_t term2, bool input); +int sml_observation_group_split_terms(struct sml_fuzzy *fuzzy, struct sml_observation_group *obs_group, uint16_t var_num, uint16_t term_num, int16_t term1, uint16_t term2, bool input); +int sml_observation_group_observation_append(struct sml_fuzzy *fuzzy, struct sml_observation_group *obs_group, struct sml_observation *obs, bool *appended); + +#ifdef __cplusplus +} +#endif diff --git a/sml/sml_fuzzy/src/sml_rule_group.c b/sml/sml_fuzzy/src/sml_rule_group.c new file mode 100644 index 0000000..31a4af9 --- /dev/null +++ b/sml/sml_fuzzy/src/sml_rule_group.c @@ -0,0 +1,579 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "sml_bit_array.h" +#include "sml_rule_group.h" +#include "sml_fuzzy_bridge.h" + +#define ALL_SET 0xff + +//Observation Group is a class to group all observation that have exactly same +//inputs for enabled inputs. i.e, if all inputs are enabled, only a single +//observation will belong to a group. + +//We need to group rules by outputs +struct sml_rule_group { + struct sol_ptr_vector observations; + struct sol_ptr_vector rules; + struct sml_bit_array relevant_inputs; +}; + +typedef struct _Tmp_Rule_Fuzzy { + struct sml_rule_group *rule_group; + struct sml_fuzzy *fuzzy; + bool error; +} Tmp_Rule_Fuzzy; + +static int _rule_group_list_observation_append(struct sml_fuzzy *fuzzy, + struct sol_ptr_vector *rule_group_list, + struct sml_observation_group *obs_group, + float weight_threshold, + uint16_t output_number, bool hard); + +static int +_ptr_vector_del_obj(struct sol_ptr_vector *pv, void *ptr) +{ + uint16_t i; + void *tmp_ptr; + + SOL_PTR_VECTOR_FOREACH_IDX (pv, tmp_ptr, i) + if (tmp_ptr == ptr) + return sol_ptr_vector_del(pv, i); + return -ENODATA; +} + +static void +_rule_append(const char *str, void *data) +{ + Tmp_Rule_Fuzzy *tmp = data; + void *rule = sml_fuzzy_rule_add(tmp->fuzzy, str); + + if (!rule) { + tmp->error = true; + return; + } + + sol_ptr_vector_append(&tmp->rule_group->rules, rule); +} + +static uint16_t +_observation_belong_in_group(struct sml_fuzzy *fuzzy, + struct sml_rule_group *rule_group, struct sml_observation_group *obs_group) +{ + uint16_t level = 0; + uint16_t i, len, j; + struct sml_variable *v; + + if (sol_ptr_vector_get_len(&rule_group->observations) == 0) + return 0; + + struct sml_observation_group *first_group = + sol_ptr_vector_get(&rule_group->observations, 0); + + struct sml_observation *first_observation1 = + sml_observation_group_get_first_observation(first_group); + struct sml_observation *first_observation2 = + sml_observation_group_get_first_observation(obs_group); + + if (first_observation1 == NULL || first_observation2 == NULL) + return 0; + + len = sml_fuzzy_variables_list_get_length(fuzzy->input_list); + for (i = 0; i < len; i++) { + v = sml_fuzzy_variables_list_index(fuzzy->input_list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(v); + uint16_t found = 0; + if (sml_fuzzy_variable_is_enabled(v) && + sml_bit_array_get(&rule_group->relevant_inputs, i)) { + for (j = 0; j < terms_len; j++) { + if (sml_observation_input_term_get(first_observation1, i, j) == + sml_observation_input_term_get(first_observation2, i, j)) + found++; + } + + if (found == terms_len) + level++; + } + } + + return level; +} + +static void +_insert_in_rule_group(struct sml_fuzzy *fuzzy, + struct sml_rule_group *rule_group, struct sml_observation_group *obs_group) +{ + uint16_t i, len, j; + struct sml_variable *v; + + struct sml_observation_group *first_group = + sol_ptr_vector_get(&rule_group->observations, 0); + + struct sml_observation *first_observation1 = + sml_observation_group_get_first_observation(first_group); + struct sml_observation *first_observation2 = + sml_observation_group_get_first_observation(obs_group); + + len = sml_fuzzy_variables_list_get_length(fuzzy->input_list); + for (i = 0; i < len; i++) { + v = sml_fuzzy_variables_list_index(fuzzy->input_list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(v); + uint16_t found = 0; + + if (sml_fuzzy_variable_is_enabled(v) && + sml_bit_array_get(&rule_group->relevant_inputs, i)) { + for (j = 0; j < terms_len; j++) { + if (sml_observation_input_term_get(first_observation1, i, j) == + sml_observation_input_term_get(first_observation2, i, j)) + found++; + } + + if (found != terms_len) + sml_bit_array_set(&rule_group->relevant_inputs, i, UNSET); + } + } + + sol_ptr_vector_append(&rule_group->observations, obs_group); +} + +static bool +_observation_conflicts_in_group(struct sml_fuzzy *fuzzy, + struct sml_rule_group *rule_group, struct sml_observation_group *obs_group, + uint16_t output_number) +{ + struct sml_observation_group *first_group = + sol_ptr_vector_get(&rule_group->observations, 0); + + if (first_group == obs_group) { + if (sol_ptr_vector_get_len(&rule_group->observations) == 1) + return false; + first_group = sol_ptr_vector_get(&rule_group->observations, 1); + } + + struct sml_observation *first_observation1 = + sml_observation_group_get_first_observation(first_group); + struct sml_observation *first_observation2 = + sml_observation_group_get_first_observation(obs_group); + + return !sml_observation_output_equals(fuzzy, first_observation1, + first_observation2, + output_number); +} + +static int +_rule_group_rule_refresh(struct sml_fuzzy *fuzzy, + struct sml_rule_group *rule_group, float weight_threshold, + uint16_t output_number) +{ + uint16_t i; + void *rule; + Tmp_Rule_Fuzzy tmp; + int error; + + SOL_PTR_VECTOR_FOREACH_IDX (&rule_group->rules, rule, i) + sml_fuzzy_rule_free(fuzzy, rule); + sol_ptr_vector_clear(&rule_group->rules); + + tmp.rule_group = rule_group; + tmp.fuzzy = fuzzy; + tmp.error = false; + + if ((error = sml_rule_group_rule_generate(fuzzy, rule_group, + weight_threshold, output_number, _rule_append, &tmp))) + return error; + + if (tmp.error) + return SML_INTERNAL_ERROR; + return 0; +} + +static int +_break_groups_hard(struct sml_fuzzy *fuzzy, + struct sol_ptr_vector *conflict_rule_group, + struct sol_ptr_vector *rule_group_list, float weight_threshold, + uint16_t output_number) +{ + uint16_t i, j; + struct sml_rule_group *rule_group; + struct sml_observation_group *obs_group; + + SOL_PTR_VECTOR_FOREACH_IDX (conflict_rule_group, rule_group, i) { + _ptr_vector_del_obj(rule_group_list, rule_group); + SOL_PTR_VECTOR_FOREACH_IDX (&rule_group->observations, obs_group, j) { + struct sml_rule_group *new_rule_group = sml_rule_group_new(); + if (!new_rule_group) + return -errno; + + sol_ptr_vector_append(&new_rule_group->observations, obs_group); + sol_ptr_vector_append(rule_group_list, new_rule_group); + sml_bit_array_size_set(&new_rule_group->relevant_inputs, + sml_fuzzy_variables_list_get_length(fuzzy->input_list), + ALL_SET); + _rule_group_rule_refresh(fuzzy, new_rule_group, weight_threshold, + output_number); + } + sml_rule_group_free(fuzzy, rule_group); + } + + return 0; +} + +static int +_break_groups(struct sml_fuzzy *fuzzy, + struct sol_ptr_vector *conflict_rule_group, + struct sol_ptr_vector *rule_group_list, float weight_threshold, + uint16_t output_number) +{ + int error; + uint16_t i, j; + struct sml_rule_group *rule_group; + struct sml_observation_group *obs_group; + + SOL_PTR_VECTOR_FOREACH_IDX (conflict_rule_group, rule_group, i) + _ptr_vector_del_obj(rule_group_list, rule_group); + + SOL_PTR_VECTOR_FOREACH_IDX (conflict_rule_group, rule_group, i) { + SOL_PTR_VECTOR_FOREACH_IDX (&rule_group->observations, obs_group, j) { + error = _rule_group_list_observation_append(fuzzy, rule_group_list, + obs_group, weight_threshold, output_number, true); + if (error) + return error; + } + sml_rule_group_free(fuzzy, rule_group); + } + return 0; +} + +static bool +_remove_from_rule_group_list(struct sml_fuzzy *fuzzy, + struct sol_ptr_vector *rule_group_list, + struct sml_observation_group *obs_group_obj, + float weight_threshold, uint16_t output_number) +{ + uint16_t i, j; + struct sml_rule_group *rule_group; + struct sml_observation_group *obs_group; + + SOL_PTR_VECTOR_FOREACH_IDX (rule_group_list, rule_group, i) { + SOL_PTR_VECTOR_FOREACH_IDX (&rule_group->observations, obs_group, j) + if (obs_group == obs_group_obj) { + if (sol_ptr_vector_get_len(&rule_group->observations) == 1) { + sol_ptr_vector_del(&rule_group->observations, j); + sol_ptr_vector_del(rule_group_list, i); + sml_rule_group_free(fuzzy, rule_group); + return true; + } + + if (_observation_conflicts_in_group(fuzzy, rule_group, + obs_group, output_number)) { + sol_ptr_vector_del(&rule_group->observations, j); + return true; + } + + _rule_group_rule_refresh(fuzzy, rule_group, weight_threshold, + output_number); + return false; + } + } + + return false; +} + +struct sml_rule_group * +sml_rule_group_new() +{ + struct sml_rule_group *rule_group = malloc(sizeof(struct sml_rule_group)); + + if (!rule_group) + return NULL; + + sol_ptr_vector_init(&rule_group->rules); + sol_ptr_vector_init(&rule_group->observations); + sml_bit_array_init(&rule_group->relevant_inputs); + return rule_group; +} + +void +sml_rule_group_free(struct sml_fuzzy *fuzzy, struct sml_rule_group *rule_group) +{ + uint16_t i; + void *rule; + + sol_ptr_vector_clear(&rule_group->observations); + SOL_PTR_VECTOR_FOREACH_IDX (&rule_group->rules, rule, i) + sml_fuzzy_rule_free(fuzzy, rule); + sol_ptr_vector_clear(&rule_group->rules); + sml_bit_array_clear(&rule_group->relevant_inputs); + free(rule_group); +} + +static int +_rule_group_list_observation_append_no_simplification(struct sml_fuzzy *fuzzy, + struct sol_ptr_vector *rule_group_list, + struct sml_observation_group *obs_group, + float weight_threshold, + uint16_t output_number) +{ + struct sml_rule_group *rule_group; + + rule_group = sml_rule_group_new(); + if (!rule_group) + return -errno; + + sol_ptr_vector_append(&rule_group->observations, obs_group); + sol_ptr_vector_append(rule_group_list, rule_group); + sml_bit_array_size_set(&rule_group->relevant_inputs, + sml_fuzzy_variables_list_get_length(fuzzy->input_list), + ALL_SET); + _rule_group_rule_refresh(fuzzy, rule_group, weight_threshold, + output_number); + + return 0; +} +static int +_rule_group_list_observation_append(struct sml_fuzzy *fuzzy, + struct sol_ptr_vector *rule_group_list, + struct sml_observation_group *obs_group, + float weight_threshold, + uint16_t output_number, bool hard) +{ + uint16_t i, insert_len, conflict_len; + struct sml_rule_group *rule_group; + struct sol_ptr_vector insert_rule_group = SOL_PTR_VECTOR_INIT; + struct sol_ptr_vector conflict_rule_group = SOL_PTR_VECTOR_INIT; + uint16_t max_level = 0; + int error = 0; + + SOL_PTR_VECTOR_FOREACH_IDX (rule_group_list, rule_group, i) { + + uint16_t cur_level = _observation_belong_in_group(fuzzy, rule_group, + obs_group); + if (cur_level < max_level || cur_level == 0) + continue; + + if (cur_level > max_level) { + max_level = cur_level; + sol_ptr_vector_clear(&insert_rule_group); + sol_ptr_vector_clear(&conflict_rule_group); + } + + if (_observation_conflicts_in_group(fuzzy, rule_group, obs_group, + output_number)) + sol_ptr_vector_append(&conflict_rule_group, rule_group); + else + sol_ptr_vector_append(&insert_rule_group, rule_group); + } + + + insert_len = sol_ptr_vector_get_len(&insert_rule_group); + conflict_len = sol_ptr_vector_get_len(&conflict_rule_group); + if (insert_len == 0 || conflict_len > 0) { + //Create new rule group + rule_group = sml_rule_group_new(); + if (!rule_group) { + error = -errno; + goto end; + } + + sol_ptr_vector_append(&rule_group->observations, obs_group); + sol_ptr_vector_append(rule_group_list, rule_group); + sml_bit_array_size_set(&rule_group->relevant_inputs, + sml_fuzzy_variables_list_get_length(fuzzy->input_list), + ALL_SET); + _rule_group_rule_refresh(fuzzy, rule_group, weight_threshold, + output_number); + } else if (insert_len > 0) { + //Insert in existing group + rule_group = sol_ptr_vector_get(&insert_rule_group, 0); + _insert_in_rule_group(fuzzy, rule_group, obs_group); + _rule_group_rule_refresh(fuzzy, rule_group, weight_threshold, + output_number); + } + + if (conflict_len > 0) { + if (hard) + error = _break_groups_hard(fuzzy, &conflict_rule_group, + rule_group_list, weight_threshold, + output_number); + else + error = _break_groups(fuzzy, &conflict_rule_group, rule_group_list, + weight_threshold, output_number); + } + +end: + sol_ptr_vector_clear(&insert_rule_group); + sol_ptr_vector_clear(&conflict_rule_group); + + return error; +} + +int +sml_rule_group_list_observation_append(struct sml_fuzzy *fuzzy, + struct sol_ptr_vector *rule_group_list, + struct sml_observation_group *obs_group, + float weight_threshold, + bool simplification_disabled, + uint16_t output_number) +{ + if (simplification_disabled) + return _rule_group_list_observation_append_no_simplification(fuzzy, + rule_group_list, obs_group, weight_threshold, output_number); + return _rule_group_list_observation_append(fuzzy, rule_group_list, + obs_group, weight_threshold, output_number, false); +} + +int +sml_rule_group_rule_generate(struct sml_fuzzy *fuzzy, + struct sml_rule_group *rule_group, + float weight_threshold, uint16_t output_number, + sml_process_str_cb process_cb, void *data) +{ + struct sml_observation_group *obs_group; + struct sml_variable *var; + uint16_t *output_weights, len; + float *output_weights_float; + uint16_t c; + uint16_t i, j, index; + int error = 0; + + output_weights = calloc(fuzzy->output_terms_count, sizeof(uint16_t)); + if (!output_weights) + return -errno; + + SOL_PTR_VECTOR_FOREACH_IDX (&rule_group->observations, obs_group, c) + sml_observation_group_fill_output_weights(fuzzy, obs_group, + output_weights); + + output_weights_float = calloc(fuzzy->output_terms_count, sizeof(float)); + if (!output_weights_float) { + error = -errno; + goto rule_generate_end; + } + + index = 0; + len = sml_fuzzy_variables_list_get_length(fuzzy->output_list); + for (i = 0; i < len; i++) { + var = sml_fuzzy_variables_list_index(fuzzy->output_list, i); + uint16_t terms_len = sml_fuzzy_variable_terms_count(var); + uint16_t total_weight = 0; + for (j = 0; j < terms_len; j++) + total_weight += output_weights[index + j]; + + for (j = 0; j < terms_len; j++) { + output_weights_float[index] = output_weights[index] / + (float)total_weight; + index++; + } + } + + obs_group = sol_ptr_vector_get(&rule_group->observations, 0); + sml_observation_group_rule_generate(fuzzy, obs_group, weight_threshold, + &rule_group->relevant_inputs, + output_weights_float, + output_number, + process_cb, data); + free(output_weights_float); + +rule_generate_end: + free(output_weights); + return error; +} + +int +sml_rule_group_list_rebuild(struct sml_fuzzy *fuzzy, + struct sol_ptr_vector *rule_group_list, + struct sol_ptr_vector *obs_group_list, + float weight_threshold, + bool simplification_disabled, + uint16_t output_number) +{ + uint16_t i; + struct sml_rule_group *rule_group; + struct sml_observation_group *obs_group; + int error; + + SOL_PTR_VECTOR_FOREACH_IDX (rule_group_list, rule_group, i) + sml_rule_group_free(fuzzy, rule_group); + sol_ptr_vector_clear(rule_group_list); + + SOL_PTR_VECTOR_FOREACH_IDX (obs_group_list, obs_group, i) + if ((error = sml_rule_group_list_observation_append(fuzzy, + rule_group_list, obs_group, weight_threshold, + simplification_disabled, output_number))) + return error; + + return 0; +} + +int +sml_rule_group_list_rebalance(struct sml_fuzzy *fuzzy, + struct sol_ptr_vector *rule_group_list, + struct sml_observation_group *obs_group, + float weight_threshold, + uint16_t output_number) +{ + if (!_remove_from_rule_group_list(fuzzy, rule_group_list, obs_group, + weight_threshold, output_number)) + return 0; + + return sml_rule_group_list_observation_append(fuzzy, rule_group_list, + obs_group, weight_threshold, + false, output_number); +} + +bool +sml_rule_group_list_observation_remove(struct sml_fuzzy *fuzzy, + struct sol_ptr_vector *rule_group_list, + struct sml_observation_group *obs_group_obj, + float weight_threshold, + uint16_t output_number) +{ + uint16_t i, j; + struct sml_rule_group *rule_group; + struct sml_observation_group *obs_group; + + SOL_PTR_VECTOR_FOREACH_IDX (rule_group_list, rule_group, i) { + SOL_PTR_VECTOR_FOREACH_IDX (&rule_group->observations, obs_group, j) + if (obs_group == obs_group_obj) { + sol_ptr_vector_del(&rule_group->observations, j); + if (sol_ptr_vector_get_len(&rule_group->observations) == 0) { + sol_ptr_vector_del(rule_group_list, i); + sml_rule_group_free(fuzzy, rule_group); + } + return true; + } + } + return false; +} diff --git a/sml/sml_fuzzy/src/sml_rule_group.h b/sml/sml_fuzzy/src/sml_rule_group.h new file mode 100644 index 0000000..f782686 --- /dev/null +++ b/sml/sml_fuzzy/src/sml_rule_group.h @@ -0,0 +1,54 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include "sml_observation_group.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct sml_rule_group; + +struct sml_rule_group *sml_rule_group_new(); +void sml_rule_group_free(struct sml_fuzzy *fuzzy, struct sml_rule_group *rule_group); +int sml_rule_group_list_observation_append(struct sml_fuzzy *fuzzy, struct sol_ptr_vector *rule_group_list, struct sml_observation_group *obs_group, float weight_threshold, bool simplification_disabled, uint16_t output_number); +int sml_rule_group_rule_generate(struct sml_fuzzy *fuzzy, struct sml_rule_group *rule_group, float weight_threshold, uint16_t output_number, sml_process_str_cb process_cb, void *data); +int sml_rule_group_list_rebuild(struct sml_fuzzy *fuzzy, struct sol_ptr_vector *rule_group_list, struct sol_ptr_vector *obs_group_list, float weight_threshold, bool simplification_disabled, uint16_t output_number); +int sml_rule_group_list_rebalance(struct sml_fuzzy *fuzzy, struct sol_ptr_vector *rule_group_list, struct sml_observation_group *obs_group, float weight_threshold, uint16_t output_number); +bool sml_rule_group_list_observation_remove(struct sml_fuzzy *fuzzy, struct sol_ptr_vector *rule_group_list, struct sml_observation_group *obs_group_obj, float weight_threshold, uint16_t output_number); + +#ifdef __cplusplus +} +#endif diff --git a/sml/sml_fuzzy/src/sml_terms_manager.c b/sml/sml_fuzzy/src/sml_terms_manager.c new file mode 100644 index 0000000..373565b --- /dev/null +++ b/sml/sml_fuzzy/src/sml_terms_manager.c @@ -0,0 +1,396 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sml_terms_manager.h" +#include "macros.h" +#include "sml_log.h" +#include "sml_string.h" +#include +#include + +#define START_TERMS_COUNT (16) +#define OVERLAP_RATIO (0.1) +#define TERM_PREFIX "%s_TERM_%d" +#define TERM_SPLIT_PREFIX "TERM_SPLIT_%s_%d" +#define TERM_LEN (150) +#define MAX_HIT (500) + +#define MAX_CAP (MAX_HIT / 1.5) +#define MIN_CAP (MAX_CAP / 20 + 1) +#define FLOAT_THREASHOLD 0.01 + +static bool +_create_term(struct sml_fuzzy *fuzzy, struct sml_variable *var, + const char *name, float min, float max) +{ + float var_min, var_max; + + sml_fuzzy_variable_get_range(var, &var_min, &var_max); + + if (fabs(var_min - min) < FLOAT_THREASHOLD) + return sml_fuzzy_variable_add_term_ramp((struct sml_object *)fuzzy, + var, name, min, max, 1); + if (fabs(var_max - max) < FLOAT_THREASHOLD) + return sml_fuzzy_variable_add_term_ramp((struct sml_object *)fuzzy, + var, name, max, min, 1); + + return sml_fuzzy_variable_add_term_triangle((struct sml_object *)fuzzy, + var, name, min, min + (max - min) / 2, max, 1); +} + +static bool +_split(struct sml_fuzzy *fuzzy, + struct sml_observation_controller *obs_controller, + struct sml_variables_list *list, struct sml_matrix *variable_hits, + uint16_t var_num, uint16_t term_num, int *error) +{ + char buf[TERM_LEN]; + float min, max, step, overlap; + struct sml_fuzzy_term *term; + struct sml_variable *var; + uint16_t cur_hits, new_hits, terms_len, i, *val; + const char *term_name; + void *tmp; + + *error = 0; + var = sml_fuzzy_variables_list_index(list, var_num); + term = sml_fuzzy_variable_get_term(var, term_num); + if (!sml_fuzzy_term_get_range(term, &min, &max)) + return false; + + term_name = sml_fuzzy_term_get_name(term); + if (!term_name) + return false; + + cur_hits = sml_matrix_cast_get(variable_hits, var_num, term_num, tmp, + uint16_t); + new_hits = cur_hits / 2; + step = ((max - min) / 2); + overlap = step * OVERLAP_RATIO; + + //create new terms in fuzzy + snprintf(buf, TERM_LEN, TERM_SPLIT_PREFIX, term_name, 0); + if (!_create_term(fuzzy, var, buf, min, min + step + overlap)) { + *error = SML_INTERNAL_ERROR; + return false; + } + + snprintf(buf, TERM_LEN, TERM_SPLIT_PREFIX, term_name, 1); + if (!_create_term(fuzzy, var, buf, max - step - overlap, max)) { + *error = SML_INTERNAL_ERROR; + return false; + } + + //Add hits for terms just created + terms_len = sml_fuzzy_variable_terms_count(var); + for (i = 0; i < 2; i++) { + val = sml_matrix_insert(variable_hits, var_num, terms_len - i - 1); + if (!val) { + *error = -ENOMEM; + return false; + } + *val = new_hits; + } + + //Update controller + if ((*error = sml_observation_controller_split_terms(fuzzy, obs_controller, + var_num, term_num, terms_len - 1, terms_len - 2, + list == fuzzy->input_list))) + return false; + + if ((*error = sml_fuzzy_bridge_variable_remove_term(var, term_num))) + return false; + + sml_matrix_remove_col(variable_hits, var_num, term_num); + return true; +} + +static bool +_merge(struct sml_fuzzy *fuzzy, + struct sml_observation_controller *obs_controller, + struct sml_variables_list *list, struct sml_matrix *variable_hits, + uint16_t var_num, uint16_t term_num, int *error) +{ + float min, max, cur_min, cur_max; + uint16_t len, i, val, found_term_num, *cur_hits, *found_hits = NULL; + void *tmp; + struct sml_fuzzy_term *term, *cur_term, *found_term = NULL; + struct sml_variable *var; + + *error = 0; + var = sml_fuzzy_variables_list_index(list, var_num); + term = sml_fuzzy_variable_get_term(var, term_num); + if (!sml_fuzzy_term_get_range(term, &min, &max)) + return false; + + //get the overlaping term with less hits + len = sml_fuzzy_variable_terms_count(var); + for (i = 0; i < len; i++) { + cur_term = sml_fuzzy_variable_get_term(var, i); + cur_hits = sml_matrix_get(variable_hits, var_num, i); + if (cur_term == term || + (found_hits != NULL && *cur_hits >= *found_hits)) + continue; + + if (!sml_fuzzy_term_get_range(cur_term, &cur_min, &cur_max)) + continue; + + if ((cur_min >= min && cur_min <= max) || + (min >= cur_min && min <= cur_max)) { + found_hits = cur_hits; + found_term = cur_term; + found_term_num = i; + } + } + + if (found_term) { + if (!sml_fuzzy_term_get_range(found_term, &cur_min, &cur_max)) + return false; + sml_fuzzy_term_set_range(found_term, fmin(min, cur_min), + fmax(max, cur_max)); + if ((*error = sml_observation_controller_merge_terms(obs_controller, + var_num, found_term_num, term_num, + list == fuzzy->input_list))) + return false; + if ((*error = sml_fuzzy_bridge_variable_remove_term(var, term_num))) + return false; + + val = sml_matrix_cast_get(variable_hits, var_num, term_num, tmp, + uint16_t); + *found_hits = *found_hits + val; + sml_matrix_remove_col(variable_hits, var_num, term_num); + } + + return true; +} + +static bool +_should_split(uint16_t val) +{ + //TODO: Improve + return val > MAX_CAP; +} + +static bool +_should_merge(uint16_t val) +{ + //TODO: Improve + return val < MIN_CAP; +} + +static int +_hit(struct sml_fuzzy *fuzzy, struct sml_variables_list *list, + struct sml_observation_controller *obs_controller, + struct sml_matrix *values, struct sml_matrix *variable_hits, bool rebuild) +{ + float measured_val; + uint16_t i, j, len, *val, terms_len; + int error; + void *tmp; + struct sml_variable *var; + bool changed = false; + + len = sml_fuzzy_variables_list_get_length(list); + for (i = 0; i < len; i++) { + var = sml_fuzzy_variables_list_index(list, i); + terms_len = sml_fuzzy_variable_terms_count(var); + for (j = 0; j < terms_len; j++) { + measured_val = sml_matrix_cast_get(values, i, j, tmp, float); + struct sml_fuzzy_term *term = sml_fuzzy_variable_get_term(var, j); + float min = NAN, max = NAN; + sml_fuzzy_term_get_range(term, &min, &max); + + val = sml_matrix_insert(variable_hits, i, j); + if (measured_val >= VARIABLE_MEMBERSHIP_THRESHOLD) + *val = *val + 1; + if (rebuild) { + if (_should_split(*val)) { + if (_split(fuzzy, obs_controller, list, variable_hits, i, j, + &error)) { + j--; + terms_len--; + changed = true; + } else if (error) + return error; + } else if (_should_merge(*val)) { + if (_merge(fuzzy, obs_controller, list, variable_hits, i, j, + &error)) { + j--; + terms_len--; + changed = true; + } else if (error) + return error; + } + } + } + } + if (rebuild) + SML_MATRIX_FOREACH_IDX(variable_hits, tmp, val, i, j) + * val = *val / 2; + + if (changed) + sml_observation_controller_post_remove_variables(obs_controller); + + return 0; +} + +static void +_remove(struct sml_matrix *variable_hits, bool *to_remove) +{ + uint16_t i, len, removed = 0; + + + if (!to_remove) + return; + + len = sml_matrix_lines(variable_hits); + for (i = 0; i < len; i++) { + if (to_remove[i]) { + sml_matrix_remove_line(variable_hits, i - removed); + removed++; + } + } +} + +void +sml_terms_manager_init(struct sml_terms_manager *terms_manager) +{ + sml_measure_init(&terms_manager->hits, sizeof(uint16_t), sizeof(uint16_t)); + terms_manager->total = 0; +} + +void +sml_terms_manager_clear(struct sml_terms_manager *terms_manager) +{ + sml_measure_clear(&terms_manager->hits); + terms_manager->total = 0; +} + +int +sml_terms_manager_remove_variables(struct sml_terms_manager *terms_manager, + bool *inputs_to_remove, + bool *outputs_to_remove) +{ + _remove(&terms_manager->hits.inputs, inputs_to_remove); + _remove(&terms_manager->hits.outputs, outputs_to_remove); + + return 0; +} + +int +sml_terms_manager_hit(struct sml_terms_manager *terms_manager, + struct sml_fuzzy *fuzzy, struct sml_observation_controller *obs_controller, + struct sml_measure *measure) +{ + int error; + + terms_manager->total++; + if (terms_manager->total == MAX_HIT) + terms_manager->total = 0; + + if ((error = _hit(fuzzy, fuzzy->input_list, obs_controller, + &measure->inputs, &terms_manager->hits.inputs, + terms_manager->total == 0))) + return error; + + if ((error = _hit(fuzzy, fuzzy->output_list, obs_controller, + &measure->outputs, &terms_manager->hits.outputs, + terms_manager->total == 0))) + return error; + + return 0; +} + +void +sml_terms_manager_debug(struct sml_terms_manager *terms_manager) +{ + sml_debug("Terms_Manager {"); + sml_debug("\tInputs (%d) {", sml_matrix_lines(&terms_manager->hits.inputs)); + sml_matrix_debug_uint16_t(&terms_manager->hits.inputs); + sml_debug("\t}"); + sml_debug("\tOutputs (%d) {", + sml_matrix_lines(&terms_manager->hits.outputs)); + sml_matrix_debug_uint16_t(&terms_manager->hits.inputs); + sml_matrix_debug_uint16_t(&terms_manager->hits.outputs); + sml_debug("\t}"); + sml_debug("}"); +} + +int +sml_terms_manager_initialize_variable(struct sml_fuzzy *fuzzy, + struct sml_variable *var) +{ + //TODO: Improve terms creation + float min, max, range, step, overlap; + const char *var_name; + char buf[TERM_LEN]; + uint16_t i; + + sml_fuzzy_variable_get_range(var, &min, &max); + + var_name = sml_fuzzy_variable_get_name(var); + if (!var_name) + return -ENODATA; + + range = max - min; + step = range / START_TERMS_COUNT; + overlap = step * OVERLAP_RATIO; + + snprintf(buf, TERM_LEN, TERM_PREFIX, var_name, 0); + if (!sml_fuzzy_variable_add_term_ramp((struct sml_object *)fuzzy, + var, buf, min, min + step + overlap, 1)) + return SML_INTERNAL_ERROR; + + for (i = 1; i < START_TERMS_COUNT - 1; i++) { + snprintf(buf, TERM_LEN, TERM_PREFIX, var_name, i); + if (!sml_fuzzy_variable_add_term_triangle((struct sml_object *)fuzzy, + var, buf, min + step * i - overlap, min + step / 2, + min + step * (i + 1) + overlap, 1)) + return SML_INTERNAL_ERROR; + } + snprintf(buf, TERM_LEN, TERM_PREFIX, var_name, START_TERMS_COUNT - 1); + if (!sml_fuzzy_variable_add_term_ramp((struct sml_object *)fuzzy, + var, buf, max, max - step - overlap, 1)) + return SML_INTERNAL_ERROR; + + return 0; +} + +void +sml_terms_manager_remove_term(struct sml_terms_manager *terms_manager, + uint16_t var_num, uint16_t term_num, bool is_input) +{ + if (is_input) + sml_matrix_remove_col(&terms_manager->hits.inputs, var_num, term_num); + else + sml_matrix_remove_col(&terms_manager->hits.outputs, var_num, term_num); +} diff --git a/sml/sml_fuzzy/src/sml_terms_manager.h b/sml/sml_fuzzy/src/sml_terms_manager.h new file mode 100644 index 0000000..22cefb1 --- /dev/null +++ b/sml/sml_fuzzy/src/sml_terms_manager.h @@ -0,0 +1,58 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "sml_fuzzy_bridge.h" +#include "sml_observation_controller.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct sml_terms_manager { + uint16_t total; + struct sml_measure hits; +}; + +void sml_terms_manager_init(struct sml_terms_manager *terms_manager); +int sml_terms_manager_remove_variables(struct sml_terms_manager *terms_manager, bool *inputs_to_remove, bool *outputs_to_remove); +int sml_terms_manager_hit(struct sml_terms_manager *terms_manager, struct sml_fuzzy *fuzzy, struct sml_observation_controller *obs_controller, struct sml_measure *measure); +void sml_terms_manager_clear(struct sml_terms_manager *terms_manager); +void sml_terms_manager_debug(struct sml_terms_manager *terms_manager); +int sml_terms_manager_initialize_variable(struct sml_fuzzy *fuzzy, struct sml_variable *var); +void sml_terms_manager_remove_term(struct sml_terms_manager *terms_manager, uint16_t var_num, uint16_t term_num, bool is_input); + +#ifdef __cplusplus +} +#endif diff --git a/sml/sml_naive/include/sml_naive.h b/sml/sml_naive/include/sml_naive.h new file mode 100644 index 0000000..ab99723 --- /dev/null +++ b/sml/sml_naive/include/sml_naive.h @@ -0,0 +1,84 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @defgroup Naive_Engine Naive engine + * @brief The SML naive testing engine. + * + * This engine is only used to for testing, it will never try to predict + * an output. It will only call the ::sml_read_state_cb + * @{ + */ + +/** + * @brief Creates a SML naive engine. + * + * @remark Free with ::sml_free + * + * @return A ::sml_object object on success. + * @return @c NULL on failure. + * + * @see ::sml_free + */ +struct sml_object *sml_naive_new(void); + +/** + * @brief Check if this SML object is a naive engine. + * + * @param sml A ::sml_object object. + * @return @c true If it is naive. + * @return @c false If it is not naive. + */ +bool sml_is_naive(struct sml_object *sml); + +/** + * @brief Check if SML was built with naive support. + * + * @return @c true If it is supported. + * @return @c false If not supported. + */ +bool sml_naive_supported(void); + +/** + * @} + */ +#ifdef __cplusplus +} +#endif diff --git a/sml/sml_naive/src/sml_naive.c b/sml/sml_naive/src/sml_naive.c new file mode 100644 index 0000000..95e17e7 --- /dev/null +++ b/sml/sml_naive/src/sml_naive.c @@ -0,0 +1,406 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "macros.h" +#include "sml_engine.h" +#include "sml_log.h" +#include +#include "config.h" +#include +#include +#include +#include +#include + +#define NAIVE_MAGIC (0x2a17e) + +typedef struct _Variable { + char *name; + bool enabled; + float min, max, val; +} Variable; + +struct sml_naive_engine { + struct sml_engine engine; + struct sol_ptr_vector input_list; + struct sol_ptr_vector output_list; +}; + +static int +_sml_process(struct sml_engine *engine) +{ + if (!engine->read_state_cb) { + sml_critical("There is not read callback registered"); + return -EINVAL; + } + + if (!engine->read_state_cb((struct sml_object *)engine, + engine->read_state_cb_data)) { + sml_debug("Read cb returned false"); + return -EAGAIN; + } + return 0; +} + +static bool +_sml_predict(struct sml_engine *engine) +{ + return true; +} + +static bool +_sml_save(struct sml_engine *engine, const char *path) +{ + sml_debug("Save not needed for naive engine"); + return true; +} + +static bool +_sml_load(struct sml_engine *engine, const char *path) +{ + sml_debug("Load not needed for naive engine"); + return true; +} + +static void +_sml_free(struct sml_engine *engine) +{ + struct sml_naive_engine *naive_engine = (struct sml_naive_engine *)engine; + uint16_t i; + Variable *var; + + SOL_PTR_VECTOR_FOREACH_IDX (&naive_engine->input_list, var, i) { + free(var->name); + free(var); + } + sol_ptr_vector_clear(&naive_engine->input_list); + + SOL_PTR_VECTOR_FOREACH_IDX (&naive_engine->output_list, var, i) { + free(var->name); + free(var); + } + sol_ptr_vector_clear(&naive_engine->output_list); + free(naive_engine); +} + +static void +_print_list(struct sol_ptr_vector *list) +{ + uint16_t i; + Variable *var; + + SOL_PTR_VECTOR_FOREACH_IDX (list, var, i) + sml_debug("\t%s: %f (%f - %f)", var->name, var->val, var->min, + var->max); +} + +static void +_sml_print_debug(struct sml_engine *engine, bool full) +{ + struct sml_naive_engine *naive_engine = (struct sml_naive_engine *)engine; + + sml_debug("Inputs(%d) {", + sol_ptr_vector_get_len(&naive_engine->input_list)); + _print_list(&naive_engine->input_list); + sml_debug("}"); + sml_debug("Outputs(%d) {", + sol_ptr_vector_get_len(&naive_engine->output_list)); + _print_list(&naive_engine->output_list); + sml_debug("}"); +} + +static struct sml_variables_list * +_sml_get_input_list(struct sml_engine *engine) +{ + struct sml_naive_engine *naive_engine = (struct sml_naive_engine *)engine; + + return (struct sml_variables_list *)&naive_engine->input_list; +} + +static struct sml_variables_list * +_sml_get_output_list(struct sml_engine *engine) +{ + struct sml_naive_engine *naive_engine = (struct sml_naive_engine *)engine; + + return (struct sml_variables_list *)&naive_engine->output_list; +} + +static bool +_sml_remove_variable(struct sml_engine *engine, struct sml_variable *variable) +{ + struct sml_naive_engine *naive_engine = (struct sml_naive_engine *)engine; + uint16_t i; + Variable *var; + + SOL_PTR_VECTOR_FOREACH_IDX (&naive_engine->input_list, var, i) + if ((struct sml_variable *)var == variable) { + if (sol_ptr_vector_del(&naive_engine->input_list, i)) { + sml_critical("Could not remove input variable"); + return false; + } + return true; + } + + SOL_PTR_VECTOR_FOREACH_IDX (&naive_engine->output_list, var, i) + if ((struct sml_variable *)var == variable) { + if (sol_ptr_vector_del(&naive_engine->output_list, i)) { + sml_critical("Could not remove output variable"); + return false; + } + return true; + } + + sml_critical("Failed to remove. Variable not in naive engine."); + return false; +} + +static int +_sml_variable_set_enabled(struct sml_engine *engine, + struct sml_variable *variable, bool enabled) +{ + Variable *var = (Variable *)variable; + + var->enabled = enabled; + + return true; +} + +static struct sml_variable * +_sml_get_input(struct sml_engine *engine, const char *name) +{ + struct sml_naive_engine *naive_engine = (struct sml_naive_engine *)engine; + uint16_t i; + Variable *var; + + SOL_PTR_VECTOR_FOREACH_IDX (&naive_engine->input_list, var, i) + if (!strcmp(var->name, name)) + return (struct sml_variable *)var; + return NULL; +} + +static struct sml_variable * +_sml_get_output(struct sml_engine *engine, const char *name) +{ + struct sml_naive_engine *naive_engine = (struct sml_naive_engine *)engine; + uint16_t i; + Variable *var; + + SOL_PTR_VECTOR_FOREACH_IDX (&naive_engine->output_list, var, i) + if (!strcmp(var->name, name)) + return (struct sml_variable *)var; + return NULL; +} + +static Variable * +_create_var(const char *name) +{ + Variable *var = malloc(sizeof(Variable)); + + if (!var) + return NULL; + + var->name = strdup(name); + if (!var->name) { + free(var); + return NULL; + } + var->enabled = true; + var->min = NAN; + var->max = NAN; + var->val = NAN; + + return var; +} + +static struct sml_variable * +_sml_new_input(struct sml_engine *engine, const char *name) +{ + struct sml_naive_engine *naive_engine = (struct sml_naive_engine *)engine; + Variable *var = _create_var(name); + + if (!var) + return NULL; + + if (sol_ptr_vector_append(&naive_engine->input_list, var)) { + free(var); + return NULL; + } + + return (struct sml_variable *)var; +} + +static struct sml_variable * +_sml_new_output(struct sml_engine *engine, const char *name) +{ + struct sml_naive_engine *naive_engine = (struct sml_naive_engine *)engine; + Variable *var = _create_var(name); + + if (!var) + return NULL; + + if (sol_ptr_vector_append(&naive_engine->output_list, var)) { + free(var); + return NULL; + } + + return (struct sml_variable *)var; +} + +static const char * +_sml_variable_get_name(struct sml_variable *sml_variable) +{ + Variable *var = (Variable *)sml_variable; + + return var->name; +} + +static float +_sml_variable_get_value(struct sml_variable *sml_variable) +{ + Variable *var = (Variable *)sml_variable; + + return var->val; +} + +static bool +_sml_variable_set_value(struct sml_variable *sml_variable, float val) +{ + Variable *var = (Variable *)sml_variable; + + var->val = val; + return true; +} + +static bool +_sml_variable_is_enabled(struct sml_variable *sml_variable) +{ + Variable *var = (Variable *)sml_variable; + + return var->enabled; +} + +static struct sml_variable * +_variables_list_index(struct sml_variables_list *list, unsigned int index) +{ + if (index > UINT16_MAX) + return NULL; + + return (struct sml_variable *)sol_ptr_vector_get( + (struct sol_ptr_vector *)list, index); +} + +static uint16_t +_sml_variables_list_get_length(struct sml_variables_list *list) +{ + return sol_ptr_vector_get_len((struct sol_ptr_vector *)list); +} + +static bool +_sml_variable_set_range(struct sml_variable *variable, float min, float max) +{ + Variable *var = (Variable *)variable; + + var->min = min; + var->max = max; + + return true; +} + +static bool +_sml_variable_get_range(struct sml_variable *variable, float *min, float *max) +{ + Variable *var = (Variable *)variable; + + if (min) + *min = var->min; + if (max) + *max = var->max; + return true; +} + +API_EXPORT struct sml_object * +sml_naive_new(void) +{ + struct sml_naive_engine *naive_engine = calloc(1, + sizeof(struct sml_naive_engine)); + + if (!naive_engine) + goto error_sml; + + sol_ptr_vector_init(&naive_engine->input_list); + sol_ptr_vector_init(&naive_engine->output_list); + + naive_engine->engine.free = _sml_free; + naive_engine->engine.process = _sml_process; + naive_engine->engine.predict = _sml_predict; + naive_engine->engine.save = _sml_save; + naive_engine->engine.load = _sml_load; + naive_engine->engine.get_input_list = _sml_get_input_list; + naive_engine->engine.get_output_list = _sml_get_output_list; + naive_engine->engine.new_input = _sml_new_input; + naive_engine->engine.new_output = _sml_new_output; + naive_engine->engine.get_input = _sml_get_input; + naive_engine->engine.get_output = _sml_get_output; + naive_engine->engine.get_name = _sml_variable_get_name; + naive_engine->engine.set_value = _sml_variable_set_value; + naive_engine->engine.get_value = _sml_variable_get_value; + naive_engine->engine.variable_set_enabled = _sml_variable_set_enabled; + naive_engine->engine.variable_is_enabled = _sml_variable_is_enabled; + naive_engine->engine.remove_variable = _sml_remove_variable; + naive_engine->engine.variables_list_get_length = + _sml_variables_list_get_length; + naive_engine->engine.variables_list_index = _variables_list_index; + naive_engine->engine.variable_set_range = _sml_variable_set_range; + naive_engine->engine.variable_get_range = _sml_variable_get_range; + naive_engine->engine.print_debug = _sml_print_debug; + naive_engine->engine.magic_number = NAIVE_MAGIC; + + return (struct sml_object *)&naive_engine->engine; + +error_sml: + sml_critical("Failed to create struct sml"); + return NULL; +} + +API_EXPORT bool +sml_is_naive(struct sml_object *sml) +{ + ON_NULL_RETURN_VAL(sml, false); + struct sml_naive_engine *naive_engine = (struct sml_naive_engine *)sml; + return naive_engine->engine.magic_number == NAIVE_MAGIC; +} + +API_EXPORT bool +sml_naive_supported(void) +{ + return true; +} diff --git a/sml/sml_naive/src/sml_naive_support.c b/sml/sml_naive/src/sml_naive_support.c new file mode 100644 index 0000000..466c0de --- /dev/null +++ b/sml/sml_naive/src/sml_naive_support.c @@ -0,0 +1,57 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "macros.h" +#include "sml_log.h" + +API_EXPORT struct sml_object * +sml_naive_new(void) +{ + sml_critical("Naive engine not supported."); + return NULL; +} + +API_EXPORT bool +sml_is_naive(struct sml_object *sml) +{ + sml_critical("Naive engine not supported."); + return false; +} + +API_EXPORT bool +sml_naive_supported(void) +{ + return false; +} + diff --git a/soletta_module/CMakeLists.txt b/soletta_module/CMakeLists.txt new file mode 100644 index 0000000..4c084e4 --- /dev/null +++ b/soletta_module/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 2.8) + +project(sml) + +add_definitions(-DSOL_FLOW_NODE_TYPE_MODULE_EXTERNAL) + +set(SML_SOLETTA_GEN_H ${CMAKE_CURRENT_SOURCE_DIR}/machine_learning/machine_learning_gen.h) +set(SML_SOLETTA_GEN_C ${CMAKE_CURRENT_SOURCE_DIR}/machine_learning/machine_learning_gen.c) +set(SML_SOLETTA_JSON ${CMAKE_CURRENT_SOURCE_DIR}/machine_learning/machine_learning.json) + +execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=modulesdir soletta + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE SML_SOLETTA_LIB_PREFIX + ) + +execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=nodeschemapath soletta + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE SCHEMA_PATH + ) + +execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir soletta + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE SOLETTA_DATA_DIR + ) + +add_custom_target(GEN_FILES +#FIXME use add_custom_command otherwise it always will build this gen files +#add_custom_command( +# OUTPUT ${SML_SOLETTA_GEN_H} ${SML_SOLETTA_GEN_C} + COMMAND ${CMAKE_FIND_ROOT_PATH}/${SOLETTA_PREFIX}/bin/sol-flow-node-type-validate.py ${CMAKE_FIND_ROOT_PATH}/${SCHEMA_PATH} ${SML_SOLETTA_JSON} + COMMAND ${CMAKE_FIND_ROOT_PATH}/${SOLETTA_PREFIX}/bin/sol-flow-node-type-gen.py --prefix=sol-flow-node-type --genspec-schema=${CMAKE_FIND_ROOT_PATH}/${SCHEMA_PATH} ${SML_SOLETTA_JSON} ${SML_SOLETTA_GEN_H} ${SML_SOLETTA_GEN_C} ${CMAKE_BINARY_DIR}/soletta_module/machine_learning.json + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/machine_learning/machine_learning.json + ) + +set(BUILT_SOURCES + ${SML_SOLETTA_GEN_H} + ${SML_SOLETTA_GEN_C} + ) +SET_SOURCE_FILES_PROPERTIES(${BUILT_SOURCES} PROPERTIES + GENERATED true + ) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../sml/common/include/ + ${SOLETTA_INCLUDE_DIRS} + ${SML_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/machine_learning/ + ) + +link_directories( + ${SOLETTA_LIBRARY_DIRS} + ${FUZZY_LITE_LIBRARY_DIRS} + ${FANN_LIBRARY_DIRS} + ) + +add_library(machine-learning SHARED + ${CMAKE_CURRENT_SOURCE_DIR}/machine_learning/machine_learning.c + ) +set_target_properties(machine-learning + PROPERTIES PREFIX "" + ) + + +target_link_libraries(machine-learning + ${SOLETTA_LIBRARIES} + sml_libs + m) + +add_dependencies(machine-learning + GEN_FILES + ) + +install(TARGETS machine-learning + LIBRARY DESTINATION ${SML_SOLETTA_LIB_PREFIX}/flow/ + ) + +install(FILES ${CMAKE_BINARY_DIR}/soletta_module/machine_learning.json + DESTINATION ${SOLETTA_DATA_DIR}/flow/descriptions +) diff --git a/soletta_module/i586-poky-linux-uclibc.cmake b/soletta_module/i586-poky-linux-uclibc.cmake new file mode 100644 index 0000000..876c540 --- /dev/null +++ b/soletta_module/i586-poky-linux-uclibc.cmake @@ -0,0 +1,15 @@ +SET(CMAKE_SYSTEM_NAME Linux) +SET(CMAKE_SYSTEM_VERSION 1) + +SET(CMAKE_C_COMPILER i586-poky-linux-uclibc-gcc) +SET(CMAKE_CXX_COMPILER i586-poky-linux-uclibc-g++ -pthread) + +# where is the target environment +SET(CMAKE_FIND_ROOT_PATH /opt/clanton-tiny/1.4.2/sysroots/i586-poky-linux-uclibc) + +# search for programs in the build host directories +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# for libraries and headers in the target directories +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff --git a/soletta_module/machine_learning/.gitignore b/soletta_module/machine_learning/.gitignore new file mode 100644 index 0000000..c43c1a3 --- /dev/null +++ b/soletta_module/machine_learning/.gitignore @@ -0,0 +1 @@ +/machine_learning_gen.* diff --git a/soletta_module/machine_learning/machine_learning.c b/soletta_module/machine_learning/machine_learning.c new file mode 100644 index 0000000..8a1ac0e --- /dev/null +++ b/soletta_module/machine_learning/machine_learning.c @@ -0,0 +1,929 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sml_ann.h" +#include "sml_fuzzy.h" + +#include "machine_learning_gen.h" + +struct tagged_float_data { + struct sol_drange value; + char *tag; +}; + +static int +mutex_lock(pthread_mutex_t *lock) +{ + int error = pthread_mutex_lock(lock); + + if (error) + SOL_WRN("Impossible to lock mutex. Error code: %d\n", error); + return error; +} + +static void +tagged_float_packet_dispose(const struct sol_flow_packet_type *packet_type, + void *mem) +{ + struct tagged_float_data *tagged_float = mem; + + free(tagged_float->tag); +} + +static int +tagged_float_packet_init(const struct sol_flow_packet_type *packet_type, + void *mem, const void *input) +{ + const struct tagged_float_data *in = input; + struct tagged_float_data *tagged_float = mem; + + tagged_float->tag = strdup(in->tag); + SOL_NULL_CHECK(tagged_float->tag, -ENOMEM); + tagged_float->value = in->value; + + return 0; +} + +#define TAGGED_FLOAT_PACKET_TYPE_API_VERSION (1) + +static const struct sol_flow_packet_type _PACKET_TYPE_TAGGED_FLOAT = { + .api_version = TAGGED_FLOAT_PACKET_TYPE_API_VERSION, + .name = "TaggedFloat", + .data_size = sizeof(struct tagged_float_data), + .init = tagged_float_packet_init, + .dispose = tagged_float_packet_dispose, +}; +static const struct sol_flow_packet_type *PACKET_TYPE_TAGGED_FLOAT = + &_PACKET_TYPE_TAGGED_FLOAT; + +#undef TAGGED_FLOAT_PACKET_TYPE_API_VERSION + +static struct sol_flow_packet * +packet_new_tagged_float(struct sol_drange *value, const char *tag) +{ + struct tagged_float_data tagged_float; + + SOL_NULL_CHECK(value, NULL); + SOL_NULL_CHECK(tag, NULL); + + tagged_float.value = *value; + tagged_float.tag = (char *)tag; + + return sol_flow_packet_new(PACKET_TYPE_TAGGED_FLOAT, &tagged_float); +} + +static int +packet_get_tagged_float(const struct sol_flow_packet *packet, + struct sol_drange *value, char **tag) +{ + struct tagged_float_data tagged_float; + int ret; + + SOL_NULL_CHECK(packet, -EBADR); + if (sol_flow_packet_get_type(packet) != PACKET_TYPE_TAGGED_FLOAT) + return -EINVAL; + + ret = sol_flow_packet_get(packet, &tagged_float); + SOL_INT_CHECK(ret, != 0, ret); + + if (tag) + *tag = tagged_float.tag; + if (value) + *value = tagged_float.value; + + return ret; +} + +static int +send_tagged_float_packet(struct sol_flow_node *src, uint16_t src_port, + struct sol_drange *value, const char *tag) +{ + struct sol_flow_packet *packet; + int ret; + + packet = packet_new_tagged_float(value, tag); + SOL_NULL_CHECK(packet, -ENOMEM); + + ret = sol_flow_send_packet(src, src_port, packet); + if (ret != 0) + sol_flow_packet_del(packet); + + return ret; +} + +struct tagger_data { + char *tag; +}; + +static int +tagger_open(struct sol_flow_node *node, void *data, + const struct sol_flow_node_options *options) +{ + struct tagger_data *mdata = data; + const struct sol_flow_node_type_machine_learning_tagger_options *opts; + + opts = (const struct + sol_flow_node_type_machine_learning_tagger_options *)options; + + if (!opts->tag) { + SOL_WRN("Valid tag is required"); + return -EINVAL; + } + + mdata->tag = strdup(opts->tag); + SOL_NULL_CHECK(mdata->tag, -ENOMEM); + + return 0; +} + +static void +tagger_close(struct sol_flow_node *node, void *data) +{ + struct tagger_data *mdata = data; + + free(mdata->tag); +} + +static int +tagger_process(struct sol_flow_node *node, void *data, uint16_t port, + uint16_t conn_id, const struct sol_flow_packet *packet) +{ + struct tagger_data *mdata = data; + int r; + struct sol_drange in_value; + + r = sol_flow_packet_get_drange(packet, &in_value); + SOL_INT_CHECK(r, < 0, r); + + return send_tagged_float_packet(node, + SOL_FLOW_NODE_TYPE_MACHINE_LEARNING_TAGGER__OUT__OUT, + &in_value, mdata->tag); +} + +static int +filter_process(struct sol_flow_node *node, void *data, uint16_t port, + uint16_t conn_id, const struct sol_flow_packet *packet) +{ + struct tagger_data *mdata = data; + int r; + struct sol_drange value; + char *tag; + + r = packet_get_tagged_float(packet, &value, &tag); + SOL_INT_CHECK(r, < 0, r); + + if (strcmp(tag, mdata->tag)) + return 0; + + return sol_flow_send_drange_packet(node, + SOL_FLOW_NODE_TYPE_MACHINE_LEARNING_FILTER__OUT__OUT, + &value); +} + +struct machine_learning_data { + //Used only in open method or/and worker thread. No need to lock + struct sml_object *sml; + uint16_t number_of_terms; + bool run_process; + + //Used by main thread and process thread. Need to be locked + struct sol_vector input_vec; + struct sol_vector output_vec; + bool process_needed, predict_needed, send_process_finished; + + struct sol_flow_node *node; + struct sol_worker_thread *worker; + pthread_mutex_t process_lock; + pthread_mutex_t read_lock; +}; + +struct machine_learning_var { + struct sml_variable *sml_variable; + struct sol_drange value; + bool range_changed; +}; + +struct machine_learning_input_var { + struct machine_learning_var base; +}; + +struct machine_learning_output_var { + struct machine_learning_var base; + double predicted_value; + char *tag; +}; + +/* TODO avoid gaps between terms */ +static void +add_term(struct sml_object *sml, int32_t term_index, + struct sml_variable *sml_var, const char *name, float var_min, + float step, uint16_t number_of_terms, float overlap) +{ + double min, max; + + if (term_index == 0) { + min = var_min; + max = min + (step / 2) + overlap; + sml_fuzzy_variable_add_term_ramp(sml, sml_var, name, max, min, 1); + } else if (term_index == number_of_terms - 1) { + max = var_min + term_index * step; + min = max - (step / 2) - overlap; + sml_fuzzy_variable_add_term_ramp(sml, sml_var, name, min, max, 1); + } else { + min = var_min + step * term_index - (step / 2) - overlap; + max = min + step + overlap; + sml_fuzzy_variable_add_term_triangle(sml, sml_var, name, min, + min + (max - min) / 2, max, 1); + } + + SOL_DBG("Term %s (%f - %f) added for %s", name, min, max, + sml_variable_get_name(sml, sml_var)); +} + +#define OVERLAP_PERCENTAGE (0.1) +static void +variable_add_terms(struct sml_object *sml, struct machine_learning_var *var, + uint16_t max_number_of_terms) +{ + + /* TODO check for used range instead of nominal range to improve terms */ + float step; + int32_t i; + char name[8]; + uint16_t number_of_terms; + float overlap; + + number_of_terms = fmin((var->value.max - var->value.min + 1) / + var->value.step, max_number_of_terms); + + step = (var->value.max - var->value.min + 1) / number_of_terms; + overlap = step * OVERLAP_PERCENTAGE; + for (i = 0; i < number_of_terms; i++) { + snprintf(name, sizeof(name), "t%d", i); + add_term(sml, i, var->sml_variable, name, var->value.min, step, + number_of_terms, overlap); + } +} +#undef OVERLAP_PERCENTAGE + +static void +set_variable(struct machine_learning_data *mdata, + struct machine_learning_var *var) +{ + sml_variable_set_value(mdata->sml, var->sml_variable, var->value.val); + + if (!var->range_changed) + return; + + var->range_changed = false; + sml_variable_set_range(mdata->sml, var->sml_variable, var->value.min, + var->value.max); + + if (sml_is_ann(mdata->sml)) + return; + + /* TODO remove terms before (if any was previouly created) */ + variable_add_terms(mdata->sml, var, mdata->number_of_terms); +} + +static bool +read_state_cb(struct sml_object *sml, void *data) +{ + struct machine_learning_data *mdata = data; + struct machine_learning_input_var *input_var; + struct machine_learning_output_var *output_var; + int i; + + if (mutex_lock(&mdata->read_lock)) + return false; + + SOL_VECTOR_FOREACH_IDX (&mdata->input_vec, input_var, i) + set_variable(mdata, &input_var->base); + SOL_VECTOR_FOREACH_IDX (&mdata->output_vec, output_var, i) + set_variable(mdata, &output_var->base); + + pthread_mutex_unlock(&mdata->read_lock); + return true; +} + +static void +output_state_changed_cb(struct sml_object *sml, + struct sml_variables_list *changed, + void *data) +{ + struct machine_learning_data *mdata = data; + struct machine_learning_output_var *output_var; + int i; + + if (mutex_lock(&mdata->read_lock)) + return; + + SOL_VECTOR_FOREACH_IDX (&mdata->output_vec, output_var, i) { + if (changed && !sml_variables_list_contains(sml, changed, + output_var->base.sml_variable)) + continue; + double value = sml_variable_get_value(sml, + output_var->base.sml_variable); + if (isnan(value)) + continue; + + output_var->predicted_value = value; + } + + pthread_mutex_unlock(&mdata->read_lock); +} + +static int +create_engine(struct machine_learning_data *mdata) +{ + int r; + + if (!mdata->sml) { + SOL_WRN("Failed to create sml"); + return -EBADR; + } + + if (!sml_set_read_state_callback(mdata->sml, read_state_cb, mdata)) { + SOL_WRN("Failed to set read callback"); + return -EINVAL; + } + + if (!sml_set_output_state_changed_callback(mdata->sml, + output_state_changed_cb, mdata)) { + SOL_WRN("Failed to set change state callback"); + return -EINVAL; + } + + sol_vector_init(&mdata->input_vec, + sizeof(struct machine_learning_input_var)); + sol_vector_init(&mdata->output_vec, + sizeof(struct machine_learning_output_var)); + + if ((r = pthread_mutex_init(&mdata->process_lock, NULL)) || + (r = pthread_mutex_init(&mdata->read_lock, NULL))) { + SOL_WRN("Failed to initialize pthread mutex lock"); + return -r; + } + return 0; +} + +#define AUTOMATIC_TERMS (15) + +static int +machine_learning_fuzzy_open(struct sol_flow_node *node, void *data, + const struct sol_flow_node_options *options) +{ + struct machine_learning_data *mdata = data; + const struct sol_flow_node_type_machine_learning_fuzzy_options *opts; + int32_t stabilization_hits; + int r; + + opts = (const struct + sol_flow_node_type_machine_learning_fuzzy_options *)options; + + mdata->node = node; + + mdata->sml = sml_fuzzy_new(); + r = create_engine(mdata); + SOL_INT_CHECK(r, < 0, r); + + if (opts->stabilization_hits.val >= 0) + stabilization_hits = opts->stabilization_hits.val; + else { + SOL_WRN("Stabilization hits (%d) must be a positive value. Assuming 0.", + opts->stabilization_hits.val); + stabilization_hits = 0; + } + + if (opts->number_of_terms.val >= 0) + mdata->number_of_terms = opts->number_of_terms.val; + else { + SOL_WRN("Number of fuzzy terms (%d) must be a positive value. " + "Assuming %d.", opts->number_of_terms.val, AUTOMATIC_TERMS); + mdata->number_of_terms = AUTOMATIC_TERMS; + } + + if (!sml_set_stabilization_hits(mdata->sml, stabilization_hits)) { + SOL_WRN("Failed to set stabilization hits"); + return -EINVAL; + } + + return 0; +} + +#undef AUTOMATIC_TERMS + +static const struct activation_function { + enum sml_ann_activation_function function; + const char *name; +} activation_functions[] = { + { SML_ANN_ACTIVATION_FUNCTION_SIGMOID, "sigmoid" }, + { SML_ANN_ACTIVATION_FUNCTION_SIGMOID_SYMMETRIC, "sigmoid_symmetric" }, + { SML_ANN_ACTIVATION_FUNCTION_GAUSSIAN, "gaussian" }, + { SML_ANN_ACTIVATION_FUNCTION_GAUSSIAN_SYMMETRIC, "gaussian_symmetric" }, + { SML_ANN_ACTIVATION_FUNCTION_ELLIOT, "elliot" }, + { SML_ANN_ACTIVATION_FUNCTION_ELLIOT_SYMMETRIC, "elliot_symmetric" }, + { SML_ANN_ACTIVATION_FUNCTION_COS, "cos" }, + { SML_ANN_ACTIVATION_FUNCTION_COS_SYMMETRIC, "cos_symmetric" }, + { SML_ANN_ACTIVATION_FUNCTION_SIN, "sin" }, + { SML_ANN_ACTIVATION_FUNCTION_SIN_SYMMETRIC, "sin_symmetric" }, + { 0, NULL } +}; + +static void +use_default_functions(enum sml_ann_activation_function *functions, + unsigned int *size) +{ + const struct activation_function *cur = &activation_functions[0]; + unsigned int i = 0; + + while (cur->name) { + functions[i++] = cur->function; + cur++; + *size = i; + } +} + +static int +parse_functions(const char *options, + enum sml_ann_activation_function *functions, + unsigned int *size) +{ + const struct activation_function *cur; + char *token, *saveptr, *func_options; + unsigned int j, i = 0; + + func_options = strdup(options); + SOL_NULL_CHECK(func_options, -ENOMEM); + + /* TODO: do we have something like strtok for sol_str_slice? */ + token = strtok_r(func_options, " ", &saveptr); + while (token) { + cur = &activation_functions[0]; + while (1) { + if (!strcmp(cur->name, token)) { + if (!i) + functions[i++] = cur->function; + else { + for (j = 0; j < i; j++) + if (functions[j] == cur->function) + break; + functions[i++] = cur->function; + } + break; + } + + cur++; + if (!cur->name) { + SOL_WRN("Invalid function: %s. Skiping it.", token); + break; + } + } + token = strtok_r(NULL, " ", &saveptr); + } + + *size = i; + free(func_options); + + return 0; +} + +/* TODO should we have SML_ACTIVATION_FUNCTION_LAST? */ +#define MAX_FUNCTIONS (SML_ANN_ACTIVATION_FUNCTION_SIN_SYMMETRIC + 1) + +static int +machine_learning_neural_network_open(struct sol_flow_node *node, void *data, + const struct sol_flow_node_options *options) +{ + double mse; + struct machine_learning_data *mdata = data; + const struct sol_flow_node_type_machine_learning_neural_network_options + *opts; + enum sml_ann_activation_function functions[MAX_FUNCTIONS]; + int r; + enum sml_ann_training_algorithm algorithm = + SML_ANN_TRAINING_ALGORITHM_RPROP; + unsigned int functions_size; + int32_t stabilization_hits; + + opts = (const struct + sol_flow_node_type_machine_learning_neural_network_options *)options; + + mdata->node = node; + + mdata->sml = sml_ann_new(); + r = create_engine(mdata); + SOL_INT_CHECK(r, < 0, r); + + if (opts->stabilization_hits.val >= 0) + stabilization_hits = opts->stabilization_hits.val; + else { + SOL_WRN("Stabilization hits (%d) must be a positive value. Assuming 0.", + opts->stabilization_hits.val); + stabilization_hits = 0; + } + + if (!sml_set_stabilization_hits(mdata->sml, stabilization_hits)) { + SOL_WRN("Failed to set stabilization hits"); + return -EINVAL; + } + + if (opts->initial_required_observations.val > 0) { + if (!sml_ann_set_initial_required_observations(mdata->sml, + opts->initial_required_observations.val)) { + SOL_WRN("Failed to set initial required observations"); + return -EINVAL; + } + } + + /* TODO: maybe we should have some kind of enum? */ + if (!strcmp(opts->training_algorithm, "quickprop")) + algorithm = SML_ANN_TRAINING_ALGORITHM_QUICKPROP; + else if (strcmp(opts->training_algorithm, "rprop")) + SOL_WRN("Training algorithm %s not supported. Using rprop.", + opts->training_algorithm); + if (!sml_ann_set_training_algorithm(mdata->sml, algorithm)) { + SOL_WRN("Failed to set training algorithm"); + return -EINVAL; + } + + /* TODO: maybe we should have an array of strings option type? */ + if (!opts->activation_functions) { + SOL_WRN("Activation functions is mandatory. Using all candidates"); + use_default_functions(functions, &functions_size); + } else { + r = parse_functions(opts->activation_functions, functions, + &functions_size); + SOL_INT_CHECK(r, < 0, r); + + if (functions_size == 0) + use_default_functions(functions, &functions_size); + } + if (!sml_ann_set_activation_function_candidates(mdata->sml, functions, + functions_size)) { + SOL_WRN("Failed to set desired error"); + return -EINVAL; + } + + if (isgreater(opts->mse.val, 0)) + mse = opts->mse.val; + else { + SOL_WRN("Desired mean squared error (%f) must be a positive value." + "Assuming 0.1", opts->mse.val); + mse = 0.1; + } + if (!sml_ann_set_desired_error(mdata->sml, mse)) { + SOL_WRN("Failed to set desired error"); + return -EINVAL; + } + + return 0; +} + +#undef MAX_FUNCTIONS + +static void +machine_learning_close(struct sol_flow_node *node, void *data) +{ + struct machine_learning_data *mdata = data; + struct machine_learning_output_var *output_var; + uint16_t i; + int error; + + sol_vector_clear(&mdata->input_vec); + SOL_VECTOR_FOREACH_IDX (&mdata->output_vec, output_var, i) + free(output_var->tag); + sol_vector_clear(&mdata->output_vec); + if ((error = pthread_mutex_destroy(&mdata->process_lock))) + SOL_WRN("Error %d when destroying pthread mutex lock", error); + if ((error = pthread_mutex_destroy(&mdata->read_lock))) + SOL_WRN("Error %d when destroying pthread mutex lock", error); + sml_free(mdata->sml); +} + +static int +input_var_connect(struct sol_flow_node *node, void *data, uint16_t port, + uint16_t conn_id) +{ + struct sol_drange initial_value = { NAN, NAN, NAN, NAN }; + struct machine_learning_data *mdata = data; + struct machine_learning_input_var *input_var; + struct sml_variable *sml_variable; + char name[12]; + + snprintf(name, sizeof(name), "InVar%d", conn_id); + sml_variable = sml_new_input(mdata->sml, name); + SOL_NULL_CHECK(sml_variable, -EBADR); + + input_var = sol_vector_append(&mdata->input_vec); + if (!input_var) { + SOL_WRN("Failed to append variable"); + sml_remove_variable(mdata->sml, sml_variable); + return -ENOMEM; + } + + input_var->base.sml_variable = sml_variable; + input_var->base.value = initial_value; + input_var->base.range_changed = false; + + SOL_DBG("Input variable %s added", name); + + return 0; +} + +static int +output_var_connect(struct sol_flow_node *node, void *data, uint16_t port, + uint16_t conn_id) +{ + struct sol_drange initial_value = { NAN, NAN, NAN, NAN }; + struct machine_learning_data *mdata = data; + struct machine_learning_output_var *output_var; + struct sml_variable *sml_variable; + char name[12]; + + snprintf(name, sizeof(name), "OutVar%d", conn_id); + sml_variable = sml_new_output(mdata->sml, name); + SOL_NULL_CHECK(sml_variable, -EBADR); + + output_var = sol_vector_append(&mdata->output_vec); + if (!output_var) { + SOL_WRN("Failed to append variable"); + sml_remove_variable(mdata->sml, sml_variable); + return -ENOMEM; + } + + output_var->base.sml_variable = sml_variable; + output_var->base.value = initial_value; + output_var->base.range_changed = false; + output_var->tag = NULL; + output_var->predicted_value = NAN; + + SOL_DBG("Output variable %s added for %s", name, output_var->tag); + + return 0; +} + +static int +input_var_process(struct sol_flow_node *node, void *data, uint16_t port, + uint16_t conn_id, const struct sol_flow_packet *packet) +{ + struct sol_drange value; + struct machine_learning_data *mdata = data; + struct machine_learning_input_var *input_var; + int r; + + r = sol_flow_packet_get_drange(packet, &value); + SOL_INT_CHECK(r, < 0, r); + + if ((r = mutex_lock(&mdata->read_lock))) + return r; + + input_var = sol_vector_get(&mdata->input_vec, conn_id); + SOL_NULL_CHECK(input_var, -EINVAL); + + if ((!sol_drange_val_equal(input_var->base.value.min, value.min)) || + (!sol_drange_val_equal(input_var->base.value.max, value.max))) + input_var->base.range_changed = true; + input_var->base.value = value; + pthread_mutex_unlock(&mdata->read_lock); + + return 0; +} + +static int +output_var_process(struct sol_flow_node *node, void *data, uint16_t port, + uint16_t conn_id, const struct sol_flow_packet *packet) +{ + struct sol_drange value; + struct machine_learning_data *mdata = data; + struct machine_learning_output_var *output_var; + char *tag; + int r; + + r = packet_get_tagged_float(packet, &value, &tag); + SOL_INT_CHECK(r, < 0, r); + + if ((r = mutex_lock(&mdata->read_lock))) + return r; + + output_var = sol_vector_get(&mdata->output_vec, conn_id); + SOL_NULL_CHECK(output_var, -EINVAL); + + if (!output_var->tag) { + output_var->tag = strdup(tag); + SOL_NULL_CHECK(output_var->tag, -ENOMEM); + } + + if ((!sol_drange_val_equal(output_var->base.value.min, value.min)) || + (!sol_drange_val_equal(output_var->base.value.max, value.max))) + output_var->base.range_changed = true; + output_var->base.value = value; + output_var->predicted_value = NAN; + pthread_mutex_unlock(&mdata->read_lock); + + return 0; +} + +static bool +machine_learning_worker_thread_setup(void *data) +{ + struct machine_learning_data *mdata = data; + + mdata->run_process = true; + return true; +} + +static void +machine_learning_worker_thread_feedback(void *data) +{ + struct machine_learning_data *mdata = data; + struct machine_learning_output_var *output_var; + uint16_t i; + int r; + + if (mutex_lock(&mdata->read_lock)) + return; + + SOL_VECTOR_FOREACH_IDX (&mdata->output_vec, output_var, i) { + if (isnan(output_var->predicted_value)) + continue; + + output_var->base.value.val = output_var->predicted_value; + output_var->predicted_value = NAN; + r = send_tagged_float_packet(mdata->node, + SOL_FLOW_NODE_TYPE_MACHINE_LEARNING_FUZZY__OUT__OUT, + &output_var->base.value, output_var->tag); + if (r < 0) + SOL_WRN("Failed to send packet %s %f", output_var->tag, + output_var->base.value.val); + } + pthread_mutex_unlock(&mdata->read_lock); + + if (mutex_lock(&mdata->process_lock)) + return; + + if (mdata->send_process_finished) { + if (!sol_flow_send_empty_packet(mdata->node, + SOL_FLOW_NODE_TYPE_MACHINE_LEARNING_FUZZY__OUT__PROCESS_FINISHED)) + mdata->send_process_finished = false; + } + + pthread_mutex_unlock(&mdata->process_lock); +} + +static int worker_schedule(struct machine_learning_data *mdata); + +static void +machine_learning_worker_thread_finished(void *data) +{ + struct machine_learning_data *mdata = data; + + mdata->worker = NULL; + machine_learning_worker_thread_feedback(data); + + //No lock needed because worker thread is dead + if (mdata->process_needed || mdata->predict_needed) + worker_schedule(mdata); +} + +static bool +machine_learning_worker_thread_iterate(void *data) +{ + struct machine_learning_data *mdata = data; + bool process_needed, predict_needed; + + if (mutex_lock(&mdata->process_lock)) + return false; + + process_needed = mdata->process_needed; + predict_needed = mdata->predict_needed; + pthread_mutex_unlock(&mdata->process_lock); + + if (!process_needed && !predict_needed) + return false; + + if ((mdata->run_process && process_needed) || !predict_needed) { + //Execute process + if (sml_process(mdata->sml) < 0) + SOL_WRN("Process failed."); + mdata->run_process = false; + } else { + //Execute predict + read_state_cb(mdata->sml, mdata); + if (sml_predict(mdata->sml)) + output_state_changed_cb(mdata->sml, NULL, mdata); + mdata->run_process = true; + } + + if (mutex_lock(&mdata->process_lock)) + return false; + if (mdata->run_process) { + //Predict has run + mdata->predict_needed = false; + } else { + //Process has run + mdata->process_needed = false; + mdata->send_process_finished = true; + } + pthread_mutex_unlock(&mdata->process_lock); + + sol_worker_thread_feedback(mdata->worker); + + return true; +} + +static int +worker_schedule(struct machine_learning_data *mdata) +{ + struct sol_worker_thread_spec spec = { + .api_version = SOL_WORKER_THREAD_SPEC_API_VERSION, + .setup = machine_learning_worker_thread_setup, + .cleanup = NULL, + .iterate = machine_learning_worker_thread_iterate, + .finished = machine_learning_worker_thread_finished, + .feedback = machine_learning_worker_thread_feedback, + .data = mdata + }; + + mdata->worker = sol_worker_thread_new(&spec); + SOL_NULL_CHECK(mdata->worker, -errno); + + return 0; +} + +static int +trigger_process(struct sol_flow_node *node, void *data, uint16_t port, + uint16_t conn_id, const struct sol_flow_packet *packet) +{ + struct machine_learning_data *mdata = data; + + if (mutex_lock(&mdata->process_lock)) + return false; + + mdata->process_needed = true; + pthread_mutex_unlock(&mdata->process_lock); + + if (!mdata->worker) + return worker_schedule(mdata); + + return 0; +} + +static int +prediction_trigger_process(struct sol_flow_node *node, void *data, + uint16_t port, uint16_t conn_id, + const struct sol_flow_packet *packet) +{ + struct machine_learning_data *mdata = data; + + if (mutex_lock(&mdata->process_lock)) + return false; + + mdata->predict_needed = true; + pthread_mutex_unlock(&mdata->process_lock); + + if (!mdata->worker) + return worker_schedule(mdata); + + return 0; +} + +#include "machine_learning_gen.c" diff --git a/soletta_module/machine_learning/machine_learning.json b/soletta_module/machine_learning/machine_learning.json new file mode 100644 index 0000000..2b967b1 --- /dev/null +++ b/soletta_module/machine_learning/machine_learning.json @@ -0,0 +1,257 @@ +{ + "name": "machine-learning", + "$schema": "http://solettaproject.github.io/soletta/schemas/node-type-genspec.schema", + "meta": { + "author": "Intel Corporation", + "license": "BSD 3-Clause", + "version": "1" + }, + "types": [ + { + "category": "machine-learning", + "description": "Tag output variables.", + "in_ports": [ + { + "data_type": "float", + "description": "Output variable value to be tagged.", + "methods": { + "process": "tagger_process" + }, + "name": "IN" + } + ], + "methods": { + "close": "tagger_close", + "open": "tagger_open" + }, + "name": "machine-learning/tagger", + "options": { + "members": [ + { + "data_type": "string", + "description": "Tag to be applied to all packets passing through this node.", + "name": "tag" + } + ], + "version": 1 + }, + "out_ports": [ + { + "data_type": "custom:PACKET_TYPE_TAGGED_FLOAT", + "description": "Tagged float.", + "name": "OUT" + } + ], + "private_data_type": "tagger_data", + "url": "http://soletta.org/doc/latest/node_types/machine_learning/tagger.html" + }, + { + "category": "machine-learning", + "description": "Filter output variables.", + "in_ports": [ + { + "data_type": "custom:PACKET_TYPE_TAGGED_FLOAT", + "description": "Output variable value to be filtered.", + "methods": { + "process": "filter_process" + }, + "name": "IN" + } + ], + "methods": { + "close": "tagger_close", + "open": "tagger_open" + }, + "name": "machine-learning/filter", + "options": { + "members": [ + { + "data_type": "string", + "description": "Tag to be used to filter packets passing through this node. If the packet's tag doesn't match this option, no packet will be sent in 'OUT' port. Otherwise a packet with only the float value will be sent.", + "name": "tag" + } + ], + "version": 1 + }, + "out_ports": [ + { + "data_type": "float", + "description": "Only the float value for packets that match the tag.", + "name": "OUT" + } + ], + "private_data_type": "tagger_data", + "url": "http://soletta.org/doc/latest/node_types/machine_learning/filter.html" + }, + { + "category": "machine-learning", + "description": "Learn output values based on input and output observation. Uses a fuzzy logic algorithm.", + "in_ports": [ + { + "data_type": "float", + "description": "Port for inputs sending float packets.", + "methods": { + "connect": "input_var_connect", + "process": "input_var_process" + }, + "name": "IN_VAR" + }, + { + "data_type": "custom:PACKET_TYPE_TAGGED_FLOAT", + "description": "Port for outputs sending tagged float packets.", + "methods": { + "connect": "output_var_connect", + "process": "output_var_process" + }, + "name": "OUT_VAR" + }, + { + "data_type": "any", + "description": "Port used to trigger machine learning prediction.", + "methods": { + "process": "prediction_trigger_process" + }, + "name": "PREDICTION_TRIGGER" + }, + { + "data_type": "any", + "description": "Port used to trigger machine learning processing.", + "methods": { + "process": "trigger_process" + }, + "name": "TRIGGER" + } + ], + "methods": { + "close": "machine_learning_close", + "open": "machine_learning_fuzzy_open" + }, + "name": "machine-learning/fuzzy", + "options": { + "members": [ + { + "data_type": "int", + "default": 5, + "description": "Amount of reads without input changes to consider input stable. If zero, it's always considered stable.", + "name": "stabilization_hits" + }, + { + "data_type": "int", + "default": 15, + "description": "Number of fuzzy terms to be created for each variable.", + "name": "number_of_terms" + } + ], + "version": 1 + }, + "out_ports": [ + { + "data_type": "custom:PACKET_TYPE_TAGGED_FLOAT", + "description": "Prediction values for output variables.", + "name": "OUT" + }, + { + "data_type": "empty", + "description": "Process has finished.", + "name": "PROCESS_FINISHED" + } + ], + "private_data_type": "machine_learning_data", + "url": "http://soletta.org/doc/latest/node_types/machine_learning/fuzzy.html" + }, + { + "category": "machine-learning", + "description": "Learn output values based on input and output observation. Uses neural network algorithm.", + "in_ports": [ + { + "data_type": "float", + "description": "Port for inputs sending float packets.", + "methods": { + "connect": "input_var_connect", + "process": "input_var_process" + }, + "name": "IN_VAR" + }, + { + "data_type": "custom:PACKET_TYPE_TAGGED_FLOAT", + "description": "Port for outputs sending tagged float packets.", + "methods": { + "connect": "output_var_connect", + "process": "output_var_process" + }, + "name": "OUT_VAR" + }, + { + "data_type": "any", + "description": "Port used to trigger machine learning prediction.", + "methods": { + "process": "prediction_trigger_process" + }, + "name": "PREDICTION_TRIGGER" + }, + { + "data_type": "any", + "description": "Port used to trigger machine learning processing.", + "methods": { + "process": "trigger_process" + }, + "name": "TRIGGER" + } + ], + "methods": { + "close": "machine_learning_close", + "open": "machine_learning_neural_network_open" + }, + "name": "machine-learning/neural-network", + "options": { + "members": [ + { + "data_type": "int", + "default": 5, + "description": "Amount of reads without input changes to consider input stable. If zero, it's always considered stable.", + "name": "stabilization_hits" + }, + { + "data_type": "int", + "default": 0, + "description": "Amound of initial observations necessary to first neural network training. If zero or negative, the default initial observation value will be used.", + "name": "initial_required_observations" + }, + { + "data_type": "float", + "default": 0.1, + "description": "Desired mean squared error. It's the difference between the estimator and what is estimated. The neural network will try to reach this value. Higher values can be reached easily, requiring less time and processing on training phase. Also, it won't try to guess the output if the desired mse wasn't reached.", + "name": "mse" + }, + { + "data_type": "string", + "default": "rprop", + "description": "Training algorithm to be used by the neural network. Supported algorithms are: 'rprop' - resilient backpropagation, and 'quickprop' - discrete pseudo-Newton method.", + "name": "training_algorithm" + }, + { + "data_type": "string", + "default": "sigmoid sigmoid_symmetric gaussian gaussian_symmetric elliot elliot_symmetric cos cos_symmetric sin sin_symmetric", + "description": "Activation functions that may be used for neural network. It'll try to use all of these functions to get the best one for its observations. Supported activation functions are: sigmoid sigmoid_symmetric gaussian gaussian_symmetric elliot elliot_symmetric cos cos_symmetric sin sin_symmetric. It's possible to set more than one, separeted by space. By default all of them are considered candidates. Reducing this set will reduce processing on training phase.", + "name": "activation_functions" + } + ], + "version": 1 + }, + "out_ports": [ + { + "data_type": "custom:PACKET_TYPE_TAGGED_FLOAT", + "description": "Prediction values for output variables.", + "name": "OUT" + }, + { + "data_type": "empty", + "description": "Process has finished.", + "name": "PROCESS_FINISHED" + } + ], + "private_data_type": "machine_learning_data", + "url": "http://soletta.org/doc/latest/node_types/machine_learning/fuzzy.html" + } + ] +} diff --git a/soletta_module/samples/foosball/README b/soletta_module/samples/foosball/README new file mode 100644 index 0000000..d7a0164 --- /dev/null +++ b/soletta_module/samples/foosball/README @@ -0,0 +1,17 @@ += Running foosball sample = +== Sample 1 == + * Running sample1 using gtk and fuzzy: + $ SOL_FLOW_MODULE_RESOLVER_CONFFILE=gtk_fuzzy.json ./foosball.fbp + * Running sample1 using gtk and neural network: + $ SOL_FLOW_MODULE_RESOLVER_CONFFILE=gtk_ann.json ./foosball.fbp +== Sample 2 == + * Running sample2 using gtk and fuzzy: + $ SOL_FLOW_MODULE_RESOLVER_CONFFILE=gtk_fuzzy.json ./foosball_limited.fbp + * Running sample2 using galileo gen 1 board and fuzzy: + * connect leds and buttons following guide in galileo.json file + $ SOL_FLOW_MODULE_RESOLVER_CONFFILE=galileo_fuzzy.json ./foosball_limited.fbp + * Running sample2 using gtk and neural network: + $ SOL_FLOW_MODULE_RESOLVER_CONFFILE=gtk_ann.json ./foosball_limited.fbp + * Running sample2 using galileo gen 1 board and neural network: + * connect leds and buttons following guide in galileo.json file + $ SOL_FLOW_MODULE_RESOLVER_CONFFILE=galileo_ann.json ./foosball_limited.fbp diff --git a/soletta_module/samples/foosball/foosball.fbp b/soletta_module/samples/foosball/foosball.fbp new file mode 100755 index 0000000..9186f36 --- /dev/null +++ b/soletta_module/samples/foosball/foosball.fbp @@ -0,0 +1,157 @@ +#!/usr/bin/env sol-fbp-runner + +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +DECLARE=PlayerSelector:fbp:player_selector.fbp +DECLARE=Time:fbp:time.fbp +DECLARE=FoosballMachine:fbp:foosball_machine.fbp + +max_goals(constant/int:value=3) + +#state machine definition +state(int/accumulator:setup_value=min:0|max:2|step:1) +state_player_selection_const(constant/int:value=0) +state_game_const(constant/int:value=1) + +state OUT -> IN[0] state_player_selection(int/equal) +state_player_selection_const OUT -> IN[1] state_player_selection +state OUT -> IN[0] state_game(int/equal) +state_game_const OUT -> IN[1] state_game + +#player selections +yellow_goalkeeper(PlayerSelector) +yellow_striker(PlayerSelector) +red_goalkeeper(PlayerSelector) +red_striker(PlayerSelector) +state_player_selection OUT -> ENABLED yellow_goalkeeper +state_player_selection OUT -> ENABLED yellow_striker +state_player_selection OUT -> ENABLED red_goalkeeper +state_player_selection OUT -> ENABLED red_striker +yellow_goalkeeper_btn(PushButton) OUT -> BUTTON yellow_goalkeeper +yellow_goalkeeper NUMBER -> IN yellow_goalkeeper_lbl(Label) +yellow_striker_btn(PushButton) OUT -> BUTTON yellow_striker +yellow_striker NUMBER -> IN yellow_striker_lbl(Label) +red_goalkeeper_btn(PushButton) OUT -> BUTTON red_goalkeeper +red_goalkeeper NUMBER -> IN red_goalkeeper_lbl(Label) +red_striker_btn(PushButton) OUT -> BUTTON red_striker +red_striker NUMBER -> IN red_striker_lbl(Label) + +yellow_goalkeeper NUMBER -> IN[0] cmp1(int/equal) +yellow_striker NUMBER -> IN[1] cmp1 + +yellow_goalkeeper NUMBER -> IN[0] cmp2(int/equal) +red_goalkeeper NUMBER -> IN[1] cmp2 + +yellow_goalkeeper NUMBER -> IN[0] cmp3(int/equal) +red_striker NUMBER -> IN[1] cmp3 + +yellow_striker NUMBER -> IN[0] cmp4(int/equal) +red_goalkeeper NUMBER -> IN[1] cmp4 + +yellow_striker NUMBER -> IN[0] cmp5(int/equal) +red_striker NUMBER -> IN[1] cmp5 + +red_goalkeeper NUMBER -> IN[0] cmp6(int/equal) +red_striker NUMBER -> IN[1] cmp6 + +cmp1 OUT -> IN[0] or1(boolean/or) +cmp2 OUT -> IN[1] or1 + +cmp3 OUT -> IN[0] or2(boolean/or) +cmp4 OUT -> IN[1] or2 + +cmp5 OUT -> IN[0] or3(boolean/or) +cmp6 OUT -> IN[1] or3 + +or1 OUT -> IN[0] or4(boolean/or) +or2 OUT -> IN[1] or4 + +or3 OUT -> IN[0] or5(boolean/or) +or4 OUT -> IN[1] or5 + +or5 OUT -> IN selection_correct(boolean/not) OUT -> IN selection_correct_led(Led:rgb=0|255|0) + +selection_correct OUT -> IN[0] can_start_game(boolean/and) +state_player_selection OUT -> IN[1] can_start_game + +can_start_game OUT -> IN[0] and_start_game(boolean/and) +start_game(PushButton) OUT -> IN[1] and_start_game OUT -> PULSE_IF_TRUE game_start(converter/boolean-to-empty) +game_start OUT -> START time(Time) OUT -> IN time_label(Label) +game_start OUT -> INC state + +state_game OUT -> IN[0] and_yellow_goal(boolean/and) +yellow_goal(PushButton) OUT -> IN[1] and_yellow_goal OUT -> PULSE_IF_TRUE yellow_goal_toggle(converter/boolean-to-empty) +yellow_goal_toggle OUT -> INC yellow_goals_ac(int/accumulator:setup_value=min:0|max:10) OUT -> IN yellow_goals(Label) +game_start OUT -> RESET yellow_goals_ac + +state_game OUT -> IN[0] and_red_goal(boolean/and) +red_goal(PushButton) OUT -> IN[1] and_red_goal OUT -> PULSE_IF_TRUE red_goal_toggle(converter/boolean-to-empty) +red_goal_toggle OUT -> INC red_goals_ac(int/accumulator:setup_value=min:0|max:10) OUT -> IN red_goals(Label) +game_start OUT -> RESET red_goals_ac + +max_goals OUT -> IN[0] yellow_goals_cmp(int/equal) +yellow_goals_ac OUT -> IN[1] yellow_goals_cmp +yellow_goals_cmp OUT -> PULSE_IF_TRUE yellow_winner(converter/boolean-to-empty) + +max_goals OUT -> IN[0] red_goals_cmp(int/equal) +red_goals_ac OUT -> IN[1] red_goals_cmp +red_goals_cmp OUT -> PULSE_IF_TRUE red_winner(converter/boolean-to-empty) + +#Machine learning +sml(FoosballMachine) +yellow_goalkeeper NUMBER -> GOAL_KEEPER1 sml +yellow_striker NUMBER -> STRIKER1 sml +red_goalkeeper NUMBER -> GOAL_KEEPER2 sml +red_striker NUMBER -> STRIKER2 sml + +yellow_winner OUT -> WINNER1 sml +red_winner OUT -> WINNER2 sml +yellow_winner OUT -> INC state +red_winner OUT -> INC state +yellow_winner OUT -> STOP time +red_winner OUT -> STOP time + +sml PROCESS_END -> IN game_over(hub/empty) +game_over OUT -> RESET time +game_over OUT -> INC state +game_over OUT -> RESET yellow_goalkeeper +game_over OUT -> RESET yellow_striker +game_over OUT -> RESET red_goalkeeper +game_over OUT -> RESET red_striker + +#prediction +game_start OUT -> PREDICTION_TRIGGER sml +predicted_winner_led(Led) +game_over OUT -> IN _(converter/empty-to-rgb:output_value=0|0|0|255|255|255) OUT -> IN predicted_winner_led +sml PREDICTED_WINNER1 -> IN pred_yellow_winner (converter/empty-to-rgb:output_value=255|255|0|255|255|255) +pred_yellow_winner OUT -> IN predicted_winner_led +sml PREDICTED_WINNER2 -> IN pred_red_winner (converter/empty-to-rgb:output_value=255|0|0|255|255|255) +pred_red_winner OUT -> IN predicted_winner_led diff --git a/soletta_module/samples/foosball/foosball_limited.fbp b/soletta_module/samples/foosball/foosball_limited.fbp new file mode 100755 index 0000000..4e326f7 --- /dev/null +++ b/soletta_module/samples/foosball/foosball_limited.fbp @@ -0,0 +1,88 @@ +#!/usr/bin/env sol-fbp-runner + +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +DECLARE=MultiplePlayerSelector:fbp:multiple_player_selector.fbp +DECLARE=FoosballMachine:fbp:foosball_machine.fbp + +players(MultiplePlayerSelector) +score1(int/accumulator:setup_value=min:0|max:10) +score2(int/accumulator:setup_value=min:0|max:10) + +main(ButtonMain) OUT -> BTN_CHANGE_PLAYER players +next(ButtonNext) OUT -> BTN_NEXT players + +players LCD -> IN lcd(Lcd) + +reset(ButtonReset) OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> RESET players + +#prediction +sml(FoosballMachine) +players PLAYER1 -> GOAL_KEEPER1 sml +players PLAYER2 -> STRIKER1 sml +players PLAYER3 -> GOAL_KEEPER2 sml +players PLAYER4 -> STRIKER2 sml + +players DONE -> PREDICTION_TRIGGER sml +sml PREDICTED_WINNER1 -> IN _(converter/empty-to-boolean:output_value=true) OUT -> IN led1(Led1) +sml PREDICTED_WINNER2 -> IN _(converter/empty-to-boolean:output_value=true) OUT -> IN led2(Led2) +false(constant/boolean:value=false) OUT -> IN led1 +false OUT -> IN led2 + +sml PREDICTED_WINNER1 -> IN _(converter/empty-to-boolean:output_value=true) OUT -> IN led1_(console) +sml PREDICTED_WINNER2 -> IN _(converter/empty-to-boolean:output_value=true) OUT -> IN led2_(console) +#Learn +players DONE -> RESET score1 +players DONE -> RESET score2 +players DONE -> IN score_lcd +players DONE -> IN game_started(boolean/toggle) +score1 OUT -> IN winner1(converter/int-to-empty:range=min:3|max:3) OUT -> WINNER1 sml +game_started OUT -> IN[0] score1_inc(boolean/and) +main OUT -> IN[1] score1_inc +score1_inc OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> INC score1 + +score2 OUT -> IN winner2(converter/int-to-empty:range=min:3|max:3) OUT -> WINNER2 sml +game_started OUT -> OUTPUT_VALUE score2_inc(converter/empty-to-boolean:output_value=false) +next OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> IN score2_inc OUT -> IN _filter(boolean/filter) TRUE -> INC score2 + +#Game reset +sml PROCESS_END -> RESET players +sml PROCESS_END -> IN game_started +sml PROCESS_END -> IN end_false(converter/empty-to-boolean:output_value=false) +end_false OUT -> IN led1 +end_false OUT -> IN led2 + +#score +str_score(string/concatenate:separator=" x ") +score1 OUT -> IN _(converter/int-to-string) OUT -> IN[0] str_score +score2 OUT -> IN _(converter/int-to-string) OUT -> IN[1] str_score +str_score OUT -> OUTPUT_VALUE score_lcd(converter/empty-to-string) +str_score OUT -> IN score_lcd OUT -> IN lcd diff --git a/soletta_module/samples/foosball/foosball_machine.fbp b/soletta_module/samples/foosball/foosball_machine.fbp new file mode 100644 index 0000000..5c570d6 --- /dev/null +++ b/soletta_module/samples/foosball/foosball_machine.fbp @@ -0,0 +1,146 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#Foosball SML +INPORT=goalkeeper1.IN:GOAL_KEEPER1 +INPORT=striker1.IN:STRIKER1 +INPORT=goalkeeper2.IN:GOAL_KEEPER2 +INPORT=striker2.IN:STRIKER2 +INPORT=winner1.IN:WINNER1 +INPORT=winner2.IN:WINNER2 +INPORT=sml.PREDICTION_TRIGGER:PREDICTION_TRIGGER +OUTPORT=predicted_winner1.OUT:PREDICTED_WINNER1 +OUTPORT=predicted_winner2.OUT:PREDICTED_WINNER2 +OUTPORT=state_end.OUT:PROCESS_END + +#state machine +sml_state_machine(int/accumulator:setup_value=val:0:min:0|max:5|step:1) +sml_state_machine OUT -> IN[0] state_start_phase1_eq(int/equal) +state_start_phase1_const(constant/int:value=1) OUT -> IN[1] state_start_phase1_eq +state_start_phase1_eq OUT -> PULSE_IF_TRUE state_start_phase1(converter/boolean-to-empty) + +sml_state_machine OUT -> IN[0] state_run_phase1_eq(int/equal) +state_run_phase1_const(constant/int:value=2) OUT -> IN[1] state_run_phase1_eq +state_run_phase1_eq OUT -> PULSE_IF_TRUE state_run_phase1(converter/boolean-to-empty) + +sml_state_machine OUT -> IN[0] state_start_phase2_eq(int/equal) +state_start_phase2_const(constant/int:value=3) OUT -> IN[1] state_start_phase2_eq +state_start_phase2_eq OUT -> PULSE_IF_TRUE state_start_phase2(converter/boolean-to-empty) + +sml_state_machine OUT -> IN[0] state_run_phase2_eq(int/equal) +state_run_phase2_const(constant/int:value=4) OUT -> IN[1] state_run_phase2_eq +state_run_phase2_eq OUT -> PULSE_IF_TRUE state_run_phase2(converter/boolean-to-empty) + +sml_state_machine OUT -> IN[0] state_end_eq(int/equal) +state_end_const(constant/int:value=5) OUT -> IN[1] state_end_eq +state_end_eq OUT -> PULSE_IF_TRUE state_end(converter/boolean-to-empty) + +#state machine timer +timer(timer:interval=100) OUT -> INC sml_state_machine +sml_state_machine OUT -> IN timer_stop(converter/int-to-boolean:true_range=min:1|max:5) OUT -> ENABLED timer +winner1 OUT -> IN _(converter/empty-to-boolean:output_value=true) OUT -> ENABLED timer +winner2 OUT -> IN _(converter/empty-to-boolean:output_value=true) OUT -> ENABLED timer + +#SML Definition +sml(SML) + +goalkeeper1(hub/int) +striker1(hub/int) +goalkeeper2(hub/int) +striker2(hub/int) + +sml_goalkeeper1(converter/int-to-float) OUT -> IN_VAR sml +sml_striker1(converter/int-to-float) OUT -> IN_VAR sml +sml_goalkeeper2(converter/int-to-float) OUT -> IN_VAR sml +sml_striker2(converter/int-to-float) OUT -> IN_VAR sml +sml_winner(converter/int-to-float) OUT -> IN tagger(machine-learning/tagger:tag=winner) +tagger OUT -> OUT_VAR sml + +sml OUT -> IN FilterSml(machine-learning/filter:tag=winner) +FilterSml OUT -> IN _(converter/float-to-empty:range=min:0.5|max:1.5) OUT -> IN predicted_winner1(hub/empty) +FilterSml OUT -> IN _(converter/float-to-empty:range=min:1.5|max:2) OUT -> IN predicted_winner2(hub/empty) + +#Phase 1 - start +state_start_phase1 OUT -> IN phase1_goalkeeper1(converter/empty-to-int) +state_start_phase1 OUT -> IN phase1_striker1(converter/empty-to-int) +state_start_phase1 OUT -> IN phase1_goalkeeper2(converter/empty-to-int) +state_start_phase1 OUT -> IN phase1_striker2(converter/empty-to-int) +state_start_phase1 OUT -> IN phase1_winner(converter/empty-to-int) + +goalkeeper1 OUT -> OUTPUT_VALUE phase1_goalkeeper1 +striker1 OUT -> OUTPUT_VALUE phase1_striker1 +goalkeeper2 OUT -> OUTPUT_VALUE phase1_goalkeeper2 +striker2 OUT -> OUTPUT_VALUE phase1_striker2 +winner1(hub/empty) OUT -> IN _(converter/empty-to-int:output_value=val:1|min:0|max:2|step:1) OUT -> OUTPUT_VALUE phase1_winner +winner2(hub/empty) OUT -> IN _(converter/empty-to-int:output_value=val:2|min:0|max:2|step:1) OUT -> OUTPUT_VALUE phase1_winner + +phase1_goalkeeper1 OUT -> IN sml_goalkeeper1 +phase1_striker1 OUT -> IN sml_striker1 +phase1_goalkeeper2 OUT -> IN sml_goalkeeper2 +phase1_striker2 OUT -> IN sml_striker2 +phase1_winner OUT -> IN sml_winner + +#Phase 1 - run +state_run_phase1 OUT -> TRIGGER sml +state_run_phase1 OUT -> IN _(converter/empty-to-boolean:output_value=false) OUT -> ENABLED timer +sml PROCESS_FINISHED -> IN _(converter/empty-to-boolean:output_value=true) OUT -> ENABLED timer + +#Phase 2 - start +state_start_phase2 OUT -> IN phase2_goalkeeper1(converter/empty-to-int) +state_start_phase2 OUT -> IN phase2_striker1(converter/empty-to-int) +state_start_phase2 OUT -> IN phase2_goalkeeper2(converter/empty-to-int) +state_start_phase2 OUT -> IN phase2_striker2(converter/empty-to-int) +state_start_phase2 OUT -> IN phase2_winner(converter/empty-to-int) + +goalkeeper1 OUT -> OUTPUT_VALUE phase2_goalkeeper1 +striker1 OUT -> OUTPUT_VALUE phase2_striker1 +goalkeeper2 OUT -> OUTPUT_VALUE phase2_goalkeeper2 +striker2 OUT -> OUTPUT_VALUE phase2_striker2 +winner1 OUT -> IN _(converter/empty-to-int:output_value=val:2|min:0|max:2|step:1) OUT -> OUTPUT_VALUE phase2_winner +winner2 OUT -> IN _(converter/empty-to-int:output_value=val:1|min:0|max:2|step:1) OUT -> OUTPUT_VALUE phase2_winner + +phase2_goalkeeper2 OUT -> IN sml_goalkeeper1 +phase2_striker2 OUT -> IN sml_striker1 +phase2_goalkeeper1 OUT -> IN sml_goalkeeper2 +phase2_striker1 OUT -> IN sml_striker2 +phase2_winner OUT -> IN sml_winner + +#Phase 2 - run +state_run_phase2 OUT -> TRIGGER sml +state_run_phase2 OUT -> IN _(converter/empty-to-boolean:output_value=false) OUT -> ENABLED timer + +#End +state_end OUT -> IN _(converter/empty-to-int:output_value=val:0|min:0|max:2|step:1) OUT -> IN sml_winner + +#Prediction phase +goalkeeper1 OUT -> IN sml_goalkeeper1 +striker1 OUT -> IN sml_striker1 +goalkeeper2 OUT -> IN sml_goalkeeper2 +striker2 OUT -> IN sml_striker2 diff --git a/soletta_module/samples/foosball/galileo_ann.json b/soletta_module/samples/foosball/galileo_ann.json new file mode 100644 index 0000000..aa594cc --- /dev/null +++ b/soletta_module/samples/foosball/galileo_ann.json @@ -0,0 +1,57 @@ +{ + "$schema": "http://solettaproject.github.io/soletta/schemas/config.schema", + "nodetypes": [ + { + "name": "ButtonMain", + "options": { + "pin": 28, + "active_low": false, + "edge_falling": true, + "edge_rising": true + }, + "type": "gpio/reader" + }, + { + "name": "ButtonNext", + "options": { + "pin": 18, + "active_low": false, + "edge_falling": true, + "edge_rising": true + }, + "type": "gpio/reader" + }, + { + "name": "ButtonReset", + "type": "hub/boolean" + }, + { + "name": "Lcd", + "type": "console" + }, + { + "name": "Led1", + "options": { + "pin": 17, + "active_low": false + }, + "type": "gpio/writter" + }, + { + "name": "Led2", + "options": { + "pin": 24, + "active_low": false + }, + "type": "gpio/writter" + }, + { + "name": "SML", + "options": { + "stabilization_hits": 0, + "initial_required_observations": 10 + }, + "type": "machine-learning/neural-network" + } + ] +} diff --git a/soletta_module/samples/foosball/galileo_fuzzy.json b/soletta_module/samples/foosball/galileo_fuzzy.json new file mode 100644 index 0000000..cb3e12c --- /dev/null +++ b/soletta_module/samples/foosball/galileo_fuzzy.json @@ -0,0 +1,57 @@ +{ + "$schema": "http://solettaproject.github.io/soletta/schemas/config.schema", + "nodetypes": [ + { + "name": "ButtonMain", + "options": { + "pin": 28, + "active_low": false, + "edge_falling": true, + "edge_rising": true + }, + "type": "gpio/reader" + }, + { + "name": "ButtonNext", + "options": { + "pin": 18, + "active_low": false, + "edge_falling": true, + "edge_rising": true + }, + "type": "gpio/reader" + }, + { + "name": "ButtonReset", + "type": "hub/boolean" + }, + { + "name": "Lcd", + "type": "console" + }, + { + "name": "Led1", + "options": { + "pin": 17, + "active_low": false + }, + "type": "gpio/writter" + }, + { + "name": "Led2", + "options": { + "pin": 24, + "active_low": false + }, + "type": "gpio/writter" + }, + { + "name": "SML", + "options": { + "stabilization_hits": 0, + "number_of_terms": 15 + }, + "type": "machine-learning/fuzzy" + } + ] +} diff --git a/soletta_module/samples/foosball/gtk_ann.json b/soletta_module/samples/foosball/gtk_ann.json new file mode 100644 index 0000000..4479df7 --- /dev/null +++ b/soletta_module/samples/foosball/gtk_ann.json @@ -0,0 +1,55 @@ +{ + "$schema": "http://solettaproject.github.io/soletta/schemas/config.schema", + "nodetypes": [ + { + "name": "ButtonMain", + "type": "gtk/pushbutton" + }, + { + "name": "ButtonNext", + "type": "gtk/pushbutton" + }, + { + "name": "ButtonReset", + "type": "gtk/pushbutton" + }, + { + "name": "Lcd", + "type": "gtk/label" + }, + { + "name": "Led1", + "options": { + "rgb": "255|0|0" + }, + "type": "gtk/led" + }, + { + "name": "Led2", + "options": { + "rgb": "255|255|0" + }, + "type": "gtk/led" + }, + { + "name": "PushButton", + "type": "gtk/pushbutton" + }, + { + "name": "Label", + "type": "gtk/label" + }, + { + "name": "Led", + "type": "gtk/led" + }, + { + "name": "SML", + "options": { + "stabilization_hits": 0, + "initial_required_observations": 10 + }, + "type": "machine-learning/neural-network" + } + ] +} diff --git a/soletta_module/samples/foosball/gtk_fuzzy.json b/soletta_module/samples/foosball/gtk_fuzzy.json new file mode 100644 index 0000000..c8e9b1b --- /dev/null +++ b/soletta_module/samples/foosball/gtk_fuzzy.json @@ -0,0 +1,55 @@ +{ + "$schema": "http://solettaproject.github.io/soletta/schemas/config.schema", + "nodetypes": [ + { + "name": "ButtonMain", + "type": "gtk/pushbutton" + }, + { + "name": "ButtonNext", + "type": "gtk/pushbutton" + }, + { + "name": "ButtonReset", + "type": "gtk/pushbutton" + }, + { + "name": "Lcd", + "type": "gtk/label" + }, + { + "name": "Led1", + "options": { + "rgb": "255|0|0" + }, + "type": "gtk/led" + }, + { + "name": "Led2", + "options": { + "rgb": "255|255|0" + }, + "type": "gtk/led" + }, + { + "name": "PushButton", + "type": "gtk/pushbutton" + }, + { + "name": "Label", + "type": "gtk/label" + }, + { + "name": "Led", + "type": "gtk/led" + }, + { + "name": "SML", + "options": { + "stabilization_hits": 0, + "number_of_terms": "val:15" + }, + "type": "machine-learning/fuzzy" + } + ] +} diff --git a/soletta_module/samples/foosball/multiple_player_selector.fbp b/soletta_module/samples/foosball/multiple_player_selector.fbp new file mode 100755 index 0000000..1c7dc47 --- /dev/null +++ b/soletta_module/samples/foosball/multiple_player_selector.fbp @@ -0,0 +1,136 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +INPORT=reset.IN:RESET +INPORT=enabled_hub.IN:ENABLED +INPORT=btn_hub.IN[0]:BTN_CHANGE_PLAYER +INPORT=next_hub.IN[0]:BTN_NEXT +OUTPORT=player1.OUT:PLAYER1 +OUTPORT=player2.OUT:PLAYER2 +OUTPORT=player3.OUT:PLAYER3 +OUTPORT=player4.OUT:PLAYER4 +OUTPORT=lcd.OUT:LCD +OUTPORT=done.OUT:DONE + +#inputs +reset(hub/empty) +_(constant/boolean:value=true) OUT -> IN enabled_hub(hub/boolean) +btn_hub(boolean/and) +enabled_hub OUT -> IN[1] btn_hub +next_hub(boolean/and) +enabled_hub OUT -> IN[1] next_hub +next_hub OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> INC player_selection + +#reset timer +timer(timer:interval=10) OUT -> INC player_selection +timer OUT -> IN _(converter/empty-to-boolean:output_value=false) OUT -> ENABLED timer +reset OUT -> IN enable_timer(converter/empty-to-boolean:output_value=true) OUT -> ENABLED timer +enable_timer OUT -> IN enabled_hub + +#state machine +player_selection(int/accumulator:setup_value=min:0|max:5) +player_selection OUT -> IN state_player1(converter/int-to-boolean:true_range=min:1|max:1) +player_selection OUT -> IN state_player2(converter/int-to-boolean:true_range=min:2|max:2) +player_selection OUT -> IN state_player3(converter/int-to-boolean:true_range=min:3|max:3) +player_selection OUT -> IN state_player4(converter/int-to-boolean:true_range=min:4|max:4) +player_selection OUT -> IN done(converter/int-to-empty:range=min:5|max:5) OUT -> IN _(converter/empty-to-boolean:output_value=false) OUT -> IN enabled_hub +reset OUT -> RESET player_selection + +#Player1 +reset OUT -> RESET player1(int/accumulator:setup_value=min:0|max:14) +btn_hub OUT -> IN[0] player1_enabled(boolean/and) +state_player1 OUT -> IN[1] player1_enabled +player1_enabled OUT -> IN _(boolean/filter) TRUE -> INC player1 + +#Player2 +reset OUT -> RESET player2(int/accumulator:setup_value=min:0|max:14) +btn_hub OUT -> IN[0] player2_enabled(boolean/and) +state_player2 OUT -> IN[1] player2_enabled +player2_enabled OUT -> IN _(boolean/filter) TRUE -> INC player2 + +#Player3 +reset OUT -> RESET player3(int/accumulator:setup_value=min:0|max:14) +btn_hub OUT -> IN[0] player3_enabled(boolean/and) +state_player3 OUT -> IN[1] player3_enabled +player3_enabled OUT -> IN _(boolean/filter) TRUE -> INC player3 + +#player4 +reset OUT -> RESET player4(int/accumulator:setup_value=min:0|max:14) +btn_hub OUT -> IN[0] player4_enabled(boolean/and) +state_player4 OUT -> IN[1] player4_enabled +player4_enabled OUT -> IN _(boolean/filter) TRUE -> INC player4 + +#LCD +#player_selection OUT -> IN _(converter/int-to-string) OUT -> IN[1] lcd(string/concatenate) +_(constant/string:value="Player 1: ") OUT -> IN[0] lcd1(string/concatenate) +player1 OUT -> IN _(converter/int-to-string) OUT -> IN[1] lcd1 +state_player1 OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> IN _(converter/empty-to-string:output_value="Player 1: 0") OUT -> IN lcd + +_(constant/string:value="Player 2: ") OUT -> IN[0] lcd2(string/concatenate) +player2 OUT -> IN _(converter/int-to-string) OUT -> IN[1] lcd2 +state_player2 OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> IN _(converter/empty-to-string:output_value="Player 2: 0") OUT -> IN lcd + +_(constant/string:value="Player 3: ") OUT -> IN[0] lcd3(string/concatenate) +player3 OUT -> IN _(converter/int-to-string) OUT -> IN[1] lcd3 +state_player3 OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> IN _(converter/empty-to-string:output_value="Player 3: 0") OUT -> IN lcd + +_(constant/string:value="Player 4: ") OUT -> IN[0] lcd4(string/concatenate) +player4 OUT -> IN _(converter/int-to-string) OUT -> IN[1] lcd4 +state_player4 OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> IN _(converter/empty-to-string:output_value="Player 4: 0") OUT -> IN lcd + +lcd1 OUT -> IN lcd(hub/string) +lcd2 OUT -> IN lcd +lcd3 OUT -> IN lcd +lcd4 OUT -> IN lcd + +#Don't allow multiple players selection +player1 OUT -> IN[0] player2_cmp(int/equal) +player2 OUT -> IN[1] player2_cmp OUT -> IN[0] player2_inc(boolean/and) OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> INC player2 +state_player2 OUT -> IN[1] player2_inc + +player1 OUT -> IN[0] player3_cmp(int/equal) +player3 OUT -> IN[1] player3_cmp OUT -> IN[0] player3_inc(boolean/and) OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> INC player3 +state_player3 OUT -> IN[1] player3_inc + +player2 OUT -> IN[0] player3_cmp2(int/equal) +player3 OUT -> IN[1] player3_cmp2 OUT -> IN[0] player3_inc2(boolean/and) OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> INC player3 +state_player3 OUT -> IN[1] player3_inc2 + +player1 OUT -> IN[0] player4_cmp(int/equal) +player4 OUT -> IN[1] player4_cmp OUT -> IN[0] player4_inc(boolean/and) OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> INC player4 +state_player4 OUT -> IN[1] player4_inc + +player2 OUT -> IN[0] player4_cmp2(int/equal) +player4 OUT -> IN[1] player4_cmp2 OUT -> IN[0] player4_inc2(boolean/and) OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> INC player4 +state_player4 OUT -> IN[1] player4_inc2 + +player3 OUT -> IN[0] player4_cmp3(int/equal) +player4 OUT -> IN[1] player4_cmp3 OUT -> IN[0] player4_inc3(boolean/and) OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> INC player4 +state_player4 OUT -> IN[1] player4_inc3 diff --git a/soletta_module/samples/foosball/player_selector.fbp b/soletta_module/samples/foosball/player_selector.fbp new file mode 100644 index 0000000..0c501f8 --- /dev/null +++ b/soletta_module/samples/foosball/player_selector.fbp @@ -0,0 +1,39 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#TODO: load players info from a file. +INPORT=number.RESET:RESET +INPORT=selection.IN[0]:ENABLED +INPORT=selection.IN[1]:BUTTON +OUTPORT=number.OUT:NUMBER + +true(constant/boolean:value=true) OUT -> IN[0] selection(boolean/and) +selection OUT -> PULSE_IF_TRUE toggle(converter/boolean-to-empty) +toggle OUT -> INC number(int/accumulator:setup_value=min:0|max:14) diff --git a/soletta_module/samples/foosball/time.fbp b/soletta_module/samples/foosball/time.fbp new file mode 100644 index 0000000..8487856 --- /dev/null +++ b/soletta_module/samples/foosball/time.fbp @@ -0,0 +1,58 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +INPORT=start_conv.IN:START +INPORT=stop_conv.IN:STOP +INPORT=end_conv.IN:RESET +OUTPORT=concat.OUT:OUT + +false(constant/boolean:value=false) +ten(constant/int:value=10) + +false OUT -> ENABLED timer(timer:interval=100) +timer OUT -> INC sec(int/accumulator:setup_value=min:0|max:59|step:1) +start_conv(converter/empty-to-boolean:output_value=true) OUT -> ENABLED timer +end_conv(converter/empty-to-boolean:output_value=false) OUT -> ENABLED timer +stop_conv(converter/empty-to-boolean:output_value=false) OUT -> ENABLED timer + +end_conv OUT -> PULSE_IF_FALSE reset_pulse(converter/boolean-to-empty) +reset_pulse OUT -> RESET sec +reset_pulse OUT -> RESET min + +sec OVERFLOW -> INC min(int/accumulator:setup_value=min:0|step:1) + + +ten OUT -> IN[0] sec_cmp(int/greater) +sec OUT -> IN[1] sec_cmp OUT -> IN custom_str(converter/boolean-to-string:false_value=":",true_value=":0") +custom_str OUT -> IN[0] sec_concat(string/concatenate) +sec OUT -> IN sec_str(converter/int-to-string) OUT -> IN[1] sec_concat + +min OUT -> IN min_str(converter/int-to-string) OUT -> IN[0] concat(string/concatenate) +sec_concat OUT -> IN[1] concat diff --git a/soletta_module/samples/garden/controller.fbp b/soletta_module/samples/garden/controller.fbp new file mode 100644 index 0000000..2efaee6 --- /dev/null +++ b/soletta_module/samples/garden/controller.fbp @@ -0,0 +1,43 @@ +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +INPORT=acc.IN:IN +OUTPORT=acc.OUT:OUT + +acc(hub/float) OUT -> OUTPUT_VALUE acc_flush +_(constant/float:value=min:0|val:0|max:100|step:1) OUT -> IN acc +acc OUT -> IN _(converter/float-to-string) OUT -> IN value(Label) +sum(float/addition) OUT -> IN _(float/filter:min=0,max=100,range_override=true) OUT -> IN acc + +inc(PushButton) OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> IN _(converter/empty-to-float:output_value=val:5|min:0|max:100|step:1) OUT -> OPERAND[0] sum +inc OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> IN acc_flush(converter/empty-to-float) OUT -> OPERAND[1] sum + +dec(PushButton) OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> IN _(converter/empty-to-float:output_value=val:-5|min:0|max:100|step:1) OUT -> OPERAND[0] sum +dec OUT -> PULSE_IF_TRUE _(converter/boolean-to-empty) OUT -> IN acc_flush diff --git a/soletta_module/samples/garden/garden.fbp b/soletta_module/samples/garden/garden.fbp new file mode 100755 index 0000000..82f88a7 --- /dev/null +++ b/soletta_module/samples/garden/garden.fbp @@ -0,0 +1,48 @@ +#!/usr/bin/env sol-fbp-runner + +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +DECLARE=Controller:fbp:controller.fbp + +moisture(Controller) +fertilizer(Controller) +light(Controller) +water_volume(Controller) +sml(SMl) +timer(timer:interval=1000) OUT -> INC _(int/accumulator) OUT -> IN counts(Label) + +moisture OUT -> IN_VAR sml +fertilizer OUT -> IN_VAR sml +light OUT -> IN_VAR sml +water_volume OUT -> IN _(machine-learning/tagger:tag=water) OUT -> OUT_VAR sml + +sml OUT -> IN _(machine-learning/filter:tag=water) OUT -> IN water_volume +timer OUT -> TRIGGER sml diff --git a/soletta_module/samples/garden/gtk.conf b/soletta_module/samples/garden/gtk.conf new file mode 100644 index 0000000..e144c6a --- /dev/null +++ b/soletta_module/samples/garden/gtk.conf @@ -0,0 +1,19 @@ +#Definitions used by examples that creates multiple buttons, leds and labels +[SolettaNodeEntry PushButton] +Type=gtk/pushbutton + +[SolettaNodeEntry Label] +Type=gtk/label + +[SolettaNodeEntry Led] +Type=gtk/led + +#Fuzzy machine learning +[SolettaNodeEntry SML] +Type=machine-learning/fuzzy +Options=stabilization_hits=0;number_of_terms=15 + +#Neural Network machine learning +#[SolettaNodeEntry SML] +#Type=machine-learning/neural-network +#Options=stabilization_hits=0;initial_required_observations=10 diff --git a/soletta_module/samples/machine-learning-simple.fbp b/soletta_module/samples/machine-learning-simple.fbp new file mode 100755 index 0000000..7bd7ac9 --- /dev/null +++ b/soletta_module/samples/machine-learning-simple.fbp @@ -0,0 +1,71 @@ +#!/usr/bin/env sol-fbp-runner + +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Timer(timer:interval=200) OUT -> IN Random1(random/float:seed=666) +Random1 OUT -> IN Input1(float/map:use_input_range=true,output_range=0|-0.5|5.5|1) +Input1 OUT -> IN Input1Value(console) + +Timer OUT -> IN Random2(random/float) +Random2 OUT -> IN Input2(float/map:use_input_range=true,output_range=0|0.5|6.5|1) +Input2 OUT -> IN Input2Value(console) + +Input1 OUT -> OPERAND[0] Output(float/multiplication) +Input2 OUT -> OPERAND[1] Output +Output OUT -> IN OutputValue(console) + +# add a random error to check if machine learning will correct this +TimerError(timer:interval=2020) OUT -> IN RandomError(random/float) +RandomError OUT -> IN OutputError(float/map:use_input_range=true,output_range=0|0|30|1) +OutputError OUT -> IN Error(console) + +Output OUT -> IN Tagger(machine-learning/tagger:tag=Result) +OutputError OUT -> IN Tagger + +# guess using fuzzy +Input1 OUT -> IN_VAR Fuzzy(machine-learning/fuzzy:stabilization_hits=2) +Input2 OUT -> IN_VAR Fuzzy +Tagger OUT -> OUT_VAR Fuzzy + +TimerTrigger(timer:interval=20) OUT -> TRIGGER Fuzzy + +Fuzzy OUT -> IN FilterFuzzy(machine-learning/filter:tag=Result) +FilterFuzzy OUT -> IN OutputGuessFuzzy(console) + +# guess using neural network +Input1 OUT -> IN_VAR NN(machine-learning/neural-network) +Input2 OUT -> IN_VAR NN +Tagger OUT -> OUT_VAR NN + +TimerTrigger OUT -> TRIGGER NN + +NN OUT -> IN FilterNN(machine-learning/filter:tag=Result) +FilterNN OUT -> IN OutputGuessNN(console) diff --git a/soletta_module/samples/machine-learning-tag-filter.fbp b/soletta_module/samples/machine-learning-tag-filter.fbp new file mode 100755 index 0000000..09e6997 --- /dev/null +++ b/soletta_module/samples/machine-learning-tag-filter.fbp @@ -0,0 +1,46 @@ +#!/usr/bin/env sol-fbp-runner + +# This file is part of the Soletta Project +# +# Copyright (C) 2015 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +ValuePi(constant/float:value=3.1415) +TaggerPi(machine-learning/tagger:tag=Pi) + +ValueZero(constant/float:value=0) +TaggerZero(machine-learning/tagger:tag=Zero) + +Filter(machine-learning/filter:tag=Pi) +Console(console) + +ValuePi OUT -> IN TaggerPi OUT -> IN Filter +ValueZero OUT -> IN TaggerZero OUT -> IN Filter + +# we expect to see only a float value 3.1415 in console +Filter OUT -> IN Console