第一次接触模糊数的运算规则时,那些抽象的定义和复杂的公式确实让人头疼。作为一个曾经被这些概念折磨过的开发者,我发现用代码实现这些运算比死记硬背公式要高效得多。本文将带你用Python从零实现模糊数的加减乘除,通过可视化结果直观理解运算本质。
模糊数本质上是对不确定性的数学描述。比如"大约2"这个模糊概念,可以表示为:
python复制fuzzy_2 = {
1: 0.4, # 数值1的隶属度为0.4
2: 1.0, # 数值2的隶属度为1.0 (核心值)
3: 0.7 # 数值3的隶属度为0.7
}
这种离散表示法非常适合编程实现。对于连续型模糊数,我们可以用函数表示:
python复制import numpy as np
def triangular_mf(x, a, b, c):
"""三角形隶属函数"""
return np.maximum(0, np.minimum((x-a)/(b-a), (c-x)/(c-b)))
关键点:
模糊数加法的数学定义看起来很复杂:
$$(A+B)(z) = \bigvee_{x+y=z} (A(x) \wedge B(y))$$
用Python实现却出奇简单:
python复制def fuzzy_add(a, b):
result = {}
for x in a:
for y in b:
z = x + y
membership = min(a[x], b[y])
if z in result:
result[z] = max(result[z], membership)
else:
result[z] = membership
return result
测试我们的实现:
python复制fuzzy_2 = {1:0.4, 2:1.0, 3:0.7}
fuzzy_3 = {2:0.5, 3:1.0, 4:0.6}
print(fuzzy_add(fuzzy_2, fuzzy_3))
# 输出: {3: 0.4, 4: 0.5, 5: 1.0, 6: 0.7, 7: 0.6}
可视化结果更直观:
code复制值 隶属度
3 0.4 ← 1+2
4 0.5 ← 1+3
5 1.0 ← 2+3 (核心值相加)
6 0.7 ← 3+3
7 0.6 ← 3+4
减法运算与加法类似,只是将x+y改为x-y:
python复制def fuzzy_sub(a, b):
result = {}
for x in a:
for y in b:
z = x - y
membership = min(a[x], b[y])
if z in result:
result[z] = max(result[z], membership)
else:
result[z] = membership
return result
测试减法:
python复制print(fuzzy_sub(fuzzy_2, fuzzy_3))
# 输出: {-3: 0.4, -2: 0.6, -1: 1.0, 0: 0.7, 1: 0.5}
运算过程解析:
code复制-3: 1-4 (min(0.4,0.6)=0.4)
-2: (1-3)或(2-4) → max(0.4,0.6)=0.6
-1: (2-3) → 1.0
0: (3-3) → 0.7
1: (3-2) → 0.5
乘法运算需要考虑所有x*y的组合:
python复制def fuzzy_mul(a, b):
result = {}
for x in a:
for y in b:
z = x * y
membership = min(a[x], b[y])
if z in result:
result[z] = max(result[z], membership)
else:
result[z] = membership
return result
测试乘法:
python复制print(fuzzy_mul(fuzzy_2, fuzzy_3))
# 输出: {2:0.4, 3:0.4, 4:0.5, 6:1.0, 8:0.6, 9:0.7, 12:0.6}
结果分析表:
| 乘积 | 组合来源 | 隶属度 |
|---|---|---|
| 2 | 1×2 | 0.4 |
| 3 | 1×3 | 0.4 |
| 4 | 1×4或2×2 | 0.5 |
| 6 | 2×3 | 1.0 |
| 8 | 2×4 | 0.6 |
| 9 | 3×3 | 0.7 |
| 12 | 3×4 | 0.6 |
除法需要特别注意除数不能为0的情况:
python复制def fuzzy_div(a, b):
result = {}
for x in a:
for y in b:
if y == 0:
continue # 跳过除以零的情况
z = x / y
membership = min(a[x], b[y])
if z in result:
result[z] = max(result[z], membership)
else:
result[z] = membership
return result
测试除法:
python复制print(fuzzy_div(fuzzy_2, fuzzy_3))
# 输出: {0.5:0.4, 0.333:0.4, 0.25:0.5, 0.666:1.0, 0.75:0.7, 1.0:0.5, 1.5:0.6}
注意:实际应用中应该对结果进行适当的舍入,避免过多小数位带来的精度问题
对于连续型模糊数,我们需要改用积分和函数操作。以三角形模糊数为例:
python复制def continuous_fuzzy_add(f_a, f_b, x_range):
"""连续模糊数加法"""
z_values = np.linspace(x_range[0], x_range[1], 1000)
result = {}
for z in z_values:
# 寻找所有x+y=z的组合
membership = 0
for x in np.linspace(x_range[0], x_range[1], 100):
y = z - x
if x_range[0] <= y <= x_range[1]:
membership = max(membership, min(f_a(x), f_b(y)))
result[z] = membership
return result
使用示例:
python复制# 定义两个三角形模糊数
fuzzy_A = lambda x: triangular_mf(x, 1, 2, 3)
fuzzy_B = lambda x: triangular_mf(x, 2, 3, 4)
# 计算加法结果
result = continuous_fuzzy_add(fuzzy_A, fuzzy_B, [0, 8])
模糊数运算在决策系统中非常有用。比如评估两个模糊风险因素的综合影响:
python复制# 定义两个风险因素的模糊评估
risk_1 = {2:0.3, 3:1.0, 4:0.5} # 风险等级约3
risk_2 = {1:0.2, 2:1.0, 3:0.4} # 风险等级约2
# 计算综合风险(加权平均)
combined_risk = fuzzy_div(
fuzzy_add(
fuzzy_mul(risk_1, {3:1.0}), # 风险1权重3
fuzzy_mul(risk_2, {2:1.0}) # 风险2权重2
),
{5:1.0} # 总权重5
)
print("综合风险模糊评估:", combined_risk)
输出结果可以帮助决策者理解风险的综合分布情况。
实现这些运算后,我发现模糊数学最精妙之处在于它用严格的数学方法处理不精确的概念。通过代码实现,这些抽象概念变得触手可及。建议读者可以尝试扩展这些基础函数,比如实现模糊数的指数运算或者更复杂的复合运算。