Zliczanie liczby potomków w języku prolog.

0

Witam,
napisałem prosty programik, przedstawiający drzewo genealogiczne. Został mi do rozwiązania jeden problem. Otóż nie działa ostatnia część czyli zliczanie liczby potomków. Nie bardzo mam pomysł jak inkrementować wartość "liczba_potomków". Proszę o pomoc.

% Author: Robert Kaszubowski
% Date: 2013-04-16

/*
  Treść zadania:
Wyrazić w Prologu wszelkie relacje rodzinne takie jak:
dziadek, babcia, syn, dziecko, córka, brat, siostra,
stryj(brat ojca), wuj(brat matki), ciotka, potomek, przodek, kuzyn, żona, mąż,
krewny, liczba potomków itd.
dla dowolnej bazy danych, która zawiera relacje: ojciec(s,s), matka(s,s), plec(s,s).
*/

% Przykladowa baza danych:
ojciec(edward,halina).     % ojciec(jestOjcem, potomek).
ojciec(jan,adam).
ojciec(piotr,krzysztof).
ojciec(jan,maria).
ojciec(adam,monika).
ojciec(adam,norbert).
matka(halina,monika).
matka(monika,maciej).      % matka(jestMatka, potomek).
matka(ewa,maria).
matka(ewa,adam).
matka(maria,krzysztof).
plec(maciej,m).
plec(norbert,m).
plec(piotr,m).
plec(krzysztof,m).

/*
  przykładowo program powinien odpowiadać na zapytania:

kuzyn(krzysztof,norbert)  -> yes
dziadek(edward,monika)    -> yes
maz(adam,halina)          -> yes
potomek(maciej,jan)       -> yes
krewni(maciej,krzysztof)  -> yes
dziadek(jan,X)            -> X=’monika’,X=’norbert’,X=’krzysztof’
liczba_potomkow(X,jan)    -> X=6

*/

plec(edward,m).
plec(jan,m).
plec(ewa,k).
plec(halina,k).
plec(adam,m).
plec(maria,k).
plec(monika,k).
plec(krzysztof,m).

% syn(X,Y) prawda gdy X jest mezczyzna i Y jest rodzicem X.
% zapytanie - syn(X,Y), czy X jest synem Y?
% X\=Y - zeby uniknac dublowania sie rezultatow.
syn(X,Y) :- plec(X,m), ojciec(Y,X),X\=Y.
syn(X,Y) :- plec(X,m), matka(Y,X),X\=Y.
corka(X,Y) :- plec(X,k), ojciec(Y,X),X\=Y.
corka(X,Y) :- plec(X,k), matka(Y,X),X\=Y.

% dziecko ma dowolna plec.
dziecko(X,Y) :- ojciec(Y,X),X\=Y.
dziecko(X,Y) :- matka(Y,X),X\=Y.

% rodzic - odwrotnie do dziecka.
rodzic(X,Y) :- dziecko(Y,X),X\=Y.

% rodzenstwo - para ludzi, ktorzy maja wspolnych rodzicow lub rodzica.
rodzenstwo(X,Y) :- rodzic(Z,X),rodzic(Z,Y),X\=Y,X\=Z,Y\=X.
brat(X,Y) :- plec(X,m),rodzic(Z,X),rodzic(Z,Y),X\=Y,X\=Z,Y\=X.
siostra(X,Y) :- plec(X,k),rodzic(Z,X),rodzic(Z,Y),X\=Y,X\=Z,Y\=X.

% wuj - brat matki.
wuj(X,Y) :- matka(Z,Y),brat(X,Z),X\=Y,X\=Z,Y\=Z.
% stryj - brat ojca
stryj(X,Y) :- ojciec(Z,Y),brat(X,Z),X\=Y,X\=Z,Y\=Z.
% ciotka - siostra matki lub brata.
ciotka(Y,X):-matka(Z,X),siostra(Y,Z),X\=Y,X\=Z,Y\=Z.
ciotka(Y,X):-ojciec(Z,X),siostra(Y,Z),X\=Y,X\=Z,Y\=Z.

babcia(B,A):-rodzic(C,A),rodzic(B,C),plec(B,k),A\=B,A\=C,B\=C.
dziadek(B,A):-rodzic(C,A),rodzic(B,C),plec(B,m),A\=B,A\=C,B\=C.

