Разрешены ли функциональные символы в механизмах правил / алгоритме Rete?

#artificial-intelligence #rule-engine #first-order-logic #rete

#искусственный интеллект #механизм правил #логика первого порядка #rete

Вопрос:

ИИ: Современный подход приводит к алгоритму Rete при обсуждении вывода в логике первого порядка.

Однако все описания алгоритма Rete, которые я нашел, похоже, используют правила, свободные от функциональных символов. Другими словами, правила выглядят так

 a(X) ∧ b(X, Y) → c(Y)
 

но не

 a(f(X)) ∧ b(X, Y) → c(f(Y))
 

(Разница может быть фундаментальной, так как это разница между Prolog и Datalog, только один из которых является полным по Тьюрингу)

Ограничен ли алгоритм Rete правилами, свободными от функциональных символов? Обрабатывают ли современные механизмы правил, такие как Drools и CLIPS, функциональные символы?

Комментарии:

1. Если я правильно понимаю вашу нотацию, то да, движок Drools допускает оценку функций как в условиях, так и в последствиях. Однако я не могу говорить за другие движки.

2. То же самое для клипов

3. @RoddyoftheFrozenPeas «функциональные символы» в логике могут отличаться от «функций» в других местах. Вот лакмусовая бумажка: можете ли вы использовать логическую переменную в качестве аргумента, присваиваемого этим «функциям» , когда вы указываете правила? (Смотрите второй пример в Q)

4. @GaryRiley Пожалуйста, посмотрите мой ответ Родди .

5. @MaxB Я только что упомянул Пролог, потому что вы это сделали. Если нет простого способа объяснить аргументы функций или почему вы хотели бы их использовать, кому-то будет трудно ответить на ваш вопрос. Ваши примеры не проливают никакого света на то, что делают аргументы функций.

Ответ №1:

В CLIPS вот как вы бы реализовали правило «Для каждого человека существует один и только один отец указанного человека, и если отец человека богат, то и он / она тоже»:

 (defrule inherited-wealth
   (forall (person ?p)
           (father ?p ?f)
           (not (father ?p ~?f)))
   (person ?p)
   (father ?p ?f)
   (rich ?f)
   =>
   (assert (rich ?p)))
 

Комментарии:

1. На самом деле есть два правила. Первый ( «Для каждого человека существует один и только один отец указанного человека» ) должен указывать на существование. Я не вижу этого в вашем коде.

2. Это то, что делает оператор forall.

3. Зачем вам вообще нужен forall? Даже без обертывания вокруг forall это правило выполняется одинаково, не так ли?

4. @Akaedintov Нет, это не так. Forall является сокращением для (not (person ?p) (not (и (father ?p ?f) (not (father ?p ~?f)))). Необходимо гарантировать, что у каждого человека есть один и только один отец.

Ответ №2:

Проблема с вашим примером заключается в том, что Drools работает против объектов Java. Условие «у каждого человека есть ровно один отец» обрабатывается путем определения Father переменной как экземпляра, а не как списка. Это упрощает проверку до того, что она просто является нулевой проверкой.

В Drools вот как вы могли бы реализовать этот простой вариант использования на английском языке:

Для каждого человека существует один и только один отец указанного человека, и если отец человека богат, то и он / она тоже.

 rule "A person has a rich father and is rich"
when
  not( Person(father == null ))

  $person: Person( $father: father,
                            isRich == true )
  Person( isRich == true ) from $father
then
  // Insert consequences here
end
 

Правая часть этого правила (следствие) будет срабатывать для каждого человека, который богат, и чей отец богат. not Предложение в начале проверяет, что все экземпляры Person в вашей рабочей памяти имеют father’s . Каждый человек, переданный в рабочую память, оценивается по их индивидуальным достоинствам, даже если передано несколько человек.

В основном, как вы бы это прочитали: «У всех людей есть отец. У каждого богатого человека есть богатый отец «. Если вы измените дизайн объекта и проверите дочерние элементы, вы можете утверждать что-то вроде «если человек богат, то все дети богаты».

Для полноты картины смоделированный здесь класс Java выглядит следующим образом:

 public class Person {
  private Person father;
  private boolean isRich;
  public Person getFather() { return this.father; }
  public Person getIsRich() { return this.isRich; }
  // Setter methods omitted for brevity
}
 

Конечно, если вместо этого вы пытаетесь проверить ситуации, в которых вы не удовлетворяете этому условию, вы, конечно, можете инвертировать его:

 rule "A person exists without a father"
when
  exists( Person( father == null) )
then
  // Do something for situation if there's a father-less person
end

rule "A person is rich and their father is not rich"
when
  Person( $father: father != null, 
                   isRich == true )
  Person( isRich == false ) from $father
then
  // Do something for the poor father
end
 

… где, конечно, вы могли бы объединить их в одно правило, но это считается плохим дизайном правил.

Drools — это язык бизнес-правил. Он предназначен для использования в комбинациях условий и последствий — «если эти условия верны, тогда сделайте это». Ваш сценарий представляет собой простое утверждение вместо условного следствие, поэтому его немного сложно смоделировать здесь, поскольку в нем отсутствуют последствия.

Однако его преимущество заключается в том, что он неявно применяется к каждому входному сигналу без необходимости указывать циклы или рекурсивные функции. Способ, которым было бы вызвано вышеупомянутое (как положительные, так и отрицательные случаи), заключался бы в создании коллекции экземпляров Person и одновременной передаче их всех в сеанс. Drools будет оценивать каждый экземпляр Person по его собственным достоинствам по сравнению с входными данными. Любые изменения в этих экземплярах без вызова одной из специальных функций обновления Drools ( update , insert , modify , retract ) будут проигнорированы с точки зрения оценки того, действительно ли правило. Так, например, если я передаю экземпляр Person без отца, а затем в одном из моих правил добавляю Person, с точки зрения предложения «когда», мой Person по-прежнему остается безотцовщиной; правила оцениваются по безупречным входным данным, если я специально не сообщу Drools иначе, используя вышеупомянутые функции.

Комментарии:

1. В правиле должно быть указано «для каждого человека существует один и только один отец …». Вместо этого вы используете его существование в качестве условия. В вашей интерпретации father поле никогда не должно быть нулевым. Неужели Drools не может указать это безоговорочно?

2. Что такое утверждение в мире условий и последствий? Я рассматривал это как условие. Поскольку утверждение может быть истинным или ложным, это показалось подходящим способом его моделирования. Если утверждение истинно, правило вычисляет; если утверждение ложно, оно не выполняется (если вы не инвертируете условие).

3. Drools — это язык бизнес-правил . Он не предназначен для моделирования абстрактных логических конструкций. Если у вас есть датчики температуры и заявление «если какой- либо датчик сообщает о температуре> 120 градусов непрерывно в течение 3 минут, затем включите пожарную сигнализацию»… мы можем сделать это с помощью drools. Ваш пример с богатым / бедным человеком наполовину переводится, если вы относитесь к нему как к условию, но ваши правила заботятся о том, хотите ли вы знать, верно ли это или ложно, и это изменит то, как вы пишете свое правило.