rete算法

 舊文回頭來看,有很多地方比較模糊,可惜我現在找不到jess的源代碼了,否則可以好好再看看實現細節,先搬過來再說,以後在研究啦,作爲入門湊合着看吧。

Rete算法是Charles Forgy在1979年的論文中首次提出的,針對基於規則知識表現的模式匹配算法。目前來說,大部分規則引擎還是基於rete算法作爲核心,但都有所改進,比如drool,jess等等,下面介紹rete算法的概念,一些術語,以及使用規則引擎需要注意的問題。

先來看看如下的表達式:

     (name-of-this-production
        LHS /* one or more conditions */
       -->
        RHS /* one or more actions */
      )

 name-of-this-production就是規則,LHS(left hand side)一系列條件,RHS(right hand side)這個是我們滿足條件後應該執行的動作。

 

 

 

結合該圖介紹幾個概念:

    production memory(PM)是由所有的production形成。

    working memory(WM)由外界輸入根據匹配算法形成的,反映了運行中的規則引擎的狀態,記錄各種數據, WM中每一個item稱爲working memory element(WME) ,由外界的輸入產生。

    agenda負責匹配,衝突解決,執行動作。

 

rete是網絡的意思(拉丁語),它將所有的規則最終解釋(或編譯)生成一個識別網絡,其中包括了alpha網絡,beta網絡。alpha網絡是根據LHS生成的網絡,它根據外界的輸入快速識別是否存在condition成立,並且跟其beta網絡交互更新整個網絡的狀態,如下圖:

 

 

最基本的alpha網絡就如上圖所示,類似於這樣,所有的condition被parse到這樣的網絡,當外界輸入wme時,該wme會進入這樣一個網絡進行辨識,如果到達最底端,證明一個condition成立了,當然,如圖這個網絡算是最簡單的實現了,實際規則引擎需要提供更快速的算法去辨識輸入的wme,比如將圖中color的各種值存入hashtable,或者是jumptable,又或者是trie tree。整個alpha network是一個巨大的字符串匹配和過濾網絡,需要將各種數據結構組合在一起去實現海量condition情況下的快速匹配。各種規則引擎的實現又是不一致的,比如jess,如下圖:

 

 (defrule done
       (TESTING)
       (number ?number)
       (TEST IS DONE)
       (INIT CREDIT 5)
       (CUSTOMER AGE ?age)
       (has ?type "PP"))
=>
     (assert (TEST COMPLETED)))

 

 

這個production的解釋後生成的網絡,這裏我們先注意紅色的節點,這些節點就是alpha網絡的節點,這個圖只是描述了大致的過程,以第一列爲例,第一個紅色node表示輸入是否匹配TESTING這個字符串,第二個node匹配在TESTING後面的參數數量(slot)是否匹配0,如果我們assert TESTING進入WM,那麼這個fact是可以匹配到done這個rule的第一個condition的,其他可以依次類推,值得注意的是最後一個condition,has是我們自定義的function,類似這樣的function,jess沒有單獨生成一列,只是將它作爲CUSTOMER AGE ?age這一列的最後一個node,這樣的condition有個特點就是需要執行一段代碼去判斷某個事實是否成立(不僅僅只是做字符串的操作),這段代碼不僅僅是字符串的匹配,同時還具有實時性,類似這樣的condition開發中需要注意,因爲alpha network在運行期會不止一次去執行這個condition是否成立,這個是匹配算法的特性決定,所以,我們需要用cache或者規則語言的特性去避免不必要的執行code以提高性能。

 

下面貼個比較複雜的例子:

 

 

 

圖太大,一個截不下來。。。。。。

   下面我們結合兩個例子說說beta網絡,當alpha網絡過濾後condition成立,WME被傳遞到beta網絡時,綠色的node就要發揮作用了,這個node就是join node,它有兩個input,一個join node ,一個alpha node(紅色),join node是由多個WME組成的,對於初始的join node 我們稱爲left input adapter 如圖中黃色的node,該node是空的,那麼第一個把這個node作爲left input的join node就只包含了一個WME,下一個join node則包含了兩個WME,以此類推。圖中天藍色的node上方的join node 完全匹配了production執行需要的condition,所以這個rule就被激活等待執行了。

 

    假設我們需要編輯業務邏輯,那麼最好的描述載體就是流程圖,簡單的流程圖包含以下一些基本單元:起始節點,邏輯判斷,執行動作,結束節點。這些節點可以完成最簡單的業務邏輯描述,那麼我們把這些流程parse到規則的時候,我們會怎麼去做,第一個邏輯判斷單元返回true,於是我們執行某個動作,第二,三個邏輯判斷單元返回true我們執行某個動作,相當於會parse到兩個規則,符合condition1,production1觸發,符合condition2,3,production2觸發,有了beta網絡,我們在觸發production2時只需要判斷condition2,3是否成立,對於更復雜的情況,beta網絡提高了速度,避免了重複匹配。

   

    開發中使用規則引擎也遇到些問題,總結如下:

    1)規則引擎中對於特殊condition的處理,由於condition會在部分production中重複出現,所以會造成condition的重複匹配問題,影響了程序的性能,這個要結合項目去優化rule腳本的parse或者使用cache去提升性能。補充:可以將動態執行的condition放到LHS的最後,保證只有在必要的時候纔會執行,當然具體情況還得看具體rule engine的實現啦

    2)內存消耗問題,rete算法是空間換時間,所以對於內存的消耗是比較大的,特別是加載rule的時候(生成網絡),在運行期內存會緩慢增長,所以gc效率需要注意,同時單個服務器所能承受的壓力(多個WM)也跟規則引擎息息相關。

    3)測試,對於使用規則去表達業務的系統,如何測試是必須解決的問題,對於這個問題,也只能保證基本的流程分支覆蓋測試,對於複雜情況下的defect很難發現,不過有些原則需要注意,如果要使用規則引擎,我們必須完全以規則引擎爲核心,對於業務邏輯必須儘可能的抽取到規則引擎去實現,對於擴展實現的function粒度必須小且簡單,不要再代碼中去實現業務邏輯。

    4)大部分的condition需要是不變的,也就是說基本信息需要保持穩定不變。比如某客戶公司上屬集團信用額度大於100w這樣的condition,這個額度變化的頻度不會很高,不需要去實時匹配。

    5)remove WME production是較複雜的操作,規則較複雜時,應該儘量少去做這樣的操作。 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章