// Catalano Fuzzy Library
// The Catalano Framework
//
// Copyright © Diego Catalano, 2012-2016
// diego.catalano at live.com
//
// Copyright © Andrew Kirillov, 2007-2008
// andrew.kirillov at gmail.com
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Lesser General Public
//    License as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public
//    License along with this library; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//

package Catalano.Fuzzy;

import Catalano.Core.FloatPoint;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Membership function composed by several connected linear functions.
 * @author Diego Catalano
 */
public class PiecewiseLinearFunction implements IMembershipFunction{
    
    /**
     * Vector of (X,Y) coordinates for end/start of each line.
     */
    protected FloatPoint[] points;

    /**
     * Initializes a new instance of the  class.
     *  This constructor must be used only by inherited classes to create the points vector after the instantiation. 
     */
    public PiecewiseLinearFunction() {
        points = null;
    }

    /**
     * Initializes a new instance of the  class.
     * @param points Array of (X,Y) coordinates of each start/end of the lines.
     * 
     * Points must be in crescent order on X axis.
     * Y value of points must be in the range of [0, 1].
     */
    public PiecewiseLinearFunction(FloatPoint[] points) {
        this.points = points;
        
        // check if X points are in a sequence and if Y values are in [0..1] range
        for ( int i = 0, n = points.length; i < n; i++ ){
            if ( ( points[i].y < 0 ) || ( points[i].y > 1 ) )
                try {
                throw new Exception( "Y value of points must be in the range of [0, 1]." );
            } catch (Exception ex) {
                Logger.getLogger(PiecewiseLinearFunction.class.getName()).log(Level.SEVERE, null, ex);
            }

            if ( i == 0 )
                continue;

            if ( points[i - 1].x > points[i].x )
                try {
                throw new Exception( "Points must be in crescent order on X axis." );
            } catch (Exception ex) {
                Logger.getLogger(PiecewiseLinearFunction.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    @Override
    public float GetMembership(float x) {
        // no values belong to the fuzzy set, if there are no points in the piecewise function
        if ( points.length == 0 )
            return 0.0f;

        // if X value is less than the first point, so first point's Y will be returned as membership
        if ( x < points[0].x )
            return points[0].y;

        // looking for the line that contais the X value
        for ( int i = 1, n = points.length; i < n; i++ ){
            // the line with X value starts in points[i-1].X and ends at points[i].X
            if ( x < points[i].x ){
                // points to calculate line's equation
                float y1 = points[i].y;
                float y0 = points[i - 1].y;
                float x1 = points[i].x;
                float x0 = points[i - 1].x;
                // angular coefficient
                float m = ( y1 - y0 ) / ( x1 - x0 );
                // returning the membership - the Y value for this X
                return m * ( x - x0 ) + y0;
            }
        }

        // X value is more than last point, so last point Y will be returned as membership
        return points[points.length - 1].y;
    }

    @Override
    public float LeftLimit() {
        return points[0].x;
    }

    @Override
    public float RightLimit() {
        return points[points.length - 1].x;
    }
    
}

 

Ads help maintain this website.