RIP RETE时间获得PHREAKY
我剛剛完成了我稱為PHREAK的新規則算法的一些高級文檔,這是混合推理中的一個文字游戲。 它仍然有點粗糙和高水平,但希望仍然很有趣。 它建立在ReteOO之上,非常好閱讀。
ReteOO算法
ReteOO是在3、4和5系列發行版中開發的。 它采用RETE算法并應用了眾所周知的增強功能,現有的學術文獻都涵蓋了所有這些增強功能:
- 節點共享
共享同時應用于Alpha和Beta網絡。 Beta網絡共享始終來自根模式。
- 字母索引
具有許多子級的Alpha節點使用哈希查找機制,以避免測試每個結果。
- Beta索引連接,不存在節點和存在節點使用哈希索引它們的內存。 這減少了相等檢查的聯接嘗試。 最近,范圍索引已添加到“不存在”中。
- 基于樹的圖
聯接匹配不包含對其父項或子項匹配的任何引用。 刪除將不得不再次重新計算所有聯接匹配,這涉及到重新創建所有那些聯接匹配對象,以便能夠找到應刪除元組的網絡部分。 這稱為對稱傳播。 樹形圖提供了父級和子級引用,因此刪除僅需遵循這些引用即可。 這是不對稱傳播。 結果更快,對GC的影響更小,并且更可靠,因為值的更改不會在不通知引擎的情況下導致內存泄漏。
- 就地修改
傳統的RETE將修改實現為刪除+插入。 這將導致所有聯接元組都經過GC處理,其中許多作為插入的一部分再次被重新創建。 相反,就地修改傳播為單遍,檢查每個節點
- 反應性
也稱為“新觸發條件”。 允許更精細的反應性來更新。 模式可以對特定屬性的更改做出反應,而忽略其他屬性。 這樣可以減輕遞歸問題,并有助于提高性能。
- 子網
否,“存在”和“累積”可以各自具有嵌套的條件元素,這些條件元素構成了子網。
- 向后鏈接
支持用于反向鏈接的Prolog樣式派生樹。 該實現是基于堆棧的,因此對于大型圖不存在方法遞歸問題。
- 懶惰真相維護
真相維護會產生運行時成本,無論是否使用TMS,都會產生運行時成本。 惰性TMS僅在首次使用時將其打開。 此外,它僅針對該對象類型啟用,因此其他對象類型不會產生運行時成本。
- 基于堆的議程
議程使用二進制堆隊列按顯著性對規則匹配進行排序,而不是使用任何線性搜索或維護方法。
- 動態規則
可以在運行時添加和刪除規則,而引擎仍將填充數據。
PHREAK算法
Drools 6引入了一種新算法,試圖解決RETE的一些核心問題。 該算法不是從頭開始重寫的方法,它結合了ReteOO的所有現有代碼及其所有增強功能。 盡管PHREAK是RETE算法的改進,但它不再被歸類為RETE實現。 就像動物進化超過特定點并改變關鍵特征一樣,該動物也被歸類為新物種。 無論優化如何,有兩個關鍵的RETE特征可強烈識別任何衍生菌株。 這是一個渴望的,面向數據的算法。 在插入,更新或刪除操作期間完成所有工作的位置; 急于產生所有規則的所有部分匹配。 相比之下,PHREAK被描述為一種懶惰的,面向目標的算法。 其中部分匹配會被嚴重延遲。
RETE的這種渴望會導致大型系統中的大量用戶流失,并浪費大量工作。 浪費的工作歸類為不會導致解雇的匹配工作。
PHREAK受到許多算法的啟發。 包括(但不限于)LEAPS,RETE / UL和面向集合的匹配。 PHREAK具有ReteOO部分中列出的所有增強功能。 此外,它還添加了以下增強功能集,將在以下各段中進行詳細說明。
- 三層上下文記憶; 節點,段和規則存儲器。
- 基于規則,分段和節點的鏈接。
- 懶惰(延遲)規則評估。
- 孤立的規則評估。
- 面向集合的傳播。
- 基于堆棧的評估,包括暫停和繼續。
當PHREAK引擎啟動時,所有規則都被認為是未鏈接的,因此,當規則未鏈接時,將不會進行任何規則評估。 進入Beta網絡之前,插入,更新和刪除操作已排隊。 根據最有可能導致解雇的規則,使用一種簡單的啟發式方法來選擇下一個評估規則; 這會延遲評估和觸發其他規則。 盡管尚未完成任何工作,但只有在規則中填充了所有正確輸入后,該規則才被視為已鏈接。 而是創建一個代表規則的目標,并將其放入優先級隊列中。 這是由顯著性命令的。 每個隊列本身都與AngendaGroup相關聯。 只有活動的AgendaGroup會檢查其隊列,以最高顯著性彈出規則的目標,并將其提交評估。 因此,完成的工作從插入,更新,刪除階段轉移到fireAllRules階段。 僅評估為其創建目標的規則,而根據這些事實進行的其他潛在規則評估將被延遲。 在評估各個規則時,仍然可以通過分段過程來實現節點共享,這將在后面說明。
RETE中每次成功的加入嘗試都會生成一個元組(或令牌,或部分匹配),該元組將傳播到子節點。 因此,它被描述為面向元組的算法。 對于到達的每個子節點,它將嘗試與該節點的另一側進行聯接,再次,每次成功的聯接嘗試都將立即傳播。 這將產生下降遞歸效果。 當節點網絡從進入beta網絡的點到所有可到達的葉節點上下左右波動時,對節點網絡進行處理。
PHREAK傳播是面向集合(或面向集合)的,而不是面向元組的。 對于正在評估的規則,它將訪問第一個節點并處理所有排隊的插入,更新和刪除。 將結果添加到集合中,并將該集合傳播到子節點。 在子節點中,所有排隊的插入,更新和刪除都將被處理,并將結果添加到同一集合中。 完成后,該集合將傳播到下一個子節點,依此類推,直到到達終端節點。 這將創建一個單一的管道類型效果,該效果與當前正在評估的規則隔離。 這將創建批處理效果,可以為某些規則構造提供性能優勢。 例如具有累積作用的子網。 將來,它將依靠多種方式來利用多核計算機。
鏈接和取消鏈接使用基于網絡分段的分層位掩碼系統。 構建規則網絡后,將為由同一組規則共享的節點創建分段。 規則本身是由段的路徑組成的,盡管如果沒有共享,則將是一個段。 將位掩碼偏移量分配給段中的每個節點。 另外,將另一個位掩碼(分層)分配給規則路徑中的每個段。 當至少有一個輸入(數據傳播)時,節點的位設置為on。 每個節點的位設置為on時,段的位也設置為on。 相反,如果任何節點的位設置為關閉,則該段也將設置為關閉。 如果將規則路徑中的每個細分均設置為啟用,則將規則鏈接到該規則中,并創建一個目標來計劃該規則以進行評估。 相同的位掩碼技術還用于跟蹤臟節點,段和規則。 如果自上次評估以來認為已變臟的規則,則可以安排已鏈接的規則進行評估。
這樣可以確保沒有規則會評估部分匹配,如果由于其中一個聯接沒有數據而導致它無法導致規則實例的情況,則不會評估。 這在RETE中是可能的,并且即使最后一個連接為空,也會為所有節點產生混亂的匹配嘗試。
雖然增量規則評估始終從根節點開始,但臟位掩碼用于允許跳過不臟的節點和段。
使用每個節點至少存在一項數據是一種相當基本的啟發式方法。 未來的工作將試圖進一步延遲鏈接; 使用諸如弧一致性的技術來確定匹配是否會導致規則實例觸發。
由于RETE僅具有一個單一的存儲器單元(節點存儲器),因此PHREAK具有3個級別的存儲器。 這樣可以在評估規則期間獲得更多的上下文理解。
PHREAK 3分層存儲系統
示例1顯示了具有三種模式的一條規則; A,B和C。它形成單個段,節點的位1、2和4。
示例1:單一規則,不共享
示例2演示了添加另一個共享模式A的規則時會發生的情況。A放置在其自己的細分中,每個規則導致兩個細分。 這兩段構成了各自規則的路徑。 第一條路段由兩條路徑共享。 當鏈接A時,該段將被鏈接,然后迭代該段共享的每個路徑,將位1設置為on。 如果稍后打開B和C,則鏈接到路徑R1的第二段; 這將導致R1的位2被打開。 將R1的位1和位2設置為打開后,現在將鏈接該規則,并創建一個目標以計劃該規則以供以后評估和觸發。
評估規則時,正是可以共享匹配結果的細分。 每個段都有一個臨時存儲器,用于將該段的所有插入,更新和刪除排隊。 如果要評估R1,它將處理A并得到一組元組。 該算法檢測到有分段分割,并將為集合中的每個插入,更新和刪除創建對等元組,并將它們添加到R2的暫存中。 這些元組將與任何現有的暫存元組合并,并等待R2最終被評估。
示例2:共享的兩個規則
示例3添加了第三條規則,并演示了共享A和B時發生的情況。 這次僅顯示段的位。 證明R4具有3個段,R3具有3個段,R1具有2個段。 A和B由R1,R3和R4共享。 而D由R3和R4共享。
示例3:共享的三個規則
當“不存在,存在或累積”節點包含多個元素時,形成子網。 在示例4中,“ B not(C)”形成子網,請注意,“ not(C)”是單個元素,不需要子網,并且在Not節點內部合并。
子網擁有自己的網段。 R1仍具有兩個段的路徑。 子網形成了另一個“內部”路徑。 鏈接子網時,它將鏈接到外部網段。
示例4:單規則,具有子網且不共享
示例5顯示了可以通過不具有子網的規則對子網節點進行分片。 這導致子網段被分成兩個部分。
示例5:兩條規則,一條與子網共享
并非具有約束的節點和累積節點都具有特殊的行為,并且永遠無法取消鏈接段,并且始終將其視為打開狀態。
所有規則評估都是遞增的,不會浪費已經重新產生的工作重新計算匹配項。
評估算法基于堆棧,而不是方法遞歸。 通過使用StackEntry表示要評估的當前節點,可以隨時暫停和恢復評估。
當規則評估到達子網時,將為外部路徑段和子網段創建StackEntry。 首先評估子網段,當集合到達子網路徑的末尾時,將其合并到其饋入的外部節點的暫存列表中。 然后恢復先前的StackEntry,在其中可以處理子網的結果。 這樣做的另一個好處是,所有工作在傳播到子節點之前都將被成批處理; 這對于累積節點效率更高。
相同的堆棧系統可用于有效的反向鏈接。 當規則評估到達查詢節點時,它會通過將其放在堆棧上來再次暫停當前評估。 然后對查詢進行評估,生成結果集,該結果集保存在內存位置中,以供恢復的StackEntry拾取并傳播到子節點。 如果查詢本身調用了其他查詢,則該過程將重復,暫停當前查詢,并為當前查詢節點設置新的評估。
關于性能的最后一點。 通常,使用PHREAK的單個規則不會比使用RETE更快。 對于使用根上下文對象啟用和禁用匹配的給定規則和相同數據集,它們都嘗試相同數量的匹配并產生相同數量的規則實例,并且花費的時間大致相同。 除了帶有子網的用例和積累。
但是,對于規則編寫得不好的規則庫,PHREAK可以認為比RETE更寬容,并且隨著規則數量和復雜性的增加,性能會更適度地下降。
RETE還將為不包含所有聯接的數據的規則生產部分機器。 PHREAK會避免這種情況。
因此,并不是說PHREAK比RETE快,它不會隨系統的增長而變慢。
AgendaGroups對RETE的性能沒有幫助,因為所有規則都在任何時候進行評估,而與組別無關。 顯著性也是如此。 這就是為什么經常使用根上下文對象來限制匹配嘗試的原因。 PHREAK僅評估活動議程組的規則,并且在該組內將嘗試避免評估(通過顯著性)不會導致規則實例觸發的規則。
通過PHREAK AgendaGroups和顯著性現在已成為有用的績效工具。 根上下文對象不再需要,并且有可能對性能產生反作用,因為它們會強制刷新和重新生成規則的匹配項。
翻譯自: https://www.javacodegeeks.com/2013/11/r-i-p-rete-time-to-get-phreaky.html
總結
以上是生活随笔為你收集整理的RIP RETE时间获得PHREAKY的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 路由器不用了怎么关闭如何才能把路由器关闭
- 下一篇: 如何更换路由器密码如何转移路由器账号密码