【正文】
Leaps 避免完全的叉集算法測試,僅僅留意主要的連接,因此當 Rete 可能建立數(shù)以百計 的激活規(guī)則時, Leaps僅僅建立一個,這導致了速度的量級增加。這再次說明在 Agenda中的應當按任意順序執(zhí)行的激活規(guī)則同樣遵循 LIFO/FIFO策略。當 Manners 在 Clips 中使用寬度( Breadth)策略執(zhí)行時不會進入無限循環(huán),在下一節(jié)會說明,它同樣不會根據(jù)座位的最高 pid 來激發(fā)已激活的規(guī)則,從沒有發(fā)現(xiàn)這種解決方案。因此,如果你直接將一個 OPS5 程序移植到CLIPS 中,但是使用默認的深度沖突解決策略,你只能在偶然情況下獲得正確的行為。該規(guī)則為 WorkingMemory 中所有的客人的所有座位安排建立叉集算法( cross product)解決方案。例如, a 實例激活規(guī)則 1和 2, b實例激活規(guī)則 3 和 4,如果 a比 b先設(shè)置,則規(guī)則 3和 4在 agenda 中將排在 1和 2前面。要特別注意的一點是,每一行有一個 pid 都比下一個要小,它的意義將會在“分配座位”規(guī)則的描述中說明。這些情景然后可以作為測試保存,增 加當規(guī)則發(fā)生變更時仍然按照用戶希望的工作的保證性。 你可以在規(guī)則編寫前提供測試來規(guī)定規(guī)則的行為。運行時系統(tǒng)只需要 droolscore 庫引用,就可以使用().addPackage(deserialized package object)載入該文件。 RuleBase 是可序列化的,因此它們能夠被當作二進制部署單元。 可以有許多更靈巧的辦法實現(xiàn)上面的案例, Drools 規(guī)則引擎十分的動態(tài),意味著許多組件能夠被動態(tài)交換( rules,packages)甚至有 working memory 正在使用的時候。另外,你可以下載droolsexamples 模塊,這是一個自包含的 Eclipse 項目。對于這個問題的解決方案是改變域?qū)ο?,能夠以一種更簡潔的方式表達商業(yè)模型。如果我們改變規(guī)則,使它更具有通用性,同樣的規(guī)則可以處理多個分類。檢查規(guī)則,并看看是否向下面例子所示。 每個系統(tǒng)有它自己的特性,有時候它可能可以對性能作出更好的調(diào)整。因此如果之前已經(jīng)有 1000 個 Person 對象在 working memory 中,如果我們再設(shè)置進來一個新的Person 對象,它需要與之前的 Person 對象進行 1000次匹配。 end . 參考書目 如果你需要了解 JSR 94 的更多信息,請 參考以下文章索引 1. Official JCP Specification for Java Rule Engine API (JSR 94) ? 2. The Java Rule Engine API documentation ? 3. The Logic From The Bottom Line: An Introduction to The Drools Project. By N. Alex Rupp, published on in 2020 ? s 4. Getting Started With the Java Rule Engine API (JSR 94): Toward RuleBased Applications. By Dr. Qusay H. Mahmoud, published on Sun Developer Network in 2020 ? 5. Jess and the API. By Ernest FriedmanHill, published on in 2020 ? 第 7 章 . 性能調(diào)整 . 性能考慮 在任何復雜的應用中,許多事情可能會對性能造成影響。 ( new PurchaseOrder( even more cheese ) )。 // 為 drl 和 dsl建立 RuleExecutionSet RuleExecutionSet ruleExecutionSet = ( reader, properties )。 例 . 使用 RuleAdministration API 注冊 LocalRuleExecutionSet // 獲得 RuleAdministration RuleAdministration ruleAdministrator = ()。因此當我們?yōu)閳猿质褂?JSR94的程序員提供 API 的同時,我 們強烈建議使用 Drools API。 . 如何使用 JSR94分為兩部分工作。 LocalRuleExecutionSetProvider ruleExecutionSetProvider = ( null )。 當注冊 RuleExecutionSet 時必須指定名稱,用于取回它。 List results = new ArrayList()。通常的建議是不要隨意估測,準確度量,剖析和計劃。 如果我們使用“ mother”屬性對 BetaNode 內(nèi)存進行索引,當新的一個 Person對象設(shè)置到內(nèi)存時,它只需要匹配之前有相同 mother屬性的對象(有相同 mother屬性的可能不只是 Person 對象,因此要進行匹配)就行了,通過索引可以非常高效率的完成這個過程。例如在“ Manners 64 example”測試中,如果我們關(guān)閉右輸入內(nèi)存索引,我們可以獲得下面的結(jié)果 Manners 64 僅使用 BetaNode 左輸入內(nèi)存索引 : 142020 毫秒運行時間 以上甚至比不使用索引更糟糕。 If == abcd == basic ..... Then // do something 上面規(guī)則示例的基本問題是,規(guī)則有太多硬編碼值。 Say we run a mega online store and customers can define their favorites in each of the categories (books, videos, music, toys, electronics, clothing). What happens if a customer has different levels for each category. Using the hard coded approach, one might have to add more rules. If we change the rule and make it more generalized, the same rule can handle multiple categories. If ?lvl // 綁定 remendation level 到 lvl 變量 ?rcat // 綁定 remendation category 到 rcat ?id // 綁定 account id 到 id ?id // 通過 id 找到 favorites 列表 ?rcat // 將 favorite 匹配到 remendation category ?lvl // 匹配 favorite level 到 remendation level Then remend all items in the favorites 如此看來,使規(guī)則具有動態(tài)性,并由數(shù)據(jù)驅(qū)動的價值在哪里呢?顯然,硬編碼規(guī)則要比讓規(guī)則具有通用性更快,但是會影響性能。這個方法不一定每次都能適用。這個模塊中有許多例子。例如說,規(guī)則可以從一個有許多使用中的 working memory 的 rulebase中刪除, RETE網(wǎng)絡將自動調(diào)整以刪除該規(guī)則而不需要將其它 fact重新設(shè)置一次。當 RuleBase 被整體更新時,這是一個有用的選項,對短期存在的 working memory。 . 一些部署方法 這節(jié)包含一些部署的建議。更進一步說,測試在規(guī)則頻繁變動的環(huán)境下,比規(guī)則更重要。 這個測試框架建立在 FIT 和 JSR94之上,對于 Jboos 規(guī)則來說是一個獨立的項目?!?l”和“ r”指左邊和右邊,“ s”是 sean,“ n”是客人姓名。但 3 與 4 以及 1與 2的位置會隨意排列。接受對自己或任何已經(jīng)分配的選擇方案。在 Clips 中提供的 Lex 和 Mea 沖突解決策略允許你快速轉(zhuǎn)換并正確的在 Clips 中運行 OPS5 程序。這個發(fā)現(xiàn)說明,被放在 Agenda 中,有同樣時間標簽的激活規(guī)則的順序仍然按照 LIFO/FIFO 的序列進行。 . Continue and Are We Done Are We Done規(guī)則僅在最后一個座位被設(shè)置后激活,這時所有的規(guī)則都已經(jīng)激活過。現(xiàn)代的基于 Rete 算法的規(guī)則引擎開始分析網(wǎng)絡并實現(xiàn)這種類型的優(yōu)化,不管它是一個 leaps 風格的懶惰評估或者一個預編譯的優(yōu)化以避免錯誤的連接。 Manners是對不同連接的叉集算法速度的殘酷壓力測試。為了正確地執(zhí)行Manners,建立路徑規(guī)則所建立的激活規(guī)則 必須在完成路徑規(guī)則之前激活。 這個方法使得鏈接記住并且嘗試連接,基于 fact 設(shè)置到節(jié)點中的順序;這樣激活規(guī)則的激發(fā)將基于 fact 的設(shè)置順序。 its purposefully designed as a bad rule to full stress test the cross product matching process, which this clearly does. Notice that each Activation has the same time tag of 35, as they were all activated by the change in Context to ASSIGN_SEATS. With OPS5 and LEX it would correctly fire the Activation with the last asserted Seating. With Depth strategy the execution is arbitrary yet Manners does correctly execute for Jess and Clips using the Depth strategy. Clips support, via the public forums, have said that Manners was] 深度算法,作為 Clips 默認的沖突解決策略,不同于在 OPS5 中默認使用的策略。 } } . 分配座位 該規(guī)則決定每一個座位的分配。 新激活的規(guī)則被放置在其它同樣優(yōu)先級的規(guī)則之前。 數(shù)據(jù) 在結(jié)果中的每一行都是“分配座位”規(guī)則執(zhí)行時輸出的。因為輸入的格式對于熟悉規(guī)則的領(lǐng)域的人來說相當簡單,它也對“情景測試”有幫助,對這些規(guī)則可以使用不同的情景。在某方面來說,規(guī)則是編碼(雖然在更高的級別),測試驅(qū)動開發(fā)的許多原則同樣適用。你接著可以序列化 Package 到一個文件(使用 java 標準序列化)。 PackageBuilder, RuleBase, . RuleBase 編譯好的 Package 被加入 RuleBase。為了更新rulebase,需要重新裝載一個新的 rulebase,然后交換出緩 存的 rulebase(任何正在使用舊的 rulebase 的線程可以繼續(xù)使用直到結(jié)束,在這個情況下 rulebase最終會被垃圾處理器收集 )。 第 8 章 . 示例 . 獲得示例 在 Drools 源代碼中一些示例被當作集成測試包含。簡單地說,在規(guī)則中使用大量的扁平對象導致與硬編碼常數(shù)同樣的問題。如果對每一個客戶在分類中有不同的級別,會發(fā)生什么事情?如果使用硬編碼,將不得不增加更多的規(guī)則。管理 100,000 甚至 1,000,000 規(guī)則是非常讓人頭疼的,盡量避免它。這里我們不分析內(nèi)存受限環(huán)境。 示例,如果有如下規(guī)則 : rule find brothers when p1: Person( $mother : mother ) p2: Person( mother == $mother ) then // do something end 如果沒有使用索引,每一個設(shè)置到 working memory 中的 Person 對象將嘗試匹配之前設(shè)置進來的所有 Person 對象,查看是否有同樣的 mother。 assert( $() + and + $() + are sisters)。 List list = new ArrayList()。 ( dsl, dslReader )。都使用 null作為參數(shù),因為這些方法的屬性映射當前不使用。更進一步說, JSR94 不提供一種規(guī)則語言,你只能使用規(guī)則引擎所提供的一小部分功能,能夠獲得的好處很有限。第一部分是管理 API用來創(chuàng)建和注冊 RuleExecutionSet。 // 建立 DRL讀取器 URL drlUrl = new URL( Reader drlReader = new InputStreamReader( () )。這也是一個 輸入屬性的字段,當前沒有使用它,因此輸入空即可。 result