Prolog cousin once removed and half sister/brother rules - prolog

Am working on a prolog genealogy project and cannot figure out how to make the rules for cousin once removed and half sister/brother rules. Below is what I have and cannot get it to work. Any help or suggestions would be appreciated. I have placed in bold what I have tried. I'm sure its something simple in the way I'm trying to code it.I just cannot figure it out.
person(marc,male).
person(faith,female).
person(alan,male).
person(kim,female).
person(missy,female).
person(eric,male).
person(charles,male).
person(eleanor,female).
person(roland,male).
person(corey,male).
person(amy,female).
person(tyler,male).
person(matty,male).
person(kaydi,female).
person(jenna,female).
person(allison,female).
person(emma,female).
person(hayley,female).
person(jaylin,female).
person(lukus,male).
person(brendon,male).
person(bradley,male).
person(tylerh,male).
person(dayna,female).
person(victor,male).
person(jacoby,male).
person(javi,male).
person(jordan,male).
person(jaxson,male).
person(kenzie,female).
person(richard,male).
person(reggie,male).
person(reggiejr,male).
person(beverly,female).
person(floyd,male).
person(marjorie,female).
person(kevin,male).
parent(marc,alan).
parent(faith,alan).
parent(charles,marc).
parent(charles,kim).
parent(charles,missy).
parent(charles,eric).
parent(eleanor,marc).
parent(eleanor,kim).
parent(eleanor,missy).
parent(eleanor,eric).
parent(eric,matty).
parent(eric,tyler).
parent(eric,kaydi).
parent(amy,matty).
parent(amy,tyler).
parent(amy,kaydi).
parent(missy,jordan).
parent(missy,jaxson).
parent(missy,kenzie).
parent(richard,jordan).
parent(corey,kenzie).
parent(corey,jaxson).
parent(kim,allison).
parent(kim,jenna).
parent(kim,emma).
parent(kim,jaylin).
parent(kim,hayley).
parent(kim,dayna).
parent(roland,allison).
parent(roland,jenna).
parent(roland,emma).
parent(roland,jaylin).
parent(roland,hayley).
parent(roland,dayna).
parent(dayna,javi).
parent(dayna,jacoby).
parent(victor,javi).
parent(victor,jacoby).
parent(jenna,bradley).
parent(brendon,bradley).
parent(tylerh,lukus).
parent(allison,lukus).
parent(reggie,reggiejr).
parent(beverly,reggiejr).
parent(floyd,beverly).
parent(marjorie,beverly).
parent(reggiejr,kevin).
parent(floyd,eleanor).
parent(marjorie,eleanor).
married(marc,faith).
married(charles,eleanor).
married(kim,roland).
married(eric,amy).
married(missy,corey).
married(dayna,victor).
married(allison,tylerh).
married(marjorie,floyd).
married(beverly,reggie).
father(X, Y) :- parent(X, Y), person(X,male).
mother(X, Y) :- parent(X, Y), person(female,Y).
son(X, Y) :- parent(Y,X), person(X,male).
daughter(X, Y) :- parent(X,Y), person(Y,female).
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
grandfather(X, Z) :- grandparent(X, Z), person(X,male).
grandmother(X, Z) :- grandparent(X, Z), person(female,Y).
grandson(X, Z) :- grandchild(X, Z), person(X,male).
granddaughter(Y, Z) :- grandchild(Y, Z), person(Y,female).
grandchild(X, Z) :- grandparent(Z, X).
sibling(X,Y) :- parent(Z,X), parent(Z,Y).
brother(Y, X) :- sibling(Y,X), person(X,male), not(X=Y).
sister(X, Y) :- sibling(X, Y), person(Y,female).
auntoruncle(X, W) :- sibling(X, Y), parent(Y, W).
auntoruncle(X, Z) :- married(X,Y), sibling(Y,W), parent(W,Z).
uncle(X, W) :- auntoruncle(X, W), person(X,male).
aunt(X, W) :- auntoruncle(X, W), person(female,Y).
cousin(X, Y) :- parent(Z, X), auntoruncle(Z, Y), Y\=X.
nieceornephew(X, Y) :- parent(Z, X), sibling(Z, Y).
nephew(X, Y) :- nieceornephew(X, Y), person(X,male).
niece(X, Y) :- nieceornephew(Y, X), person(Y,female).
greatgrandparent(X, Z) :- parent(X, Y), grandparent(Y, Z).
greatgrandfather(X, Z) :- greatgrandparent(X, Z), person(X,male).
greatgrandmother(X, Z) :- greatgrandparent(X, Z), person(female,Y).
greatgrandchild(X, Z) :- child(X, Y), grandchild(X, Z).
greatgrandson(X, Z) :- greatgrandchild(X, Z), person(X,male).
greatgranddaughter(X, Z) :- greatgrandchild(X, Z), person(female,Y).
married_to(X,Y) :- married(X,Y), not divorced(X,Y).
whatgender(X,Y) :- person(X,Y).
**child(X, Y) :- parent(Y, X).
cousinonceremoved(X, Y) :- cousin(Z, Y), child(X, Z).
halfsibling(X,Y) :- parent(Z,X), parent(Z,Y), parent(P,X), \+parent(P,Y).
halfbrother(X,Y) :- halfsibling(X,Y), male(X).
halfsister(X,Y) :- halfsibling(X,Y), female(X).**
strong text

