Soletta machine learning
Machine learning for IoT devices
 All Data Structures Files Functions Typedefs Enumerations Enumerator Groups Pages
Data Structures | Macros | Typedefs | Functions
Engine

The SML common functions. More...

Data Structures

struct  sml_object
 
struct  sml_variable
 
struct  sml_variables_list
 

Macros

#define SML_INTERNAL_ERROR   3
 
#define SML_VARIABLE_NAME_MAX_LEN   (127)
 

Typedefs

typedef void(* sml_change_cb )(struct sml_object *sml, struct sml_variables_list *changed, void *data)
 Called every time the SML made a prediction. More...
 
typedef bool(* sml_read_state_cb )(struct sml_object *sml, void *data)
 A user defined callback to read the variables values. More...
 

Functions

bool sml_erase_knowledge (struct sml_object *sml)
 Erase all previous knowledge. More...
 
void sml_free (struct sml_object *sml)
 Frees the SML engine. More...
 
bool sml_load (struct sml_object *sml, const char *path)
 Load the SML state from the disk. More...
 
bool sml_load_debug_log_file (struct sml_object *sml, const char *str)
 Load to current engine the debug data logged to a file. More...
 
bool sml_load_fll_file (struct sml_object *sml, const char *filename)
 Reads a FLL file. More...
 
bool sml_predict (struct sml_object *sml)
 Make a prediction based on the most recent observations. More...
 
void sml_print_debug (struct sml_object *sml, bool full)
 Prints SML debug information. More...
 
int sml_process (struct sml_object *sml)
 Process variables and make predictions. More...
 
bool sml_save (struct sml_object *sml, const char *path)
 Save the SML state on the disk. More...
 
bool sml_set_debug_log_file (struct sml_object *sml, const char *str)
 Set the file to be used to debug data changes in this engine. More...
 
bool sml_set_learn_disabled (struct sml_object *sml, bool disable)
 Disable the SML learning. More...
 
bool sml_set_max_memory_for_observations (struct sml_object *sml, unsigned int max_size)
 Set maximum memory that can be used to store observation history data. More...
 
bool sml_set_output_state_changed_callback (struct sml_object *sml, sml_change_cb output_state_changed_cb, void *data)
 Register a change callback. More...
 
bool sml_set_read_state_callback (struct sml_object *sml, sml_read_state_cb read_state_cb, void *data)
 Register a read callblack. More...
 
bool sml_set_stabilization_hits (struct sml_object *sml, uint16_t hits)
 Set the stabilization hits. More...
 

Detailed Description

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:

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 chosen one. Registering callbacks is simple as well:

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);
light = sml_new_output(sml, "Light");
sml_variable_set_range(sml, light, 0, 1);
sml_set_read_state_callback(sml, read_state_cb, NULL);
sml_set_output_state_changed_callback(sml, output_state_changed_cb, NULL);

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.

Although we have the possibility to define each term to describe your problem, for this example we will let the fuzzy engine do this for you. To improve the quality of the automatically created terms, we need to give fuzzy engine some hints about the variable being used. As both variables are boolean values, lets set the default term width to 0.5 and the range from 0 to 1. So we will have 2 terms, one for on and another for off.

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.

for (int i = 0; i < 150; i++) {
if (sml_process(sml) < 0) {
printf("Failed to process\n");
}
}
sml_free(sml);
return 0;
}

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 presence 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).

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;
}

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.

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");
}
}

A few tips to obtain good predictions.

Macro Definition Documentation

#define SML_INTERNAL_ERROR   3

SML error code. Could not complete an operation

#define SML_VARIABLE_NAME_MAX_LEN   (127)

Maximum size of variables name

Typedef Documentation

typedef void(* sml_change_cb)(struct sml_object *sml, struct sml_variables_list *changed, void *data)

Called every time the SML made a prediction.

Parameters
smlThe sml_object Object.
changedA sml_variables_list with the predicted variables.
dataUser defined data.
See Also
sml_set_output_state_changed_callback
typedef bool(* sml_read_state_cb)(struct sml_object *sml, void *data)

A user defined callback to read the variables values.

Parameters
smlThe sml_object object
dataThe user defined data
Returns
true on success.
false if no reads were done.
See Also
sml_set_read_state_callback

Function Documentation

