Cut issue in prolog - prolog

I'm trying to do an exercise in prolog. I put a lot of cut (I know. Too much and some of them are useful and I will discuss in future to remove some of them), otherwise the program doesn't stop itself. Here is my code:
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), is_monomial(Q).
/* coefficienti */
coefficients(Poly1, Result) :- is_polynomial(Poly1), coefficienti(Poly1, Result), !.
coefficients(Poly1, Result) :- as_polynomial(Poly1, Result1), coefficienti(Result1, Result), !.
coefficienti(poly([]), []) :- !.
coefficienti(poly([m(X, _, _)|Xs]), [X|Ys]) :- coefficienti(poly(Xs), Ys), !.
/* variabili */
variables(Poly1, Result) :- is_polynomial(Poly1), variabili(Poly1, Result), !.
variables(Poly1, Result) :- as_polynomial(Poly1, Result1), variabili(Result1, Result), !.
variabili(poly([]), []) :- !.
variabili(poly([m(_, _, X)|Xs]), [X|Ys]) :- variabili(poly(Xs), Ys), !.
/* monomi */
monomials(Poly1, Result) :- is_polynomial(Poly1), monomi(Poly1, Result), !.
monomials(Poly1, Result) :- as_polynomial(Poly1, Result1), monomi(Result1, Result), !.
monomi(poly([]), []) :- !.
monomi(poly([X|Xs]), [X|Ys]) :- monomi(poly(Xs), Ys), !.
/* somma */
polyplus(Poly1, Poly2, Result) :- is_polynomial(Poly1), is_polynomial(Poly2), poly_plus(Poly1, Poly2, Result), !.
polyplus(Poly1, Poly2, Result) :- is_polynomial(Poly1), as_polynomial(Poly2, Q), poly_plus(Poly1, Q, Result), !.
polyplus(Poly1, Poly2, Result) :- as_polynomial(Poly1, Q), is_polynomial(Poly2), poly_plus(Q, Poly2, Result), !.
polyplus(Poly1, Poly2, Result) :- as_polynomial(Poly1, Q1), as_polynomial(Poly2, Q2), poly_plus(Q1, Q2, Result).
poly_plus(poly([]), poly(Q), poly(Q)) :- !.
poly_plus(poly([X|Xs]), poly(Q), poly([X|Z])) :- poly_plus(poly(Xs), poly(Q), poly(Ys)), compress_somma(X, Ys, Z), compara(Ys, Z).
poly_plus(poly([X|Xs]), poly(Q), poly(Z)) :- poly_plus(poly(Xs), poly(Q), poly(Ys)), compress_somma(X, Ys, Z).
compress_somma(_X, [], []) :- !.
compress_somma(m(X,Y,Z), [m(R,Y,Z)| List1], [m(K,Y,Z)| List2]) :- compress_somma(m(X,Y,Z), List1, List2), K is (R + X), !.
compress_somma(X, [Y| List], [Y| List]) :- compress_somma(X, List, List).
/* differenza */
polyminus(Poly1, Poly2, Result) :- is_polynomial(Poly1), is_polynomial(Poly2), poly_minus(Poly1, Poly2, Result), !.
polyminus(Poly1, Poly2, Result) :- is_polynomial(Poly1), as_polynomial(Poly2, X), poly_minus(Poly1, X, Result), !.
polyminus(Poly1, Poly2, Result) :- as_polynomial(Poly1, X), is_polynomial(Poly2), poly_minus(X, Poly2, Result), !.
polyminus(Poly1, Poly2, Result) :- as_polynomial(Poly1, Y), as_polynomial(Poly2, Z), poly_minus(Y, Z, Result).
poly_minus(poly([]), poly(X), poly(X)) :- !.
poly_minus(poly([X|Xs]), poly(Q), poly([X|Z])) :- poly_minus(poly(Xs), poly(Q), poly(Ys)), compress_differenza(X, Ys, Z), compara(Ys, Z).
poly_minus(poly([X|Xs]), poly(Q), poly(Z)) :- poly_minus(poly(Xs), poly(Q), poly(Ys)), compress_differenza(X, Ys, Z).
compress_differenza(_X, [], []) :- !.
compress_differenza(m(X,Y,Z), [m(R,Y,Z)| List1], [m(K,Y,Z)| List2]) :- compress_differenza(m(X,Y,Z), List1, List2), K is (X - R), !.
compress_differenza(X, [Y| List], [Y| List]) :- compress_differenza(X, List, List).
/*moltiplicazione */
compara([], []) :- !.
compara([X|Xs], [X|Ys]) :- compara(Xs, 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]), !.
The program gives me as output the right one but, instead of give me the end of the procedure it looks like it's waiting for something and I have to "force" the end with "enter". Is there some problem or it should be normal? Are you able to help me in someway? Thanks everyone

Okay. I solve my problem thanks to #coder. To solve it I put another cut (maybe the good one) in a single line of the closure "as_polynomial":
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), is_monomial(Q).
Then I also remove is_monomial(Q) because it was not useful

Related

Prolog cousin once removed and half sister/brother rules

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

Why doesn't it unify? Prolog issue

