2009-09-15 14 views
9

Następująca historia pochodzi z N. Wirtha (1976) Algorytmy + Datastructures = Programy.Jak mogę zaimplementować: "Jestem moim własnym dziadkiem" w Prologu?

I poślubił wdowę (nazwijmy ją biała) która miała dorosłą córkę (nazywają ją D). Mój ojciec (F), który odwiedzał nas dość często, zakochał się w mojej krokodynce i ożenił się z nią. Stąd mój ojciec stał się moim zięciem, a moja córka stała się moją matką. Kilka miesięcy później moja żona urodziła syna (S1), który stał się moim szwagrem , a także moim stryjem. Ta żona mojego ojca, , czyli moja przybrana córka, również miała syna (S2).

Ja próbuje modelować te relacje w prologu, więc w końcu będę mógł wpisać:

| ?- grandfather(i,i). 

I będę mieć „tak” lub „nie” na niezależnie od tego, czy jestem moim własnym dziadkiem, czy nie.

Oto kod Pisałem tak daleko (grandpa.pl):

aunt(X,Y):- 
    sibling(X,Z), 
    parent(Z,Y), 
    female(X). 

brother(X,Y):- 
    sibling(X,Y), 
    male(X). 

brother_in_law(X,Y):- 
    child(X,Z), 
    married(Z,W), 
    parent(W,Y), 
    not(sibling(X,Y)), 
    male(X). 

brother_in_law(s1,f). 

child(X,Y):- 
    parent(Y,X). 

daughter(X,Y):- 
    parent(Y,X), 
    child(X,Y), 
    female(X). 

daughter(d,w). 

father(X,Y):- 
    parent(X,Y), 
    male(X). 

father(f,i). 

father_in_law(X,Y):- 
    child(X,Z), 
    married(Y,Z), 
    not(child(X,Y)), 
    male(X). 

grandparent(X,Y):- 
    parent(X,Z), 
    parent(Z,Y). 

grandmother(X,Y):- 
    grandparent(X,Y), 
    female(X). 

grandfather(X,Y):- 
    grandparent(X,Y), 
    male(X). 

grandchild(X,Y):- 
    child(X,Z), 
    child(Z,Y). 

married(X,Y):- 
    wife(X,Y), 
    female(X). 

married(X,Y):- 
    husband(X,Y), 
    male(X). 

married(i,w). 
married(f,d). 

mother(X,Y):- 
    parent(X,Y), 
    female(X). 

parent(X,Y):- 
    child(Y,X). 

sibling(X,Y):- 
    parent(Z,X), 
    parent(Z,Y). 

sister(X,Y):- 
    sibling(X,Y), 
    female(X). 

son(X,Y):- 
    parent(Y,X), 
    male(X). 

son(s1,w). 
son(s2,d). 

son_in_law(X,Y):- 
    child(X,Z), 
    not(child(X,Y)), 
    married(Z,Y), 
    male(X). 

son_in_law(f,i). 

step_daughter(X,Y):- 
    child(X,Z), 
    married(Z,Y), 
    not(child(X,Y)), 
    female(X). 

step_daughter(d,i). 

step_parent(X,Y):- 
    married(X,Z), 
    parent(Z,Y), 
    not(parent(X,Y)). 

step_father(X,Y):- 
    step_parent(X,Y), 
    male(X). 

step_mother(X,Y):- 
    step_parent(X,Y), 
    female(X). 

step_mother(d,i). 

uncle(X,Y):- 
    sibling(X,Z), 
    parent(Z,Y), 
    male(X). 

uncle(s1,i). 

Teraz mam wiele kłopotów z definicjami kołowych tak, że dostać się do nieskończonej pętli podczas uruchamiania kwerendy : dziadek (ja, i).

Na przykład mam:

(1 ms) yes {trace} | ? - dziadek (ja, i). 1 1 Połączenie: dziadek (i, i)?
2 2 Zadzwoń: dziadek (i, i)?
3 3 Zadzwoń: rodzic (i, _103)?
4 4 Zadzwoń: dziecko (_127, i)?
5 5 Zadzwoń: rodzic (i, _151)?
6 6 Zadzwoń: dziecko (_175, i)?
7 7 Zadzwoń: rodzic (i, _199)?
8 8 Zadzwoń: dziecko (_223, i)?
9 9 Zadzwoń: rodzic (i, _247)?
10 10 Zadzwoń: dziecko (_271, i)?
11 11 Zadzwoń: rodzic (i, _295)?
12 12 Zadzwoń: dziecko (_319, i)?
13 13 Połączenie: rodzic (i, _343)?
14 14 Zadzwoń: dziecko (_367, i)?
15 15 Zadzwoń: rodzic (i, _391)?
...

To dlatego, że dziecko określa się jako nie mający rodzica, a rodzic określa sam ma posiadanie dziecka (jak zobaczysz w powyższych orzeczników napisałem).

Czy ktoś może mi pomóc ponownie zdefiniować moje predykaty dla tych relacji, aby móc stwierdzić, czy jestem moim własnym dziadkiem?

+0

Heh, ja rzeczywiście miał to zrobić dla mojej klasy AI. Zastanawiam się, czy nadal mam kod ... Zobaczę, kiedy wrócę do domu. Pamiętam, że to też boli mój mózg. –

+5

Używają Prolog w West Virgina? ;-) –

+0

@ T.E.D .: Shh! TheTXI Cię usłyszy! –

Odpowiedz

3

Moja prolog Oczywiście była długa dawno temu, ale co o usunięcie

