Jump to content

Implementing a Fuzzy Set

- - - - -

  • Please log in to reply
11 replies to this topic

#1
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
  • Location:Upstate, South Carolina
  • Programming Language:C, C++, PL/SQL, Delphi/Object Pascal, Pascal, Transact-SQL, Others
  • Learning:Java, C#, PHP, JavaScript, Lisp, Fortran, Haskell, Others
Before reading this tutorial, be sure to read http://forum.codecal...y-part-1-a.html and http://forum.codecal...zy-boolean.html.

Now we're going to look at fuzzy sets. The key characteristic of this is that every item of interest contains two values: the quantity of interest, and the probability that it is in the set. We can represent that probability using an Fbool. It has some nice properties that relate to the new functionality of the Fset. The real question is: how do we connect it with the quantity of interest?

The “obvious” choice is to use a set<T>. The problem is a set doesn't really deal with pairs of values. We could use a struct to define that quantity/probability pairing, but since a set<T> doesn't really provide any additional functionality that we explicitly care about. We don't want to use a vector<T> either, since we need to be able to access the probability directly through the quantity of interest. The container we really need is the map<T,X>. Since we might be interested in a variety of different quantities, our final Fset will actually be a template. Fset<T> will use map<T,Fbool> to contain its data. However, to get everything working we'll use Fset with map<string,Fbool>.

We'll want to be aware of the following features of a map as we move forward:
maps have the following methods/operations: size(), empty(), max_size(), ==, !=, <, >, <=, >=, find(key), lower_bound(key), upper_bound(key), equal_range(key), =, swap(), begin(), end(), rbegin(), rend(), insert(), erase(), clear(), and [].

We're going to define an insert, size, empty, erase, clear, &&, ||, !, and [] based on the definition of a Fuzzy Set presented in the first tutorial. With all this in mind, let's look at fset.h:
#ifndef FSET_DEFINED
#define FSET_DEFINED

#include "fbool.h"
#include <map>
#include <string>

class Fset
{
  std::map<std::string,Fbool> setdata;
public:
  void insert(const std::string,double);
  void insert(const std::string,bool);
  int size();
  bool empty();
  void erase(std::string);
  void clear();
  Fset operator&&(Fset);
  Fset operator||(Fset);
  Fset operator!();
  Fbool& operator[](std::string);
};
#endif

The actual definitions of the functions are located in fset.cpp:

fset.cpp
#include "fbool.h"
#include "fset.h"
#include <string>

void Fset::insert(const std::string key, double prob)
{
  Fset::setdata.insert(std::pair<std::string,Fbool>(key,prob));
}

void Fset::insert(const std::string key, bool prob)
{
  Fset::setdata.insert(std::pair<std::string,Fbool>(key,prob));
}

int Fset::size()
{
  return Fset::setdata.size();
}

bool Fset::empty()
{
  return Fset::setdata.empty();
}

void Fset::erase(std::string key)
{
  Fset::setdata.erase(key);
}

void Fset::clear()
{
  Fset::setdata.clear();
}

Fset Fset::operator&&(Fset operand)
{
  Fset temp;
  Fbool temp2;
  std::map<std::string,Fbool>::iterator pos1;
  std::map<std::string,Fbool>::iterator pos2;
  for (pos1 = this->setdata.begin(), pos2 = operand.setdata.begin(); pos1 != this->setdata.end() && pos2 != operand.setdata.end();)
  {
    if (pos1->first < pos2->first)
    {
      temp2.setval(false);
      temp.insert(pos1->first,temp2.getval());
      ++pos1;
    }
    else if (pos1->first > pos2->first)
    {
      temp2.setval(false);
      temp.insert(pos2->first,temp2.getval());
      ++pos2;
    }
    else
    {
      temp.insert(pos2->first,((pos1->second)&&(pos2->second)).getval());
      ++pos1;
      ++pos2;
    }
  }
  return temp;
}

