如何在Prolog家族代码中找到侄子?

时间:2019-02-19 12:09:44

标签: prolog

我正在尝试让Prolog在家谱的侄子中输出人,因为nephew(X,Y)将列出

X = the nephew
Y = Aunt/ Uncle

我已经尝试编写一些代码,我对son命令的工作很有信心,并且我相信兄弟姐妹的作品,但是将它们结合起来非常困难。

parent(pam,bob).
parent(john,bob).
parent(john,liz).
parent(bob,ann).
parent(bob,pat).
parent(pat,jim).
parent(liz,joe).
parent(liz,tim).
parent(joe,kim).

female(pam).
female(liz).
female(ann).
female(pat).
female(zoe).
female(kim).

male(bob).
male(john).
male(jim).
male(joe).
male(tim).

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

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

nephew(X, Y) :- sibling(Y, Z), son(Z, X).

1 个答案:

答案 0 :(得分:0)

你是如此亲密。

如果您运行查询

nephew(X,Y),你会得到

?- nephew(X,Y).
X = pam,
Y = liz ;
X = john,
Y = liz ;
X = liz,
Y = joe ;
X = liz,
Y = tim ;
false.

您注意到这是错误的。

但是,如果您重命名变量以便更容易理解它们

sibling(Child_a, Child_b) :-
    parent(Parent, Child_a),
    parent(Parent, Child_b),
    Child_a \= Child_b.

son(Child,Parent) :-
    parent(Parent, Child),
    male(Child).

nephew(Parent, Child_a) :-
    sibling(Child_a, Child_b),
    son(Child_b, Parent).

您会看到兄弟姐妹/ 2和儿子/ 2是正确的,并且应该会看到侄子/ 2的问题。

重命名变量时,请从事实开始并进行回溯,不要从子句的开头开始并进行回溯。


有助于弄清多语句谓词问题的另一种方法是将它们的一部分作为单独的查询运行,例如

?- sibling(Parent,Aunt_uncle),son(Nephew,Parent).
Parent = liz,
Aunt_uncle = bob,
Nephew = joe ;
Parent = liz,
Aunt_uncle = bob,
Nephew = tim ;
Parent = pat,
Aunt_uncle = ann,
Nephew = jim ;
false.

尽管此查询提供了比所需更多的信息,但结果中包含正确的值。将其放在谓词中并仅返回所需的值即可使此查询按预期工作。


侄子/ 2的正确答案是

nephew(Nephew,Aunt_uncle) :-
    sibling(Parent,Aunt_uncle),
    son(Nephew,Parent).

示例运行:

?- nephew(Nephew,Aunt_uncle).
Nephew = jim,
Aunt_uncle = ann ;
Nephew = joe,
Aunt_uncle = bob ;
Nephew = tim,
Aunt_uncle = bob ;
false.

在编写代码时,建议还创建测试用例。

如果您使用的是SWI-Prolog,则可以使用以下测试用例。

:- begin_tests(family).

% example of single test case

test(001) :-
    sibling(bob,liz).

test(002) :-
    son(tim,liz).

test(003,[nondet]) :-
    nephew(tim,bob).

% example of test cases that test multiple variations for one predicate

sibling_test_case(bob,liz).
sibling_test_case(liz,bob).
sibling_test_case(ann,pat).
sibling_test_case(pat,ann).
sibling_test_case(joe,tim).
sibling_test_case(tim,joe).

test(004, [forall(sibling_test_case(Child_a,Child_b))]) :-
    sibling(Child_a,Child_b).

son_test_case(bob,pam).
son_test_case(bob,john).
son_test_case(jim,pat).
son_test_case(joe,liz).
son_test_case(tim,liz).

test(005, [forall(son_test_case(Child,Parent)),nondet]) :-
    son(Child,Parent).

nephew_test_case(joe,bob).
nephew_test_case(tim,bob).
nephew_test_case(jim,ann).

test(006, [forall(nephew_test_case(Nephew,Aunt_uncle)),nondet]) :-
    nephew(Nephew,Aunt_uncle).

:- end_tests(family).

这些与run_tests.

一起运行
?- run_tests.
% PL-Unit: family ................. done
% All 17 tests passed
true.

请参阅:Prolog Unit Tests