minor fix
[oweals/gnunet.git] / src / sensor / plugin_sensor_model_gaussian.c
index bf2090217a97e7e9b9b355d8c218e2f474e5fd0e..95d74f073c99b4a3281405d12fe5102d22449961 100644 (file)
@@ -42,6 +42,16 @@ struct Plugin
    */
   const struct GNUNET_CONFIGURATION_Handle *cfg;
 
+  /*
+   * Number of initial readings to be used for training only
+   */
+  int training_window;
+
+  /*
+   * Number of standard deviations considered within "normal"
+   */
+  int confidence_interval;
+
 };
 
 /*
@@ -55,20 +65,104 @@ struct Model
    */
   struct Plugin *plugin;
 
+  /*
+   * Number of readings so far
+   */
+  int n;
+
+  /*
+   * Sum of readings
+   */
+  long double sum;
+
+  /*
+   * Sum square of readings
+   */
+  long double sumsq;
+
 };
 
+/**
+ * Update local sums of model with a new value.
+ *
+ * @param model Targe model
+ * @param val New value
+ */
+static void
+update_sums (struct Model *model, double val)
+{
+  model->sum += val;
+  model->sumsq += val * val;
+  model->n++;
+}
+
+
+/**
+ * Feed a new value to a model
+ *
+ * @param cls closure (model state)
+ * @param val value to be fed to the model
+ * @return #GNUNET_YES in case of a detected outlier, #GNUNET_NO otherwise
+ */
+static int
+sensor_gaussian_model_feed (void *cls, double val)
+{
+  struct Model *model = cls;
+  struct Plugin *plugin = model->plugin;
+  long double mean;
+  long double stddev;
+  long double allowed_variance;
+
+  if (model->n < plugin->training_window)
+  {
+    update_sums (model, val);
+    return GNUNET_NO;
+  }
+  mean = model->sum / model->n;
+  stddev =
+      sqrt ((model->sumsq - 2 * mean * model->sum +
+             model->n * mean * mean) / (model->n - 1));
+  allowed_variance = (plugin->confidence_interval * stddev);
+  if ((val < (mean - allowed_variance)) || (val > (mean + allowed_variance)))
+    return GNUNET_YES;
+  return GNUNET_NO;
+}
+
+
+/**
+ * Destroy a model instance
+ *
+ * @param cls closure (model state)
+ */
+static void
+sensor_gaussian_model_destroy_model (void *cls)
+{
+  struct Model *model = cls;
+
+  GNUNET_free (model);
+}
+
+
+/**
+ * Create a model instance
+ *
+ * @param cls closure (plugin state)
+ * @return model state to be used for later calls
+ */
 static void *
 sensor_gaussian_model_create_model (void *cls)
 {
   struct Plugin *plugin = cls;
   struct Model *model;
 
-  model = GNUNET_new(struct Model);
+  model = GNUNET_new (struct Model);
+
   model->plugin = plugin;
   return model;
 }
 
-/*
+
+/**
  * Entry point for the plugin.
  *
  * @param cls The struct GNUNET_CONFIGURATION_Handle.
@@ -80,18 +174,42 @@ libgnunet_plugin_sensor_model_gaussian_init (void *cls)
   static struct Plugin plugin;
   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   struct GNUNET_SENSOR_ModelFunctions *api;
+  unsigned long long num;
 
   if (NULL != plugin.cfg)
     return NULL;                /* can only initialize once! */
   memset (&plugin, 0, sizeof (struct Plugin));
   plugin.cfg = cfg;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, "sensor-model-gaussian",
+                                             "TRAINING_WINDOW", &num))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         _("Missing `TRAINING_WINDOW' value in configuration.\n"));
+    return NULL;
+  }
+  plugin.training_window = (int) num;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, "sensor-model-gaussian",
+                                             "CONFIDENCE_INTERVAL", &num))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         _("Missing `CONFIDENCE_INTERVAL' value in configuration.\n"));
+    return NULL;
+  }
+  plugin.confidence_interval = (int) num;
   api = GNUNET_new (struct GNUNET_SENSOR_ModelFunctions);
+
   api->cls = &plugin;
-  LOG(GNUNET_ERROR_TYPE_DEBUG, "Guassian model plugin is running\n");
+  api->create_model = &sensor_gaussian_model_create_model;
+  api->destroy_model = &sensor_gaussian_model_destroy_model;
+  api->feed_model = &sensor_gaussian_model_feed;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Gaussian model plugin is running.\n");
   return api;
 }
 
-/*
+
+/**
  * Exit point from the plugin.
  *
  * @param cls The plugin context (as returned by "init")