|
6 | 6 | * using @c AND or @c OR logical connectives.
|
7 | 7 | *
|
8 | 8 | * Fuzzy inference works by sending any process's crisp input to the fuzzifier,
|
9 |
| -* which applies a fuzzy membership function and maps the actual readings into |
| 9 | +* which applies a fuzzy membership function and maps the actual readings into |
10 | 10 | * fuzzy values. The inference engine applies fuzzy rules from the knowledge base
|
11 | 11 | * and produces the fuzzy output. This output can not be used directly in any
|
12 | 12 | * process or system. It needs to be mapped into the original domain. For this,
|
13 | 13 | * the defuzzifier is used, which is the inverse process of fuzzification. It
|
14 | 14 | * converts the fuzzy output into crisp output, which can be fed to the process.
|
15 | 15 | *
|
16 | 16 | * The FIS Fuzzy Inference System engine provides an API for building and
|
17 |
| -* evaluation of type-1 fuzzy logic inference systems. |
18 |
| -* |
| 17 | +* evaluation of type-1 fuzzy logic inference systems. |
| 18 | +* |
19 | 19 | * The types of inferences supported by FIS are listed in the \ref qlibs::fis::type enum
|
20 | 20 | * and are detailed below:
|
21 | 21 | *
|
|
24 | 24 | * In a Mamdani system, the output of each rule is a fuzzy set. Since Mamdani
|
25 | 25 | * systems have more intuitive and easier to understand rule bases, they are
|
26 | 26 | * well-suited to expert system applications where the rules are created
|
27 |
| -* from human expert knowledge. |
| 27 | +* from human expert knowledge. |
28 | 28 | *
|
29 | 29 | * The output of each rule is a fuzzy set derived from the output membership
|
30 | 30 | * function and the implication method of the FIS. These output fuzzy sets are
|
|
65 | 65 | * function of the input values.
|
66 | 66 | *
|
67 | 67 | * and \f$w_i\f$, the rule firing strength, that is determined by the rule antecedent
|
68 |
| -* |
| 68 | +* |
69 | 69 | * The output of each rule is the weighted output level, which is the product of
|
70 | 70 | * \f$w_i\f$ and \f$u_i\f$.
|
71 |
| -* |
| 71 | +* |
72 | 72 | * The final output of the system is the weighted average/sum over all rule outputs:
|
73 | 73 | *
|
74 | 74 | * <center> \f$out= \frac{ \sum_{i=1}^{N}w_{i}u_{i} }{ \sum_{i=1}^{N}w_{i}} \f$ </center>
|
75 |
| -* |
| 75 | +* |
76 | 76 | * where \f$N\f$ is the number of rules.
|
77 | 77 | *
|
78 |
| -* Because of the linear dependence of each rule on the input variables, the Sugeno |
79 |
| -* method is ideal for acting as an interpolating supervisor of multiple linear |
80 |
| -* controllers that are to be applied, respectively, to different operating |
| 78 | +* Because of the linear dependence of each rule on the input variables, the Sugeno |
| 79 | +* method is ideal for acting as an interpolating supervisor of multiple linear |
| 80 | +* controllers that are to be applied, respectively, to different operating |
81 | 81 | * conditions of a dynamic nonlinear system.
|
82 | 82 | *
|
83 | 83 | * To specificy a FIS of this type, use the \ref qlibs::fis::Sugeno enum definition when
|
|
104 | 104 | * In the Tsukamoto inference system, the consequent of each fuzzy if-then rule
|
105 | 105 | * is represented by a fuzzy set with a monotonical membership function, As a result,
|
106 | 106 | * the inferred output of each rule is defined as a crisp value induced by the
|
107 |
| -* rule's firing strength. |
| 107 | +* rule's firing strength. |
108 | 108 | *
|
109 | 109 | * The overall output is taken as the weighted average of each rule's output.
|
110 | 110 | * Since each rule infers a crisp output, the Tsukamoto fuzzy model aggregates
|
|
131 | 131 | * </center>
|
132 | 132 | *
|
133 | 133 | * @section qfis_defuzz Defuzzification Methods
|
134 |
| -* |
| 134 | +* |
135 | 135 | * FIS supports five different methods, as listed in the \ref qlibs::fis::deFuzzMethod enum
|
136 | 136 | * for computing a single crisp output value for such a fuzzy set.
|
137 | 137 | *
|
138 |
| -* -# \ref qlibs::fis::centroid (default): this method applies only to \ref qlibs::fis::Mamdani |
139 |
| -* systems and returns the center of gravity of the fuzzy set along the x-axis. |
140 |
| -* If you think of the area as a plate with uniform thickness and density, the |
| 138 | +* -# \ref qlibs::fis::centroid (default): this method applies only to \ref qlibs::fis::Mamdani |
| 139 | +* systems and returns the center of gravity of the fuzzy set along the x-axis. |
| 140 | +* If you think of the area as a plate with uniform thickness and density, the |
141 | 141 | * centroid is the point along the x-axis about which the fuzzy set would balance.
|
142 |
| -* The centroid is computed using the following formula, where \f$\mu(x)\f$ is |
| 142 | +* The centroid is computed using the following formula, where \f$\mu(x)\f$ is |
143 | 143 | * the membership value for point \f$x_i\f$ in the universe of discourse.
|
144 | 144 | *
|
145 | 145 | *
|
146 | 146 | * <center> \f$\text{centroid}= \frac{ \sum_{i=1}\mu(x_{i})x_{i} }{ \sum_{i=1}\mu(x_{i})} \f$ </center>
|
147 | 147 | *
|
148 |
| -* -# \ref qlibs::fis::bisector : this method applies only for \ref qlibs::fis::Mamdani systems and finds the |
149 |
| -* vertical line that divides the fuzzy set into two sub-regions of equal area. |
| 148 | +* -# \ref qlibs::fis::bisector : this method applies only for \ref qlibs::fis::Mamdani systems and finds the |
| 149 | +* vertical line that divides the fuzzy set into two sub-regions of equal area. |
150 | 150 | * It is sometimes, but not always, coincident with the centroid line.
|
151 | 151 | *
|
152 | 152 | * -# \ref qlibs::fis::mom : Middle of Maximum. Only for \ref qlibs::fis::Mamdani systems.
|
|
155 | 155 | *
|
156 | 156 | * -# \ref qlibs::fis::lom : Largest of Maximum. Only for \ref qlibs::fis::Mamdani systems.
|
157 | 157 | *
|
158 |
| -* -# \ref qlibs::fis::wtaver (default): Weighted average of all rule outputs. This method applies only |
| 158 | +* -# \ref qlibs::fis::wtaver (default): Weighted average of all rule outputs. This method applies only |
159 | 159 | * for \ref qlibs::fis::Sugeno and \ref qlibs::fis::Tsukamoto systems.
|
160 | 160 | *
|
161 |
| -* -# \ref qlibs::fis::wtsum : Weighted sum of all rule outputs. This method applies only |
| 161 | +* -# \ref qlibs::fis::wtsum : Weighted sum of all rule outputs. This method applies only |
162 | 162 | * for \ref qlibs::fis::Sugeno and \ref qlibs::fis::Tsukamoto systems.
|
163 | 163 | *
|
164 |
| -* @note The defuzzification method is selected by default when setting up the |
| 164 | +* @note The defuzzification method is selected by default when setting up the |
165 | 165 | * FIS instance with \ref qlibs::fis::instance::setup(). However, the user can later change the default
|
166 | 166 | * method using the \ref qlibs::fis::instance::setDeFuzzMethod() function.
|
167 | 167 | *
|
|
188 | 188 | * -# <tt> IF the service IS excellent OR the food IS delicious, THEN the tip IS generous. </tt>
|
189 | 189 | *
|
190 | 190 | * This leads to a system with 2 inputs : @c service and @c food and 1 output: @c tip
|
191 |
| -* |
| 191 | +* |
192 | 192 | * <center>
|
193 | 193 | * @htmlonly
|
194 | 194 | * <!DOCTYPE html>
|
|
213 | 213 | * -# (food)rancid : A @a trapezoidal membership function with points located on <tt> [0 0 1 3] </tt>
|
214 | 214 | * -# (food)delicious : A @a trapezoidal membership function with points located on <tt> [7 9 10 10] </tt>
|
215 | 215 | *
|
216 |
| -* and 3 membership functions for the output |
| 216 | +* and 3 membership functions for the output |
217 | 217 | *
|
218 | 218 | * -# (tip)cheap : A @a triangular membership function with points located on <tt> [0 5 10] </tt>
|
219 | 219 | * -# (tip)average : A @a triangular membership function with points located on <tt> [10 15 20] </tt>
|
|
257 | 257 | * @endcode
|
258 | 258 | *
|
259 | 259 | * @attention
|
260 |
| -* Please note that all tag names are unique. |
| 260 | +* Please note that all tag names are unique. |
261 | 261 | *
|
262 |
| -* Then, we will define the rules of |
| 262 | +* Then, we will define the rules of |
263 | 263 | * the fuzzy system using the previously defined tags. Rules should be defined as
|
264 | 264 | * an array of type \ref qlibs::fis::rules and the contents should be rules constructed
|
265 |
| -* with the provided statements: |
266 |
| -* |
| 265 | +* with the provided statements: |
| 266 | +* |
267 | 267 | * - \ref #FIS_RULES_BEGIN to start the rules set
|
268 | 268 | * - \ref #FIS_RULES_END to end the rules set
|
269 | 269 | * - \ref #IF to start a rule sentence
|
|
275 | 275 | * Let's apply some of these statements to build the rule set.
|
276 | 276 | *
|
277 | 277 | * @code{.c}
|
278 |
| -* static const fis::rules rules[] = { |
| 278 | +* static const fis::rules rules[] = { |
279 | 279 | * FIS_RULES_BEGIN
|
280 | 280 | * IF service IS service_poor OR food IS food_rancid THEN tip IS tip_cheap END
|
281 | 281 | * IF service IS service_good THEN tip IS tip_average END
|
|
285 | 285 | * @endcode
|
286 | 286 | *
|
287 | 287 | * Additionally, we also need to define a vector where the firing strength of each
|
288 |
| -* rule will be stored. The size of the vector will be the number of rules. In |
| 288 | +* rule will be stored. The size of the vector will be the number of rules. In |
289 | 289 | * this particular case, there will be only three.
|
290 | 290 | *
|
291 | 291 | * @code{.c}
|
292 | 292 | * static real_t rulesStrength[ 3 ];
|
293 | 293 | * @endcode
|
294 | 294 | *
|
295 |
| -* First step is to configure the instance that represents the fuzzy |
| 295 | +* First step is to configure the instance that represents the fuzzy |
296 | 296 | * system using the \ref qlibs::fis::instance::setup() API:
|
297 | 297 | *
|
298 | 298 | * @code{.c}
|
299 | 299 | * tipper.setup( fis::Mamdani, tipper_inputs, tipper_outputs, MFin, MFout, rules, rulesStrength );
|
300 | 300 | * @endcode
|
301 | 301 | *
|
302 | 302 | * Then, we can proceed to the construction of the fuzzy system. First, we must
|
303 |
| -* configure the inputs and outputs by setting the ranges of each. For this, we |
304 |
| -* will use the \ref qlibs::fis::instance::setupInput() and \ref qlibs::fis::instance::setupOutput() |
| 303 | +* configure the inputs and outputs by setting the ranges of each. For this, we |
| 304 | +* will use the \ref qlibs::fis::instance::setupInput() and \ref qlibs::fis::instance::setupOutput() |
305 | 305 | * methods as follows:
|
306 | 306 | *
|
307 | 307 | * @code{.c}
|
|
310 | 310 | * tipper.setupOutput( tip, 0.0f, 30.0f );
|
311 | 311 | * @endcode
|
312 | 312 | *
|
313 |
| -* The next step is to configure the membership functions by relating I/O, |
314 |
| -* tags, shape and parameters one by one by using the \ref qlibs::fis::instance::setupInputMF() and |
| 313 | +* The next step is to configure the membership functions by relating I/O, |
| 314 | +* tags, shape and parameters one by one by using the \ref qlibs::fis::instance::setupInputMF() and |
315 | 315 | * \ref qlibs::fis::instance::setupOutputMF() methods as follows:
|
316 | 316 | * Then, let's define the parameters of all the membership functions:
|
317 | 317 | *
|
|
331 | 331 | *
|
332 | 332 | * @section qfis_eval Evaluating a Fuzzy Inference System
|
333 | 333 | *
|
334 |
| -* If we already have a fuzzy system configured with \ref qlibs::fis::instance::setup(), we can |
335 |
| -* evaluate it by using \ref qlibs::fis::instance::fuzzify(), \ref qlibs::fis::instance::inference() and |
336 |
| -* \ref qlibs::fis::instance::deFuzzify(). |
337 |
| -* Input values can be set with \ref qlibs::fis::instance::setInput() and output values can be |
| 334 | +* If we already have a fuzzy system configured with \ref qlibs::fis::instance::setup(), we can |
| 335 | +* evaluate it by using \ref qlibs::fis::instance::fuzzify(), \ref qlibs::fis::instance::inference() and |
| 336 | +* \ref qlibs::fis::instance::deFuzzify(). |
| 337 | +* Input values can be set with \ref qlibs::fis::instance::setInput() and output values can be |
338 | 338 | * obtained with \ref qlibs::fis::instance::getOutput(). Also you can use the stream operator @c <<
|
339 | 339 | * to set the inputs and the index operator [] to get the outputs of the FIS
|
340 | 340 | * system (see example bellow).
|
341 | 341 | *
|
342 |
| -* To show its use, first we are going to put everything together in a single |
343 |
| -* code snippet and we are going to create two functions, @c tipper_init() and |
344 |
| -* @c tipper_run() that will be in charge of setting up the fuzzy inference |
| 342 | +* To show its use, first we are going to put everything together in a single |
| 343 | +* code snippet and we are going to create two functions, @c tipper_init() and |
| 344 | +* @c tipper_run() that will be in charge of setting up the fuzzy inference |
345 | 345 | * system and evaluating it respectively.
|
346 | 346 | *
|
347 | 347 | * @code{.c}
|
348 | 348 | * #include "tipper_fis.h"
|
349 |
| -* #include "qfis.h" |
350 |
| -* |
| 349 | +* #include <qlibs.h> |
| 350 | +* |
351 | 351 | * // I/O Names
|
352 | 352 | * enum : fis::tag { service, food};
|
353 | 353 | * enum : fis::tag { tip};
|
|
371 | 371 | * };
|
372 | 372 | * //Rule strengths
|
373 | 373 | * real_t rStrength[ 3 ] = { 0.0f };
|
374 |
| -* |
375 |
| -* |
| 374 | +* |
| 375 | +* |
376 | 376 | * void tipper_init( void )
|
377 | 377 | * {
|
378 | 378 | * tipper.setup( fis::Mamdani, tipper_inputs, tipper_outputs, MFin, MFout, rules, rStrength );
|
|
388 | 388 | * tipper.setupOutputMF( tip, average, fis::trimf, (const real_t[]){ 10.0f, 15.0f, 20.0f } );
|
389 | 389 | * tipper.setupOutputMF( tip, generous, fis::trimf, (const real_t[]){ 20.0f, 25.0f, 30.0f } );
|
390 | 390 | * }
|
391 |
| -* |
| 391 | +* |
392 | 392 | * void tipper_run( real_t *inputs, real_t *outputs )
|
393 | 393 | * {
|
394 | 394 | * // Set the crips inputs
|
395 | 395 | * tipper << service << inputs[ service ] << food << inputs[ food ];
|
396 |
| -* |
| 396 | +* |
397 | 397 | * tipper.fuzzify();
|
398 | 398 | * if ( tipper.inference() ) {
|
399 | 399 | * tipper.deFuzzify();
|
400 | 400 | * }
|
401 | 401 | * else {
|
402 | 402 | * // Error!
|
403 | 403 | * }
|
404 |
| -* |
| 404 | +* |
405 | 405 | * // Get the crips outputs
|
406 | 406 | * outputs[ tip ] = tipper[ tip ];
|
407 | 407 | * }
|
|
0 commit comments