Drools 中的前向連結與後向鏈接
1.概述
Drools 是一個強大的開源業務規則管理系統 (BRMS),以 Java 編寫。它允許開發人員透過以聲明式格式編寫規則,將業務邏輯與應用程式程式碼分開。最值得注意的是,它提供了基於前向鍊式和後向鍊式推理的規則引擎、DMN 決策引擎以及其他項目。
在本教程中,我們將主要關注正向鏈接和反向鏈接,重點介紹它們的區別、用例以及性能影響。如果您剛開始使用 Drools,請查看我們的簡介和 Spring 整合文章,因為我們的範例程式碼將基於它們。
2. 前向鏈接
正向連結從已知事實開始,並主動應用規則來產生新的事實。引擎評估所有可用數據,觸發匹配的規則,並持續此過程,直到無法再得出其他結論。
在資料驅動的方法中,將事實插入 Drools 的工作記憶體會立即觸發與這些事實相符的規則。這些規則創造新的事實,進而啟動進一步的規則,從而形成級聯的推理鏈。因此,前向連結可以動態回應不斷變化的數據,使其成為監控系統、即時分析或基於流的處理等環境的理想選擇:
例如,在電信供應引擎中,新增具有特定計劃的客戶會立即啟動一系列配置 - 更新帳單、編程開關、調整記錄以及跨多個系統協調。
讓我們來看看為前向連結設計的一些規則:
dialect "mvel"
rule "Suggest Manager Role"
when
Applicant(experienceInYears > 10)
Applicant(currentSalary > 1000000 && currentSalary <= 2500000)
then
suggestedRole.setRole("Manager");
end
rule "Suggest Senior Developer Role"
when
Applicant(experienceInYears > 5 && experienceInYears <= 10)
Applicant(currentSalary > 500000 && currentSalary <= 1500000)
then
suggestedRole.setRole("Senior developer");
end
rule "Suggest Developer Role"
when
Applicant(experienceInYears > 0 && experienceInYears <= 5)
Applicant(currentSalary > 200000 && currentSalary <= 1000000)
then
suggestedRole.setRole("Developer");
end
設定好規則後,讓我們看看前向連結的實際作用:
private void forwardChaining() {
KieSession ksession = new DroolsBeanFactory().getKieSession();
Applicant applicant = new Applicant("Daniel", 38, 1_600_000.0, 11);
SuggestedRole suggestedRole = new SuggestedRole();
ksession.setGlobal("suggestedRole", suggestedRole);
ksession.insert(applicant);
int fired = ksession.fireAllRules();
System.out.println("Rules fired: " + fired);
System.out.println("Suggested role: " + suggestedRole.getRole());
ksession.dispose();
}
根據我們設定的規則,控制台應該顯示觸發了一條規則,建議的角色是 Manager .
3. 反向連結
反向連結則採用相反的方法。它不是從資料開始,而是從目標或查詢開始。然後,引擎反向運行以確定哪些事實或規則可以支持該結論。
在 Drools 中,後向連結是透過查詢和邏輯插入來實現的。當規則或查詢請求某個事實時,Drools 會搜尋能夠邏輯推斷該事實的規則。如果找到匹配項,它會嘗試滿足觸發這些規則所需的條件,並以遞歸方式朝著初始目標努力:
它在詢問系統中尤其有效,例如診斷工具或查詢驅動的應用程式。例如,我們可能會在保險中使用反向連結來識別哪些保單在特定的再保險合約範圍內。
讓我們看一些規則和查詢來演示後向連結:
dialect "mvel"
query belongsTo(String x, String y)
Fact(x, y;)
or
(Fact(z, y;) and belongsTo(x, z;))
end
rule "Great Wall of China BELONGS TO Planet Earth"
when
belongsTo("Great Wall of China", "Planet Earth";)
then
result.setValue("Decision one taken: Great Wall of China BELONGS TO Planet Earth");
end
rule "print all facts"
when
belongsTo(element, place;)
then
result.addFact(element + " IS ELEMENT OF " + place);
end
現在,讓我們運行規則:
public Result backwardChaining() {
Result result = new Result();
KieSession ksession = new DroolsBeanFactory().getKieSession();
ksession.setGlobal("result", result);
ksession.insert(new Fact("Asia", "Planet Earth"));
ksession.insert(new Fact("China", "Asia"));
ksession.insert(new Fact("Great Wall of China", "China"));
ksession.fireAllRules();
return result;
}
結果,我們應該看到以下流程:
Decision one taken: Great Wall of China BELONGS TO Planet Earth
Great Wall of China IS ELEMENT OF China
Asia IS ELEMENT OF Planet Earth
China IS ELEMENT OF Asia
Great Wall of China IS ELEMENT OF Planet Earth
Great Wall of China IS ELEMENT OF Asia
China IS ELEMENT OF Planet Earth
4.混合推理
Drools 支持混合推理,允許我們在同一規則集中混合使用兩種鍊式推理方法。我們可以使用前向鍊式推理以響應式方式處理傳入數據,同時使用後向鍊式推理查詢特定條件。例如,我們可以使用後向鍊式推理驗證條件,然後觸發前向鍊式推理規則插入新的事實,從而橋接兩種模式,獲得更靈活、更有效率的解決方案。
讓我們看一個直觀的圖表來說明前向連結和後向連結如何運作:
正向連結從已知事實(事實 A、事實 B)開始,觸發規則 1,推斷事實 C,然後觸發規則 2,最後推斷事實 D。
後向連結從目標(事實 D)開始,尋找可以導致該目標的規則,檢查需要事實 C 的規則 2,並遞歸評估必要的事實和規則。
5.性能考慮
由於前向連結會全域回應所有相關事實,因此如果規則庫龐大且資料流頻繁,它可能會遭遇效能瓶頸。 Rete演算法有助於優化模式匹配,但在擴展時仍需考慮。
同時,由於後向連結是針對特定目標的,因此通常執行的規則較少,並且對於有針對性的邏輯查詢來說更為精簡 - 但除非出現提示,否則它不會自動回應新資料。
因此,對於即時、自動反應環境,我們選擇前向連結;而當精確度和最小化規則遍歷很重要時,我們選擇後向連結。
6. 結論
在本文中,我們探討了前向連結和後向連結是什麼、如何以及何時實現它們,以及它們之間的主要差異。