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
60template <class T> //,class T2>
61class Fuzzifier : public UnaryFunctor
62{
63public:
64
65 inline
66 Fuzzifier(const std::string & name, const std::string & description="", double scale=1.0, double bias=0.0) : UnaryFunctor(name, description, scale, bias),
67 INVERSE(false) {}; // srcMax(1.0),
68
69 // Auto ok
70 // Fuzzifier(const Fuzzifier<T> & op) : UnaryFunctor(op), INVERSE(op.INVERSE){}
71
72 virtual
73 inline
74 ~Fuzzifier(){};
75
77 /*
78 virtual inline
79 void updateBean() const override {
80 updateScale();
81 }
82 */
83
84 inline
85 bool isInversed(){
86 return INVERSE;
87 }
88
89protected:
90
91 mutable
92 bool INVERSE;
93
94 inline virtual
95 void updateScale() const {
96
97 if (!INVERSE){
98 this->scaleFinal = ::abs(scale);
99 this->biasFinal = bias;
100 }
101 else {
102 this->scaleFinal = - ::abs(scale);
103 this->biasFinal = bias + ::abs(scale);
104 }
105 }
106
107 /*
108 inline
109 void setReferencesAndCopy(const BeanLike & b){
110 setReferences();
111 this->copy(b);
112 this->updateBean();
113 };
114 */
115
116private:
117
118 //virtual
119 //void setReferences() = 0;
120
121};
122
124
127template <class T>
128class FuzzyIdentity : public Fuzzifier<T> {
129
130public:
131
132 inline
133 FuzzyIdentity() :Fuzzifier<T>(__FUNCTION__, "Identity function") {};
134
135 virtual inline
136 ~FuzzyIdentity(){};
137
138 virtual inline
139 double operator()(double x) const {
140 return x;
141 }
142
143};
144
146
169template <class T> //,class T2>
170class FuzzyStep : public Fuzzifier<T> {
171
172public:
173
175
181 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) {
182 this->parameters.link("position", this->range.tuple());
183 this->parameters.link("scale", this->scale);
184 this->parameters.link("bias", this->bias);
185 set(startPos, endPos, scale, bias);
186 };
187
188 FuzzyStep(const FuzzyStep<T> & f) : Fuzzifier<T>(f), span(1.0){
189 this->parameters.copyStruct(f.getParameters(), f, *this);
190 updateBean();
191 }
192
193 ~FuzzyStep(){};
194
195 inline
196 void set(double rangeMin, double rangeMax, double scale=1.0, double bias=0.0){
197 this->range.set(rangeMin, rangeMax);
198 this->setScale(scale, bias);
199 this->updateBean();
200 }
201
202 inline
203 void set(const drain::Range<double> & r, double scale=1.0, double bias=0.0){
204 this->range.set(r);
205 this->setScale(scale, bias);
206 this->updateBean();
207 }
208
209
210
211 virtual inline
212 void updateBean() const override {
213
214 drain::Logger mout(__FILE__, __FUNCTION__);
215
216 this->INVERSE = (range.min > range.max);
217
218 if (!this->INVERSE){
219 rangeFinal.min = range.min;
220 rangeFinal.max = range.max;
221 span = range.max - range.min;
222 }
223 else {
224 //cerr << "set INVERSE" << endl;
225 rangeFinal.min = range.max;
226 rangeFinal.max = range.min;
227 span = range.min - range.max;
228 }
229
230 this->updateScale();
231
232 mout.debug2(this->scaleFinal , ',' , this->biasFinal );
233
234 }
235
236 inline
237 virtual
238 double operator()(double x) const {
239
240 if (x <= rangeFinal.min)
241 return this->biasFinal;
242 else if (x >= rangeFinal.max)
243 return this->biasFinal + this->scaleFinal;
244 else {
245 // TODO: integrate span in scaleFinal?
246 return this->biasFinal + this->scaleFinal*(x-rangeFinal.min) / span; // div by span not possible
247 }
248
249 }
250
252
253protected:
254
255 mutable double span;
256
257 mutable
258 drain::Range<double> rangeFinal;
259
260};
261
263
278template <class T> //,class T2>
279class FuzzyTriangle : public Fuzzifier<T> {
280
281public:
282
283 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)
284 this->parameters.link("position", this->range.tuple());
285 this->parameters.link("peakPos", this->peakPos);
286 this->parameters.link("scale", this->scale);
287 this->parameters.link("bias", this->bias);
288
289 set(startPos, endPos, peakPos, scale, bias);
290
291 };
292
293 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)
294 this->parameters.link("position", this->range.tuple());
295 this->parameters.link("peakPos", this->peakPos);
296 this->parameters.link("scale", this->scale);
297 this->parameters.link("bias", this->bias);
298
299 set(range.min, range.max, (range.min+range.max)/2, scale, bias);
300
301 }
302
304 this->parameters.copyStruct(f.getParameters(), f, *this);
305 updateBean();
306 }
307
308 ~FuzzyTriangle(){};
309
311 // std::numeric_limits<double>::signaling_NaN()
312 inline
313 void set(double startPos, double endPos, double peakPos=std::numeric_limits<double>::min, double scale=1.0, double bias=0.0){ // todo join
314
315 this->range.set(startPos, endPos);
316
317 this->peakPos = peakPos;
318 /*
319 if (!std::isnan(peakPos))
320 this->peakPos = peakPos;
321 else
322 this->peakPos = (startPos + endPos) / 2.0;
323 */
324
325 this->setScale(scale, bias); //
326 this->updateBean();
327 }
328
329 inline
330 void set(const drain::Range<double> & r, double peakPos=std::numeric_limits<double>::min, double scale=1.0, double bias=0.0){ // todo join
331 this->range.set(r);
332 this->peakPos = peakPos;
333 this->setScale(scale, bias); //
334 this->updateBean();
335 }
336
337
338 virtual
339 void updateBean() const override {
340
341 if (!range.contains(peakPos))
342 peakPos = (range.min + range.max) / 2.0;
343
344 this->INVERSE = (range.min > range.max);
345
346 if (!this->INVERSE){
347 span.set(range.min - peakPos, range.max - peakPos);
348 }
349 else {
350 span.set(range.max - peakPos, range.min - peakPos);
351 }
352
353 this->updateScale();
354
355 }
356
357 inline
358 virtual
359 double operator()(double x) const {
360
361 x = x - peakPos;
362 if (x > span.max)
363 return this->biasFinal;
364 else if (x > 0.0)
365 return this->biasFinal + this->scaleFinal*(1.0 - x/span.max);
366 else if (x > span.min)
367 return this->biasFinal + this->scaleFinal*(1.0 - x/span.min);
368 else // x < spanHi
369 return this->biasFinal;
370
371 };
372
375
377 mutable // adjusted if outside range
378 double peakPos = 0.0;
379
380
381protected:
382
383 mutable
384 drain::Range<double> span = {-1.0, +1.0};
385
386
387};
388
389
390
392
413template <class T>
414class FuzzyBell : public Fuzzifier<T> {
415
416public:
417
418 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) {};
419 //setReferences();
420 this->parameters.link("location", this->location = location);
421 this->parameters.link("width", this->width = width);
422 this->parameters.link("scale", this->scale = scale);
423 this->parameters.link("bias", this->bias = bias);
424 //set(location, width, scale, bias);
425 this->updateBean();
426 }
427
428 FuzzyBell(const FuzzyBell & f) : Fuzzifier<T>(f) {
429 this->parameters.copyStruct(f.getParameters(), f, *this);
430 this->updateBean();
431 }
432
433 virtual
434 ~FuzzyBell(){};
435
436 void set(double location = 0.0, double width = 1.0, double scale=1.0, double bias=0.0){
437 this->location = location;
438 this->width = width;
439 this->setScale(scale, bias);
440 this->updateBean();
441 }
442
443 // New 2025
444 void set(const UniTuple<double,2> & range, double scale=1.0, double bias=0.0){
445 this->location = 0.5 * (range[0] + range[1]);
446 this->width = (range[1] - range[0]);
447 this->setScale(scale, bias);
448 this->updateBean();
449 }
450
451
452 virtual
453 void updateBean() const override {
454 this->widthInv = 1.0/width;
455 this->INVERSE = (width<0.0);
456 this->updateScale();
457 }
458
459 virtual inline
460 double operator()(double x) const {
461
462 x = widthInv * (x - this->location);
463 return this->biasFinal + this->scaleFinal/(1.0 + x*x);
464
465 };
466
467 double location = 0.0;
468 double width = 1.0;
469
470protected:
471
472 //double scale;
473 mutable
474 double widthInv = 1.0;
475
476
477};
478
480
494template <class T>
495class FuzzyBell2 : public Fuzzifier<T> {
496
497public:
498
499 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) {
500 //setReferences();
501 this->parameters.link("location", this->location = location);
502 this->parameters.link("width", this->width = width);
503 this->parameters.link("scale", this->scale = scale);
504 this->parameters.link("bias", this->bias = bias);
505 updateBean();
506 };
507
508 FuzzyBell2(const FuzzyBell2 & f) : Fuzzifier<T>(f) {
509 this->parameters.copyStruct(f.getParameters(), f, *this);
510 updateBean();
511 }
512
513 virtual
514 ~FuzzyBell2(){};
515
516 //inline
517 void set(double location = 0.0, double width = 1.0, double scale=1.0, double bias=0.0) {
518 this->location = location;
519 this->width = width;
520 this->setScale(scale, bias);
521 updateBean();
522 }
523
525 // New 2025
526 void set(const UniTuple<double,2> & range, double scale=1.0, double bias=0.0){
527 this->location = 0.5 * (range[0] + range[1]);
528 this->width = (range[1] - range[0]);
529 this->setScale(scale, bias);
530 this->updateBean();
531 }
532
533
534 virtual inline
535 double operator()(double x) const {
536 x = steepness * (x - location);
537 x = 1.0 + x*x;
538 return this->biasFinal + this->scaleFinal/(x*x); // *x*x*x*x
539 };
540
541
542 virtual
543 void updateBean() const override {
544 steepness = sqrt(sqrt(2.0)-1.0)/width;
545 this->INVERSE = (width<0.0);
546 this->updateScale();
547 }
548
549 double location = 0.0;
550 double width = 1.0;
551
552protected:
553
554 mutable
555 double steepness = 1.0;
556
557
558};
559
561
570template <class T> //,class T2>
571class FuzzySigmoid : public Fuzzifier<T> {
572
573public:
574
575 FuzzySigmoid(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0) :
576 Fuzzifier<T>(__FUNCTION__, "Fuzzy sign function.", scale, bias), absWidth(0.0) {
577 this->parameters.link("location", this->location = location);
578 this->parameters.link("width", this->width = width);
579 this->parameters.link("scale", this->scale = scale);
580 this->parameters.link("bias", this->bias = bias);
581 this->updateBean();
582 };
583
584
585 FuzzySigmoid(const FuzzySigmoid & f) : Fuzzifier<T>(f), absWidth(f.absWidth) {
586 this->parameters.copyStruct(f.getParameters(), f, *this);
587 //this->setReferencesAndCopy(f);
588 //set(location, width, scale, bias);
589 this->updateBean();
590 }
591
592 ~FuzzySigmoid(){};
593
594 inline
595 void set(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0){
596 this->location = location;
597 this->width = width;
598 this->setScale(scale, bias); //
599 this->updateBean();
600 }
601
602
603 inline
604 virtual
605 double operator()(double x) const {
606 x = x - this->location;
607 if (x > 0.0)
608 return this->biasFinal + this->scaleFinal * x/(absWidth + x);
609 else if (x < 0.0)
610 return this->biasFinal + this->scaleFinal * x/(absWidth - x);
611 else // x==0.0
612 return this->biasFinal;
613 };
614
615 double location = 0.0;
616 double width = 1.0;
617
618protected:
619
620 inline
621 virtual
622 void updateScale() const {
623
624 this->INVERSE = (width<0.0);
625
626 if (!this->INVERSE){
627 this->scaleFinal = +this->scale;
628 this->biasFinal = this->bias;
629 this->absWidth = width;
630 }
631 else {
632 this->scaleFinal = -this->scale;
633 this->biasFinal = this->bias;
634 this->absWidth = -width;
635 }
636 }
637
638 mutable
639 double absWidth;
640
641
642};
643
645
653template <class T>
654class FuzzyStepsoid : public Fuzzifier<T> {
655
656public:
657
658 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) {
659 //this->setReferences();
660 //this->parameters.link("location", this->range.tuple()); consider
661 this->parameters.link("location", this->location = location);
662 this->parameters.link("width", this->width = width);
663 this->parameters.link("scale", this->scale = scale);
664 this->parameters.link("bias", this->bias = bias);
665 this->updateBean();
666 };
667
668 FuzzyStepsoid(const FuzzyStepsoid & f): Fuzzifier<T>(f), widthFinal(f.widthFinal) {
669 this->parameters.copyStruct(f.getParameters(), f, *this);
670 this->updateBean();
671 }
672
673 ~FuzzyStepsoid(){};
674
675 inline
676 void set(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0){
677 this->location = location;
678 this->width = width;
679 this->setScale(scale, bias); //
680 this->updateBean();
681 }
682
683 virtual
684 void updateBean() const override {
685 this->INVERSE = (width<0.0);
686 this->updateScale();
687 widthFinal = fabs(width);
688 //widthFinal = this->INVERSE ? -width : width; // abs(width) FOR INT!
689 //std::cerr << this->getName() << ' ' << this->getParameters() << '\n';
690 //std::cerr << location << ',' << width << ',' << widthFinal << ',' << (int)this->INVERSE << '\n';
691 }
692
693 virtual
694 double operator()(double x) const {
695 x = x - this->location;
696 if (x > 0.0)
697 return this->biasFinal + this->scaleFinal * x/(widthFinal + x); // was: biasFinal+ ...
698 else if (x < 0.0)
699 return this->biasFinal + this->scaleFinal * x/(widthFinal - x);
700 else // x==0.0
701 return this->biasFinal;
702 };
703
704 double location = 0.0;
705 double width = 1.0;
706
707protected:
708
709 inline
710 virtual
711 void updateScale() const {
712
713 //const double SCALE = (this->dstMax != 0.0) ? this->dstMax : 1.0;
714
715 if (!this->INVERSE){
716 this->scaleFinal = +0.5*this->scale; //*SCALE;
717 this->biasFinal = this->bias + 0.5*this->scale; // )*SCALE;
718 }
719 else {
720 this->scaleFinal = -0.5*this->scale; // *SCALE;
721 this->biasFinal = this->bias + 0.5*this->scale; // )*SCALE;
722 }
723
724 }
725
726 mutable
727 double widthFinal;
728
729};
730
732
739template <class T>
740class FuzzyTwinPeaks : public Fuzzifier<T> {
741
742public:
743
744 FuzzyTwinPeaks(double location=0.0, double width=1.0, double scale = 1.0, double bias = 0.0) :
745 Fuzzifier<T>(__FUNCTION__, "Fuzzy function of two peaks.", scale, bias) {
747 this->parameters.link("location", this->location = location);
748 this->parameters.link("width", this->width = width);
749 this->parameters.link("scale", this->scale = scale);
750 this->parameters.link("bias", this->bias = bias);
751 this->updateBean();
752 };
753
754 FuzzyTwinPeaks(const FuzzyTwinPeaks & f) : Fuzzifier<T>(__FUNCTION__, "Fuzzy function of two peaks.") {
755 this->parameters.copyStruct(f.getParameters(), f, *this);
756 this->updateBean();
757 }
758
759 virtual
760 ~FuzzyTwinPeaks(){};
761
762 //inline
763 void set(double location = 0.0, double width = 1.0, double scale=1.0, double bias=0.0) {
764 this->location = location;
765 this->width = width;
766 this->setScale(scale, bias);
767 updateBean();
768 }
769
770 virtual
771 void updateBean() const override {
772 this->INVERSE = (width<0.0);
773 steepness = 1.0/fabs(width);
774 this->updateScale();
775 }
776
777
778 virtual inline
779 double operator()(double x) const {
780 x = steepness * (x - location);
781 return this->biasFinal + this->scaleFinal*(x*x)/(1.0 + x*x*x*x);
782 };
783
784
785
786 double location = 0.0;
787 double width = 1.0;
788
789protected:
790
791
792 virtual inline
793 void updateScale() const {
794
795 if (this->width >= 0.0){
796 this->scaleFinal = +2.0*this->scale;
797 this->biasFinal = this->bias;
798 }
799 else {
800 this->scaleFinal = -2.0*this->scale;
801 this->biasFinal = this->bias;
802 }
803 }
804
805 mutable
806 double steepness = 1.0;
807
808
809};
810
811
812} // drain::
813
814#endif /* FUZZY_H_*/
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:62
bool isInversed()
Updates internal variables. Should be called after modifying public members.
Definition Fuzzy.h:85
A smooth symmetric peak function that resembles the Gaussian bell curve. Diminishes quicker than Fuzz...
Definition Fuzzy.h:495
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:543
void set(const UniTuple< double, 2 > &range, double scale=1.0, double bias=0.0)
Set peak to a given half-width range.
Definition Fuzzy.h:526
A smooth symmetric peak function that resembles the Gaussian bell curve.
Definition Fuzzy.h:414
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:453
Identity function - returns the input value.
Definition Fuzzy.h:128
A smooth step function, by default from -1.0 to +1.0.
Definition Fuzzy.h:571
A simple linear transition from 0 to 1 .
Definition Fuzzy.h:170
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:212
FuzzyStep(T startPos=-1.0, T endPos=1.0, double scale=1.0, double bias=0.0)
Constructor.
Definition Fuzzy.h:181
A smooth step function between 0.0 and 1.0. Increasing (decreasing) with positive (negative) width....
Definition Fuzzy.h:654
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:684
A basic triangular peak function with linear around the peak.
Definition Fuzzy.h:279
void set(double startPos, double endPos, double peakPos=std::numeric_limits< double >::min, double scale=1.0, double bias=0.0)
Sets the parameters of the membership function.
Definition Fuzzy.h:313
double peakPos
Peak position.
Definition Fuzzy.h:378
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:339
drain::Range< double > range
Start and end position.
Definition Fuzzy.h:374
A function taking shape of two peaks, with a zero in the middle .
Definition Fuzzy.h:740
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:771
FuzzyTwinPeaks(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0)
Definition Fuzzy.h:744
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:407
Tuple of N elements of type T.
Definition UniTuple.h:65
Definition DataSelector.cpp:1277
Definition Functor.h:116