65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 mvvm light 和 OxyPlot 的模糊库,带有 GUI

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (4投票s)

2014年9月8日

CPOL

2分钟阅读

viewsIcon

24073

downloadIcon

2

具有 GUI 并使用 Lagrange 插值生成成员曲线的模糊库

引言

这段代码是一个模糊评估器,它接受一些清晰值作为输入,并评估一个新的清晰值作为输出。我的主要目标是创建一个具有良好GUI的模糊评估器,并且易于通过使用C#运算符重载进行设置。

背景

因为我正在为我的太阳能加热系统开发一个应用程序,所以我需要一个具有良好GUI的模糊逻辑评估器,而这段代码就是一个衍生产品。

使用代码

主要的类是SetResult,它是用名称和最小/最大清晰输出值创建的。

// create result set 
Motor = new Fuzzy.SetResult("Motor", 0, 30);

然后添加波形。 波形是使用拉格朗日曲线拟合算法创建的,因此我们只需要指定名称和零点。 我已经预定义了一些常用的波形,但是很容易创建新的波形。

Motor += WaveForm.ParabolicLow("SLOW", -20, 0, 20); 
Motor += WaveForm.Parabolic("MEDIUM", 10, 20); 
Motor += WaveForm.ParabolicHigh("FAST", 10, 30, 40);

然后以相同的方式创建输入集,参数 2,(0 和 1)是Evaluate 中描述的输入的索引。

// create a "input" 
set Fuzzy.Set Temperature = new Fuzzy.Set("Temperature", 0, 20, 90); 
Temperature += WaveForm.ParabolicLow("LOW", 0, 20, 40); 
Temperature += WaveForm.Parabolic("MEDIUM", 30, 80); 
Temperature += WaveForm.ParabolicHigh("HIGH", 60, 90, 120); 
// create a "input" 
set Fuzzy.Set DeltaTemperature = new Fuzzy.Set("DeltaTemperature", 1, 0.0, 5.0); 
DeltaTemperature += WaveForm.ParabolicLow("LOW", -2.5, 0, 2.5); 
DeltaTemperature += WaveForm.Parabolic("MEDIUM", 2.0, 3.0); 
DeltaTemperature += WaveForm.ParabolicHigh("HIGH", 2.5, 5.0, 7.5);

由于我还没有看到任何在 C# 中定义规则的好方法 - 我想出了这个,它使用重载,首先我定义了 If 和 THEN 类,它们使用 Fuzzy 论文通常使用的语言,但我对显式的方式更满意,用参数声明规则,规则和 IF 逻辑通过重载存储在“Motor”对象中。 我有 ==, !=, & , | 的重载。

// create rules 
// explicit 
new Fuzzy.Rule("Rule FAST", Temperature == "LOW" & DeltaTemperature == "LOW", Motor == "FAST"); 
new Fuzzy.Rule("Rule MEDIUM", Temperature != "MEDIUM" & DeltaTemperature == "LOW", Motor == "MEDIUM"); 
new Fuzzy.Rule("Rule MEDIUM", Temperature == "HIGH" | DeltaTemperature == "LOW", Motor == "MEDIUM"); 
// or implicit 
new IF(Temperature == "HIGH" & DeltaTemperature == "HIGH", new THEN(Motor == "SLOW")); 
// etc

可以通过GUI更改曲线(零点)(右键单击并选择成员函数)。
因此为了不丢失新的设置,我添加了一个零点的XML生成器,可以保存和重新加载。

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
{ 
	// store settings 
	String xmlStore = Motor.GetXml(); 
	// Debug.WriteLine(xmlStore); 
	Settings.Default.SetResultXML = xmlStore; 
	Settings.Default.Save(); 
}

并在程序初始化时加载。

// load setting if exist 
if (!String.IsNullOrEmpty(Settings.Default.SetResultXML) && 
Settings.Default.SetResultXML.Contains("SetResult")) 
{ 
	Motor.LoadXml(Settings.Default.SetResultXML); 
}

接下来是连接GUI和模糊逻辑。

GUI是在代码中定义的,因为我们不知道在设计时要使用多少个集合! 实际上我们知道,但是我希望 GUI 用代码来更改,而不是必须手动更改代码和 WPF。

// Create/Connect UI, only neede if you want UI feedback. 
ucFuzzySet set = new ucFuzzySet(Motor); 
set.Height = 100; 
wpfFuzzySet.Children.Add(set); 
Motor.UpdateUI(); 
foreach (Fuzzy.Set S in Motor.Sets) 
{ 
	set = new ucFuzzySet(S); 
	set.Height = 100; 
	wpfFuzzySet.Children.Add(set); 
	S.UpdateUI(); 
}

模糊逻辑的执行是通过调用 Motor.COG 完成的,我已经实现了经常使用的重心法。 参数按照 Set 声明中的参数 2 索引。

public void Evaluate() 
{ 
	Double result = Motor.COG(wpfTemp.Value, wpfDelta.Value); 
}

我还没有找到一个绝妙的方法来摆脱调用 ucFuzzySet(Motor); 中的 Set,因为这一定会破坏 MVVM 模式!!也许使用 MVVM 消息传递可以解决这个问题。

关注点

最奇怪的事情是使用拉格朗日来制作用于成员函数的曲线。 该代码还演示了 MVVM light 工具包和 OxyPlot 库的一些用法。

© . All rights reserved.