-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCOGDefuzzSetObj.cpp
More file actions
314 lines (262 loc) · 7.13 KB
/
COGDefuzzSetObj.cpp
File metadata and controls
314 lines (262 loc) · 7.13 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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
//
// File: COGDefuzzSetObj.cpp
//
// Purpose: Set object for Center of Gravity Defuzzification method
//
// Copyright � 2001 Louder Than A Bomb! Software
//
// This file is part of the FFLL (Free Fuzzy Logic Library) project (http://ffll.sourceforge.net)
// It is released under the BSD license, see http://ffll.sourceforge.net/license.txt for the full text.
//
// include files
#include "COGDefuzzSetObj.h"
#include "FuzzyOutSet.h"
#include "FuzzyOutVariable.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#include "debug.h"
#endif
//
// Function: COGDefuzzSetObj()
//
// Purpose: Constructor
//
// Arguments:
//
// FuzzyOutSet* par - set that this is part of
//
// Returns:
//
// none
//
// Author: Michael Zarozinski
// Date: 6/01
//
// Modification History
// Author Date Modification
// ------ ---- ------------
//
//
COGDefuzzSetObj::COGDefuzzSetObj(FuzzyOutSet* par)
: DefuzzSetObj(par), FFLLBase(par)
{
values = NULL;
}; // end COGDefuzzSetObj::COGDefuzzSetObj()
//
// Function: ~COGDefuzzSetObj()
//
// Purpose: Destructor
//
// Arguments:
//
// none
//
// Returns:
//
// none
//
// Author: Michael Zarozinski
// Date: 6/01
//
// Modification History
// Author Date Modification
// ------ ---- ------------
//
//
COGDefuzzSetObj::~COGDefuzzSetObj()
{
if (values)
delete[] values;
}; // end COGDefuzzSetObj::~COGDefuzzSetObj()
//
// Function: init()
//
// Purpose: Intializes the look up table
//
// Arguments:
//
// int array_max - how many elements are in the look up table
//
// Returns:
//
// 0 - success
// non-zero - failure
//
// Author: Michael Zarozinski
// Date: 6/01
//
// Modification History
// Author Date Modification
// ------ ---- ------------
//
//
int COGDefuzzSetObj::init(int array_max)
{
values = new _cog_struct[array_max];
if (values == NULL)
{
set_msg_text_int(ERR_ALLOC_MEM);
assert(values != NULL);
return -1;
} // end if error allocating memory
return 0;
}; // end COGDefuzzSetObj::init()
//
// Function: calc()
//
// Purpose: Calculates the cog under the curve for EVERY Degree of Membership (DOM),
// creating a lookup table.
//
// Arguments:
//
// void
//
// Returns:
//
// void
//
// Author: Michael Zarozinski
// Date: 8/01
//
// Modification History
// Author Date Modification
// ------ ---- ------------
// Michael Z 4/03 removed adding min_x to set_moment()
//
void COGDefuzzSetObj::calc()
{
int dom_idx, x_idx; // counters
int start_idx, end_idx; // the indexes that start/end the membership
// function in the values array.
int y; // holds 'y' value for the curve (refered to as DOM
// everywhere else but that gets confising here cuz
// we're looping through the doms
RealType area_sum; // area sum
RealType area; // area
RealType moment_sum; // sum of the moments
// get the min val and idx_multiplier for the var...
FuzzyOutSet* set_base = get_parent();
RealType idx_mult = set_base->get_idx_multiplier();
RealType min_x = set_base->get_left_x();
start_idx = set_base->get_start_x();
end_idx = set_base->get_end_x();
//
// To calc the COG for each DOM, we treat each index in the values[]
// array as a point mass. Where the mass is equal to the area.
// Remember Calc 1 where you treated each "segment" of the curve
// you were integrating as a rectangle? That's what we're doing here,
// however when we calculate the HEIGHT of the rectangle we're taking
// the LESSER of the dom_idx or the value in the values[] array.
//
//
// MAX_DOM X
// X X
// X X
// X X
// X X
// X X
// X X
// X X
// dom_idx ----------------------------------------
// XXXXXXXXXXXXXXXXX
// XXXXXXXXXXXXXXXXXXX
// XXXXXXXXXXXXXXXXXXXXX
// DOM 0 XXXXXXXXXXXXXXXXXXXXXXX
// | |
// start_idx end_idx
//
// loop through all the doms
for (dom_idx = 0; dom_idx < FuzzyVariableBase::get_dom_array_count(); dom_idx++)
{
// init area and moment for this dom
area_sum = 0.0;
moment_sum = 0.0;
// go through the DOMs for the curve
for (x_idx = start_idx; x_idx <= end_idx; x_idx++)
{
// get the DOM for this 'x' value
y = set_base->get_dom(x_idx);
// use the LESSER of the 'y' value for this 'x' position or
// the dom we're checking
if (y > dom_idx)
area = dom_idx;
else
area = y;
// add the area to the accumulator
area_sum += area;
// add the moment to the accumulator
moment_sum += (RealType)x_idx * area;
} // end loop through curve
set_area(dom_idx, area_sum);
// since the moment invovles the distance from 0 and we use the x_idx
// above in our calcs, we need to multiply by the index multiplier
// to convert an index to a 'x' value. Note: we could have multiplied
// above when we calculated each moment but it's faster to just perform
// ONE multiplication here
// 4/03 - removing min_x in set_moment, this was causing slight output inconsistencies
set_moment(dom_idx, (moment_sum * idx_mult ));
} // end loop through DOM
} // end COGDefuzzSetObj::calc()
//
// Function: get_defuzz_x()
//
// Purpose: This fuction gets the defuzzified 'x' value for a DOM passed in.
//
// Arguments:
//
// int dom - 'y' value to get the 'x' value for
//
// Returns:
//
// RealType - the defuzzified 'x' value for the set
//
// Author: Michael Zarozinski
// Date: 12/01
//
// Modification History
// Author Date Modification
// ------ ---- ------------
//
//
RealType COGDefuzzSetObj::get_defuzz_x(int dom )
{
if (dom < 0)
{
return FLT_MIN;
}
RealType area = get_area(dom);
if (!area)
{
return FLT_MIN;
}
RealType moment = get_moment(dom);
FuzzyOutSet* set_base = get_parent();
FuzzyOutVariable* parent = set_base->get_parent();
RealType left_x = parent->get_left_x();
// be sure to account for the left x (start of the var)
return (left_x + (moment / area));
} // end COGDefuzzSetObj::get_defuzz_x()
/////////////////////////////////////////////////////////////////////
////////// Trivial Functions That Don't Require Headers /////////////
/////////////////////////////////////////////////////////////////////
RealType COGDefuzzSetObj::get_area(int _idx) const
{
return values[_idx].area;
};
RealType COGDefuzzSetObj::get_moment(int _idx) const
{
return values[_idx].moment;
};
void COGDefuzzSetObj::set_area(int _idx, RealType val)
{
values[_idx].area = val;
};
void COGDefuzzSetObj::set_moment(int _idx, RealType val)
{
values[_idx].moment = val;
};
int COGDefuzzSetObj::get_defuzz_type() const
{
return DefuzzVarObj::DEFUZZ_COG;
};