«1. Обзор

В этой статье мы увидим, что такое обратная цепочка и как мы можем использовать ее с Drools.

Эта статья является частью серии, посвященной механизму бизнес-правил Drools.

2. Зависимости Maven

Давайте начнем с импорта зависимости drools-core:

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

3. Прямая цепочка

Прежде всего, с прямой цепочкой мы начинаем с анализа данных и продвигаемся вперед к конкретному выводу.

Примером применения прямой цепочки может быть система, которая обнаруживает новые маршруты, проверяя уже известные соединения между узлами.

4. Обратная цепочка

В отличие от прямой цепочки, обратная цепочка начинается непосредственно с вывода (гипотезы) и подтверждает его путем обратного отслеживания последовательности фактов.

При сравнении прямой цепочки и обратной цепочки первая может быть описана как «управляемая данными» (данные в качестве входных данных), а последняя может быть описана как «управляемая событиями (или целями)» (цели). в качестве входных данных).

Примером применения обратной цепочки может быть проверка наличия маршрута, соединяющего два узла.

5. Обратная цепочка Drools

Проект Drools был создан в первую очередь как система прямой цепочки. Но, начиная с версии 5.2.0, он также поддерживает обратную цепочку.

Давайте создадим простое приложение и попробуем проверить простую гипотезу — находится ли Великая Китайская стена на планете Земля.

5.1. Данные

Давайте создадим простую базу фактов, описывающую вещи и их местонахождение:

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

5.2. Определение правил

Теперь давайте создадим файл «.drl» с именем BackwardChaining.drl, который мы поместим в /resources/com/baeldung/drools/rules/. Он будет содержать все необходимые запросы и правила, которые будут использоваться в примере.

Основной запрос ownTo, который будет использовать обратную цепочку, можно записать так:

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

5.3. Создание приложения

Теперь нам понадобится класс Java для представления фактов:

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

    @Position(1)
    private String place;

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

Здесь мы используем аннотацию @Position, чтобы сообщить приложению, в каком порядке Drools будет предоставлять значения для этих атрибутов.

Кроме того, мы создадим POJO, представляющий результаты:

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

А теперь мы можем запустить пример:

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

Когда тестовые примеры выполняются, они добавляют заданные факты (†«Азия принадлежит планете Земля», «Китай принадлежит Азии», «Великая Китайская стена принадлежит Китаю»).

После этого факты обрабатываются по правилам, описанным в BackwardChaining.drl, что обеспечивает рекурсивный запрос ownTo(String x, String y).

Этот запрос вызывается правилами, которые используют обратную цепочку, чтобы определить, является ли гипотеза («Великая Китайская стена ПРИНАДЛЕЖИТ планете Земля») истинной или ложной.

6. Заключение

Мы показали обзор Backward Chaining, функции Drools, используемой для извлечения списка фактов для проверки правильности решения.

Как всегда, полный пример можно найти в нашем репозитории GitHub.