Confusing Fuzzy Logic problem

Started by
8 comments, last by jacmoe 14 years, 11 months ago
Hi, I'm trying to make a very simple fuzzy logic plug in for an even simipler racing game. I know all my fuzzy logic theory and what I have to do, but I've run into a problem where I cant see a solution that doesnt result in very messy code. When I'm aggragating the outputs to calculate the final shape of the output functions, I'm getting very odd results. Currently, my outputs are a series of straight lines which I am plugging in a degree of membership to try and get a NEW set of straightline equations that make up the shape of the output functions results. I know this WILL work, even if it does sound slightly confusing, my problem is getting all these straight lines without having a giant nested if statement, declaring where the start and end points are for all the output function lines. A short ascii diagram: (Picture one is how the output graph is represented, each line is a simple straight line equation. Picture two is what I'm trying to get after I input the degree of membership, each of the lines here are to be straight lines also.)

Output shape
//*|            |             
//*|\    /\    /|                 
//*| \  /  \  / | 
//*|  \/    \/  |                                
//0|__/\____/\__|_1     

//*|
//*|    __
//*|   /  \  
//*|__/    \
//0|________\______1          


Advertisement
Instead of a bunch of `if' statements, what I have done in the past is write a class PiecewiseLinearFunction that takes a list of (x,y) points and can then interpolate linearly between them. This allows you to very quickly create whatever shape you want, without messy code. You can even write a graphical editor if you need to expose this to game designers.

If you need help imagining what that class would look like, I can try to write one for you.
Actually, I had some time to write it. So here it is:
#include <iostream>#include <map>namespace PLF {  struct Point {    double x, y;        Point(double x, double y) : x(x), y(y) {    }  };}class PiecewiseLinearFunction {  std::map<double, double> points;  public:  template <typename It>  PiecewiseLinearFunction(It begin, It end) {    for (It it=begin; it!=end; ++it)      points[it->x] = it->y;  }    double operator()(double x) {    typedef std::map<double, double>::const_iterator PointsIt;    std::pair<PointsIt, PointsIt> range = points.equal_range(x);    PointsIt left = range.second;    if(left==points.begin())      return left->second;    if(left==points.end())      return (--left)->second;    --left;    PointsIt right = range.first;    if(left==right)      return left->second;    double lambda = (x-left->first)/(right->first-left->first);    return (1.0-lambda)*left->second + lambda*right->second;  }};int main() {  PLF::Point points[] = {    PLF::Point(0.0, 1.0/3.0),    PLF::Point(0.15, 1.0/3.0),    PLF::Point(0.3, 1.0),    PLF::Point(0.45, 1.0),    PLF::Point(0.675, 0.0)  };  PiecewiseLinearFunction plf(points, points+sizeof(points)/sizeof(points[0]));    for(double x=-.5;x<1.5; x+=.1)    std::cout << x << ' ' << plf(x) << '\n';}
Thanks Alvaro but I'm not sure this is what I'm needing.

If i understand your code correctly you've created a class that takes in a list of x,y points and calculates the equations of the lines between these points?

If this is the case, then this isn't my problem. My problem is using a vast amount of IF statements to calculate the points from which I will then be able to calculate the equation of the line.

Sorry I should have made that clearer the first time.
Quote:Original post by ScottH87
If this is the case, then this isn't my problem. My problem is using a vast amount of IF statements to calculate the points from which I will then be able to calculate the equation of the line.

Sorry I should have made that clearer the first time.


I still don't understand what you want. Can you give an example of input and the output you would want for it?

Basically we're trying to calculate the final shape of the ouput function so that we can apply the centroid method to the defuzzify it and get an output.

The problem I'm having is generating the final shape. We want to represent the final shape as a series of straight line equations bounded by the axes. The real difficulty lies in calculating the start and end points of each line because each line has different criterea to follow (i.e if we have a degree of membership to only one function, then the shape is bounded by JUST that function. If we have multiple degrees of membership, then we need to work out points of intersection between the functions in order to get the final shape.) The way to do this is different for each line, dependant on whether it is the first line of the membership function or the last line.

I know I'm not describing this really clearly, but I really dont know how else to describe it.
Quote:Original post by ScottH87
I know I'm not describing this really clearly, but I really dont know how else to describe it.


I'm having a hard time understanding what you are saying. Perhaps what you need is some way of performing operations with piece-wise linear functions.

Why don't you find an easy example where you could do everything by hand and post it in detail? That would clarify exactly what you mean.
Yikes! Keeping track of an arbitrary number of crossing line segments will be a great deal of work. The usual way this is handled it to sample the output domain, and calculate the consequent of each fuzzy rule along this domain. In the end, their is one 1-D array for each firing fuzzy rule, which can then be merged element-by-element, for instance by taking the maximum.


-Will Dwinnell
Data Mining in MATLAB
why can't you just use methods used by most of the people? do you have some special accuracy issues? i mean. you can quite nicely approximate defuzzified value by evaluating numerically integrals of maximum value of all output functions, or even calculate output as weighted sum of all output centers of weight which for simple trapezoids would be very fast and simple.
Quote:Original post by alvaro
Actually, I had some time to write it. So here it is:
*** Source Snippet Removed ***

Thanks a lot, Alvaro!
Very handy - thanks for taking the time to post it. :)

Too many projects; too much time

This topic is closed to new replies.

Advertisement