隶属度函数(智能控制1)

2018-01-17  本文已影响529人  小火伴

模糊控制中有一个隶属度函数的概念。

是模糊集合中会用到的函数,是一般集合中指示函数的一般化[1]。指示函数可以说明一个集合中的元素是否属于特定子集合。一元素的指示函数的值可能是0或是1,而一元素的隶属函数会是0到1之间的数值,表示元素属于某模糊集合的“真实程度”(degree of truth)。
这次我们编写6种常见隶属度函数(来源:百度文库)的计算程序。

按这个文件命名哦!
membership_function.py

'''
六种常见的隶属度函数
矩阵
梯形
抛物线
高斯
柯西
伽马
'''
from math import exp
import numpy as np
import matplotlib.pyplot as plt


class MembershipDegree(object):
    def no_mold(self,mold):
        # 选择模式是否存在
        print('no this mold: {0} ???\n we have 0/1/2 represent small/medium/large'.format(mold))
        exit(1)

    def y_array(self,f,x):
        y=[]
        for xx in x:
           y.append(f(xx))
        y=np.array(y)
        return y
    def huahua(self,x,y):
        plt.plot(x, y)
        plt.ylim(-0.2, 1.2)
        plt.xlim(x[0] - (max(x) - min(x)) * 0.1, x[-1] + (max(x) - min(x)) * 0.1)
        # plt.axes([x[0]-(max(x)-min(x))*0.1,x[-1]+(max(x)-min(x))*0.1,-0.2,1.2])
        plt.grid()
        
        
class Matrix(MembershipDegree):
    def __init__(self,a,b=None,mold=0):
        super().__init__()
        if (mold == 1):
            assert b != None
        self.a=a
        self.b=b
        self.mold=mold
    def matrix(self,x):
        a,b,mold=self.a,self.b,self.mold
        # 矩阵型
        if(mold==1):
            # 中间型
            if (a<=x<=b):
                u = 1
            else:
                u = 0
        elif(mold==0):
            # 偏小型
            if (x<=a):
                u=1
            else:
                u=0
        elif(mold==2):
            # 偏大型
            if (x<a):
                u=0
            else:
                u=1
        else:
            super().no_mold(mold)
            return
        return u

class Trapezoid(MembershipDegree):
    def __init__(self,a,b,c=None,d=None,mold=0):
        super().__init__()
        if (mold == 1):
            assert c != None and d != None
        self.a,self.b,self.c,self.d,self.mold=a,b,c,d,mold
    def trapezoid(self,x):
        a, b, c, d, mold=self.a,self.b,self.c,self.d,self.mold
        # 梯形
        if(mold==1):
            assert c!=None and d!=None
            # 中间型
            if(a<=x<=b):
                u=(x-a)/(b-a)
            elif(b<=x<=c):
                u=1
            elif(c<=x<=d):
                u=(d-x)/(d-c)
            else:
                u=0
        elif(mold==0):
            # 小
            if(x<=a):
                u=1
            elif(x>b):
                u=0
            else:
                u=(b-x)/(b-a)
        elif(mold==2):
            # 大
            if (x <= a):
                u = 0
            elif (x > b):
                u = 1
            else:
                u = 1-(b - x) / (b - a)
        else:
            super().no_mold(mold)
            return
        return u

class Paracurve(MembershipDegree):
    def __init__(self,a,b,c=None,d=None,mold=0,k=3):
        super().__init__()
        self.a, self.b, self.c, self.d, self.mold,self.k= a, b, c, d, mold,k
        self.temp = Trapezoid(a, b, c, d, mold)
    def paracurve(self,x):
        # k次抛物线 哈哈-->>就是在梯形型基础上对每一个结果k次方
        a, b, c, d, mold, k=self.a, self.b, self.c, self.d, self.mold, self.k
        u=self.temp.trapezoid(x)**k
        return u

class Gauss(MembershipDegree):
    def __init__(self,a=0,mold=0,theta=1):
        self.a,self.mold,self.theta=a,mold,theta
    def gauss(self,x):
        a, mold, theta=self.a,self.mold,self.theta
        # theta:方差
        # a:均值

        # 高斯型
        f=lambda :exp(-((x-a)/theta)**2)
        if(mold==1):
            u=f()
        elif(mold==0):
            if(x<=a):
                u=1
            else:
                u=f()
        elif(mold==2):
            if(x<=a):
                u=0
            else:
                u=1-f()
        else:
            super().no_mold(mold)
            return
        return u