I'm trying to do a predicate in prolog which substitute the value I give to the variables of the polynomial and then it calculate the result. Here is my code:
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), compress_monomial([v(Z, Y)| Vars], A), ordina_m(A, Q), !.
as_monomial(*(X, Y), m(G, K, Q)) :- as_monomial(X, m(G, TD, Vars)), K is (TD + 1), compress_monomial([v(1, Y)| Vars], A), ordina_m(A, 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_var(List, Sorted) :- sort(0, #=<, List, Sorted).
compress_monomial([], []) :- !.
compress_monomial([X| Xs], A2) :- compress_monomial(Xs, A), compress_monomial2(X, A, A2), !.
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)).
variables(Poly1, Result) :- is_polynomial(Poly1), variabili(Poly1, Result), !.
variables(Poly1, Result) :- as_polynomial(Poly1, Result1), variabili(Result1, Result), !.
variabili(poly([]), []) :- !.
variabili(poly([m(_, _, [])| Xs]), Ys) :- variabili(poly(Xs), Ys), !.
variabili(poly([m(X, Y, [v(_, A)| Vs])| Xs]), Z) :- variabili(poly([m(X, Y, Vs)| Xs]), Ys), ordina_var([A| Ys], R), compressV(R, Z), !.
compressV([], []).
compressV([X|T],[X|T1]):- member(X,T),!,canc(X,T,R), compressV(R,T1).
compressV([X|T],[X|T1]) :- compressV(T,T1).
canc(_L, [], []).
canc(L, [L|S], Z) :- canc(L, S, Z).
canc(L, [H|S], [H|Z]):- canc(L, S, Z), !.
as_polynomial(+(X, Y), poly(C)) :- as_monomial(Y, G), as_polynomial(X, poly(Gs)), compress_polynomial([G| Gs], C), !.
as_polynomial(-(X, Y), poly(C)) :- as_monomial(-Y, G), as_polynomial(X, poly(Gs)), compress_polynomial([G| Gs], C), !.
as_polynomial(X, poly([X])) :- is_monomial(X), !.
as_polynomial(X, poly([Q])) :- as_monomial(X, Q), !.
compress_polynomial([], []) :- !.
compress_polynomial([X| Xs], A2) :- compress_polynomial(Xs, A), compress_polynomial2(X, A, A2), !.
compress_polynomial2(m(X, Y, Z), [], [m(X, Y, Z)]) :- !.
compress_polynomial2(m(X, Y, Z), [m(X1, Y, Z)| Xs], [m(X2, Y, Z)| Xs]) :- X2 is (X + X1), !.
compress_polynomial2(X, [Y| Ys], [Y| Z]) :- compress_polynomial2(X, Ys, Z), !.
polyval(Poly1, V, Result) :- is_polynomial(Poly1), variables(Poly1, Vars), poly_val(Poly1, Vars, V, Result), !.
polyval(Poly1, V, Result) :- as_polynomial(Poly1, P1), variables(P1, Vars), poly_val(P1, Vars, V, Result), !.
poly_val(poly([]), , , poly([])) :- !.
poly_val(poly([m(X, Y, Z)| Xs]), Vars, V, poly([R| Ys])) :- poly_val(poly(Xs), Vars, V, poly(Ys)), print(m(X, Y, Z)), mon_val(m(X, Y, Z), Vars, V, R), !.
mon_val(m(X, Y, []), [_], [_], m(X, Y, [])) :- !.
mon_val(m(X, Y, [v(W, Z)| Vs]), [Z| Vs2], [Val| Vvs], m(X2, Y2, Z2)) :- integer(Val), mon_val(m(X, Y, Vs), Vs2, Vvs, m(X3, Y2, Z2)), X2 is (X3 * (Val ^ W)), !.
mon_val(m(X, Y, [v(W, Z)| Vs]), [_| Vs2], [_| Vvs], m(X, Y2, Z2)) :- mon_val(m(X, Y, [v(W, Z)| Vs]), Vs2, Vvs, m(X, Y3, Z2)), Y2 is (Y3 + W), !.
I hope I put all the code you need to prove it, in case please say it to me and I apologise for it. I know about the cut but, at the moment, it is just a trial. My problem is in mon_val because it looks like doesn't want to unify. An example of query I use is polyval(x+x+y, [1, 3], Q). where the output is "false" and it should return poly(m(1, 0, []), m(1, 0, []), m(3, 0, [])). Are you able to help me doing that? I just want to solve the problem and later I will also implement the sum between the numbers which is pretty easy with the rest of the code I have. Thanks guys
If you wanna know, at the end I solve the problem myself (which is, according some of you, the best way to learn and I'm agree). So my poly-val becomes:
polyval(Poly1, V, Result) :- is_polynomial(Poly1), variables(Poly1, Vars), poly_val(Poly1, Vars, V, Result), !.
polyval(Poly1, V, Result) :- as_polynomial(Poly1, P1), variables(P1, Vars), poly_val(P1, Vars, V, Result), !.
poly_val(poly([]), _, _, poly([])) :- !.
poly_val(poly([X| Xs]), Vars, V, poly(Z)) :- poly_val(poly(Xs), Vars, V, poly(Ys)), mon_val(X, Vars, V, R), compress_polynomial([R| Ys], Z), !.
/* mon_val(Monomio, Variabili, ValoreVariabili, Result) */
mon_val(m(X, _, []), [_], [_], m(X,0, [])) :- !.
mon_val(m(X, _, Z), [], [], m(X,0, Z)) :- !.
mon_val(m(X, Y, [v(W, Z) | R]), [Z| Vs], [Val|Vvs], m(X2, Y2, Z2)) :- integer(Val), mon_val(m(X, Y, R), Vs, Vvs, m(X3, Y2, Z2)), X2 is (X3 * (Val ^ W)), !.
mon_val(m(X, Y, Z), [_|Vs2], [_| Vvs], m(X2, Y2, A)) :- mon_val(m(X, Y, Z), Vs2, Vvs, m(X2, Y2, A)), !.`

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) :- !.

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