#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. Ваш пример с богатым / бедным человеком наполовину переводится, если вы относитесь к нему как к условию, но ваши правила заботятся о том, хотите ли вы знать, верно ли это или ложно, и это изменит то, как вы пишете свое правило.