An Example of Backward Chaining in Drools – Drools中后向链的一个例子

最后修改: 2017年 11月 17日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this article, we’ll see how what Backward Chaining is and how we can use it with Drools.

在这篇文章中,我们将看到什么是后向链,以及我们如何在Drools中使用它。

This article is a part of a series showcasing the Drools Business Rules Engine.

本文是展示Drools 业务规则引擎的系列文章之一。

2. Maven Dependencies

2.Maven的依赖性

Let’s start by importing the drools-core dependency:

让我们从导入drools-core 依赖性开始。

<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-core</artifactId>
    <version>7.4.1.Final</version>
</dependency>

3. Forward Chaining

3.前向连锁

First of all, with forward chaining, we start by analyzing data and make our way towards a particular conclusion.

首先,在前向链中,我们从分析数据开始,并向一个特定的结论迈进。

An example of applying forward chaining would be a system that discovers new routes by inspecting already known connections between nodes.

应用前向链的一个例子是,一个通过检查节点之间已经知道的连接来发现新路线的系统。

4. Backward Chaining

4.后向连锁

As opposed to forward chaining, backward chaining starts directly with the conclusion (hypothesis) and validates it by backtracking through a sequence of facts.

与前向链相比,后向链直接从结论(假设)开始,通过回溯一连串的事实来验证它。

When comparing forward chaining and backward chaining, the first one can be described as “data-driven” (data as input), while the latter one can be described as “event(or goal)-driven” (goals as inputs).

当比较前向链和后向链时,前者可以被描述为 “数据驱动”(数据作为输入),而后者可以被描述为 “事件(或目标)驱动”(目标作为输入)。

An example of applying backward chaining would be to validate if there’s a route connecting two nodes.

应用后向链的一个例子是验证是否有一个连接两个节点的路由。

5. Drools Backward Chaining

5.Drools的后向链

The Drools project was created primarily as a forward chaining system. But, starting with version 5.2.0, it supports backward chaining as well.

Drools项目主要是作为一个前向链式系统而创建的。但是,从5.2.0版本开始,它也支持后向链。

Let’s create a simple application and try to validate a simple hypothesis – if the Great Wall of China is on Planet Earth.

让我们创建一个简单的应用程序,并尝试验证一个简单的假设–如果中国的长城在地球上

5.1. The Data

5.1.数据

Let’s create a simple fact base describing things and its location:

让我们建立一个简单的事实基础,描述事物和它的位置。

  1. Planet Earth
  2. Asia, Planet Earth
  3. China, Asia
  4. Great Wall of China, China

5.2. Defining Rules

5.2.定义规则

Now, let’s create a “.drl” file called BackwardChaining.drl which we’ll place in /resources/com/baeldung/drools/rules/. This will contain all necessary queries and rules to be used in the example.

现在,让我们创建一个名为BackwardChaining.drl的”.drl “文件,我们将把它放在/resources/com/baeldung/drools/rules/。这将包含所有必要的查询和规则,以用于这个例子。

The main belongsTo query, that will utilize backward chaining, can be written as:

主要的belongsTo查询,将利用后向链,可以写成。

query belongsTo(String x, String y)
    Fact(x, y;)
    or
    (Fact(z, y;) and belongsTo(x, z;))
end

Additionally, let’s add two rules that will make it possible to review our results easily:

此外,让我们添加两条规则,这将使我们能够轻松地审查我们的结果。

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

5.3. Creating the Application

5.3.创建应用程序

Now, we’ll need a Java class for representing facts:

现在,我们需要一个Java类来代表事实。

public class Fact {
 
    @Position(0)
    private String element;

    @Position(1)
    private String place;

    // getters, setters, constructors, and other methods ...    
}

Here we use the @Position annotation to tell the application in which order Drools will supply values for those attributes.

这里我们使用@Position注解来告诉应用程序,Drools将以何种顺序为这些属性提供值。

Also, we’ll create the POJO representing results:

另外,我们将创建代表结果的POJO。

public class Result {
    private String value;
    private List<String> facts = new ArrayList<>();
 
    //... getters, setters, constructors, and other methods
}

And now, we can run the example:

而现在,我们可以运行这个例子。

public class BackwardChainingTest {

    @Before
    public void before() {
        result = new Result();
        ksession = new DroolsBeanFactory().getKieSession();
    }

    @Test
    public void whenWallOfChinaIsGiven_ThenItBelongsToPlanetEarth() {

        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();
        
        assertEquals(
          result.getValue(),
          "Decision one taken: Great Wall of China BELONGS TO Planet Earth");
    }
}

When the test cases are executed, they add the given facts (“Asia belongs to Planet Earth“, “China belongs to Asia”, “Great Wall of China belongs to China”).

当测试用例被执行时,它们会添加给定的事实(”亚洲属于地球“,”中国属于亚洲”,”中国的长城属于中国”)。

After that, the facts are processed with the rules described in BackwardChaining.drl, which provides a recursive query belongsTo(String x, String y).

之后,用BackwardChaining.drl中描述的规则处理事实,它提供了一个递归查询belongsTo(String x, String y)。

This query is invoked by the rules which use backward chaining to find if the hypothesis (“Great Wall of China BELONGS TO Planet Earth”), is true or false.

这个查询是由规则调用的,规则使用后向链来寻找假设(“中国长城属于地球”),是真还是假。

6. Conclusion

6.结论

We’ve shown an overview of Backward Chaining, a feature of Drools used to retrieve a list of facts to validate if a decision is true.

我们已经展示了后向链的概况,这是Drools的一个功能,用于检索事实列表,以验证一个决策是否真实。

As always, the full example can be found in our GitHub repository.

一如既往,完整的例子可以在我们的GitHub 仓库中找到。