Loading...
Searching...
No Matches
Fuzzy.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31#ifndef FUZZY_H_
32#define FUZZY_H_
33
34#include <drain/Log.h>
35#include <cmath>
36
37#include "Functor.h"
38#include "Range.h"
39
40
41// using namespace std;
42
43namespace drain
44{
45
47
53template <class T> //,class T2>
54class Fuzzifier : public UnaryFunctor
55{
56public:
57
58 inline
59 Fuzzifier(const std::string & name, const std::string & description="", double scale=1.0, double bias=0.0) : UnaryFunctor(name, description, scale, bias),
60 INVERSE(false) {}; // srcMax(1.0),
61
62 // Auto ok
63 // Fuzzifier(const Fuzzifier<T> & op) : UnaryFunctor(op), INVERSE(op.INVERSE){}
64
65 virtual
66 inline
67 ~Fuzzifier(){};
68
70 /*
71 virtual inline
72 void updateBean() const override {
73 updateScale();
74 }
75 */
76
77 mutable
78 bool INVERSE;
79
80protected:
81
82 inline
83 virtual
84 void updateScale() const {
85
86 if (!INVERSE){
87 this->scaleFinal = scale;
88 this->biasFinal = bias;
89 }
90 else {
91 this->scaleFinal = -scale;
92 this->biasFinal = bias + scale;
93 }
94 }
95
96 /*
97 inline
98 void setReferencesAndCopy(const BeanLike & b){
99 setReferences();
100 this->copy(b);
101 this->updateBean();
102 };
103 */
104
105private:
106
107 //virtual
108 //void setReferences() = 0;
109
110};
111
113
131template <class T> //,class T2>
132class FuzzyStep : public Fuzzifier<T> {
133
134public:
135
137
143 FuzzyStep(T startPos = -1.0, T endPos = 1.0, double scale = 1.0, double bias = 0.0) : Fuzzifier<T>(__FUNCTION__, "Fuzzy step function.", scale, bias), span(1.0) {
144 this->parameters.link("position", this->range.tuple());
145 this->parameters.link("scale", this->scale);
146 this->parameters.link("bias", this->bias);
147 set(startPos, endPos, scale, bias);
148 };
149
150 FuzzyStep(const FuzzyStep<T> & f) : Fuzzifier<T>(f), span(1.0){
151 this->parameters.copyStruct(f.getParameters(), f, *this);
152 updateBean();
153 }
154
155 ~FuzzyStep(){};
156
157 inline
158 void set(double rangeMin, double rangeMax, double scale=1.0, double bias=0.0){
159 this->range.min = rangeMin;
160 this->range.max = rangeMax;
161 this->setScale(scale, bias);
162 this->updateBean();
163 }
164
165 inline
166 void set(const drain::Range<double> & r, double scale=1.0, double bias=0.0){
167 this->range.set(r);
168 this->setScale(scale, bias);
169 this->updateBean();
170 }
171
172
173
174 virtual
175 inline
176 void updateBean() const override {
177
178 drain::Logger mout(__FILE__, __FUNCTION__);
179
180 this->INVERSE = (range.min > range.max);
181
182 if (!this->INVERSE){
183 rangeFinal.min = range.min;
184 rangeFinal.max = range.max;
185 span = range.max - range.min;
186 }
187 else {
188 //cerr << "set INVERSE" << endl;
189 rangeFinal.min = range.max;
190 rangeFinal.max = range.min;
191 span = range.min - range.max;
192 }
193
194 this->updateScale();
195
196 mout.debug2(this->scaleFinal , ',' , this->biasFinal );
197
198 }
199
200 inline
201 virtual
202 double operator()(double x) const {
203
204 if (x <= rangeFinal.min)
205 return this->biasFinal;
206 else if (x >= rangeFinal.max)
207 return this->biasFinal + this->scaleFinal;
208 else
209 return this->biasFinal + this->scaleFinal*(x-rangeFinal.min) / span; // div by undetectValue not possible, unless start==end
210
211 }
212
213 //std::pair<double,double> range;
215
216protected:
217
218 mutable double span;
219
220 //
221 mutable
222 drain::Range<double> rangeFinal;
223 //std::pair<double,double> rangeFinal;
224
225
226};
227
229
239template <class T> //,class T2>
240class FuzzyTriangle : public Fuzzifier<T> {
241
242public:
243
244 FuzzyTriangle(double startPos=-1.0, double endPos=+1.0, double peakPos=0.0, double scale = 1.0, T bias = 0) : Fuzzifier<T>(__FUNCTION__, "Fuzzy triangle function.", scale, bias){ // : start(start), peak(peak), end(end), scale(scale), _spanLow(start-peak), _spanHigh(end-peak)
245 this->parameters.link("position", this->range.tuple());
246 this->parameters.link("peakPos", this->peakPos);
247 this->parameters.link("scale", this->scale);
248 this->parameters.link("bias", this->bias);
249
250 set(startPos, endPos, peakPos, scale, bias);
251
252 };
253
254 FuzzyTriangle(drain::Range<double> range, double scale = 1.0, T bias = 0) : Fuzzifier<T>(__FUNCTION__, "Fuzzy triangle function.", scale, bias){ // : start(start), peak(peak), end(end), scale(scale), _spanLow(start-peak), _spanHigh(end-peak)
255 this->parameters.link("position", this->range.tuple());
256 this->parameters.link("peakPos", this->peakPos);
257 this->parameters.link("scale", this->scale);
258 this->parameters.link("bias", this->bias);
259
260 set(range.min, range.max, (range.min+range.max)/2, scale, bias);
261
262 }
263
265 this->parameters.copyStruct(f.getParameters(), f, *this);
266 updateBean();
267 }
268
269 ~FuzzyTriangle(){};
270
272 // std::numeric_limits<double>::signaling_NaN()
273 inline
274 void set(double startPos, double endPos, double peakPos=0.0, double scale=1.0, double bias=0.0){ // todo join
275
276 this->range.set(startPos, endPos);
277
278 this->peakPos = peakPos;
279 /*
280 if (!std::isnan(peakPos))
281 this->peakPos = peakPos;
282 else
283 this->peakPos = (startPos + endPos) / 2.0;
284 */
285
286 this->setScale(scale, bias); //
287 this->updateBean();
288 }
289
290
291 virtual
292 void updateBean() const override {
293
294 if (!range.contains(peakPos))
295 peakPos = (range.min + range.max) / 2.0;
296
297 this->INVERSE = (range.min > range.max);
298
299 if (!this->INVERSE){
300 span.set(range.min - peakPos, range.max - peakPos);
301 }
302 else {
303 span.set(range.max - peakPos, range.min - peakPos);
304 }
305
306 this->updateScale();
307
308 }
309
310 inline
311 virtual
312 double operator()(double x) const {
313
314 x = x - peakPos;
315 if (x > span.max)
316 return this->biasFinal;
317 else if (x > 0.0)
318 return this->biasFinal + this->scaleFinal*(1.0 - x/span.max);
319 else if (x > span.min)
320 return this->biasFinal + this->scaleFinal*(1.0 - x/span.min);
321 else // x < spanHi
322 return this->biasFinal;
323
324 };
325
328
330 mutable // adjusted if outside range
331 double peakPos = 0.0;
332
333
334protected:
335
336 mutable
337 drain::Range<double> span = {-1.0, +1.0};
338
339
340};
341
342
343
345
362template <class T>
363class FuzzyBell : public Fuzzifier<T> {
364
365public:
366
367 FuzzyBell(double location=0.0, double width=1.0, double scale = 1.0, double bias = 0.0) : Fuzzifier<T>(__FUNCTION__, "Fuzzy bell function.", scale, bias), widthInv(1.0) { // location(location), scale(scale), a(1.0/width), INVERSE(a<0.0) {};
368 //setReferences();
369 this->parameters.link("location", this->location = location);
370 this->parameters.link("width", this->width = width);
371 this->parameters.link("scale", this->scale = scale);
372 this->parameters.link("bias", this->bias = bias);
373 //set(location, width, scale, bias);
374 this->updateBean();
375 }
376
377 FuzzyBell(const FuzzyBell & f) : Fuzzifier<T>(f) {
378 this->parameters.copyStruct(f.getParameters(), f, *this);
379 this->updateBean();
380 }
381
382 virtual
383 ~FuzzyBell(){};
384
385 void set(double location = 0.0, double width = 1.0, double scale=1.0, double bias=0.0){
386 this->location = location;
387 this->width = width;
388 this->setScale(scale, bias);
389 this->updateBean();
390 }
391
392
393 virtual
394 void updateBean() const override {
395 this->widthInv = 1.0/width;
396 this->INVERSE = (width<0.0);
397 this->updateScale();
398 }
399
400 inline
401 virtual
402 double operator()(double x) const {
403
404 x = widthInv * (x - this->location);
405 return this->biasFinal + this->scaleFinal/(1.0 + x*x);
406
407 };
408
409 double location;
410 double width;
411
412protected:
413
414 //double scale;
415 mutable
416 double widthInv;
417
418
419};
420
422
431template <class T>
432class FuzzyBell2 : public Fuzzifier<T> {
433
434public:
435
436 FuzzyBell2(double location=0.0, double width=1.0, double scale = 1.0, double bias = 0.0) : Fuzzifier<T>(__FUNCTION__, "Fuzzy Gaussian-like bell function.", scale, bias) {
437 //setReferences();
438 this->parameters.link("location", this->location = location);
439 this->parameters.link("width", this->width = width);
440 this->parameters.link("scale", this->scale = scale);
441 this->parameters.link("bias", this->bias = bias);
442 updateBean();
443 };
444
445 FuzzyBell2(const FuzzyBell2 & f) : Fuzzifier<T>(f) {
446 this->parameters.copyStruct(f.getParameters(), f, *this);
447 updateBean();
448 }
449
450 virtual
451 ~FuzzyBell2(){};
452
453 //inline
454 void set(double location = 0.0, double width = 1.0, double scale=1.0, double bias=0.0) {
455 this->location = location;
456 this->width = width;
457 this->setScale(scale, bias);
458 updateBean();
459 }
460
461
462
463 inline
464 virtual
465 double operator()(double x) const {
466 x = steepness * (x - location);
467 x = 1.0 + x*x;
468 return this->biasFinal + this->scaleFinal/(x*x); // *x*x*x*x
469
470 };
471
472
473 virtual
474 void updateBean() const override {
475 steepness = sqrt(sqrt(2.0)-1.0)/width;
476 this->INVERSE = (width<0.0);
477 this->updateScale();
478 }
479
480 double location;
481 double width;
482
483protected:
484
485 mutable
486 double steepness;
487
488
489};
490
492
496template <class T> //,class T2>
497class FuzzySigmoid : public Fuzzifier<T> {
498
499public:
500
501 FuzzySigmoid(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0) :
502 Fuzzifier<T>(__FUNCTION__, "Fuzzy sign function.", scale, bias), absWidth(0.0) {
503 this->parameters.link("location", this->location = location);
504 this->parameters.link("width", this->width = width);
505 this->parameters.link("scale", this->scale = scale);
506 this->parameters.link("bias", this->bias = bias);
507 this->updateBean();
508 };
509
510
511 FuzzySigmoid(const FuzzySigmoid & f) : Fuzzifier<T>(f), absWidth(f.absWidth) {
512 this->parameters.copyStruct(f.getParameters(), f, *this);
513 //this->setReferencesAndCopy(f);
514 //set(location, width, scale, bias);
515 this->updateBean();
516 }
517
518 ~FuzzySigmoid(){};
519
520 inline
521 void set(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0){
522 this->location = location;
523 this->width = width;
524 this->setScale(scale, bias); //
525 this->updateBean();
526 }
527
528
529 inline
530 virtual
531 double operator()(double x) const {
532 x = x - this->location;
533 if (x > 0.0)
534 return this->biasFinal + this->scaleFinal * x/(absWidth + x);
535 else if (x < 0.0)
536 return this->biasFinal + this->scaleFinal * x/(absWidth - x);
537 else // x==0.0
538 return this->biasFinal;
539 };
540
541 double location;
542 double width;
543
544protected:
545
546 inline
547 virtual
548 void updateScale() const {
549
550 this->INVERSE = (width<0.0);
551
552 if (!this->INVERSE){
553 this->scaleFinal = +this->scale;
554 this->biasFinal = this->bias;
555 this->absWidth = width;
556 }
557 else {
558 this->scaleFinal = -this->scale;
559 this->biasFinal = this->bias;
560 this->absWidth = -width;
561 }
562 }
563
564 mutable
565 double absWidth;
566
567
568};
569
571
575template <class T>
576class FuzzyStepsoid : public Fuzzifier<T> {
577
578public:
579
580 FuzzyStepsoid(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0) : Fuzzifier<T>(__FUNCTION__, "Fuzzy step function", scale, bias), widthFinal(1.0) {
581 //this->setReferences();
582 //this->parameters.link("location", this->range.tuple()); consider
583 this->parameters.link("location", this->location = location);
584 this->parameters.link("width", this->width = width);
585 this->parameters.link("scale", this->scale = scale);
586 this->parameters.link("bias", this->bias = bias);
587 this->updateBean();
588 };
589
590 FuzzyStepsoid(const FuzzyStepsoid & f): Fuzzifier<T>(f), widthFinal(f.widthFinal) {
591 this->parameters.copyStruct(f.getParameters(), f, *this);
592 this->updateBean();
593 }
594
595 ~FuzzyStepsoid(){};
596
597 inline
598 void set(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0){
599 this->location = location;
600 this->width = width;
601 this->setScale(scale, bias); //
602 this->updateBean();
603 }
604
605 virtual
606 void updateBean() const override {
607 this->INVERSE = (width<0.0);
608 this->updateScale();
609 widthFinal = fabs(width);
610 //widthFinal = this->INVERSE ? -width : width; // abs(width) FOR INT!
611 //std::cerr << this->getName() << ' ' << this->getParameters() << '\n';
612 //std::cerr << location << ',' << width << ',' << widthFinal << ',' << (int)this->INVERSE << '\n';
613 }
614
615 inline
616 virtual
617 double operator()(double x) const {
618 x = x - this->location;
619 if (x > 0.0)
620 return this->biasFinal + this->scaleFinal * x/(widthFinal + x); // was: biasFinal+ ...
621 else if (x < 0.0)
622 return this->biasFinal + this->scaleFinal * x/(widthFinal - x);
623 else // x==0.0
624 return this->biasFinal;
625 };
626
627 double location;
628 double width;
629
630protected:
631
632 inline
633 virtual
634 void updateScale() const {
635
636 //const double SCALE = (this->dstMax != 0.0) ? this->dstMax : 1.0;
637
638 if (!this->INVERSE){
639 this->scaleFinal = +0.5*this->scale; //*SCALE;
640 this->biasFinal = this->bias + 0.5*this->scale; // )*SCALE;
641 }
642 else {
643 this->scaleFinal = -0.5*this->scale; // *SCALE;
644 this->biasFinal = this->bias + 0.5*this->scale; // )*SCALE;
645 }
646
647 }
648
649 mutable
650 double widthFinal;
651
652};
653
655
659template <class T>
660class FuzzyTwinPeaks : public Fuzzifier<T> {
661
662public:
663
664 FuzzyTwinPeaks(double location=0.0, double width=1.0, double scale = 1.0, double bias = 0.0) :
665 Fuzzifier<T>(__FUNCTION__, "Fuzzy function of two peaks.", scale, bias) {
667 this->parameters.link("location", this->location = location);
668 this->parameters.link("width", this->width = width);
669 this->parameters.link("scale", this->scale = scale);
670 this->parameters.link("bias", this->bias = bias);
671 this->updateBean();
672 };
673
674 FuzzyTwinPeaks(const FuzzyTwinPeaks & f) : Fuzzifier<T>(__FUNCTION__, "Fuzzy function of two peaks.") {
675 this->parameters.copyStruct(f.getParameters(), f, *this);
676 this->updateBean();
677 }
678
679 virtual
680 ~FuzzyTwinPeaks(){};
681
682 //inline
683 void set(double location = 0.0, double width = 1.0, double scale=1.0, double bias=0.0) {
684 this->location = location;
685 this->width = width;
686 this->setScale(scale, bias);
687 updateBean();
688 }
689
690 virtual
691 void updateBean() const override {
692 this->INVERSE = (width<0.0);
693 steepness = 1.0/fabs(width);
694 this->updateScale();
695 }
696
697
698 virtual inline
699 double operator()(double x) const {
700 x = steepness * (x - location);
701 return this->biasFinal + this->scaleFinal*(x*x)/(1.0 + x*x*x*x);
702 };
703
704
705
706 double location;
707 double width;
708
709protected:
710
711
712 virtual inline
713 void updateScale() const {
714
715 if (this->width >= 0.0){
716 this->scaleFinal = +2.0*this->scale;
717 this->biasFinal = this->bias;
718 }
719 else {
720 this->scaleFinal = -2.0*this->scale;
721 this->biasFinal = this->bias;
722 }
723 }
724
725 mutable
726 double steepness;
727
728
729};
730
731
732} // drain::
733
734#endif /* FUZZY_H_*/
735
736// Drain
double scale
Relative scale, typically 1. Optional.
Definition Functor.h:99
double scaleFinal
Scaling factor after encodings of src and dst images are known.
Definition Functor.h:106
double bias
"Relative" bias, typically 0. Optional.
Definition Functor.h:102
virtual void updateBean() const override
Called after setParameters()
Definition Functor.h:65
double biasFinal
Scaling factor after encodings of src and dst images are known.
Definition Functor.h:110
A base class for fuzzy functions; also an unary functor.
Definition Fuzzy.h:55
bool INVERSE
Updates internal variables. Should be called after modifying public members.
Definition Fuzzy.h:78
A smooth symmetric peak function that resembles the Gaussian bell curve. Diminishes quicker than Fuzz...
Definition Fuzzy.h:432
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:474
A smooth symmetric peak function that resembles the Gaussian bell curve.
Definition Fuzzy.h:363
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:394
A smooth step function, by default from -1.0 to +1.0.
Definition Fuzzy.h:497
A basic, linear transition from 0 to scale between (start) and (end) .
Definition Fuzzy.h:132
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:176
FuzzyStep(T startPos=-1.0, T endPos=1.0, double scale=1.0, double bias=0.0)
Constructor.
Definition Fuzzy.h:143
A smooth step function between 0.0 and 1.0. Increasing (decreasing) with positive (negative) width....
Definition Fuzzy.h:576
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:606
A basic triangular peak function with linear around the peak.
Definition Fuzzy.h:240
double peakPos
Peak position.
Definition Fuzzy.h:331
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:292
void set(double startPos, double endPos, double peakPos=0.0, double scale=1.0, double bias=0.0)
Sets the parameters of the membership function.
Definition Fuzzy.h:274
drain::Range< double > range
Start and end position.
Definition Fuzzy.h:327
A function taking shape of two peaks, with a zero in the middle .
Definition Fuzzy.h:660
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:691
FuzzyTwinPeaks(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0)
Definition Fuzzy.h:664
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:312
Logger & debug2(const TT &... args)
Debug information.
Definition Log.h:676
Definition Range.h:52
void copyStruct(const ReferenceMap &m, const T &src, T &dst, extLinkPolicy policy=RESERVE)
Experimental. Copies references and values of a structure to another.
Definition ReferenceMap.h:399
Definition DataSelector.cpp:1277
Definition Functor.h:116