• 沒有找到結果。

程式碼的再利用-繼承 FuzzyControl 類別

第七章 類別庫的運用與模糊控制器的軟體實作

7.1 程式碼的再利用-繼承 FuzzyControl 類別

在第六章的最後,我們曾經提到的 FuzzyControl 類別,它本身只 定義了基本的行為而已,基中的成員函式 DoCreateFuzzyValue 和 DoCreateRule 並沒有定義任何的程式碼,而在上一章也已提到了,是 由於無法事前得知所要實作的“案例”究竟為何,所以不能把程式碼 一開始就寫死在類別中。而本章就要繼承 FuzzyControl 類別,並且覆 寫 DoCreateFuzzyValue 和 DoCreateRule 兩個成員函式。

首先,我們將訂定一個類別,命名為 MyFuzzyControl,而它是繼 承自 FuzzyControl 類別:

class MyFuzzyControl : public FuzzyControl {

public:

virtual void DoCreateFuzzyValue( ) //將重新定義(覆寫)

{ }

virtual void DoCreateRule( ) //將重新定義(覆寫)

{ } };

在 MyFuzzyControl 類別,只有 DoCreateFuzzyValue 和 DoCreateRule 兩個成員函式,而這兩個函式也正覆寫了父類別的同名函式(即使父 類別並沒有定義),既然是針對“案例”,理所當然的要覆寫它們。

重新來看看我們的案例吧!在 MyFuzzyControl 類別中,只有 DoCreateFuzzyValue 和 DoCreateRule 兩個函式要填入程式碼,顧名思 意,我們就看案例中,模糊變數和控制規則的部份即可。首先是表示 車子與目的地的模糊變數 s:(如圖 7-1)

VC C SF F VF 1

0 200 400 600 800 1000 1200

圖 7-1 距離 s 的模糊變數

根據以上的模糊變數,我們可以在 DoCreateFuzzyValue 函式寫出下列 的程式碼:

FuzzyValueBuilder FVBUilder; //建立一個 FuzzyValueBuilder 物件

FVBuilder.BuildFuzzyValue("Distance",0,1200); //建立模糊變數 FVBuilder.BuildZTypeFunc("VC",200,400); //加入歸屬函數

FVBuilder.BuildLambdaTypeFunc("C",200,400,600); //加入歸屬函數 FVBuilder.BuildLambdaTypeFunc("SF",400,600,800); //加入歸屬函數 FVBuilder.BuildLambdaTypeFunc("F",600,800,1000); //加入歸屬函數 FVBuilder.BuildSTypeFunc("VF",800,1000); //加入歸屬函數

m_pFirstValue = FVBuilder.GetFuzzyValue( ); //FVBuilder 物件傳回“成品”

在建模糊變數之前,要先建立一個 FuzzyValueBuilder 物件來幫助我 們建立模糊變數,而在物件生成模式 Builder 之下,很快的,我們就 得到了一個表示距離 s 的模糊變數。最後的 m_pFirstValue 是 FuzzyControl 的資料成員,當然 MyFuzzyControl 也繼承了它,而它是 一個 FuzzyValue 型別的指標變數。

接下來是汽車速度 v 的模糊變數:(如圖 7-2)

VLS LS MS HS VHS 1

0 100 200 300 400 500 600

圖 7-2 汽車速度 v 的模糊變數

承續剛剛的程式碼,接下來的程式碼如下:

FVBuilder.BuildFuzzyValue("Speed",0,600); //建立模糊變數 FVBuilder.BuildZTypeFunc("VLS",100,200); //加入歸屬函數

FVBuilder.BuildLambdaTypeFunc("LS",100,200,300); //加入歸屬函數 FVBuilder.BuildLambdaTypeFunc("MS",200,300,400); //加入歸屬函數 FVBuilder.BuildLambdaTypeFunc("HS",300,400,500); //加入歸屬函數 FVBuilder.BuildSTypeFunc("VHS",400,500); //加入歸屬函數

m_pSecondValue= FVBuilder.GetFuzzyValue( ); //FVBuilder 物件傳回“成品”

FuzzyValueBuilder 物件是可以一再使用的,並不需要再另外建立一 個。而在建立表示距離 s 的模糊變數時,FuzzyValueBuilder 物件已經

把“成品”傳給了 m_pFirstValue 了,所以此時建立代表汽車速度 v 的模糊變數時,並沒有覆蓋掉前一個模糊變數的情況。

最後是輸出值 vout 的模糊變數:(如圖 7-3)

VLS LS MS HS VHS 1

0 100 200 300 400 500 600

圖 7-3 控制器的輸出值 vout 的模糊變數

而成員函式 DoCreateFuzzyValue 接下來的程式碼如下:

FVBuilder.BuildFuzzyValue("Output",0,600); //建立模糊變數 FVBuilder.BuildZTypeFunc("VLS",100,200); //加入歸屬函數

FVBuilder.BuildLambdaTypeFunc("LS",100,200,300); //加入歸屬函數 FVBuilder.BuildLambdaTypeFunc("MS",200,300,400); //加入歸屬函數 FVBuilder.BuildLambdaTypeFunc("HS",300,400,500); //加入歸屬函數 FVBuilder.BuildSTypeFunc("VHS",400,500); //加入歸屬函數

m_OutputValue = FVBuilder.GetFuzzyValue( ); //FVBuilder 物件傳回“成品”

以上三段程式碼即是要填在 DoCreateFuzzyValue 函式的部份,代表著 三個模糊變數的建立。而在建立完成並且 FuzzyValueBuilder 物件也 分別將“成品”傳給了 m_pFirstValue、m_pSecondValue 和

m_pOutputValue 之後,隨著 DoCreateFuzzyValue 函式區段(scope)

的消失,FuzzyValueBuilder 物件也將消失,而在此它也完成了建立模

糊變數的任務。也因為這個 DoCreateFuzzyValue 函式中有實際操作 FuzzyValueBuilder 物件,所以理所當然的在 Builder 模式的規劃下,

MyFuzzyValue 類別是此模式中的 Director。

完成了 DoCreateFuzzyValue 函式的部份,接著就是負責建立控制 規則庫的 DoCreateRule 函式,首先先回顧一下在第五章中整理好的 控制規則:(如圖 7-4)

圖 7-4 控制規則表

而根據上表,我們先在 DoCreateRule 函式填入表示第 1 條規則的程 式碼:

m_pFuzzyRuleBase = new FuzzyRuleBase; //建立一個 FuzzyRuleBase 物件 m_pFuzzyRuleBase->AddRule(m_pFirstValue->GetFunc("VC"),

m_pSecondValue->GetFunc("VLS"), m_pOutputValue->GetFunc("VLS"));

//建立第 1 條規則

v

s VLS LS MS HS VHS VC VLS VLS VLS VLS VLS C MS MS LS LS VLS SF HS HS MS LS VLS F VHS HS HS MS MS VF VHS VHS VHS VHS VHS

建立第 1 條規則之前,必須先建立一個 FuzzyRuleBase 物件,並回傳 該物件指標給 m_pFuzzyRuleBase,而此指標變數是 MyFuzzyControl 類別的資料成員,當然,是繼承自 FuzzyControl 類別。而之後我們就 以 m_pFuzzyRuleBase 這個指標變數“操作”FuzzyRuleBase 物件來 加入新的控制規則。(至於剩下的第 2 條至第 25 條,請詳見附錄的完 整程式碼)