Prolog, wydawałoby się, dopełniający rekurencyjne wywołanie bez powrotu

0

Pytanie

Mam zdefiniowane są następujące dwa żebra:

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

add(X, L, [X | L]).

Teraz staram się rekurencyjnie zbudować drogę od a do c (a,b,c), przy użyciu to:

path(FROM,TO,W):-
    edge(FROM,TO),
    add(TO, [], X),
    add(FROM, X, W).
path(FROM,TO,W):-
    edge(FROM,Y),
    path(Y,TO, W),
    add(FROM, W, _).

Wydaje się, że to działa w podstawowym przypadku, jak path(a,b,X) wyprowadzi X = [a,b]. Jednak path(a,c,X) tylko wyjścia X = [b,c]tak , jakby on po prostu przechodzi do podstawowego wariantu i kończy go tam, a nie wraca do niestabilność i wiele błędnych połączeń. Ostatecznie, chciałbym, aby wyprowadził X = [a,b,c] ale nie mam pomysłów.

Fyi, używam SWI-Prolog.

prolog
2021-11-23 21:03:28
2

Najlepsza odpowiedź

1

Jak można samemu zdiagnozować problem? Do tego jest prosty sposób. Po pierwsze, określić przypadki, w których można się spodziewać, że to będzie prawdą, i przypadki, w których można się spodziewać, że to się nie uda. Oto niektóre plus kilka pomocnicze określenia celu ułatwienia debugowania

:- initialization(path(a,b,[a,b])).
:- initialization(path(a,c,[a,b,c])).   % intended to be true, initially false
:- initialization(\+path(a,b,[a,_,c])).
:- initialization(\+path(a,d,_)).       % no node d, thus no path

:- op(950, fy, *).
:- meta_predicate(*(0)).

*_G_0.   % this permits us to remove goals by adding a * in front.

Teraz zapisz program ..i powiedz [program]. Otrzymasz ostrzeżenie typu

* user:user:path(a,c,[a,b,c]) - goal failed

Tak, wiemy, że nie rozwiązały problemu.

Teraz spróbuj podsumować program, dodając * przed celem. Można zauważyć, że dla każdego takiego uogólnienia będzie pojawiać się więcej błędów (a w jednym przypadku nawet uchybienia). Za wyjątkiem ostatniego celu, gdzie wszystko jest po staremu. Dlatego usunięcie lub wymiana tego celu wydaje się dobrym pomysłem.

Prędzej czy później natkniesz się z cyklami. Dla acykliczne oddechowych użyjpath/4:

?- path(edge, Path, A, B).
2021-11-24 18:06:52
0

Twój kod działa prawidłowo, bo on odrzuca wynik, uzyskany za pomocą celów add(FROM, W, _)w drugim zdaniu predykatu path/3. Aby rozwiązać ten problem, należy zmienić kod w następujący sposób:

path(From, To, W):-
    edge(From, To),
    add(To, [], X),
    add(From, X, W).

path(From, To, PATH):-   
    edge(From, Y),
    path(Y,To, W),
    add(From, W, PATH). % <== get PATH

Jeszcze najlepsza wersja tego kodu wygląda następująco:

path(From, To, [From, To]) :-
    edge(From, To).

path(From, To, [From|Path]) :-
    edge(From, X),
    path(X, To, Path).
2021-11-24 13:56:11

Legenda, dziękuję ci!
Dragonslayer

W innych językach

Ta strona jest w innych językach

Русский
..................................................................................................................
Italiano
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................