In previous chapter we implemented a drools project to understand difference between Stateful and Stateless session. In this tutorial we will try to understand what is Backward chaining using example.
What is Forward and Backward chaining?
Chaining is the process of performing a sequence of steps in a particular order.
1) Forward Chaining
We first analyze the data in a particular sequence. Based on the results of the data we arrive at a decision. For example if want to find out for a particular test the five students out of 100 who came first. Here we will take the data and then based on the analysis decide the results. This is forward chaining
2) Backward Chaining
We first take a decision and then check if the decision is true or no by backtracking through sequence of events. For example if i want to find out if a particular student has passed or not? Then I will take a decision that the student has passed. Then analyze the data by backtracking through the sequence of analysis of data. Accordingly its decided if the decision is correct or not.
Based on requirement either of the two apporaches can be used. Sometimes the combination of both forward and backward chaining is also used. Backward chaining is often referred to as derivation queries and drools implements it with query construct.
3) Create Example
For our example here we will insert facts related to event of Sport and then verify if some of our decisions are correct. We will create Eclipse Maven project as follows
Download counts: 467
- After downloading, unzip the project.
- Go to Eclipse IDE -> File -> Import -> Maven -> Existing Maven project -> Select the project.
Create the Event class as follows
package com.hi.techpoints.model;
import org.kie.api.definition.type.Position;
public class Event {
@Position(0)
private String entity;
@Position(1)
private String event;
public Event(String entity, String event) {
super();
this.entity = entity;
this.event = event;
}
public String getEntity() {
return entity;
}
public void setEntity(String entity) {
this.entity = entity;
}
public String getEvent() {
return event;
}
public void setEvent(String event) {
this.event = event;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((entity == null) ? 0 : entity.hashCode());
result = prime * result + ((event == null) ? 0 : event.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Event other = (Event) obj;
if (entity == null) {
if (other.entity != null)
return false;
} else if (!entity.equals(other.entity))
return false;
if (event == null) {
if (other.event != null)
return false;
} else if (!event.equals(other.event))
return false;
return true;
}
}
In rules.drl we use the query construct. Recursion is an important part of derivation queries and allows for search of trees. The rules.drl file will be as follows-
package rules
import com.hi.techpoints.model.Event
dialect "mvel"
query isContainedIn( String x, String y)
Event( x, y; )
or
( Event( z, y; ) and isContainedIn( x, z; ) )
end
rule "Check the condition is true"
when
isContainedIn("Hockey", "Sport Event"; )
then
System.out.println( "Decision taken -- Hockey is in the Sport Event" );
System.out.println( "-----------------------------" );
System.out.println( "-----------All Facts-----------------" );
end
rule "Check the condition is false"
when
not isContainedIn("Hockey", "Sport Event"; )
then
System.out.println( "Decision taken -- Hockey is not in the Sport Event" );
System.out.println( "-----------------------------" );
System.out.println( "-----------All Facts-----------------" );
end
rule "get all facts"
when
isContainedIn(entity, event; )
then
System.out.println( "Entity " + entity + " is in " + event );
end
Finally we define RunDrools class. Here load the facts and the rules in the drools working memory and firing all the rules. We make use of stateful session for firing the rules.
package com.hi.techpoints;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import com.hi.techpoints.model.Event;
public class RunDrools {
public static final void main(String[] args) {
try {
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("ksession-rule");
kSession.insert(new Event("Outdoor", "Sport Event"));
//kSession.insert(new Event("Hockey", "Outdoor"));
kSession.insert(new Event("Required 11 players", "Hockey"));
kSession.fireAllRules();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
On running the RunDrools class as a java application we get the output as-
In rules.drl we have 2 decisions to make-
- Hockey is present in Sport Event.
- Hockey is not present in Sport Event.
As we have commented a fact that ‘Hockey is in Outdoor’, so in our facts we have Outdoor is in Sport Event but Hockey not in the Outdoor.
So our decisions
- Hockey is present in Sport Event is false
- Hockey is not present in Sport Event is true
We will now modify the DroolsTest class by uncommenting the fact that France is in Europe.
package com.hi.techpoints;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import com.hi.techpoints.model.Event;
public class RunDrools {
public static final void main(String[] args) {
try {
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("ksession-rule");
kSession.insert(new Event("Outdoor", "Sport Event"));
kSession.insert(new Event("Hockey", "Outdoor"));
kSession.insert(new Event("Required 11 players", "Hockey"));
kSession.fireAllRules();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
On running the DroolsTest class as a java application we get the output as-
So our decisions
- Hockey is present in Sport Event is true
- Hockey is not present in Sport Event is false