一、实验目的
自动控制系统需要根据设备内温度、设备内湿度决定设备的运转时间。其中,温度的论域是[0℃, 100℃],有3个模糊标记:低、中、高;湿度的论域是[0%, 60%],有3个模糊标记:小、中、大;运转时间论域是[0s, 1000s],有3个模糊标记:短、中、长。这些模糊标记在模糊规则中被使用。试编写一个相对通用的通过输入的温度和湿度,计算出设备需要运转的时间的模糊逻辑系统。
二、实验分析与设计
根据实验目的中的要求,自动控制系统并没有给定温度、湿度以及运转时间的模糊集合,下面我将以《计算智能》P46页例3.3为例,在jupyter notebook环境下,利用python语言设计一个相对通用的通过输入温度与湿度实现输出设备运转时间的模糊逻辑系统,同时利用MATLAB的Fuzzy Logic Toolbox工具包进行进一步仿真设计。
提要
模糊计算的基本流程:模糊计算依据模糊规则,从几个控制变量的输入得到最终输出的过程,这个过程可以细分为以下四个模块:
- 模糊规则库
- 模糊规则库是专家提供的模糊规则,类似“当温度高而湿度小的时候,设备的运行时间长”的陈述;
- 模糊化
- 模糊化是根据隶属度函数从具体的输入得到对模糊集隶属度的过程,由于规则是由模糊的自然语言表述的,而输入是准确的数值,没有模糊化的过程,规则就难以被应用;
- 推理方法
- 推理方法是从模糊规则和输入对相关模糊集的隶属度得到模糊结论的方法;
- 去模糊化
- 去模糊化是将模糊结论转化为具体的、精确的输出的过程。
系统详细功能设计
1. 输入处理
- 温度转换:将温度值转换为三个模糊集合(低、中、高)的隶属度。
- 湿度转换:将湿度值转换为三个模糊集合(小、中、大)的隶属度。
图一 温度与湿度的隶属度函数图
- 当温度为64℃且湿度为22%时,通过隶属度函数图计算得到如下结果:
表一 输入温度与湿度的隶属度
输入变量 | 模糊标记 | 隶属度 |
温度 | 低 | 0 |
中 | 0.53 | |
高 | 0.1 | |
湿度 | 小 | 0.075 |
中 | 0.467 | |
大 | 0 |
2. 模糊规则定义
- 定义模糊规则集,例如:
- R1: 当温度低而湿度小的时候,设备的运行时间是中。
- R2: 当温度中而湿度小的时候,设备的运行时间是长。
- R3: 当温度高而湿度小的时候,设备的运行时间是长。
- R4: 当温度低而湿度中的时候,设备的运行时间是短。
- 更多规则见以下表格:
表二 专家提供的模糊控制规则
湿度 \ 温度 | 低 | 中 | 高 |
小 | 中 | 长 | 长 |
中 | 短 | 中 | 中 |
大 | 长 | 短 | 中 |
3. 模糊推理
- 使用模糊逻辑运算符(如模糊AND、OR)来处理模糊规则。
- 应用最大-最小推理来计算输出。
4. 输出处理
- 去模糊化:将模糊推理的结果转换为具体的运转时间。
- 使用质心(中心平均)方法或其他去模糊化技术。
- 输出结果:输出最终计算出的设备运转时间。
5. 系统验证
- 通过测试不同的输入值来验证系统的准确性和可靠性。
- 调整模糊集合和规则以优化系统性能。
三、实验代码
根据模块二对系统的功能分析,本次实现我设计三种方式实现基于模糊逻辑的自动控制系统:
- 一是基于python手动实现模糊计算的逻辑;(不含任何现有的模糊逻辑库函数)
- 二是基于python中的scikit-fuzzy库实现模糊计算;
- 三是基于MATLAB中的Fuzzy Logic Toolbox工具包实现模糊逻辑的设计和仿真。
方式一
第一种方式,利用python语言,手动实现该自动控制系统的模糊计算逻辑,不使用任何封装好的库。
1. 首先定义了一个统一的隶属度计算函数membership_function,基于该函数进而使用lambda匿名函数模拟了温度、湿度以及运行时间的模糊集合,可通过传入具体的温度和湿度得到对应的隶属度值;
# 定义隶属度函数
def membership_function(x, a, b, c):
if x <= a or x >= c:
return 0
elif a < x <= b:
return (x - a) / (b - a)
else:
return (c - x) / (c - b)
# 定义输入输出变量的模糊集合
wendu_low = lambda x: membership_function(x, 0, 0, 40) # low 对应低温度
wendu_mid = lambda x: membership_function(x, 20, 50, 80) # mid 对应中温度
wendu_hig = lambda x: membership_function(x, 60, 100, 100) # hig 对应高温度
shidu_low = lambda x: membership_function(x, 0, 0, 23.78) # low 对应低湿度
shidu_mid = lambda x: membership_function(x, 15, 30, 45) # mid 对应中湿度
shidu_hig = lambda x: membership_function(x, 35, 60, 60) # hig 对应高湿度
time_sht = lambda x: membership_function(x, 0, 0, 250) # sht 对应运行时间短
time_mid = lambda x: membership_function(x, 250, 500, 750) # mid 对应运行时间中
time_log = lambda x: membership_function(x, 750, 1000, 1000) # log 对应运行时间长
2. 然后基于上述定义的模糊集合,利用min方法创建模糊控制规则表(即给定温度和湿度,使用min函数获取两者隶属度的最小值填入模糊规则表),并建立与运行时间的映射关系;
# 定义模糊控制规则,根据表二共有九条规则
rule1 = lambda x, y: min(wendu_low(x), shidu_low(y))
rule2 = lambda x, y: min(wendu_mid(x), shidu_low(y))
rule3 = lambda x, y: min(wendu_hig(x), shidu_low(y))
rule4 = lambda x, y: min(wendu_low(x), shidu_mid(y))
rule5 = lambda x, y: min(wendu_mid(x), shidu_mid(y))
rule6 = lambda x, y: min(wendu_hig(x), shidu_mid(y))
rule7 = lambda x, y: min(wendu_low(x), shidu_hig(y))
rule8 = lambda x, y: min(wendu_mid(x), shidu_hig(y))
rule9 = lambda x, y: min(wendu_hig(x), shidu_hig(y))
rule_val = [[rule1, rule2, rule3], [rule4, rule5, rule6], [rule7, rule8, rule9]] # 设备运行时间隶属度
rule_map = [['中', '长', '长'], ['短', '中', '中'], ['长', '短', '中']] # 建立设备运行时间映射表
3. 先带入题目条件所给的温度(64℃)和湿度(%)值,测试所构建的隶属度函数是否正确,将最终结果保留三位小数,输出结果如下截图所示:
wendu, shidu = 64, 22
wv_low, wv_mid, wv_hig = wendu_low(wendu), wendu_mid(wendu), wendu_hig(wendu)
sv_low, sv_mid, sv_hig = shidu_low(shidu), shidu_mid(shidu), shidu_hig(shidu)
print(f"在温度为{wendu}℃时,温度为低的隶属度值为{round(wv_low, 3)},温度为中的隶属度值为{round(wv_mid, 3)}, 温度为高的隶属度值为{round(wv_hig, 3)}")
print(f"在湿度为{shidu}%时,湿度为低的隶属度值为{round(sv_low, 3)},湿度为中的隶属度值为{round(sv_mid, 3)}, 湿度为高的隶属度值为{round(sv_hig, 3)}")
4. 下面封装模糊规则库的隶属度计算函数get_table_of_rule,将题目中所给的64℃与22%湿度带入,并将隶属度值填入专家提供的模糊规则控制表中,运行结果如下:
# 模糊规则库隶属度计算函数
def get_table_of_rule(rule_val, wendu, shidu):
rule_membership = np.zeros((3, 3)) # 所有模糊规则的隶属度值
print("下列输出从左到右温度依次由低到高,从上到下湿度依次由小到大:")
for i in range(3):
for j in range(3):
rule_membership[i][j] = round(rule_val[i][j](wendu, shidu), 3)
print(rule_membership[i][j], end="\t")
print('\n')
return rule_membership
wendu, shidu = 64, 22
rule_membership = get_table_of_rule(rule_val, wendu, shidu)
表三 在温度为64℃,湿度为22%下模糊控制规则的隶属度值
湿度 \ 温度 | 低 | 中 | 高 |
小 | 中(0.000) | 长(0.075) | 长(0.075) |
中 | 短(0.000) | 中(0.467) | 中(0.100) |
大 | 长(0.000) | 短(0.000) | 中(0.000) |
5. 下面封装计算激活的模糊规则强度函数membership_of_activation_rules,使用max方法计算合并激活规则之后的隶属度值,通过计算得到设备运行时间为短的强度为0.0,设备运行时间为中的强度为0.467,设备运行时间为长的强度为0.075;
def membership_of_activation_rules(rule_membership):
actRuleMembership = {'短': 0.0, '中': 0.0, '长': 0.0} # 激活规则的强度
for i in range(3):
for j in range(3):
if rule_map[i][j] == '短':
actRuleMembership['短'] = max(actRuleMembership['短'], rule_membership[i][j])
elif rule_map[i][j] == '中':
actRuleMembership['中'] = max(actRuleMembership['中'], rule_membership[i][j])
else:
actRuleMembership['长'] = max(actRuleMembership['长'], rule_membership[i][j])
print("将激活规则合并之后的强度如下:")
print(actRuleMembership)
return actRuleMembership
actRuleMembership = membership_of_activation_rules(rule_membership) # 调用
6. 下面封装设备的运行时间计算函数get_operation_time,利用步骤5计算得到的激活规则强度传入函数即可;(这里利用书上的典型值法求的最终的结果)
def get_operation_time(actRuleMembership):
# 利用典型值法求解最终设备运行时间
typical_val = {'短': 100, '中': 500, '长': 1000}
operation_time = round((actRuleMembership['短'] * typical_val['短'] + actRuleMembership['中'] * typical_val['中'] + actRuleMembership['长'] * typical_val['长']) / (actRuleMembership['短'] + actRuleMembership['中'] + actRuleMembership['长']), 2)
return operation_time
operation_time = get_operation_time(actRuleMembership) # 调用
print(f"在温度为{wendu}℃,湿度为{shidu}%的环境下,设备运行时间为{operation_time}s")
7. 最后封装通用的计算设备运行时间的函数,通过输入温度值与湿度值即可得到最终的设备运行时间,这里通过随机生成10组温度值与湿度值结算最终的运行时间;
def general_get_operation_time(rule_val, wendu, shidu):
rule_membership = get_table_of_rule(rule_val, wendu, shidu)
actRuleMembership = membership_of_activation_rules(rule_membership)
operation_time = get_operation_time(actRuleMembership)
print(f"在温度为{wendu}℃,湿度为{shidu}%的环境下,设备运行时间为{operation_time}s")
wendu = np.random.randint(0, 81, size=10)
shidu = np.random.randint(30, 61, size=10)
for i in range(10):
general_get_operation_time(rule_val, wendu[i], shidu[i])
表四 不同温度与湿度下设备的运行时间
温度(℃) | 79 | 68 | 47 | 63 | 51 | 15 | 76 | 71 | 8 | 14 |
湿度(%) | 48 | 54 | 41 | 33 | 51 | 38 | 41 | 47 | 50 | 44 |
运行时间(s) | 472.02 | 233.33 | 310.65 | 500.0 | 100.0 | 283.99 | 367.0 | 291.3 | 1000.0 | 858.78 |
方式二
第二种方式,利用python中封装好的scikit-fuzzy库实现该自动控制系统的计算,最终的计算结果采用质心法得到。
1. 导入模糊逻辑的库以及用numpy辅助计算
import numpy as np
import skfuzzy as fuzz
from skfuzzy import control as ctrl
2. 利用Antecedent函数创建输入和输出变量
temperature = ctrl.Antecedent(np.arange(0, 101, 1), 'temperature')
humidity = ctrl.Antecedent(np.arange(0, 61, 1), 'humidity')
time = ctrl.Consequent(np.arange(0, 1001, 1), 'time')
3. 利用trimf函数定义温度、湿度以及运转时间的隶属度函数
temperature['low'] = fuzz.trimf(temperature.universe, [0, 0, 40])
temperature['mid'] = fuzz.trimf(temperature.universe, [20, 53, 80])
temperature['high'] = fuzz.trimf(temperature.universe, [60, 100, 100])
humidity['small'] = fuzz.trimf(humidity.universe, [0, 0, 25])
humidity['mid'] = fuzz.trimf(humidity.universe, [15, 30, 45])
humidity['large'] = fuzz.trimf(humidity.universe, [30, 60, 60])
time['short'] = fuzz.trimf(time.universe, [0, 0, 350])
time['mid'] = fuzz.trimf(time.universe, [250, 500, 750])
time['long'] = fuzz.trimf(time.universe, [650, 1000, 1000])
4. 利用Rule函数定义模糊规则
# 定义模糊规则
rule1 = ctrl.Rule(temperature['low'] & humidity['small'], time['mid'])
rule2 = ctrl.Rule(temperature['low'] & humidity['mid'] , time['short'])
rule3 = ctrl.Rule(temperature['low'] & humidity['large'], time['long'])
rule4 = ctrl.Rule(temperature['mid'] & humidity['small'], time['long'])
rule5 = ctrl.Rule(temperature['mid'] & humidity['mid'] , time['mid'])
rule6 = ctrl.Rule(temperature['mid'] & humidity['large'], time['short'])
rule7 = ctrl.Rule(temperature['high'] & humidity['small'], time['long'])
rule8 = ctrl.Rule(temperature['high'] & humidity['mid'] , time['mid'])
rule9 = ctrl.Rule(temperature['high'] & humidity['large'], time['mid'])
5. 创建模糊控制系统
operation_ctrl = ctrl.ControlSystem([rule1, rule2, rule3, rule4, rule5, rule6, rule7, rule8, rule9])
6. 定义设备运转时间的计算函数,通过封装函数即可实现通过输入温度和湿度计算出最终的运转时间,在这里scikit-fuzzy内部使用的质心法计算最终输出,与方法一不同
def get_operation_time(temperature, humidity):
operation = ctrl.ControlSystemSimulation(operation_ctrl)
operation.input['temperature'] = temperature
operation.input['humidity'] = humidity
operation.compute()
return operation.output['time']
7. 函数调用
temperature = 64
humidity = 22
operation_time = get_operation_time(temperature, humidity)
print(f"在温度为{temperature}℃,湿度为{humidity}%的情况下,设备能够运行的时间为{operation_time}s")
8. 随机生成多组温度与湿度计算运行时间
temperature = np.random.randint(0, 41, size=10)
humidity = np.random.randint(30, 61, size=10)
for i in range(10):
operation_time = round(get_operation_time(temperature[i], humidity[i]), 2)
print(f"在温度为{temperature[i]}℃,湿度为{humidity[i]}%的情况下,设备能够运行的时间为{operation_time}s")
方式三(MATLAB仿真)
第三种方式,利用MATLAB对该自动控制系统进行设计与仿真处理。
1. 首先在MATLAB命令行输入fuzzy创建模糊推理器,后续在该控制器上进行输入输出变量以及模糊规则等设计;
2. 由于自动控制系统有温度与湿度两个输入变量,因此需要在该模糊推力器中再添加一个输入变量,点击Edit中的Add Variable下的Input添加;
3. 在该控制器的Name处对输入输出变量进行命名,然后通过双击变量(图中的黄色与蓝色区域)对其隶属度函数进行设置,在隶属度设置界面左侧有Range属性,右侧有Name、Type和Params属性,以温度为低的隶属度曲线为例,Range设置为[0 100],Name命名为低,Type选择trimf,Params输入[0 0 40],其余变量同理设置即可,如下图所示;
4. 下面close隶属度函数设置界面,点击Edit中的Rules设置模糊控制规则库,Connection用来设置输入变量的关系,按专家给出的模糊控制规则表一共设置一下九条规则:
5. 点击View中的Surface Viewer查看输入输出的变量曲面,点击Rule Viewer可以查看对具体的输入对应的输出情况;
6. 在Rule Viewer中可以手动设置温度与湿度的值,右上角即可查看运行时间的最终输出;
四、实验体会
本次实验通过三种方式实现了自动控制系统的模糊逻辑,最大的收获是让我进一步认识了模糊逻辑,同时也了解到了模糊逻辑在生活中的运用。与此同时,通过手动编写模糊逻辑的代码,让我进一步认识到了模糊逻辑的实现原理。
在实现此实验之前,我查询了相关资料,模糊逻辑可以利用python中的scikit-fuzzy实现,同时也可以利用MATLAB中的Fuzzy Logic Toolbox工具包实现,因此,我对以上两种方式都进行了尝试。第一份代码是利用python中的scikit-fuzzy库函数编写的,通过了解该库中模糊逻辑的函数原理,我开始了第二份代码的编写,也就是不使用scikit-fuzzy现有的函数,纯手动进行了模糊逻辑的计算实现,最终结果也符合预期,并且达到了实验目的,即通过简单的输入温度与湿度值即可得到最终的设备运行时间。在编写完这两份代码之后,我学习了MATLAB中模糊逻辑的工具包,再次对该自动控制系统进行了仿真,最终实验结果也与预期的结果一样,同时也实现了通过简单输入即可得到运行时间的目的!
标签:上机,模糊,控制系统,shidu,humidity,time,湿度,wendu From: https://blog.csdn.net/m0_73962294/article/details/143169320