/// <summary> /// Defuzzify a membership function using the Bisector method. /// https://www.mathworks.com/help/fuzzy/examples/defuzzification-methods.html /// </summary> /// <param name="mf"></param> /// <returns></returns> public static double DefuzzBisect(MemberFunction mf) { double areaTotal = 0; double[] areas = new double[mf.Length]; // Find the area of each segment for (int i = 0; i < mf.Length - 1; i++) { double x1 = mf.Coords[i][0]; double x2 = mf.Coords[i + 1][0]; double y1 = mf.Coords[i][1]; double y2 = mf.Coords[i + 1][1]; areas[i] = 0.5 * (x2 - x1) * (y1 + y2); areaTotal += areas[i]; } double halfArea = areaTotal / 2; double xMin = 0; double xMax = 0; double yLast = 0; double x = 0; double y = 0; double m = 0; // This is our accumulating area double tmpArea = 0; for (int i = 0; i < mf.Length - 1; i++) { // Get the area of this segment m = areas[i]; x = xMax = mf.Coords[i][0]; // Add points in until we cross over to the haldway point if (tmpArea + m <= halfArea) { tmpArea += m; } // Cut the distance in hald until we are reasonable close to the point we want else { xMin = mf.Coords[i][0]; xMax = mf.Coords[i + 1][0]; yLast = mf.Coords[i][1]; while (halfArea - tmpArea > 0.000001) { x = xMin + ((xMax - xMin) / 2); y = mf.fuzzify(x); m = Area(new double[2] { xMin, yLast }, new double[2] { x, y }); if (tmpArea + m > halfArea) { xMax = x; } else if (tmpArea + m <= halfArea) { tmpArea += m; xMin = x; } } break; } } return(x); }
public void fuzzifyTest() { MemberFunction mf1 = new MemberFunction(new List <double[]>() { new double[2] { 1, 0 }, //0 new double[2] { 2, 1 }, //1 <-- horiz new double[2] { 3, 1 }, //2 <-- Vertical new double[2] { 3, 2 }, //3 <-- horiz new double[2] { 4, 2 }, //4 new double[2] { 5, 0 } //5 }); Assert.AreEqual(mf1.fuzzify(0), 0); Assert.AreEqual(mf1.fuzzify(1), 0); Assert.AreEqual(mf1.fuzzify(2), 1); Assert.AreEqual(mf1.fuzzify(3), 1); Assert.AreEqual(mf1.fuzzify(4), 2); Assert.AreEqual(mf1.fuzzify(5), 0); Assert.AreEqual(mf1.fuzzify(0.5), 0); Assert.AreEqual(mf1.fuzzify(1.5), 0.5); Assert.AreEqual(mf1.fuzzify(2.5), 1); Assert.AreEqual(mf1.fuzzify(3.5), 2); Assert.AreEqual(mf1.fuzzify(4.5), 1); Assert.AreEqual(mf1.fuzzify(5.5), 0); Assert.AreEqual(mf1.fuzzify(-100), 0); Assert.AreEqual(mf1.fuzzify(100), 0); Assert.AreEqual(mf1.fuzzify(double.PositiveInfinity), 0); Assert.AreEqual(mf1.fuzzify(double.NegativeInfinity), 0); }