Last active
October 28, 2015 21:50
-
-
Save PtrMan/ca558152d115e05622e6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "bindings/Array.h" | |
#include <iostream> | |
using namespace std; | |
float interpolateLinear(float t, float a, float b) { | |
return (1.0f-t)*a + t*b; | |
} | |
float isInRange(float x, float min, float max) { | |
return x >= min && x <= max; | |
} | |
struct TriangleFunction { | |
enum class EnumSide { | |
NEGATIVE, | |
POSITIVE | |
}; | |
float center; | |
float width; | |
float calculateYForWholeRange(float x) { | |
if( isInRange(x) ) { | |
return calculateY(x); | |
} | |
else { | |
return 0.0f; | |
} | |
} | |
bool isInRange(float x) { | |
return ::isInRange(x, center-width, center+width); | |
} | |
// invariant, x has to be in range | |
float calculateY(float x) { | |
float relativeDistance; | |
EnumSide side; | |
calculateRelativeAbsoluteDistanceWithSide(x, relativeDistance, side); | |
return interpolateLinear(relativeDistance, 1.0f, 0.0f); | |
} | |
void calculateRelativeAbsoluteDistanceWithSide(float x, float &relativeDistance, EnumSide &side) { | |
if( x > center ) { | |
side = EnumSide::POSITIVE; | |
relativeDistance = (x - center) / width; | |
} | |
else { | |
side = EnumSide::NEGATIVE; | |
relativeDistance = (-(x - center)) / width; | |
} | |
} | |
}; | |
struct FuzzificationForTriangle { | |
TriangleFunction::EnumSide side; | |
float relativeDistance; | |
float membership; | |
bool inRange; | |
}; | |
struct FuzzifierContext { | |
Array<TriangleFunction> triangleFunctions; | |
Array<FuzzificationForTriangle> triangleFuzzification; | |
void calculateMembershipsForValue(float x) { | |
for( int triangleFunctionI = 0; triangleFunctionI < triangleFunctions.getCount(); triangleFunctionI++ ) { | |
cout << "index =="<< triangleFunctionI << endl; | |
bool inRange = triangleFuzzification[triangleFunctionI].inRange = triangleFunctions[triangleFunctionI].isInRange(x); | |
if( inRange ) { | |
cout << "INRANGE" << endl; | |
triangleFuzzification[triangleFunctionI].membership = triangleFunctions[triangleFunctionI].calculateY(x); | |
triangleFunctions[triangleFunctionI].calculateRelativeAbsoluteDistanceWithSide(x, triangleFuzzification[triangleFunctionI].relativeDistance, triangleFuzzification[triangleFunctionI].side); | |
} | |
else { | |
triangleFuzzification[triangleFunctionI].membership = 0.0f; | |
} | |
} | |
} | |
// defuzification | |
// centroid method, see http://www.csee.wvu.edu/classes/cpe521/presentations/DEFUZZ.pdf | |
// page 10 | |
float defuzificationCentroid(float maxXRange, float stepsize) { | |
// very stupid implementation, we just iterate and calculate the maximum | |
float weightSum = 0.0f; | |
float valueSum = 0.0f; | |
for( float xi = 0.0f; xi < maxXRange; xi += stepsize ) { | |
float currentValue = 0.0f; | |
for( int triangleI = 0; triangleI < triangleFuzzification.getCount(); triangleI++ ) { | |
float yValue = min( triangleFunctions[triangleI].calculateYForWholeRange(xi), triangleFuzzification[triangleI].membership); | |
currentValue = max(currentValue, yValue); | |
} | |
weightSum += (currentValue * xi); | |
valueSum += currentValue; | |
} | |
// ask< is this correct? > | |
float centroidX = weightSum / valueSum; | |
return centroidX; | |
} | |
}; | |
main() { | |
FuzzifierContext fuzzylogicContext; | |
TriangleFunction a, b; | |
fuzzylogicContext.triangleFunctions.add(a); | |
fuzzylogicContext.triangleFunctions[0].center = 1.0f; | |
fuzzylogicContext.triangleFunctions[0].width = 1.0f; | |
fuzzylogicContext.triangleFunctions.add(b); | |
fuzzylogicContext.triangleFunctions[1].center = 2.0f; | |
fuzzylogicContext.triangleFunctions[1].width = 2.0f; | |
FuzzificationForTriangle triangleA, triangleB; | |
fuzzylogicContext.triangleFuzzification.add(triangleA); | |
fuzzylogicContext.triangleFuzzification.add(triangleB); | |
fuzzylogicContext.calculateMembershipsForValue(1.4f); | |
// debug membership | |
cout << "membership A=" << fuzzylogicContext.triangleFuzzification[0].membership << endl; | |
cout << "membership B=" << fuzzylogicContext.triangleFuzzification[1].membership << endl; | |
float centeroid = fuzzylogicContext.defuzificationCentroid(8.0f, 0.05f); | |
cout << "centeroid " << centeroid << endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Tutorial
https://www.youtube.com/watch?v=R4TPFpYXvS0