LSR/hedges.py
2020-06-04 19:21:01 +02:00

135 lines
3.2 KiB
Python

# -*- coding: utf-8 -*-
"""
Hedge functions, based on the definitions in the IEEE standard.
Each function here maps a mf to a new mf.
I'm following Annex A in IEEE 1855-2016, definintions A.1-A.13.
@author: james.power@mu.ie Created on Wed Aug 1 14:14:46 2018
"""
# Each hedge takes a membership function and modifies it,
# returning a 'hedged' membership function of the same size.
import numpy as np
import skfuzzy.membership as skmemb
import extramf
def above(mf):
''' A.1: above(mf)=0 if x<x_max, 1-mf if x>= x_max; cf below'''
max_pos = np.argmax(mf)
new_mf = 1 - mf
new_mf[:max_pos] = 0
return new_mf
def any_of(mf):
'''A.2: any(mf) = 1.. ('any' is a Python built-in)'''
return np.ones_like(mf)
def below(mf):
'''A.3: below(mf) = 0 if x>x_max, 1-mf(x) if x<x_max; cf above'''
max_pos = np.argmax(mf)
new_mf = 1 - mf
new_mf[max_pos:] = 0
return new_mf
def extremely(mf):
'''A.4: extremely(mf) = mf ** 3'''
return mf ** 3
def intensify(mf):
'''A.5: 2*mf^2 if mf<0.5, 1-2*(1-mf)^2 otherwise; cf seldom '''
new_mf = np.zeros_like(mf)
under, over = np.nonzero(mf <= 0.5), np.nonzero(mf > 0.5)
new_mf[under] = 2 * (mf[under] ** 2)
new_mf[over] = 1 - (2 * ((1 - mf[over]) ** 2))
return new_mf
def more_or_less(mf):
'''A.6: more_or_less(mf) = mf ^ 3'''
return mf ** (1/3)
def norm(mf):
'''A.7: norm divides by maximum'''
return mf / mf.max()
def is_not(mf):
'''A.8: not(mf) = 1-mf ('not' is a Python keyword)'''
return 1 - mf
def plus(mf):
'''A.9: more_or_less(mf) = mf ^ (5/4)'''
return mf ** (5/4)
def seldom(mf):
'''
A.10: (mf/2)^(1/2) if mf<=0.5, and 1-((1-mf)/2)^(1/2) otherwise;
cf intensify
'''
new_mf = np.zeros_like(mf)
under, over = np.nonzero(mf <= 0.5), np.nonzero(mf > 0.5)
new_mf[under] = np.sqrt(mf[under] / 2)
new_mf[over] = 1 - np.sqrt((1 - mf[over]) / 2)
return new_mf
def slightly(mf):
'''A.11: Defined as: intensify [ norm (plus S AND not very S) ]'''
def min_and(x, y):
''' Let's implement AND as the elementwise min of two arrays'''
return np.minimum.reduce([x, y])
return intensify(norm(min_and(plus(mf), is_not(very(mf)))))
def somewhat(mf):
'''A.12: somewhat(mf) = mf ^ (1/2)'''
return mf ** (1/2)
def very(mf):
'''A.13: very(mf) = mf ^ 2'''
return mf ** 2
# List of all hedges, maps name to function
_IEEE_HEDGES = {
'above': above,
'any': any_of,
'below': below,
'extremely': extremely,
'intensify': intensify,
'more_or_less': more_or_less,
'norm': norm,
'not': is_not,
'plus': plus,
'seldom': seldom,
'slightly': slightly,
'somewhat': somewhat,
'very': very,
}
def test_all_hedges(y):
results = []
hedgenames = sorted(all_hedges.keys()) # Want them in alphabetical order
for name in hedgenames:
func = all_hedges[name]
results.append(func(y))
return (hedgenames, results)
if __name__ == '__main__':
x = np.arange(0, 100)
y = skmemb.gaussmf(x, 50, 15)
(titles, data) = test_all_hedges(y)
extramf.visualise_all(x, [y]+data, ['original (gaussian)']+titles)