Related

Arguments aren't sufficient instantiated

I read my code for an hour but I'm not able to understand where the problem is. I read that this error means that I use an argument I didn't instantiate before but I can't see where it is. Can you help me?
as_monomial(X, m(X, 0, [])) :- number(X), !.
as_monomial(^(Y, Z), m(1, Z, [v(Z, Y)])) :- !.
as_monomial(*(X, ^(Y, Z)), m(G, K, Q)) :- as_monomial(X, m(G, TD, Vars)), K is (TD + Z), ordina_m([v(Z, Y)| Vars], Q), !.
as_monomial(*(X, Y), m(G, K, Q)) :- as_monomial(X, m(G, TD, Vars)), K is (TD + 1), ordina_m([v(1, Y)| Vars], Q), !.
as_monomial(-(X), m(-A, Y, L)) :- as_monomial(X, m(A, Y, L)).
as_monomial(X, m(1, 1, [v(1, X)])).
ordina_m(List, Sorted) :- sort(2, #=<, List, Sorted).
ordina_poly1(List, Sorted) :- sort(2, #>=, List, Sorted).
ordina_poly2(List, Sorted) :- sort(3, #=<, List, Sorted).
is_monomial(m(_C, TD, VPs)) :- integer(TD), TD >= 0, is_list(VPs).
is_polynomial(poly(M)) :- is_list(M), foreach(member(Monomio, M), is_monomial(Monomio)).
as_polynomial(+(X, Y), poly(C)) :- as_monomial(Y, G), as_polynomial(X, poly(Gs)), inverti(G, H), inverti2(Gs, Hs), ordina_poly2([H| Hs], D), inverti2(D, F), ordina_poly1(F, C), !.
as_polynomial(-(X, Y), poly(C)) :- as_monomial(-Y, G), as_polynomial(X, poly(Gs)), inverti(G, H), inverti2(Gs, Hs), ordina_poly2([H| Hs], D), inverti2(D, F), ordina_poly1(F, C), !.
as_polynomial(X, poly([X])) :- is_monomial(X), !.
as_polynomial(X, poly([Q])) :- as_monomial(X, Q), !.
/* grado massimo */
maxdegree(Poly1, Result) :- is_polynomial(Poly1), max_degree(Poly1, Result), !.
maxdegree(Poly1, Result) :- as_polynomial(Poly1, Result1), max_degree(Result1, Result), !.
max_degree(poly([]), 0) :- !.
max_degree(poly([m(_, X, _)|Xs]), X) :- max_degree(poly(Xs), Ys), X > Ys, !.
max_degree(poly([m(_, X, _)|Xs]), Ys) :- max_degree(poly(Xs), Ys), X =< Ys, !.
/* grado minimo */
mindegree(Poly1, Result) :- is_polynomial(Poly1), min_degree(Poly1, Result), !.
mindegree(Poly1, Result) :- as_polynomial(Poly1, Result1), min_degree(Result1, Result), !.
min_degree(poly([m(_, X, _)]), X) :- !.
min_degree(poly([m(_, X, _)|Xs]), X) :- min_degree(poly(Xs), Ys), X < Ys, !.
min_degree(poly([m(_, X, _)|Xs]), Ys) :- min_degree(poly(Xs), Ys), X >= Ys, !.
inverti(m(_, _, []), m(_, _, [])) :- !.
inverti(m(X, Y, [v(W, Z)| Xs]), m(X, Y, [v(Z, W)| Ys])) :- inverti(m(X, Y, Xs), m(X, Y, Ys)), !.
inverti2([], []) :- !.
inverti2([m(X, Y, [])| Zs], [m(X, Y, [])| Ss]) :- inverti2(Zs, Ss), !.
inverti2([m(X, Y, [v(W, Z)| Xs])| Zs], [m(X, Y, [v(Z, W)| Ys])| Ss]) :- inverti2([m(X, Y, Xs)| Zs], [m(X, Y, Ys)| Ss]), !.
I will not include code for as/is_polynomial cuz I already use it before and I don't have problem with that piece of code. Can you help me please?
An example for it, I tried, is maxdegree(x^5+y^500+4, R). (same thing for mindegree)
I solve my problem adding a clausure in both maxdegree and mindegree as base case:
max_degree(poly([m(_, _X, [])]), 0) :- !.
max_degree(poly([m(_, X, _)]), X).
min_degree(poly([m(_, _X, [])]), 0) :- !.
min_degree(poly([m(_, X, _)]), X) :- !.

How to find if somebody is somebodies second cousin once removed in prolog?

I am writing a program to return true if a person is another persons second cousin once removed. The only information that is known is who is the parent of who else. I am using the family tree from here http://en.wikipedia.org/wiki/Cousin#Second_cousins_once_removed. Overall I got everything working but i cant make it find the second cousin once removed. The first cousin and the once removed ones work, just looking to get some help on how to find a second cousin that is also once removed.
parent(adam, betty).
parent(agatha, betty).
parent(adam, charles).
parent(agatha, charles).
parent(bill, david).
parent(betty, david).
parent(charles, emma).
parent(corinda, emma).
parent(dawn, frank).
parent(david, frank).
parent(emma, gwen).
parent(eric, gwen).
parent(frank, harry).
parent(felicity, harry).
child(X, Y) :-
parent(Y, X).
grandparent(X, Y) :-
parent(X, Z),
parent(Z, Y).
greatgrandparent(X, Y) :-
parent(P, Y),
grandparent(X, P).
cousin(X, Y) :-
grandparent(Z, X),
grandparent(Z, Y),
\+sibling(X, Y),
X \= Y.
sibling(X, Y) :-
parent(Z, X),
parent(Z, Y),
X \= Y.
cousinonceremoved(X, Y) :-
cousin(Z, Y),
child(X, Z).
secondcousin(X, Y) :-
greatgrandparent(Z, X),
greatgrandparent(Z, Y),
\+sibling(X, Y),
\+cousin(X, Y),
X \= Y.
Just as stated in the article: "The child of one's second cousin".
secondCousinOnceRemoved(H, G) :- child(H, F), secondcousin(F, G).

Prolog defining a male

So my lecturer wrote this code as an answer to one of a question. Today we found out that the rule male and female are both wrong, can somebody confirm this for me? Also, taking advantage of of this post I would like to ask you kind people if you could send/link me a tutorial explaining prolog in detail, if you could do this it'd be great! Thanks a lot.
/* FACTS */
parents(david, george, noreen).
parents(jennifer, george, noreen).
parents(georgejr, george, noreen).
parents(scott, george, noreen).
parents(joanne, george, noreen).
parents(jessica, david, edel).
parents(clara, david, edel).
parents(michael, david, edel).
parents(laura, georgejr, susan).
parents(anna, scott, siobhan).
parents(edel, mick, peggy).
parents(maria, mick, peggy).
parents(assumpta, mick, peggy).
parents(patrick, kevin, maria).
parents(hugh, kevin, maria).
parents(helena, kevin, maria).
parents(roisin, wim, assumpta).
/* Relationships */
father(X, Y) :- parents(Y, X, _).
male(X) :- father(X, _).
mother(X, Y) :- parents(Y, _, X).
female(X) :- mother(X, _).
grandfather(X, Y) :- father(X, Z), father(Z, Y).
grandfather(X, Y) :- father(X, Z), mother(Z, Y).
grandmother(X, Y) :- mother(X, Z), mother(Z, Y).
grandmother(X, Y) :- mother(X, Z), father(Z, Y).
brother(X, Y) :- male(X), father(Z, X), father(Z, Y), X \== Y.
sister(X, Y) :- female(X), father(Z, X), father(Z, Y), X \== Y.
/* New realtionships */
parent(X,Y) :- father(X,Y); mother(X,Y).
uncle(X,Y) :- parent(Z,Y), brother(X,Z), Z \== X.
aunt(X,Y) :- parent(Z,Y), sister(X,Z), Z \== X.
sibling(X,Y) :- brother(X,Y); sister(X,Y).
cousin(X,Y) :- parent(Z,X), parent(W,Y), sibling(Z,W).

Prolog and ancestor relationship

I have to write a small prolog program which checks if a given person is a ancestor of a second one.
These are the facts and rules:
mother(tim, anna).
mother(anna, fanny).
mother(daniel, fanny).
mother(celine, gertrude).
father(tim, bernd).
father(anna, ephraim).
father(daniel, ephraim).
father(celine, daniel).
parent(X,Y) :- mother(X,Y).
parent(X,Y) :- father(X,Y).
The test if a person is an ancestor of another person is easy:
ancestor(X, Y) :- parent(X, Y).
ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
But now I have to write a method ancestor(X,Y,Z) which also prints out the relationship between two persons. It should look like this
?- ancestor(ephraim, tim, X).
false.
?- ancestor(tim, ephraim, X).
X = father(mother(tim)).
And that is the problem: I have no clue how do to this.
You can use an accumulator to adapt #Scott Hunter's solution :
mother(anna, fanny).
mother(daniel, fanny).
mother(celine, gertrude).
father(tim, bernd).
father(anna, ephraim).
father(daniel, ephraim).
father(celine, daniel).
ancestor(X, Y, Z) :- ancestor(X, Y, X, Z).
ancestor(X, Y, Acc, father(Acc)) :- father(X, Y).
ancestor(X, Y, Acc, mother(Acc)) :- mother(X, Y).
ancestor(X, Y, Acc, Result) :-
father(X, Z),
ancestor(Z, Y, father(Acc), Result).
ancestor(X, Y, Acc, Result) :-
mother(X, Z),
ancestor(Z, Y, mother(Acc), Result).
edit : as Scott Hunter showed in his edit, there's no need for an explicit accumulator here, since we can left the inner part of the term unbound easily at each iteration. His solution is therefore better !
A term manipulation alternative to the accumulator tecnique by #Mog:
parent(X, Y, mother(X)) :- mother(X, Y).
parent(X, Y, father(X)) :- father(X, Y).
ancestor(X, Y, R) :-
parent(X, Y, R).
ancestor(X, Y, R) :-
parent(X, Z, P),
ancestor(Z, Y, A),
eldest(A, P, R).
eldest(A, P, R) :-
A =.. [Af, Aa],
( atom(Aa)
-> T = P
; eldest(Aa, P, T)
),
R =.. [Af, T].
To test, I made tim a father: father(ugo, tim).
?- ancestor(tim, ephraim, X).
X = father(mother(tim)) .
?- ancestor(ugo, ephraim, X).
X = father(mother(father(ugo))) .
Simply add a term which tracts what kind of parent is used at each step (edited to get result in proper order):
ancestor(X,Y,father(X)) :- father(X,Y).
ancestor(X,Y,mother(X)) :- mother(X,Y).
ancestor(X,Y,father(Z2)) :- father(Z,Y), ancestor(X,Z,Z2).
ancestor(X,Y,mother(Z2)) :- mother(Z,Y), ancestor(X,Z,Z2).

Define a connectivity graph in Prolog

I'm continuing some researches in lattices and semilattices and suddenly having this question.
Basically, we have a RelationList of [a,b] pairs, which means that (a,b) is an edge. Now we should know, is a graph formed by this RelationList 1-connectivity or not.
By the way, we have an ordered graph, so order of (a,b) is important.
clear_link(X, Y, RelationList) :-
(member([X,Y], RelationList)
;
member([Y,X], RelationList)),
X =\= Y.
linked(X, Y, RelationList) :-
clear_link(X, Y, RelationList),
!.
linked(X, Y, RelationList) :-
clear_link(X, Z, RelationList),
linked(Z, Y, RelationList).
simple_connect(RelationList, E) :-
forall((member(X, E),
member(Y, E), X < Y),
linked(X, Y, RelationList)).
But, for 6-element graph I have stackoverflow.
?- simple_connect([[2,1],[2,3],[4,3],[4,5],[6,5]],[1,2,3,4,5,6]).
ERROR: Out of local stack
Am I defining it wrong?
I've correct some. Now it's fine
clear_link(X, Y, RelationList) :-
member([X,Y], RelationList),
X =\= Y.
linked(X, Y, RelationList) :-
clear_link(X, Y, RelationList),
!.
linked(X, Y, RelationList) :-
clear_link(X, Z, RelationList),
linked(Z, Y, RelationList),
!.
simple_connect(RelationList, E) :-
forall((member(X, E),
member(Y, E), X < Y),
linked(X, Y, RelationList)).
connective_graph(RelationList, E) :-
findall(Relation, (
member(X, RelationList),
sort(X, Relation)
),SortRelationList),
simple_connect(SortRelationList, E).
And
?- connective_graph([[2,1],[2,3],[4,3],[4,5],[6,5]],[1,2,3,4,5,6]).
true.
?- connective_graph([[2,1],[4,3],[4,5],[6,5]],[1,2,3,4,5,6]).
false.
Right answer (copy to post)
connected(X, Y, RelationList) :-
(member([X,Y], RelationList);
member([Y,X], RelationList)).
path(X, Y, RelationList, Path) :-
travel(X, Y, RelationList, [X], ReversePath),
reverse(ReversePath, Path),!.
travel(X, Y, RelationList, Point, [Y | Point]) :-
connected(X, Y, RelationList).
travel(X, Y, RelationList, Visited, Path) :-
connected(X, Z, RelationList),
Z =\= Y,
\+member(Z, Visited),
travel(Z, Y, RelationList, [Z|Visited], Path).
connective_graph(RelationList, E) :-
forall((member(X, E),
member(Y, E),
X < Y)
,path(X,Y,RelationList,_)).

Resources