% zona - kobieta, ma dziecko, i to dziecko ma jeszcze jednego rodzica.
zona(X,Y) :- plec(X,k),dziecko(Z,X),dziecko(Z,Y),X\=Y,X\=Z,Y\=Z.
maz(X,Y) :- plec(X,m),dziecko(Z,X),dziecko(Z,Y),X\=Y,X\=Z,Y\=Z.

% kuzyn - mezczyzna, ktory jest synem wuja lub ciotki.
kuzyn(X,Y) :- plec(X,m),dziecko(X,Z),wuj(Z,Y),X\=Y,X\=Z,Y\=Z.

% wymagana rekurencja.
potomek(X,Y) :- rodzic(Y,X).
potomek(X,Y) :- rodzic(Z,X),potomek(Z,Y).

% przodek - odwrotnie do potomka.
przodek(X,Y) :- dziecko(Y,X).
przodek(X,Y) :- dziecko(Z,X),przodek(Z,Y).

% krewny - dowolny stopien relacji rodzinnych.
krewny(X,Y) :- dziecko(X,Y);rodzic(X,Y);kuzyn(X,Y);babcia(X,Y);dziadek(X,Y),X\=Y.

% Y ma X potomkow
liczba_potomkow(X,Y) :- potomek(_,Y),X is X+1.  % <- To nie dziala.

2

Nie działa, bo niestety taki kod jest bez sensu (backtracking zupełnie inaczej działa).

Nie wiem czy to do końca zgodne z waszymi zasadami, ale najładniej zrobić tak:

liczba_potomkow(Liczba, Osoba) :-
	bagof(C, potomek(C, Osoba), Potomstwo),
	length(Potomstwo, Liczba).
1

Dzięki za odpowiedź. Już sobie z tym poradziłem i dopisałem trochę od siebie. Wrzucam bo może przyda się to komuś jeszcze :) Wymaga to jednak jeszcze lekkiego szlifu.

% Robert Kaszubowski
% Przykladowa baza danych:
ojciec(edward,halina).     % ojciec(jestOjcem, potomek).
ojciec(jan,adam).
ojciec(piotr,krzysztof).
ojciec(jan,maria).
ojciec(adam,monika).
ojciec(adam,norbert).
matka(halina,monika).
matka(monika,maciej).      % matka(jestMatka, potomek).
matka(ewa,maria).
matka(ewa,adam).
matka(maria,krzysztof).
plec(maciej,m).
plec(norbert,m).
plec(piotr,m).
plec(krzysztof,m).

% rozwijam baze danych.
plec(edward,m).
plec(jan,m).
plec(ewa,k).
plec(halina,k).
plec(adam,m).
plec(maria,k).
plec(monika,k).
plec(krzysztof,m).

syn(X,Y) :- plec(X,m), ojciec(Y,X),X\==Y.
syn(X,Y) :- plec(X,m), matka(Y,X),X\==Y.
corka(X,Y) :- plec(X,k), ojciec(Y,X),X\==Y.
corka(X,Y) :- plec(X,k), matka(Y,X),X\==Y.

dziecko(X,Y) :- ojciec(Y,X),X=\=Y.
dziecko(X,Y) :- matka(Y,X),X\==Y.

rodzic(X,Y) :- dziecko(Y,X),X\==Y.

rodzenstwo(X,Y) :- rodzic(Z,X),rodzic(Z,Y),X\==Y,X\==Z,Y\==X.
brat(X,Y) :- plec(X,m),rodzic(Z,X),rodzic(Z,Y),X\==Y,X\==Z,Y\==X.
siostra(X,Y) :- plec(X,k),rodzic(Z,X),rodzic(Z,Y),X\==Y,X\==Z,Y\==X.

wuj(X,Y) :- matka(Z,Y),brat(X,Z),X\==Y,X\==Z,Y\==Z.
% stryj - brat ojca
stryj(X,Y) :- ojciec(Z,Y),brat(X,Z),X\==Y,X\==Z,Y=\=Z.
% ciotka - siostra matki lub ojca.
ciotka(X,Y) :- matka(Z,Y),siostra(X,Z),X\==Y,X\==Z,Y\==Z.
ciotka(X,Y) :- ojciec(Z,Y),siostra(X,Z),X\==Y,X\==Z,Y\==Z.

