Проблема с вашим примером заключается в том, что 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 в вашей рабочей памяти имеют отца. Каждый человек, переданный в рабочую память, оценивается по его личным достоинствам, даже если передано несколько человек.
В основном, как бы вы прочитали это было бы: У всех людей есть отец. У каждого богатого человека есть богатый отец. Если вы инертите дизайн объекта и проверяете детей, вы можете утверждать что-то вроде того, что если человек богат, то все дети богаты.
Для полноты смоделированный здесь класс 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, с точки зрения предложения when мой Person все еще не имеет отца; правила оцениваются в отношении безупречных входных данных, если только я специально не уведомлю Drools об ином, используя вышеупомянутые функции.
person
Roddy of the Frozen Peas
schedule
08.01.2021
rich(father(X)) → rich(X)
. Здесьfather
— функциональный символ. - person bobcat   schedule 07.01.2021rich(father(X)) → rich(X)
в CLIPS. Вы могли бы (вроде) сформулировать это такrich(X) ^ father(X, Y) -> rich(Y)
, но это другое, потому что функциональные символы подразумевают существование и уникальностьfather
кого-то. В Прологе функциональные символы используются для определения всех структур данных. - person bobcat   schedule 08.01.2021