As promise in Getting Fuzzy Part 1, here is an implementation of a Fuzzy Boolean.
In the previous tutorial, we looked at what fuzzy logic is. Now we need to write a formal definition of what a fuzzy bool should do so we can create an Fbool class. This is where we have to get very precise.
We need to define a few basic things: the methods and the properties of the class. The only major data element in an Fbool is the floating point value that represents a value between 0% and 100%. This means we need a double that will be limited to values between 0.0 and 1.0. We need to overload the following operators: !, &&, and ||. The overloaded operators have to work on Fbools as well as bools. We need to be able to cast an Fbool to a bool (generate a random float between 0.0 and 1.0... below the internal float returns true, else false).
Since we are dealing with random numbers, we MUST initialize the random number generator and keep track of whether it's been initialized (so we aren't reinitializing it repeatedly). Bools will be treated as 1.0 when true, 0.0 when false. Finally, we need a way to set or get the internal float while enforcing the restriction of being between 0.0 and 1.0.
All of this is represented in the header file below:
fbool.h
Notice that I've defined almost every possible way to use each operator. I did this on purpose because, for me, an explicit statement is clearer than defining the implicit conversions along with a few operator combinations. An obvious extension is defining && and || against floats.Code:# ifndef FBOOL_DEFINED # define FBOOL_DEFINED class Fbool{ static bool randomized; double probability; public: void setval(double val); void setval(bool val); double getval() const; bool tobool() const; Fbool(double val); Fbool(bool val); Fbool(); Fbool operator&&(Fbool); Fbool operator&&(bool); Fbool operator||(Fbool); Fbool operator||(bool); Fbool operator!(); }; Fbool operator&&(bool, Fbool); Fbool operator||(bool, Fbool); # endif
The definitions are located in the file below:
fbool.cpp
An important detail when dealing with floats is that we MUST ensure that we handle values in a reasonable way. In this case, the setvalue() function must enforce keeping values within the range of 0.0 and 1.0. We also make sure that true corresponds with 1.0 and false with 0.0 so that everything remains consistent both with the previous definition and also integer conversions with booleans.Code:#include <ctime> #include <cstdlib> #include "fbool.h" bool Fbool::randomized=false; void Fbool::setval(double val) { if (val > 1.0) this->probability = 1.0; else if (val < 0.0) this-> probability = 0.0; else this->probability = val; } void Fbool::setval(bool val) { if (val) this->probability = 1.0; else this-> probability = 0.0; } double Fbool::getval() const { return this->probability; } bool Fbool::tobool() const { return double(rand())/RAND_MAX <= this->probability; } Fbool::Fbool(double val) { if (!randomized) { randomized = true; srand(time(0)); } if (val > 1.0) this->probability = 1.0; else if (val < 0.0) this-> probability = 0.0; else this->probability = val; } Fbool::Fbool(bool val) { if (!randomized) { randomized = true; srand(time(0)); } if (val) this->probability = 1.0; else this-> probability = 0.0; } Fbool::Fbool() { if (!randomized) { randomized = true; srand(time(0)); } this-> probability = 0.0; } Fbool Fbool::operator&&(Fbool var) { double temp; if (this->probability < var.probability) return Fbool(this->probability); else return Fbool(var.probability); } Fbool Fbool::operator&&(bool var) { if (var) return Fbool(this->probability); else return Fbool(false); } Fbool Fbool::operator||(Fbool var) { if (this->probability > var.probability) return Fbool(this->probability); else return Fbool(var.probability); } Fbool Fbool::operator||(bool var) { if (var) return Fbool(true); else return Fbool(this->probability); } Fbool Fbool::operator!() { return Fbool(1.0-this->probability); } Fbool operator&&(bool var1, Fbool var2) { return var2&&var1; } Fbool operator||(bool var1, Fbool var2) { return var2||var1; }
Finally, we have a quick test utility to demonstrate the behavior:
testfbool.cpp
Sample output from this is:Code:#include <iostream> #include "fbool.h" using std::cout; int main(int argc, char* argv[]) { Fbool mytestbool; cout<<"default value: "<<mytestbool.getval()<<"\n"; int i; int pass=0, count=0; for(i=1;i<=100;i++) { count++; if (mytestbool.tobool()) pass++; } cout<<pass<<" of "<<count<<" were true\n"; mytestbool.setval(true); pass=0; count=0; cout<<"true value: "<<mytestbool.getval()<<"\n"; for(i=1;i<=100;i++) { count++; if (mytestbool.tobool()) pass++; } cout<<pass<<" of "<<count<<" were true\n"; mytestbool.setval(0.75); pass=0; count=0; cout<<"0.75 value: "<<mytestbool.getval()<<"\n"; for(i=1;i<=100;i++) { count++; if (mytestbool.tobool()) pass++; } cout<<pass<<" of "<<count<<" were true\n"; mytestbool.setval(1.25); pass=0; count=0; cout<<"1.25 value: "<<mytestbool.getval()<<"\n"; for(i=1;i<=100;i++) { count++; if (mytestbool.tobool()) pass++; } cout<<pass<<" of "<<count<<" were true\n"; mytestbool.setval(0.25); pass=0; count=0; cout<<"0.25 value: "<<mytestbool.getval()<<"\n"; for(i=1;i<=100;i++) { count++; if (mytestbool.tobool()) pass++; } cout<<pass<<" of "<<count<<" were true\n"; mytestbool.setval(-1.25); pass=0; count=0; cout<<"-1.25 value: "<<mytestbool.getval()<<"\n"; for(i=1;i<=100;i++) { count++; if (mytestbool.tobool()) pass++; } cout<<pass<<" of "<<count<<" were true\n"; Fbool mytest2(0.25); mytestbool.setval(0.75); cout<<"mytestbool: "<<mytestbool.getval()<<"\n"; cout<<"mytest2: "<<mytest2.getval()<<"\n"; cout<<"mytestbool&&mytest2: "<<(mytestbool&&mytest2).getval()<<"\n"; cout<<"mytestbool||mytest2: "<<(mytestbool||mytest2).getval()<<"\n"; cout<<"mytestbool&&true: "<<(mytestbool&&true).getval()<<"\n"; cout<<"mytestbool&&false: "<<(mytestbool&&false).getval()<<"\n"; cout<<"mytestbool||true: "<<(mytestbool||true).getval()<<"\n"; cout<<"mytestbool||false: "<<(mytestbool||false).getval()<<"\n"; cout<<"!mytestbool: "<<(!mytestbool).getval()<<"\n"; cout<<"!mytest2: "<<(!mytest2).getval()<<"\n"; }
default value: 0
0 of 100 were true
true value: 1
100 of 100 were true
0.75 value: 0.75
77 of 100 were true
1.25 value: 1
100 of 100 were true
0.25 value: 0.25
23 of 100 were true
-1.25 value: 0
0 of 100 were true
mytestbool: 0.75
mytest2: 0.25
mytestbool&&mytest2: 0.25
mytestbool||mytest2: 0.75
mytestbool&&true: 0.75
mytestbool&&false: 0
mytestbool||true: 1
mytestbool||false: 0.75
!mytestbool: 0.25
!mytest2: 0.75
Now that is neat! As I was reading and looking through your class I was thinking of a way to do that using PHP. I don't think it would be hard to port. What have you used this for?
Thanks for the great read, +rep.
I haven't used it for anything at this point. It was just a nice concrete concept for showing how to create a class. It's got some interesting applications, however,
1) Using this as a simple random variable with a fixed probability of returning true
2) With the above in mind, you can use (fbool1||fbool2).tobool() to get the higher probability, or you can use fbool1.tobool() || fbool2.tobool() to get probability (1-(1-fbool1)*(1-fbool2))
3) Similarly, you can use (fbool1&&fbool2).tobool() to get the lower probability, or you can use fbool1.tobool() && fbool2.tobool() to get probability (fbool1*fbool2)
4) I will be using this as part of the Fset in part 3
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks