1. Overview
In this article, we’ll see how what Backward Chaining is and how we can use it with Drools.
This article is a part of a series showcasing the Drools Business Rules Engine.
2. Maven Dependencies
Let’s start by importing the drools-core dependency:
<dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artifactId> <version>7.4.1.Final</version> </dependency>
3. Forward Chaining
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
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
The Drools project was created primarily as a forward chaining system. But, starting with version 5.2.0, it supports backward chaining as well.
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
Let’s create a simple fact base describing things and its location:
- Planet Earth
- Asia, Planet Earth
- China, Asia
- Great Wall of China, China
5.2. Defining Rules
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.
The main belongsTo query, that will utilize backward chaining, can be written as:
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
Now, we’ll need a Java class for representing facts:
public class Fact { @Position(0) private String element; @Position(1) private String place; // getters, setters, contructors, and other methods ... }
Here we use the @Position annotation to tell the application in which order Drools will supply values for those attributes.
Also, we’ll create the POJO representing results:
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).
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
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.
As always, the full example can be found in our GitHub repository.