-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathFuzzyControl.h
More file actions
218 lines (178 loc) · 6.36 KB
/
FuzzyControl.h
File metadata and controls
218 lines (178 loc) · 6.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/***************************************************
Fuzzy Control tools
by Tomás de Camino Beck
www.funcostarica.org
www.inventoria.org
Disclaimer: This code is still being tested and debugged, contributions
are welcomed
License:
This Library was created by Tomàs de Camino Beck (tomas@funcostarica.org)
and is released under an open source MIT license. See details at:
http://opensource.org/licenses/MIT
/***************************************************/
//We will use a structured data type to create label type def
//in C++ struct is a public object.
struct fuzzyDef {
float mina = 0;
float minb = 0;
float maxa = 0;
float maxb = 0;
float centroid = 0;
float (*membership)(fuzzyDef, float);//pointer to membership function
float miu = 0.0; //to store current membership or fuzzy weight for defuzzification
};
//to create the entire domain of discourse for a fuzzy variable
//with n sets
struct fuzzyDomain {
fuzzyDef* fset ;
int nset;
};
/*****fuzzy membership functions*****/
/* they receibe the fuzzyDef as argument to get parameters */
float triangle(float t) {
//creates a triangle from -1 to 1
return max(1 - abs(t), 0);
}
float triangle(fuzzyDef fset, float x) {
//triangle function between a min and max
float mid = ((fset.maxa - fset.mina) / 2) + fset.mina;
if (x < fset.mina) return 0;
if (x > fset.maxa) return 0;
return triangle( (x - mid) / (fset.maxa - fset.mina) * 2);
}
float increasing(fuzzyDef fset, float x) {
if (x < fset.mina)return 0;
if (x > fset.maxa)return 1;
return (x - fset.mina) / (fset.maxa - fset.mina);
}
float decreasing(fuzzyDef fset, float x) {
if (x < fset.mina)return 1;
if (x > fset.maxa)return 0;
return (fset.maxa - x) / (fset.maxa - fset.mina);
}
float trapezoid(fuzzyDef fset, float x) {
if (x < fset.mina || x > fset.maxb)return 0;
if (x > fset.maxa && x < fset.minb)return 1;
if (x >= fset.mina && x <= fset.maxa)return increasing(fset, x);
if (x >= fset.minb && x <= fset.maxb)return decreasing(fset, x);
}
/************ Fuzzy Operations ****************/
/**********************************************/
//function that return the truth of the membership given de parameter v
//is stores de value in miu for use in other functions
float truthDegree(fuzzyDef *fset, float v) {
return fset->miu = fset->membership(*fset, v);;
}
//Fuzzy union definition
float fuzzyUnion(fuzzyDef *set1, fuzzyDef *set2, float v) {
float degree1 = truthDegree(set1, v);
float degree2 = truthDegree(set2, v);
if (degree1 >= degree2) return degree1;
else return degree2;
}
//Fuzzy intersection definition
float fuzzyIntersection(fuzzyDef *set1, fuzzyDef *set2, float v) {
float degree1 = truthDegree(set1, v);
float degree2 = truthDegree(set2, v);
if (degree1 <= degree2) return degree1;
else return degree2;
}
/***** Membership Q ***********/
//return true if current miu value > 0
//use for if statements to define fuzzy rules
boolean isMember(fuzzyDef *set1) {
return set1->miu > 0;
}
//fuzzy "And" and "Or" to simplify
boolean isMemberAnd(fuzzyDef *set1, fuzzyDef *set2){
return (set1->miu > 0 && set2->miu > 0);
}
boolean isMemberAnd(fuzzyDef *set1, fuzzyDef *set2,fuzzyDef *set3){
return (set1->miu > 0 && set2->miu > 0 && set3->miu > 0);
}
boolean isMemberOr(fuzzyDef *set1, fuzzyDef *set2){
return (set1->miu > 0 || set2->miu > 0);
}
boolean isMemberOr(fuzzyDef *set1, fuzzyDef *set2,fuzzyDef *set3){
return (set1->miu > 0 || set2->miu > 0|| set3->miu > 0);
}
void setMiu(fuzzyDef *set1,float v){
set1->miu=max(set1->miu,v);
}
/*********fuzzy domain functions ********/
//to set the centroid value for weighted average
void setCentroid(fuzzyDef *set1) {
if (set1->minb > 0) {
set1->centroid = (set1->maxa + set1->minb) / 2;
}
else set1->centroid = (set1->mina + set1->maxa) / 2;
}
//set miu in a fuzzy domain, all to 0
void resetDomain(fuzzyDomain *domain) {
for (int i = 0; i < domain->nset; i++) {
domain->fset[i].miu = 0;
}
}
//calculates truth degree in all sets of a domain
void truthDegree(fuzzyDomain *domain, float v) {
for (int i = 0; i < domain->nset; i++) {
truthDegree(&domain->fset[i], v);
}
}
//sets a standard fuzzy domain with n membership functions
void setDomain(fuzzyDomain *domain, float maxvalue) {
if (domain->nset > 1) {
float d = maxvalue / ((domain->nset + 1) );
int s = domain->nset - 1;
domain->fset[0].mina = d;
domain->fset[0].maxa = 2 * d;
domain->fset[0].centroid = (domain->fset[0].mina + domain->fset[0].maxa) / 2;
domain->fset[0].membership = &decreasing;
for (int i = 1; i < s; i++) {
domain->fset[i].mina = i * d;
domain->fset[i].maxa = (i + 2) * d;
domain->fset[i].centroid = (domain->fset[i].mina + domain->fset[i].maxa) / 2;
domain->fset[i].membership = ▵
}
domain->fset[s].mina = maxvalue - d * 2;
domain->fset[s].maxa = maxvalue - d;
domain->fset[s].centroid = (domain->fset[s].mina + domain->fset[s].maxa) / 2;
domain->fset[s].membership = &increasing;
}
}
//sets a standard fuzzy domain with n membership functions
//void //sets a standard fuzzy domain with n membership functions
void setDomain(fuzzyDomain *domain, float minvalue, float maxvalue) {
if (domain->nset > 1) {
float d = (maxvalue - minvalue) / ((domain->nset + 1));
int s = domain->nset - 1;
domain->fset[0].mina = minvalue + d;
domain->fset[0].maxa = minvalue + 2 * d;
domain->fset[0].centroid = (domain->fset[0].mina + domain->fset[0].maxa) / 2;
domain->fset[0].membership = &decreasing;
for (int i = 1; i < s; i++) {
domain->fset[i].mina = minvalue + i * d;
domain->fset[i].maxa = minvalue + (i + 2) * d;
domain->fset[i].centroid = (domain->fset[i].mina + domain->fset[i].maxa) / 2;
domain->fset[i].membership = ▵
}
domain->fset[s].mina = maxvalue - d * 2;
domain->fset[s].maxa = maxvalue - d;
domain->fset[s].centroid = (domain->fset[s].mina + domain->fset[s].maxa) / 2;
domain->fset[s].membership = &increasing;
}
}
/*defuzzifying functions
weighted average for speed and simplicity
it works well if fuzzy membership functions are simetrical
*/
float weightedAverage(fuzzyDomain *domain) {
float wsum = 0;
float sum = 0;
for (int i = 0; i < domain->nset; i++) {
wsum += domain->fset[i].miu * domain->fset[i].centroid;
sum += domain->fset[i].miu;
}
if (sum > 0) return wsum / sum;
else return 0;
}