Fset Fset::operator||(Fset operand)
{
  Fset temp;
  std::map<std::string,Fbool>::iterator pos1;
  std::map<std::string,Fbool>::iterator pos2;
  for (pos1 = this->setdata.begin(), pos2 = operand.setdata.begin(); pos1 != this->setdata.end() && pos2 != operand.setdata.end();)
  {
    if (pos1->first < pos2->first)
    {
      temp.insert(pos1->first,(pos1->second).getval());
      ++pos1;
    }
    else if (pos1->first > pos2->first)
    {
      temp.insert(pos2->first,(pos2->second).getval());
      ++pos2;
    }
    else
    {
      temp.insert(pos2->first,((pos1->second)||(pos2->second)).getval());
      ++pos1;
      ++pos2;
    }
  }
  return temp;
}

Fset Fset::operator!()
{
  Fset temp;
  std::map<std::string,Fbool>::iterator pos1;
  for (pos1 = this->setdata.begin(); pos1 != this->setdata.end();++pos1)
  {
    temp.insert(pos1->first,(!(pos1->second)).getval());
  }
  return temp;
}

Fbool& Fset::operator[](std::string key)
{
  return Fset::setdata[key];
}

The operators && and || deserve some comment. In order to make sure we cover all the elements, we'll move through both fuzzy sets element by element, adding the appropriate pair. We are taking advantage of the fact that maps store the keys in order by <, so we can meaningfully compare the keys as we step through them with the iterators.

A simple test program is listed below:

testfset.cpp
#include "fset.h"
#include <iostream>
#include <string>
using std::string;
using std::cout;

int main(int argc,char* argv[])
{
  Fset mytestset;
  cout<<"mytestset.empty = "<<mytestset.empty()<<"\n";
  cout<<"mytestset.count = "<<mytestset.size()<<"\n";
  mytestset.insert("false",false);
  mytestset.insert("true",true);
  mytestset.insert("third",0.33);
  mytestset.insert("half",0.5);
  cout<<"mytestset.empty = "<<mytestset.empty()<<"\n";
  cout<<"mytestset.count = "<<mytestset.size()<<"\n";

  Fset mytest2;
  mytest2.insert("false",true);
  mytest2.insert("true",false);
  mytest2.insert("quarter",0.25);
  mytest2.insert("half",0.5);
  cout<<"mytest2.empty = "<<mytest2.empty()<<"\n";
  cout<<"mytest2.count = "<<mytest2.size()<<"\n";

  Fset andset = mytest2&&mytestset;
  Fset orset = mytest2||mytestset;
  Fset notset = !mytestset;

  cout<<"andset[\"false\"] = "<<andset["false"].getval()<<"\n";
  cout<<"orset[\"false\"] = "<<orset["false"].getval()<<"\n";
  cout<<"notset[\"false\"] = "<<notset["false"].getval()<<"\n";
  return 0;
}

This program will produce the following output:
mytestset.empty = 1
mytestset.count = 0
mytestset.empty = 0
mytestset.count = 4
mytest2.empty = 0
mytest2.count = 4
andset["false"] = 0
orset["false"] = 1
notset["false"] = 1

Edited by WingedPanther, 20 November 2008 - 02:11 AM.
correct includes based on file name changes between this post and my hard drive

Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#2
Guest_Jordan_*

Guest_Jordan_*
  • Guests
Very cool! Thanks for the excellent read, again! +rep

#3
John

John

    Writes binary right handed and hex left handed

  • Moderators
  • 6,321 posts
  • Location:New York, NY
The code shows Fset andset = mytest2&&mytestset;, I am guessing that second & should be & and for some reason got converted to its html entity?

#4
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
  • Location:Upstate, South Carolina
  • Programming Language:C, C++, PL/SQL, Delphi/Object Pascal, Pascal, Transact-SQL, Others
  • Learning:Java, C#, PHP, JavaScript, Lisp, Fortran, Haskell, Others
You're right John. I'm not sure why that happened.
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#5
Hamed

Hamed

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
Where we can use Fuzzy set or Fuzzy logic in our programming?

#6
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
  • Location:Upstate, South Carolina
  • Programming Language:C, C++, PL/SQL, Delphi/Object Pascal, Pascal, Transact-SQL, Others
  • Learning:Java, C#, PHP, JavaScript, Lisp, Fortran, Haskell, Others