bool sml_erase_knowledge ( struct sml_object sml)

Erase all previous knowledge.

Erases everything that the SML has learned, this will required that the SML is trained again.

Parameters
smlThe sml_object object.
Returns
true on success.
false on failure.
void sml_free ( struct sml_object sml)

Frees the SML engine.

Parameters
smlThe engine to be freed.
bool sml_load ( struct sml_object sml,
const char *  path 
)

Load the SML state from the disk.

Parameters
smlThe sml_object object.
pathA direcoty to load the engine files.
Returns
true on success.
false on failure.
See Also
sml_save
bool sml_load_debug_log_file ( struct sml_object sml,
const char *  str 
)

Load to current engine the debug data logged to a file.

Load all data logged in file set by sml_set_debug_log_file to current engine. Used for debug purposes.

To use this feature, sml must be compiled with build type set to Debug.

Parameters
smlThe sml_object object.
strA string with full path of file to be used to load debug data.
Returns
@ true if loading debug was successful. false if operation failed or if sml was not compiled using Debug build type.
See Also
sml_set_debug_log_file
bool sml_load_fll_file ( struct sml_object sml,
const char *  filename 
)

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!
Parameters
smlThe sml_object object.
filenameA fll file path.
Returns
true on success.
false on failure.
bool sml_predict ( struct sml_object sml)

Make a prediction based on the most recent observations.

This is useful for making predictions without the normal SML flow, without a mainloop and a registered sml_change_cb. Take a look in the following example:

//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);
...
Remarks
sml_change_cb and sml_read_state_cb won't be called !
Parameters
smlThe sml_object object.
Returns
true on success.
false on failure.
void sml_print_debug ( struct sml_object sml,
bool  full 
)

Prints SML debug information.

Parameters
smlThe sml_object object.
fulltrue for full log, false otherwise.
int sml_process ( struct sml_object sml)

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.
Parameters
smlThe sml_object object.
Returns
::0 on success
A negative value on failure.
See Also
sml_set_read_state_callback
bool sml_save ( struct sml_object sml,
const char *  path 
)

Save the SML state on the disk.

Parameters
smlThe sml_object object.
pathA direcoty to save the engine files.
Returns
true on success.
false on failure.
See Also
sml_load
bool sml_set_debug_log_file ( struct sml_object sml,
const char *  str 
)

Set the file to be used to debug data changes in this engine.

This file will be used to log all calls to methods that changes the current state of the sml engine data. This information may be used to reproduce the execution of sml for debug purposes. Methods that configure the sml are not logged.

To use this feature, sml must be compiled with build type set to Debug.

Parameters
smlThe sml_object object.
strA string with full path of file to be used to write debug data. Use NULL or an empty string to disable data debug.
Returns
@ true if debug file was updated successfully. false if operation failed or if sml was not compiled using Debug build type.
See Also
sml_load_debug_log_file
bool sml_set_learn_disabled ( struct sml_object sml,
bool  disable 
)

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.

Remarks
Learning is enabled by default.
Parameters
smlThe sml_object object.
disabletrue to disable learn, false otherwise
Returns
true on success.
false on failure.
bool sml_set_max_memory_for_observations ( struct sml_object sml,
unsigned int  max_size 
)

Set maximum memory that can be used to store observation history data.

Remarks
max_size = 0 means infinite (it is also the default).
Parameters
smlThe sml_object object.
max_sizeMax memory size in bytes.
Returns
true on success.
false on failure.
bool sml_set_output_state_changed_callback ( struct sml_object sml,
sml_change_cb  output_state_changed_cb,
void *  data 
)

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.
Parameters
smlThe sml_object object.
output_state_changed_cbA sml_change_cb.
dataUser data to sml_read_state_cb.
Returns
true on success.
false on failure.
bool sml_set_read_state_callback ( struct sml_object sml,
sml_read_state_cb  read_state_cb,
void *  data 
)

Register a read callblack.

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.
Parameters
smlThe sml_object object.
read_state_cbA sml_read_state_cb.
dataUser data to sml_read_state_cb.
Returns
true on success.
false on failure.
bool sml_set_stabilization_hits ( struct sml_object sml,
uint16_t  hits 
)

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.
Parameters
smlThe sml_object object.
hitsThe number of hits to be considered stable.
Returns
true on success.
false on failure.