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
116template <class T>
117class FuzzyIdentity : public Fuzzifier<T> {
118
119public:
120
121 inline
122 FuzzyIdentity() :Fuzzifier<T>(__FUNCTION__, "Identity function") {};
123
124 virtual inline
125 ~FuzzyIdentity(){};
126
127 virtual inline
128 double operator()(double x) const {
129 return x;
130 }
131
132};
133
135
153template <class T> //,class T2>
154class FuzzyStep : public Fuzzifier<T> {
155
156public:
157
159
165 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) {
166 this->parameters.link("position", this->range.tuple());
167 this->parameters.link("scale", this->scale);
168 this->parameters.link("bias", this->bias);
169 set(startPos, endPos, scale, bias);
170 };
171
172 FuzzyStep(const FuzzyStep<T> & f) : Fuzzifier<T>(f), span(1.0){
173 this->parameters.copyStruct(f.getParameters(), f, *this);
174 updateBean();
175 }
176
177 ~FuzzyStep(){};
178
179 inline
180 void set(double rangeMin, double rangeMax, double scale=1.0, double bias=0.0){
181 this->range.min = rangeMin;
182 this->range.max = rangeMax;
183 this->setScale(scale, bias);
184 this->updateBean();
185 }
186
187 inline
188 void set(const drain::Range<double> & r, double scale=1.0, double bias=0.0){
189 this->range.set(r);
190 this->setScale(scale, bias);
191 this->updateBean();
192 }
193
194
195
196 virtual
197 inline
198 void updateBean() const override {
199
200 drain::Logger mout(__FILE__, __FUNCTION__);
201
202 this->INVERSE = (range.min > range.max);
203
204 if (!this->INVERSE){
205 rangeFinal.min = range.min;
206 rangeFinal.max = range.max;
207 span = range.max - range.min;
208 }
209 else {
210 //cerr << "set INVERSE" << endl;
211 rangeFinal.min = range.max;
212 rangeFinal.max = range.min;
213 span = range.min - range.max;
214 }
215
216 this->updateScale();
217
218 mout.debug2(this->scaleFinal , ',' , this->biasFinal );
219
220 }
221
222 inline
223 virtual
224 double operator()(double x) const {
225
226 if (x <= rangeFinal.min)
227 return this->biasFinal;
228 else if (x >= rangeFinal.max)
229 return this->biasFinal + this->scaleFinal;
230 else
231 return this->biasFinal + this->scaleFinal*(x-rangeFinal.min) / span; // div by undetectValue not possible, unless start==end
232
233 }
234
235 //std::pair<double,double> range;
237
238protected:
239
240 mutable double span;
241
242 //
243 mutable
244 drain::Range<double> rangeFinal;
245 //std::pair<double,double> rangeFinal;
246
247
248};
249
251
261template <class T> //,class T2>
262class FuzzyTriangle : public Fuzzifier<T> {
263
264public:
265
266 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)
267 this->parameters.link("position", this->range.tuple());
268 this->parameters.link("peakPos", this->peakPos);
269 this->parameters.link("scale", this->scale);
270 this->parameters.link("bias", this->bias);
271
272 set(startPos, endPos, peakPos, scale, bias);
273
274 };
275
276 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)
277 this->parameters.link("position", this->range.tuple());
278 this->parameters.link("peakPos", this->peakPos);
279 this->parameters.link("scale", this->scale);
280 this->parameters.link("bias", this->bias);
281
282 set(range.min, range.max, (range.min+range.max)/2, scale, bias);
283
284 }
285
287 this->parameters.copyStruct(f.getParameters(), f, *this);
288 updateBean();
289 }
290
291 ~FuzzyTriangle(){};
292
294 // std::numeric_limits<double>::signaling_NaN()
295 inline
296 void set(double startPos, double endPos, double peakPos=std::numeric_limits<double>::min, double scale=1.0, double bias=0.0){ // todo join
297
298 this->range.set(startPos, endPos);
299
300 this->peakPos = peakPos;
301 /*
302 if (!std::isnan(peakPos))
303 this->peakPos = peakPos;
304 else
305 this->peakPos = (startPos + endPos) / 2.0;
306 */
307
308 this->setScale(scale, bias); //
309 this->updateBean();
310 }
311
312 inline
313 void set(const drain::Range<double> & r, double peakPos=std::numeric_limits<double>::min, double scale=1.0, double bias=0.0){ // todo join
314 this->range.set(r);
315 this->peakPos = peakPos;
316 this->setScale(scale, bias); //
317 this->updateBean();
318 }
319
320
321 virtual
322 void updateBean() const override {
323
324 if (!range.contains(peakPos))
325 peakPos = (range.min + range.max) / 2.0;
326
327 this->INVERSE = (range.min > range.max);
328
329 if (!this->INVERSE){
330 span.set(range.min - peakPos, range.max - peakPos);
331 }
332 else {
333 span.set(range.max - peakPos, range.min - peakPos);
334 }
335
336 this->updateScale();
337
338 }
339
340 inline
341 virtual
342 double operator()(double x) const {
343
344 x = x - peakPos;
345 if (x > span.max)
346 return this->biasFinal;
347 else if (x > 0.0)
348 return this->biasFinal + this->scaleFinal*(1.0 - x/span.max);
349 else if (x > span.min)
350 return this->biasFinal + this->scaleFinal*(1.0 - x/span.min);
351 else // x < spanHi
352 return this->biasFinal;
353
354 };
355
358
360 mutable // adjusted if outside range
361 double peakPos = 0.0;
362
363
364protected:
365
366 mutable
367 drain::Range<double> span = {-1.0, +1.0};
368
369
370};
371
372
373
375
392template <class T>
393class FuzzyBell : public Fuzzifier<T> {
394
395public:
396
397 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) {};
398 //setReferences();
399 this->parameters.link("location", this->location = location);
400 this->parameters.link("width", this->width = width);
401 this->parameters.link("scale", this->scale = scale);
402 this->parameters.link("bias", this->bias = bias);
403 //set(location, width, scale, bias);
404 this->updateBean();
405 }
406
407 FuzzyBell(const FuzzyBell & f) : Fuzzifier<T>(f) {
408 this->parameters.copyStruct(f.getParameters(), f, *this);
409 this->updateBean();
410 }
411
412 virtual
413 ~FuzzyBell(){};
414
415 void set(double location = 0.0, double width = 1.0, double scale=1.0, double bias=0.0){
416 this->location = location;
417 this->width = width;
418 this->setScale(scale, bias);
419 this->updateBean();
420 }
421
422 // New 2025
423 void set(const UniTuple<double,2> & range, double scale=1.0, double bias=0.0){
424 this->location = 0.5 * (range[0] + range[1]);
425 this->width = (range[1] - range[0]);
426 this->setScale(scale, bias);
427 this->updateBean();
428 }
429
430
431 virtual
432 void updateBean() const override {
433 this->widthInv = 1.0/width;
434 this->INVERSE = (width<0.0);
435 this->updateScale();
436 }
437
438 inline
439 virtual
440 double operator()(double x) const {
441
442 x = widthInv * (x - this->location);
443 return this->biasFinal + this->scaleFinal/(1.0 + x*x);
444
445 };
446
447 double location = 0.0;
448 double width = 1.0;
449
450protected:
451
452 //double scale;
453 mutable
454 double widthInv = 1.0;
455
456
457};
458
460
469template <class T>
470class FuzzyBell2 : public Fuzzifier<T> {
471
472public:
473
474 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) {
475 //setReferences();
476 this->parameters.link("location", this->location = location);
477 this->parameters.link("width", this->width = width);
478 this->parameters.link("scale", this->scale = scale);
479 this->parameters.link("bias", this->bias = bias);
480 updateBean();
481 };
482
483 FuzzyBell2(const FuzzyBell2 & f) : Fuzzifier<T>(f) {
484 this->parameters.copyStruct(f.getParameters(), f, *this);
485 updateBean();
486 }
487
488 virtual
489 ~FuzzyBell2(){};
490
491 //inline
492 void set(double location = 0.0, double width = 1.0, double scale=1.0, double bias=0.0) {
493 this->location = location;
494 this->width = width;
495 this->setScale(scale, bias);
496 updateBean();
497 }
498
500 // New 2025
501 void set(const UniTuple<double,2> & range, double scale=1.0, double bias=0.0){
502 this->location = 0.5 * (range[0] + range[1]);
503 this->width = (range[1] - range[0]);
504 this->setScale(scale, bias);
505 this->updateBean();
506 }
507
508
509 virtual inline
510 double operator()(double x) const {
511 x = steepness * (x - location);
512 x = 1.0 + x*x;
513 return this->biasFinal + this->scaleFinal/(x*x); // *x*x*x*x
514 };
515
516
517 virtual
518 void updateBean() const override {
519 steepness = sqrt(sqrt(2.0)-1.0)/width;
520 this->INVERSE = (width<0.0);
521 this->updateScale();
522 }
523
524 double location = 0.0;
525 double width = 1.0;
526
527protected:
528
529 mutable
530 double steepness = 1.0;
531
532
533};
534
536
540template <class T> //,class T2>
541class FuzzySigmoid : public Fuzzifier<T> {
542
543public:
544
545 FuzzySigmoid(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0) :
546 Fuzzifier<T>(__FUNCTION__, "Fuzzy sign function.", scale, bias), absWidth(0.0) {
547 this->parameters.link("location", this->location = location);
548 this->parameters.link("width", this->width = width);
549 this->parameters.link("scale", this->scale = scale);
550 this->parameters.link("bias", this->bias = bias);
551 this->updateBean();
552 };
553
554
555 FuzzySigmoid(const FuzzySigmoid & f) : Fuzzifier<T>(f), absWidth(f.absWidth) {
556 this->parameters.copyStruct(f.getParameters(), f, *this);
557 //this->setReferencesAndCopy(f);
558 //set(location, width, scale, bias);
559 this->updateBean();
560 }
561
562 ~FuzzySigmoid(){};
563
564 inline
565 void set(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0){
566 this->location = location;
567 this->width = width;
568 this->setScale(scale, bias); //
569 this->updateBean();
570 }
571
572
573 inline
574 virtual
575 double operator()(double x) const {
576 x = x - this->location;
577 if (x > 0.0)
578 return this->biasFinal + this->scaleFinal * x/(absWidth + x);
579 else if (x < 0.0)
580 return this->biasFinal + this->scaleFinal * x/(absWidth - x);
581 else // x==0.0
582 return this->biasFinal;
583 };
584
585 double location = 0.0;
586 double width = 1.0;
587
588protected:
589
590 inline
591 virtual
592 void updateScale() const {
593
594 this->INVERSE = (width<0.0);
595
596 if (!this->INVERSE){
597 this->scaleFinal = +this->scale;
598 this->biasFinal = this->bias;
599 this->absWidth = width;
600 }
601 else {
602 this->scaleFinal = -this->scale;
603 this->biasFinal = this->bias;
604 this->absWidth = -width;
605 }
606 }
607
608 mutable
609 double absWidth;
610
611
612};
613
615
619template <class T>
620class FuzzyStepsoid : public Fuzzifier<T> {
621
622public:
623
624 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) {
625 //this->setReferences();
626 //this->parameters.link("location", this->range.tuple()); consider
627 this->parameters.link("location", this->location = location);
628 this->parameters.link("width", this->width = width);
629 this->parameters.link("scale", this->scale = scale);
630 this->parameters.link("bias", this->bias = bias);
631 this->updateBean();
632 };
633
634 FuzzyStepsoid(const FuzzyStepsoid & f): Fuzzifier<T>(f), widthFinal(f.widthFinal) {
635 this->parameters.copyStruct(f.getParameters(), f, *this);
636 this->updateBean();
637 }
638
639 ~FuzzyStepsoid(){};
640
641 inline
642 void set(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0){
643 this->location = location;
644 this->width = width;
645 this->setScale(scale, bias); //
646 this->updateBean();
647 }
648
649 virtual
650 void updateBean() const override {
651 this->INVERSE = (width<0.0);
652 this->updateScale();
653 widthFinal = fabs(width);
654 //widthFinal = this->INVERSE ? -width : width; // abs(width) FOR INT!
655 //std::cerr << this->getName() << ' ' << this->getParameters() << '\n';
656 //std::cerr << location << ',' << width << ',' << widthFinal << ',' << (int)this->INVERSE << '\n';
657 }
658
659 virtual
660 double operator()(double x) const {
661 x = x - this->location;
662 if (x > 0.0)
663 return this->biasFinal + this->scaleFinal * x/(widthFinal + x); // was: biasFinal+ ...
664 else if (x < 0.0)
665 return this->biasFinal + this->scaleFinal * x/(widthFinal - x);
666 else // x==0.0
667 return this->biasFinal;
668 };
669
670 double location = 0.0;
671 double width = 1.0;
672
673protected:
674
675 inline
676 virtual
677 void updateScale() const {
678
679 //const double SCALE = (this->dstMax != 0.0) ? this->dstMax : 1.0;
680
681 if (!this->INVERSE){
682 this->scaleFinal = +0.5*this->scale; //*SCALE;
683 this->biasFinal = this->bias + 0.5*this->scale; // )*SCALE;
684 }
685 else {
686 this->scaleFinal = -0.5*this->scale; // *SCALE;
687 this->biasFinal = this->bias + 0.5*this->scale; // )*SCALE;
688 }
689
690 }
691
692 mutable
693 double widthFinal;
694
695};
696
698
702template <class T>
703class FuzzyTwinPeaks : public Fuzzifier<T> {
704
705public:
706
707 FuzzyTwinPeaks(double location=0.0, double width=1.0, double scale = 1.0, double bias = 0.0) :
708 Fuzzifier<T>(__FUNCTION__, "Fuzzy function of two peaks.", scale, bias) {
710 this->parameters.link("location", this->location = location);
711 this->parameters.link("width", this->width = width);
712 this->parameters.link("scale", this->scale = scale);
713 this->parameters.link("bias", this->bias = bias);
714 this->updateBean();
715 };
716
717 FuzzyTwinPeaks(const FuzzyTwinPeaks & f) : Fuzzifier<T>(__FUNCTION__, "Fuzzy function of two peaks.") {
718 this->parameters.copyStruct(f.getParameters(), f, *this);
719 this->updateBean();
720 }
721
722 virtual
723 ~FuzzyTwinPeaks(){};
724
725 //inline
726 void set(double location = 0.0, double width = 1.0, double scale=1.0, double bias=0.0) {
727 this->location = location;
728 this->width = width;
729 this->setScale(scale, bias);
730 updateBean();
731 }
732
733 virtual
734 void updateBean() const override {
735 this->INVERSE = (width<0.0);
736 steepness = 1.0/fabs(width);
737 this->updateScale();
738 }
739
740
741 virtual inline
742 double operator()(double x) const {
743 x = steepness * (x - location);
744 return this->biasFinal + this->scaleFinal*(x*x)/(1.0 + x*x*x*x);
745 };
746
747
748
749 double location = 0.0;
750 double width = 1.0;
751
752protected:
753
754
755 virtual inline
756 void updateScale() const {
757
758 if (this->width >= 0.0){
759 this->scaleFinal = +2.0*this->scale;
760 this->biasFinal = this->bias;
761 }
762 else {
763 this->scaleFinal = -2.0*this->scale;
764 this->biasFinal = this->bias;
765 }
766 }
767
768 mutable
769 double steepness = 1.0;
770
771
772};
773
774
775} // drain::
776
777#endif /* FUZZY_H_*/
778
779// 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:470
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:518
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:501
A smooth symmetric peak function that resembles the Gaussian bell curve.
Definition Fuzzy.h:393
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:432
Identity function - returns the input value.
Definition Fuzzy.h:117
A smooth step function, by default from -1.0 to +1.0.
Definition Fuzzy.h:541
A basic, linear transition from 0 to scale between (start) and (end) .
Definition Fuzzy.h:154
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:198
FuzzyStep(T startPos=-1.0, T endPos=1.0, double scale=1.0, double bias=0.0)
Constructor.
Definition Fuzzy.h:165
A smooth step function between 0.0 and 1.0. Increasing (decreasing) with positive (negative) width....
Definition Fuzzy.h:620
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:650
A basic triangular peak function with linear around the peak.
Definition Fuzzy.h:262
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:296
double peakPos
Peak position.
Definition Fuzzy.h:361
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:322
drain::Range< double > range
Start and end position.
Definition Fuzzy.h:357
A function taking shape of two peaks, with a zero in the middle .
Definition Fuzzy.h:703
virtual void updateBean() const override
Called after setParameters()
Definition Fuzzy.h:734
FuzzyTwinPeaks(double location=0.0, double width=1.0, double scale=1.0, double bias=0.0)
Definition Fuzzy.h:707
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