На этом шаге мы рассмотрим детерминизм и отсечение.
Если бы предикат friend, определенный в предыдущей программе, не содержал отсечений, то это был бы недетерминированный предикат (способный производить множественные решения при помощи поиска с возвратом). В предыдущих реализациях Пролога программисты должны были обращать особое внимание на недетерминированные предложения из-за сопутствующих им дополнительных требований к ресурсам памяти. Теперь Пролог сам выполняет проверку на недетерминированные предложения, облегчая вашу работу.
В Прологе существует директива компилятора check_determ. Если вставить эту директиву в самое начало программы, то Пролог будет выдавать предупреждение в случае обнаружения недетерминированных предложений в процессе компиляции.
Вы можете превратить недетерминированные предложения в детерминированные, вставляя отсечения в тело правил, определяющих данный предикат. Например, помещение отсечений в предложения, определяющие предикат friend, делает этот предикат детерминированным, поскольку в данном случае обращение к friend может возвратить одно и только одно решение.
Следующая программа pro32_1.pro демонстрирует, как вы можете использовать предикат not для того, чтобы выявить успевающего студента: студента, у которого средний балл (GPA) не менее 3.5 и у которого в настоящее время не продолжается испытательный срок.
domains name=symbol gpa = real predicates honor_student(name) student(name,gpa) probation(name) clauses honor_student(Name):- student(Name,GPA), GPA>=3.5, not(probation(Name)). student("Betty Blue",3.5). student("David Smith",2.0). student("John Johnson",3.7). probation("Betty Blue"), probation("David Smith"). goal honor_student (X).
Этo приводит к предотвращению связывания внутри not несвязанных переменных. При вызове изнутри not подцели со свободными переменными, Пролог возвратит сообщение об ошибке: "Free variables not allowed in not or retractall" (Свободные переменные не разрешены в not или retract). Это происходит вследствие того, что для связывания свободных переменных в подцели, подцель должна унифицироваться с каким-либо другим предложением и выполняться. Правильным способом управления несвязанными переменными подцели внутри not является использование анонимных переменных.
likes(bill,Anyone):- % Anyone - выходной аргумент
likes(sue,Anyone),
not(hates(bill,Anyone).
В этом примере Anyone связывается посредством likes(sue,Anyone) до того, как Пролог делает вывод, что hates (bill, Anyone) не является истиной. Данное предложение работает корректно.
Если вы измените его таким образом, что обращение к not будет выполняться первым, то получите сообщение об ошибке: "Free variable are not allowed in not" (Свободные переменные в not не разрешены).
likes(bill,Anyone):- % Это не будет работать правильно
not(hates(bill,Anyone)),
likes(sue,Anyone).
Даже если вы замените в not(hates (bill, Anyone)) Anyone на анонимную переменяю, и предложение, таким образом, не будет возвращать ошибку, все равно получите неправильный результат.
likes(bill,Anyone):- % Это не будет работать правильно
not(hates(bill,_)),
likes(sue,Anyone).
Это предложение утверждает, что Биллу нравится кто угодно, если неизвестно ничего о том, кого Билл ненавидит, и если этот "кто-то" правится Сью. Подлинное предложение утверждало, что Биллу нравится тот, кто нравится Сью, и при этом Билл не испытывает к этому человеку ненависти.
Неверное использование предиката not приведет к сообщению об ошибке или к ошибкам в логике вашей программы. Следующая программа pro32_2.pro является примером правильного использования предиката not.
predicates likes_shopping(symbol) has_credit_card (symbol, symbol) bottomed_out(symbol,symbol) clauses likes_shopping(Who):- has_credit_card(Who,Card), not(bottomed_out(Who, Card)), write(Who," can shop with the ",Card, " credit card.\n"). has_credit_card(chris,visa). has_credit_card(chris,diners). has_credit_card(joe,shell). has_credit_card(sam,mastercard). has_credit_card(sam,citibank). bottomed_out(chris,diners). bottomed_out(sam,mastercard). bottomed_out(chris, visa) . goal likes_shopping(Who).
Со следующего шага мы начнем рассматривать факты и правила в качестве процедур.