domains
country=symbol
predicates
euro_pair(country,country)
border(country,country)
find_non_border_pair
goal
find_non_border_pair.
clauses
euro_pair("France","Germany").
euro_pair("France","Spain").
euro_pair("France","Italy").
euro_pair("Germany","Spain").
euro_pair("Germany","Italy").
euro_pair("Spain","Italy").
euro_pair("Russia","Finland").
euro_pair("Russia","Poland").
border("France","Germany").
border("France","Spain").
border("France","Italy").
border("Russia","Finland").
border("Russia","Poland").
border("Spain","Germany").
find_non_border_pair:-
* euro_pair(X,Y),
not(border(X,Y)),
not(border(Y,X)),
write("X=",X," Y=",Y),nl,
fail.
1. Как видно из программы наша цель find_non_border_pair означает, что мы хотим найти пары стран, не имеющих общей границы. В программе же представлены только сами пары стран и пары стран, имеющие общие границы.
Вместо того, чтобы выдавать на экран все пары стран с общими границами, а потом визуально искать все пары, не попавшие в этот список, лучше воспользоваться более простым и эффективным средством- предикатом not (отрицанием, то есть недостижением цели). Его пишут в программе как not, чтобы отличить его от логического оператора “ ”.
|
|
Если мы хотим вызывать цель многократно, то лучше использовать цель в форме правила, не содержащего в себе данных (нулевой арности) А само правило определить в разделе clauses.
Это полезно, когда для достижения цели надо доказать много разных подцелей, включающих в себе достаточно сложные операции. Это поможет упростить процедуру запросов. При этом такие правила можно создавать “в запас”, а потом их использовать в работе программы.
2.В случае цели без аргументов вне зависимости оттого будете вы использовать внутреннюю или внешнюю цель ответ вы получите только один:
X=Germany Y=Italy
1 Solution
Это объясняется тем, что к предикату find_non_border_pair не могут быть поставлены точки возврата, так как такое утверждение в программе только одно, других просто нет.
Чтобы получить все возможные ответы, надо в теле правила
find_non_border_pair поставить предикат fail,который заставит поставить точки отката у подцели правила euro_pair(X,Y) (cимвол *):
find_non-border_pair:-
*euro_pair(X,Y),
not(border(X,Y)),
not(border(Y,X)),
write(“X=”,X,” Y=”,Y),nl,
fail.
Предикат fail вызывает откат, ибо он всегда неуспешен.
3.Для внешней цели можно обойтись без предиката fail, но тогда в правило надо добавить аргументы find_non_border_pair(X,Y)и не забыть произвести изменения в разделе предикатов –find_non_border_pair(country,country)
4.Предикат not не допускает свободной переменной в подцели, так как для связывания свободной переменной подцель должна быть унифицирована с каким-то предложением и выполнена, то есть переменная должна быть означена до своего использования. Как видите, предикат not позволяет ввести в программу элементы логики.
Например,
Goal: not(border(“France”,”Germany”))
Ответ: False (France и Germany –соседи)