C# 中的 Takagi-Sugeno 模糊系统实现






4.64/5 (11投票s)
简单的 API,可根据 Takagi-Sugeno 模糊系统在 C# 中定义您自己的模糊系统。
引言
最近,在我的人工智能课程中,我被分配了一个需要使用模糊逻辑来解决简单问题的项目。这个想法是让一个踢足球的机器人根据一些简单的模糊规则去追逐足球。
像往常一样,我开始寻找一些现成的模糊系统实现(我知道,我知道,但这很有效!)。令我惊讶的是,我找到了很多关于这个主题的文章,但没有提供一个简单的框架来构建你自己的模糊系统。
因此,有了这篇文章。这里提供的代码并不是一个完整的模糊系统实现,而是为你自己的需求提供一个良好的起点。此外,我还包含了一个作为使用 FuzzyLogic 命名空间示例的踢足球机器人。
背景
这只是一个简单的模糊系统入门速成课程。它不是数学或形式化的,而是非常技术性的。
我们在日常编程中都使用逻辑,但这种逻辑是非真即假的。没有中间状态。这对于确定性情况非常有效。然而,我们的大脑并不是这样工作的,很少将事实视为完全真实或完全虚假。
模糊逻辑旨在通过消除绝对真假并赋予成员度来重现大脑的工作方式。这允许你了解一个变量在多大程度上属于一个值或另一个值。
基于我为踢足球机器人所做的研究,我对模糊系统是什么得出了这些结论:
- 语言变量:这些变量的值就是语言。例如:对于语言变量“方向”,可能的值可以是“北”、“东”、“南”和“西”。
- 隶属函数:这些函数接受一个精确值(角度)作为参数,并输出一个介于 0 和 1 之间的数字。每个语言值都有一个相关的隶属函数。隶属函数的想法是定义一个精确值与特定语言值相关的程度。最常见的隶属函数是:
- 线性,
- 三角形,和
- 梯形
例如,“北”这个语言值可以有一个参数为 a=0°、b=90° 和 c=180° 的三角形隶属函数。这意味着 45° 的角度与“北”这个语言值有 0.5 的隶属度。
- 模糊集:这些集合包含特定语言变量的所有可能的语言值,每个值都与同一个精确值的隶属度相关联。例如:由方向语言变量和精确值 80° 定义的集合将是
(direction, 80°) :== {(north, 0.9),(west,0),(south,0),(east,0.1)}
- 模糊规则:模糊规则基本上是 IF <条件> THEN <决策>。对于这个例子,条件部分的形式是 <语言变量 1> = <语言值 1> AND <语言变量 2> = <语言值 2> AND ...。在 Takagi-Sugeno 模糊系统中,决策部分是精确值的赋值。例如:IF direction=north AND direction=west THEN turn:=-15°。
基于 Takagi-Sugeno 的模糊规则集可以轻松地从所有模糊值计算出精确输出。模糊规则集将包含有限数量的规则,所有规则在决策部分具有相同的精确变量。精确变量的最终值将是每个规则的精确值的加权平均值。每个规则的权重由每个(<语言变量>,<语言值>)对的隶属度乘积决定。
Using the Code
当你查看代码时,你会发现它非常简单。由于它是为特定目的而开发的,类中缺少许多可能很有用的方法。然而,我努力使代码尽可能面向对象,以便其他人可以轻松地添加自己的代码。
让我们开始吧。该项目定义了一个新的 FuzzyLogic 命名空间,其中包含:
- 类
TagakiSugenoFuzzySystem
。此类允许你定义一组规则,所有规则都定义相同的精确变量并计算聚合的精确输出。 - 类
TagakiSugenoFuzzyRule
。此类定义了 Takagi-Sugeno 系统中的一条规则。它由语言值数组和一个精确输出定义。 - 接口
IMembershipFunction
。定义了一个接口,允许你为VariableValue
创建自己的隶属函数。 - 类
VariableValue
。定义了一个语言值,并具有一个IMembershipFunction
,它为特定值定义了一个Membership
函数。 - 类
Variable
。它由一个VariableValue
列表组成。 - 类
FuzzySet
。它将一个精确值与一个变量关联起来,并提供了一个方法来计算精确值与Variable
的每个VariableValue
的隶属度。
为了让你了解如何使用这个命名空间,我将带你浏览踢足球机器人示例。
示例
在这个示例中,我将定义一个模糊系统来引导踢足球机器人走向足球。为此,我定义了 2 个语言变量及其关联值,如下所示:
distance
:left
,center
,right
angle
:north
,west
,south
,east
角度指的是球相对于机器人航向的位置。距离定义了球在机器人左侧、中心还是右侧。
在附带的项目中,你可以找到 Form1
窗体的构造函数。这是我定义模糊系统来计算机器人车轮必须转动多少的地方。
我们开始定义系统及其变量:
distancia.addValue(new VariableValue
("left", new TriangleMembershipFunction(-4000, -10, 0)));
distancia.addValue(new VariableValue
("center", new TriangleMembershipFunction(-10, 0, 10)));
distancia.addValue(new VariableValue
("right", new TriangleMembershipFunction(0, 10, 4000)));
angulo.addValue(new VariableValue
("north", new TriangleMembershipFunction(0, 90, 180)));
angulo.addValue(new VariableValue
("west", new TriangleMembershipFunction(90, 180, 270)));
angulo.addValue(new VariableValue
("south", new TriangleMembershipFunction(180, 270, 360)));
angulo.addValue(new VariableValue
("east", new InverseTrapezoidalMembershipFunction(0, 90, 270, 360)));
接下来,我们定义系统将工作的模糊规则。这里是前三条:
system.addRule(new TagakiSugenoFuzzyRule(15, new string[] { "north", "left" }));
system.addRule(new TagakiSugenoFuzzyRule(0, new string[] { "north", "center" }));
system.addRule(new TagakiSugenoFuzzyRule(-15, new string[] { "north", "right" }));
让我们来看第一条规则。它说如果角度指向北方,并且球在机器人的左侧,车轮应该转动 15°。同样的逻辑适用于其余规则。
一旦模糊系统完全定义完毕,我们就可以开始输出结果。为此,我们定义系统的输入 FuzzySet
,如下所示:
FuzzySet setDistancia = new FuzzySet(distancia, robot.getDistancia(posPelota));
FuzzySet setAngulo = new FuzzySet(angulo, robot.getAngulo(posPelota));
FuzzySet[] sets = { setAngulo, setDistancia };
一旦集合就位,我们就可以将它们馈送到模糊系统以获得精确结果,并实现系统产生的决策。在这里,我们将机器人向前移动 5 个单位,方向是机器人转向后的方向,转向的角度由模糊系统给出的精确输出决定。
robot.angRobot += Math.PI * system.CrispOutput(sets) / 180;
robot.posRobot.X += (float)(5 * Math.Cos(robot.angRobot));
robot.posRobot.Y += (float)(5 * Math.Sin(robot.angRobot));
关注点
当前代码实现的一个严重限制是,每个规则必须具有完全相同的条件数量,并且顺序也必须相同。这很容易改变,但由于时间限制未能实现。如果社区有兴趣,我可以花时间来完成它,或者更好的是将其放到 SourceForge 上。
历史
- 2008-10-07:第一个版本