It's used in AI, or anywhere that a truth value is probabilistic rather than deterministic.
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#7
Occulta

Occulta

    Newbie

  • Members
  • Pip
  • 3 posts
I have registered only to ask you this (:
Fuzzy set is a set. Then why don't you use std::set to inherit from? Something like this:

#include <set>

#include <utility>


class FuzzySet: public std::set<std::pair<T, float> >

{

    //some declarations like this:

    bool contains(T elem);

};

in this case you don't need to redeclare functions like size(), empty(), insert(), etc.
If you don't want your class to use std interface of std::set, you can inherit it with private. If you need some of your functions differ from std, you can just override it as virtual (set::insert() for example (actually i don't know is it virtual) ) or you can overload some. For example:

    iterator FuzzySet::insert(T elem, float f);


Where am i wrong?

#8
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
  • Location:Upstate, South Carolina
  • Programming Language:C, C++, PL/SQL, Delphi/Object Pascal, Pascal, Transact-SQL, Others
  • Learning:Java, C#, PHP, JavaScript, Lisp, Fortran, Haskell, Others
I'd say you are correct. This tutorial was meant to be an introduction to fuzzy sets, and to give users an idea of how they could be implemented. I've also extended my own knowledge of C++ quite a bit since I wrote this, and probably would have reworked several things.

If you wanted to rework this class along the lines you suggest, I'd love to see a tutorial on it :)
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#9
Occulta

Occulta

    Newbie

  • Members
  • Pip
  • 3 posts
maybe a few days later (:

#10
Occulta

Occulta

    Newbie

  • Members
  • Pip
  • 3 posts
on the other hand it seems to be correct just to edit a little code and probably it needn't a single tutorial. It's just a small refactoring.

#11
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
  • Location:Upstate, South Carolina
  • Programming Language:C, C++, PL/SQL, Delphi/Object Pascal, Pascal, Transact-SQL, Others
  • Learning:Java, C#, PHP, JavaScript, Lisp, Fortran, Haskell, Others
You could use this as the basis of a tutorial on refactoring :)
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#12
Predictor

Predictor

    Newbie

  • Members
  • PipPip
  • 20 posts

Hamed said:

Where we can use Fuzzy set or Fuzzy logic in our programming?

Fuzzy logic may be used where set membership is graded, and some useful operation may be performed on such set memberships. Here is a simple example:

In considering colors in an image, some will be considered "light", some "medium" and others "dark".
Brightness in images is indicated by numbers. In most image formats, the higher the number, the brighter the color.
Many photographic images suffer from poor contrast, meaning that the difference in brightness between the darkest and lightest colors is too small.
Contrast enhancement, it follows, is a process of making light colors lighter and dark colors darker.
One way to do this, is to define sets over the brightness of colors, and create rules which determine changes to those colors:

IF color is "light" THEN newcolor is "very light"
IF color is "medium" THEN newcolor is "medium"
IF color is "dark" THEN newcolor is "very dark"

Traditional definitions of the sets of colors which are "light", "dark", etc. have hard boundaries. More usefully in this case, fuzzy definitions of these sets may be graded.
Fuzzy logic permits us to fire the above rules as mathematical functions, and deliver useful results.
This example is explained in greater detail in an article I published in the Mar/Apr-2002 issue of "PC AI" magazine:

Putting Fuzzy Logic to Work: An Introduction to Fuzzy Rules

Note several important things:

The fuzziness in fuzzy logic is not the same thing as probability. A color which is consider 0.7 "dark" will not, some day, be resolved as being completely in the set "dark", or in the set "not dark": It will always be regarded as 0.7 "dark". The graded membership from 0.0 to 1.0 is part of the definition of the fuzzy set.

The output of the fuzzy rule is often not a single number, but is itself a fuzzy set (commonly represented in the computer as an array of fuzzy membership values). Typically, these output fuzzy sets are combined to produce the single output fuzzy set. When a single number is needed, some defuzzification technique, such as taking the centroid, is used.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users