parent(X,Y):- 
    child(Y,X). 

i po prostu wymianą wykorzystanie parent(A,B) z child(B,A)? Nadal możesz dodawać fakty o rodzicach, ponieważ zasada odwrotna jest wciąż dostępna - możesz również usunąć tę, ale w tym przypadku nie możesz już używać faktów dotyczących rodziców i będziesz musiał zapisać wszystkie swoje fakty jako dziecko (a, b) także.

To jest to samo?

1

Zauważ, że moja wiedza o Prologu jest stary (i nigdy tak głęboko) ...

myślę, że trzeba, aby rodzic (lub dziecko) podstawowy (nie zależy od innych relacji).

child(X,Y):- 
    parent(Y,X). 

parent(X,Y):- 
    child(Y,X). 

jest prawdopodobnie przyczyną pętli.

5

usunąłem wszystko, co było konieczne w kodzie i zmienił kilka rzeczy i to, co skończyło się z:

% married(Husband, Wife) 
married(i,w). 
married(f,d). 

Można by przypuszczać, że married(X,Y) :- married(Y,X), ale prowadzi do nieprzyjemnych okrągłych dowodów, więc po prostu najpierw postawi męża na konwencję.

W przypadku rodzicielstwa pojawia się podobny problem. Musimy rozważyć krok rodziców jako prawdziwych rodziców, ponieważ zagadka zależy od tego. Wiemy, że nigdy nie możesz być swoim biologicznym przodkiem!

Jednak parent(X,Y) :- parent(Z,Y), married(X,Z) napotyka na te same problemy, dlatego właśnie nazwałem rodzicielstwo biologiczne bio_parent.

bio_parent(f,i). 
bio_parent(w,d). 
bio_parent(w,s1). 
bio_parent(i,s1). 
bio_parent(d,s2). 
bio_parent(f,s2). 

Pamiętaj, że musimy jasno powiedzieć o obojgu rodzicach, ponieważ nie ma sposobu, aby zakończyć biologiczny rodzicielstwo od małżeństwa! Również twój sposób specyfikacji był problematyczny. Trzeba było coś takiego:

son(X,Y) :- child(X,Y), male(X). 
son(a,b). 

jednak od tych zasad Prolog nie mógł wywnioskować child(a,b), więc skończyło się na pokojowe synów, którzy nie byli dziećmi! Wystąpiło to kilka razy w kodzie. Jeśli czerpiesz b z a, zawsze podawaj jako fakt fakt, a! Na pierwszy rzut oka może to wydawać się wadą Prologa, ale tak nie jest. Pamiętaj, że każda klauzula jest tylko jednym ze sposobów udowodnienia określonego orzeczenia. W powyższym przykładzie stwierdziłeś, że każde dziecko płci męskiej jest synem, a także jest nim a, tak się składa, że ​​jest synem b. Nigdzie nie jest powiedziane, że bycie mężczyzną to jedyny sposób na to, by ktoś mógł być synem, ale może to być wyjątek.

Następny jest nieco rozwlekły, ponieważ nasza definicja married zmusza nas do traktowania ojców kroków oddzielnie od matek krok. Jednoczesnie jednoczymy je z rodzicami .

step_father(X,Y) :- married(X,Z),bio_parent(Z,Y),\+bio_parent(X,Y). 
step_mother(X,Y) :- married(Z,X),bio_parent(Z,Y),\+bio_parent(X,Y). 
step_parent(X,Y) :- step_father(X,Y). 
step_parent(X,Y) :- step_mother(X,Y). 

Jak już powiedziałem, musimy uważać rodziców-ojców za rodziców!

parent(X,Y) :- step_parent(X,Y). 
parent(X,Y) :- bio_parent(X,Y). 

grandparent(X,Y):- 
    parent(X,Z), 
    parent(Z,Y). 

W twoim kodzie były też inne błędy, które wyjąłem, po prostu pokażę kilka przykładów, abyś mógł się z nich uczyć.

Po pierwsze, mówisz, że żony są małżeństwem, a mężczyźni są małżeństwem. Więc żony płci męskiej byłyby niezamężne. Powinno być odwrotnie, kobiety będące małżonkami nazywane są żonami!

% wrong: 
% 
% married(X,Y):- 
% wife(X,Y), 
% female(X). 
% 
% married(X,Y):- 
% husband(X,Y), 
% male(X). 
% 
% right: 
% wife(X,Y) :- married(Y,X). % according to our new definition of 'married' 
% husband(X,Y) :- married(X,Y). 

Tutaj dodałem ostatnią linię, jak zwykle nie rozważyć sobie własne rodzeństwo:

% sibling(X,Y):- 
% parent(Z,X), 
% parent(Z,Y), 
% X \= Y. % added this 

Te dwie ostatnie są fakty na niewłaściwym orzecznika ponownie. Zasadniczo zastępujesz odliczenia Prologa o . Powinny one zostać odjęte, a nie określone jako fakty!

% son_in_law(f,i). 
% step_mother(d,i). 

Teraz wypróbuj ten program. I nie bądź zaskoczony: nie tylko ty będziesz ich dziadkiem! ;-)

0
couples(i,w). 
mother_of(w,d). 
father_of(f,i). 
couples(f,d). 
son_in_law(f,i). 
mother_of(d,i). 
mother_of(w,s1). 
mother_of(d,s2). 
grand(F,C):- son_in_law(F,C),couples(H,D),mother_of(D,C). 
grand(F,C):- father_of(F,D),father_of(D,C). 

zapytania

?-grand(i,i).