2017-01-31 6 views
3

Моя цель - иметь возможность перемещать узлы в диаграмме и выводить длину пути в Prolog. Я использую рекурсию, и я застрял в этой проблеме. Вот моя попытка.Как я могу избежать этой ловушки в моей рекурсии Prolog?

edge(a,b). 
edge(b,c). 
edge(a,d). 
edge(d,f). 

distance(X,Y,1) :- edge(X,Y). 
distance(X,Y,Dis) :- edge(X,Z), distance(Z, Y, D), Dis is D +1. 

Вопрос: Я хотел бы иметь возможность сказать Dis = 0. Если путь недействителен. Как и в, нет ребра, соединяющего два узла, Dis = 0. В настоящее время мой код говорит false для недопустимого пути. Мои попытки в этом начинании привели к тому, что я нарушил рекурсию. Спасибо за любую помощь.

+3

Вы уверены в семантике расстояния? Разве Dis Dis = 0 не означает, что оба узла одинаковы? Это можно кодировать как расстояние (X, X, 0). – Hashcut

ответ

4

Как @Hashcut говорит в своем комментарии, было бы более разумно, если бы Dis = 0, то X = Y. На самом деле совершенно логично, что ваш предикат потерпит неудачу, если путь недействителен.

Теперь, если вы действительно хотите делать то, что вы говорите, вы можете сделать это так:

distance_(X,Y,1) :- edge(X,Y). 
distance_(X,Y,Dis) :- edge(X,Z), distance_(Z, Y, D), Dis is D + 1. 

distance(X,Y,D) :- distance_(X,Y,D) -> true ; D = 0. 

Мы просто переименовать исходный предикат в distance_, а затем создать предикат distance, который делает то же самое, как и раньше если путь существует, или унифицируйте D с 0, если он не работает. -> используется для отказа от выбора D = 0, если путь действителен.

Обратите внимание, что у вас есть такое поведение:

?- distance(a,a,X). 
X = 0. 

?- distance(b,f,X). 
X = 0. 

Что-то странно, но ожидается, из-за того, что вы хотите.