babcia(B,A):-rodzic(C,A),rodzic(B,C),plec(B,k),A\==B,A\==C,B\==C.
dziadek(B,A):-rodzic(C,A),rodzic(B,C),plec(B,m),A\==B,A\==C,B\==C.

% zona - kobieta, ma dziecko, i to dziecko ma jeszcze jednego rodzica.
zona(X,Y) :- plec(X,k),dziecko(Z,X),dziecko(Z,Y),X\==Y,X\==Z,Y=\=Z.
maz(X,Y) :- plec(X,m),dziecko(Z,X),dziecko(Z,Y),X\==Y,X\==Z,Y\==Z.

% kuzyn - mezczyzna, ktory jest synem wuja lub ciotki.
kuzyn(X,Y) :- plec(X,m),dziecko(X,Z),wuj(Z,Y),X\==Y,X\==Z,Y\==Z.
kuzyn(X,Y) :- plec(X,m),dziecko(X,Z),ciotka(Z,Y),X\==Y,X\==Z,Y=\=Z.
kuzyn(X,Y) :- plec(X,m),dziecko(X,Z),stryj(Z,Y),X\==Y,X\==Z,Y\==Z.


potomek(X,Y) :- rodzic(Y,X).  % rodzic(Y,X). to to samo co dziecko(X,Y).
potomek(X,Y) :- rodzic(Z,X),potomek(Z,Y).

% przodek - odwrotnie do potomka.
przodek(X,Y) :- dziecko(Y,X).
przodek(X,Y) :- dziecko(Z,X),przodek(Z,Y).

% krewny - dowolny stopien relacji rodzinnych.
krewny(X,Y) :- dziecko(X,Y);rodzic(X,Y);kuzyn(X,Y);babcia(X,Y);dziadek(X,Y),X\==Y.

liczba_przodkow(X,Z) :- findall(Y, przodek(X,Y), X1),counter(X1,Z).

counter([],0).
counter([_|T],N) :- counter(T,N1),N is N1+1.

matka3(tak,X,Y) :- matka(X,Y).
matka3(nie,X,Y) :- not(matka(X,Y)),matka(Z,Y),Z\==X.
%matka3(nie,X,Y) :- not(matka(X,Y)),matka(Z,Y),Z\==X.
matka3(brak_danych,X,Y) :- not(matka(X,Y)),not(matka(Z,Y)),Z\==X.
%matka3(brak_danych,X,Y) :- not(matka(X,Y)).

0

Witam, mam identyczne zadanie do wykonania w prologu. Pobrałem z internetu program SWI-Prolog
Skopiowałem cały kod z postu wyżej i wkleiłem to pustego pliku notatnika zapisałem z rozszerzeniem takim jak wymagał SWI-prolog czyli *.pl

Uruchomiłem file -> Consult... i wybrałem plik z zapisanym kodem który się skompilował.

% c:/Documents and Settings/yasuma/Moje dokumenty/Prolog/drzewo.pl compiled 0.00 sec, 56 clauses

W oknie prologu teraz wpisywałem po kolei:

1 ?- ojciec(adam,monika).
true .

2 ?- plec(ewa,k).
true.

3 ?- kuzyn(krzysztof,norbert).
ERROR: =\=/2: Arithmetic: `krzysztof/0' is not a function
   Exception: (7) dziecko(krzysztof, _G433) ? creep
   Exception: (6) kuzyn(krzysztof, norbert) ? creep
4 ?- 

W związku z tym, mam pytanie czy ten program który skopiowałem z postu wyżej jest prawidłowo napisany? Jeśli nie to czy mógłby go ktoś trochę 'udoskonalić' aby odpowiadał na zapytania takie jak w treści zadania czyli:

kuzyn(krzysztof,norbert) -> yes
dziadek(edward,monika) -> yes
maz(adam,halina) -> yes
potomek(maciej,jan) -> yes
krewni(maciej,krzysztof) -> yes
dziadek(jan,X) -> X=’monika’,X=’norbert’,X=’krzysztof’
liczba_potomkow(X,jan) -> X=6

Z góry dziękuję za jakąkolwiek pomoc i pozdrawiam forumowiczów 4programmers

1 użytkowników online, w tym zalogowanych: 0, gości: 1