Un exemple d’enchaînement arrière dans Drools

Un exemple de chaînage arrière dans Drools

1. Vue d'ensemble

Dans cet article, nous verrons ce qu'est le chaînage arrière et comment nous pouvons l'utiliser avec Drools.

Cet article fait partie d'une série présentant lesDrools Business Rules Engine.

2. Dépendances Maven

Commençons par importer les drools-coredependency:


    org.drools
    drools-core
    7.4.1.Final

3. Chaînage avant

Tout d’abord, avec l’enchaînement en avant, nous commençons par analyser les données et nous dirigeons vers une conclusion particulière.

Un exemple d'application d'un chaînage en aval serait un système qui découvre de nouvelles routes en inspectant des connexions déjà connues entre des nœuds.

4. Chaînage arrière

Contrairement au chaînage avant,backward chaining starts directly with the conclusion (hypothesis) and validates it by backtracking through a sequence of facts.

Lors de la comparaison du chaînage avant et du chaînage arrière,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).

Un exemple d’application du chaînage en amont serait de valider s’il existe une route reliant deux nœuds.

5. Drools enchaînement arrière

Le projet Drools a été créé principalement en tant que système de chaînage en aval. Cependant, à partir de la version 5.2.0, il prend également en charge le chaînage arrière.

Créons une application simple et essayons de valider une hypothèse simple -if the Great Wall of China is on Planet Earth.

5.1. Les données

Créons une base de faits simple décrivant les choses et leur emplacement:

  1. Planète Terre

  2. Asie, planète Terre

  3. Chine, Asie

  4. Grande Muraille de Chine, Chine

5.2. Définition des règles

Maintenant, créons un fichier ".drl" appeléBackwardChaining.drl que nous placerons dans/resources/com/example/drools/rules/. Cela contiendra toutes les requêtes et règles nécessaires à utiliser dans l'exemple.

La requête principalebelongsTo, qui utilisera le chaînage arrière, peut être écrite comme suit:

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

De plus, ajoutons deux règles qui permettront d'examiner facilement nos résultats:

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. Création de l'application

Maintenant, nous aurons besoin d'une classe Java pour représenter les faits:

public class Fact {

    @Position(0)
    private String element;

    @Position(1)
    private String place;

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

Ici, nous utilisons l'annotation@Position pour indiquer à l'application dans quel ordre Drools fournira des valeurs pour ces attributs.

Nous allons également créer le POJO représentant les résultats:

public class Result {
    private String value;
    private List facts = new ArrayList<>();

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

Et maintenant, nous pouvons lancer l'exemple:

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");
    }
}

Lorsque les cas de test sont exécutés, ils ajoutent les faits donnés («Asia belongs to Planet Earth», «Chinebelongs to Asie», «La Grande Muraille de Chine appartient à la Chine»).

Après cela, les faits sont traités avec les règles décrites dansBackwardChaining.drl, qui fournit une requête récursivebelongsTo(String x, String y).

Cette requête est invoquée par les règles qui utilisent le chaînage vers l'arrière pour trouver si l'hypothèse (“Great Wall of China BELONGS TO Planet Earth”) est vraie ou fausse.

6. Conclusion

Nous avons présenté un aperçu du chaînage en arrière, une fonctionnalité de Drools utilisée pour récupérer une liste de faits afin de valider si une décision est vraie.

Comme toujours, l'exemple complet se trouve dans nosGitHub repository.