class Cauchy(MembershipDegree):
    def __init__(self,a,mold=0,alpha=1,beta=2):
        assert alpha > 0 and beta > 0
        if (mold == 1):
            assert beta % 2 == 0
        self.a,self.mold,self.alpha,self.beta=a,mold,alpha,beta
    def cauchy(self,x):
        '''
        柯西型
        :param x:
        :param a: 绝对值开始/结束
        :param mold:
        :param alpha: 可以选1/sqrt(a)
        :param beta: 变化速度 越大越快 1为线性
        :return:
        '''
        a, mold, alpha, beta=self.a,self.mold,self.alpha,self.beta
        f=lambda b:1/(1+alpha*(x-alpha)**b)
        if(mold==1):
            u=f(beta)
        elif(mold==0):
            if(x<=a):
                u=1
            else:
                u=f(beta)
        elif(mold==2):
            if(x<=a):
                u=0
            else:
                u=f(-beta)
        else:
            super().no_mold(mold)
            return
        return u

class Gamma(MembershipDegree):
    def __init__(self,a,b=None,mold=0,k=2):
        if (mold == 1):
            assert b != None
        self.a,self.b,self.mold,self.k=a,b,mold,k
    def gamma(self,x):
        '''
        伽马型
        :param x:
        :param a:
        :param b:
        :param mold:
        :param k:
        :return:
        '''
        a, b, mold, k= self.a, self.b, self.mold, self.k
        f=lambda :exp(-k*(x-a))
        if(mold==1):
            if(x<a):
                u=exp(k*(x-a))
            elif(x>b):
                u=exp(-k*(x-b))
            else:
                u=1
        elif(mold==0):
            if(x<=a):
                u=1
            else:
                u=f()
        elif(mold==2):
            if(x<=a):
                u=0
            else:
                u=1-f()
        else:
            super().no_mold(mold)
            return
        return u


if __name__ == '__main__':

    # 画图测试
    x=np.arange(0,10,0.01)
    # 实例化一个伽马
    g=Gauss(a=3,mold=1)
    # 用父类函数运算哈哈哈
    y=g.y_array(g.gauss,x)
    g.huahua(x,y)
    # plt.savefig('test')
    plt.show()
    pass

test.png

科学隶属度函数确定方法
因为还有期末考试,所以我做了个demo

隶属度函数的建立

——关于年老,年轻,不大不小的设计说明

隶属度函数是模糊控制的应用基础,正确构造隶属度函数是能否用好模糊控制的关键之一。隶属度函数的确定过程,本质上说应该是客观的,但每个人对于同一个模糊概念的认识理解又有差异,因此,隶属度函数的确定又带有主观性。
由于时间、精力所限,结合题目情况,是一个生活观念的判断,我选择了例证法。即预选了几个年龄1~100岁,设置了几个有确定值的选项,如年轻,比较年轻,不年轻。让朋友圈的人帮忙打分。因为告诉大家我在做大作业,所以亲朋好友比较配合,很有默契地选择了有规律答案,方便我做拟合。
基于获得的少量数据,加上我主观判断,我选择了高斯、柯西型函数等,调整了一下参数,比较粗糙,还望多多包涵。

old_or_young.py

'''
设计一个年老,很年轻,不老也不年轻模糊集的隶属度函数
'''
from matplotlib import pyplot as plt
import numpy as np
# 从上一个包中导入
import membership_function as mf

x=np.arange(0,100,0.05)

young=mf.Paracurve(a=25,b=35,k=5)
y=young.y_array(young.paracurve,x)
young.huahua(x,y)
plt.vlines(25,0,1,linestyles='-')
plt.annotate('<-sure young\n 25 years old',xy=(25,0),xytext=(16,-0.15),arrowprops = dict(facecolor = 'black', shrink = 0.1))
plt.annotate('no young->\n 35 years old',xy=(35,0),arrowprops = dict(facecolor = 'black', shrink = 0.1))
plt.savefig('young')
plt.show()

strong=mf.Gamma(35,55,1,k=2)
y=strong.y_array(strong.gamma,x)
strong.huahua(x,y)
plt.vlines(35,0,1,linestyles='-')
plt.vlines(55,0,1,linestyles='-')
plt.annotate('stronger',xy=(40,0.3))
plt.savefig('strong')
plt.show()

young=mf.Paracurve(a=50,b=65,mold=2,k=5)
y=young.y_array(young.paracurve,x)
young.huahua(x,y)
plt.vlines(65,0,1,linestyles='-')
plt.annotate('big age->\n 65 years old',xy=(65,0),arrowprops = dict(facecolor = 'black', shrink = 0.1))
plt.savefig('bigage')
plt.show()

young.png strong.png bigage.png
上一篇下一篇

猜你喜欢

热点阅读