sensor: towards profiler
[oweals/gnunet.git] / src / sensor / plugin_sensor_model_gaussian.c
1 /*
2  * This file is part of GNUnet
3  * (C) 2013 Christian Grothoff (and other contributing authors)
4  *
5  * GNUnet is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published
7  * by the Free Software Foundation; either version 3, or (at your
8  * option) any later version.
9  *
10  * GNUnet is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with GNUnet; see the file COPYING.  If not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * @file sensor/plugin_sensor_model_gaussian.c
23  * @brief Gaussian model for sensor analysis
24  * @author Omar Tarabai
25  */
26
27 #include "platform.h"
28 #include "gnunet_sensor_model_plugin.h"
29 #include "gnunet_sensor_service.h"
30 #include "sensor.h"
31
32 #define LOG(kind,...) GNUNET_log_from (kind, "sensor-model-gaussian", __VA_ARGS__)
33
34 /*
35  * Plugin state information
36  */
37 struct Plugin
38 {
39
40   /*
41    * Configuration handle
42    */
43   const struct GNUNET_CONFIGURATION_Handle *cfg;
44
45   /*
46    * Number of initial readings to be used for training only
47    */
48   int training_window;
49
50   /*
51    * Number of standard deviations considered within "normal"
52    */
53   int confidence_interval;
54
55 };
56
57 /*
58  * State of single model instance
59  */
60 struct Model
61 {
62
63   /*
64    * Pointer to the plugin state
65    */
66   struct Plugin *plugin;
67
68   /*
69    * Number of readings so far
70    */
71   int n;
72
73   /*
74    * Sum of readings
75    */
76   long double sum;
77
78   /*
79    * Sum square of readings
80    */
81   long double sumsq;
82
83 };
84
85 /**
86  * Update local sums of model with a new value.
87  *
88  * @param model Targe model
89  * @param val New value
90  */
91 static void
92 update_sums (struct Model *model, double val)
93 {
94   model->sum += val;
95   model->sumsq += val * val;
96   model->n++;
97 }
98
99
100 /**
101  * Feed a new value to a model
102  *
103  * @param cls closure (model state)
104  * @param val value to be fed to the model
105  * @return #GNUNET_YES in case of a detected outlier, #GNUNET_NO otherwise
106  */
107 static int
108 sensor_gaussian_model_feed (void *cls, double val)
109 {
110   struct Model *model = cls;
111   struct Plugin *plugin = model->plugin;
112   long double mean;
113   long double stddev;
114   long double allowed_variance;
115
116   if (model->n < plugin->training_window)
117   {
118     update_sums (model, val);
119     return GNUNET_NO;
120   }
121   if (model->n == plugin->training_window)
122     LOG (GNUNET_ERROR_TYPE_DEBUG, "Gaussian model out of training period.\n");
123   mean = model->sum / model->n;
124   stddev =
125       sqrt ((model->sumsq - 2 * mean * model->sum +
126              model->n * mean * mean) / (model->n - 1));
127   allowed_variance = (plugin->confidence_interval * stddev);
128   if ((val < (mean - allowed_variance)) || (val > (mean + allowed_variance)))
129     return GNUNET_YES;
130   update_sums (model, val);
131   return GNUNET_NO;
132 }
133
134
135 /**
136  * Destroy a model instance
137  *
138  * @param cls closure (model state)
139  */
140 static void
141 sensor_gaussian_model_destroy_model (void *cls)
142 {
143   struct Model *model = cls;
144
145   GNUNET_free (model);
146 }
147
148
149 /**
150  * Create a model instance
151  *
152  * @param cls closure (plugin state)
153  * @return model state to be used for later calls
154  */
155 static void *
156 sensor_gaussian_model_create_model (void *cls)
157 {
158   struct Plugin *plugin = cls;
159   struct Model *model;
160
161   model = GNUNET_new (struct Model);
162
163   model->plugin = plugin;
164   return model;
165 }
166
167
168 /**
169  * Entry point for the plugin.
170  *
171  * @param cls The struct GNUNET_CONFIGURATION_Handle.
172  * @return NULL on error, otherwise the plugin context
173  */
174 void *
175 libgnunet_plugin_sensor_model_gaussian_init (void *cls)
176 {
177   static struct Plugin plugin;
178   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
179   struct GNUNET_SENSOR_ModelFunctions *api;
180   unsigned long long num;
181
182   if (NULL != plugin.cfg)
183     return NULL;                /* can only initialize once! */
184   memset (&plugin, 0, sizeof (struct Plugin));
185   plugin.cfg = cfg;
186   if (GNUNET_OK !=
187       GNUNET_CONFIGURATION_get_value_number (cfg, "sensor-model-gaussian",
188                                              "TRAINING_WINDOW", &num))
189   {
190     LOG (GNUNET_ERROR_TYPE_ERROR,
191          _("Missing `TRAINING_WINDOW' value in configuration.\n"));
192     return NULL;
193   }
194   plugin.training_window = (int) num;
195   if (GNUNET_OK !=
196       GNUNET_CONFIGURATION_get_value_number (cfg, "sensor-model-gaussian",
197                                              "CONFIDENCE_INTERVAL", &num))
198   {
199     LOG (GNUNET_ERROR_TYPE_ERROR,
200          _("Missing `CONFIDENCE_INTERVAL' value in configuration.\n"));
201     return NULL;
202   }
203   plugin.confidence_interval = (int) num;
204   api = GNUNET_new (struct GNUNET_SENSOR_ModelFunctions);
205
206   api->cls = &plugin;
207   api->create_model = &sensor_gaussian_model_create_model;
208   api->destroy_model = &sensor_gaussian_model_destroy_model;
209   api->feed_model = &sensor_gaussian_model_feed;
210   LOG (GNUNET_ERROR_TYPE_DEBUG, "Gaussian model plugin is running.\n");
211   return api;
212 }
213
214
215 /**
216  * Exit point from the plugin.
217  *
218  * @param cls The plugin context (as returned by "init")
219  * @return Always NULL
220  */
221 void *
222 libgnunet_plugin_sensor_model_gaussian_done (void *cls)
223 {
224   struct GNUNET_SENSOR_ModelFunctions *api = cls;
225   struct Plugin *plugin = api->cls;
226
227   plugin->cfg = NULL;
228   GNUNET_free (api);
229   LOG (GNUNET_ERROR_TYPE_DEBUG, "Guassian model plugin is finished\n");
230   return NULL;
231
232 }
233
234 /* end of plugin_sensor_model_gaussian.c */