我有以下gprolog程序:
father(charles, harry).
daughter(elizabeth, george).
son(william, charles).
father(X, Y) :- son(Y, X).
father(X, Y) :- daughter(Y, X).
daughter(X, Y) :- \+son(X, Y), father(Y, X).
son(X, Y) :- \+daughter(X, Y), father(Y, X).
鉴于我所拥有的,我尝试了这个问题:
| ?- son(harry, charles).
...得到了一个no
(据我所知,a.k.a。,“Prolog无法证明这一点。”)。当我对它进行跟踪时,它似乎没有太大帮助:
{trace}
| ?- son(harry, charles).
1 1 Call: son(harry,charles) ?
1 1 Fail: son(harry,charles) ?
由于son(harry, charles)
应与我的代码的最后一行匹配,我认为程序只需从检查第一部分开始:\+daughter(X, Y)
(“Prolog无法证明Harry是女儿查尔斯“,对吧?”事实上:
| ?- \+daughter(harry, charles).
1 1 Call: \+daughter(harry,charles) ?
2 2 Call: daughter(harry,charles) ?
2 2 Fail: daughter(harry,charles) ?
1 1 Exit: \+daughter(harry,charles) ?
(1 ms) yes
那么它会进入第二部分,对吗?它会检查father(Y, X)
,即father(charles, harry)
,这是事实!
| ?- father(charles, harry).
1 1 Call: father(charles,harry) ?
1 1 Exit: father(charles,harry) ?
(1 ms) yes
这两个都是真的,为什么不为yes
提供son(harry, charles)
?作为一个重要的注释,这确实编译了不连贯的谓词警告:
compiling /Users/nicolejulian/Dropbox/AI/test.pl for byte code...
/Users/nicolejulian/Dropbox/AI/test.pl:4: warning: discontiguous predicate father/2 - clause ignored
/Users/nicolejulian/Dropbox/AI/test.pl:5: warning: discontiguous predicate father/2 - clause ignored
/Users/nicolejulian/Dropbox/AI/test.pl:6: warning: discontiguous predicate daughter/2 - clause ignored
/Users/nicolejulian/Dropbox/AI/test.pl:7: warning: discontiguous predicate son/2 - clause ignored
/Users/nicolejulian/Dropbox/AI/test.pl compiled, 8 lines read - 617 bytes written, 11 ms
(1 ms) yes
一些早期的实验表明,我基本上可以在警告和无限循环之间做出选择,所以我按原样进行了调查。 (例如,对所有左侧标签进行分组会删除警告,但会导致查询| ?- father(elizabeth, george).
崩溃)。
无论如何,只要我不能“欺骗”并添加son(harry, charles)
作为一个事实,我不了解Prolog的执行步骤?
答案 0 :(得分:1)
您显示的警告中的关键词是忽略子句。所以你的父/子逻辑,过去father(charles, harry)
的所有内容都被忽略了。尝试使它们连续:
father(charles, harry).
father(X, Y) :- son(Y, X).
father(X, Y) :- daughter(Y, X).
daughter(elizabeth, george).
daughter(X, Y) :- \+son(X, Y), father(Y, X).
son(william, charles).
son(X, Y) :- \+daughter(X, Y), father(Y, X).
然后,您将获得 true 作为查询的答案。
但如果您在a
之后键入true
(请求所有解决方案),那么逻辑中会出现进一步的问题。它不是优雅地结束,而是进入循环并溢出堆栈。这是由于父子,儿子和女儿之间存在循环逻辑。所以你可能想要考虑那个部分。
要绕过循环逻辑,请考虑this tutorial中给出的示例。本案例使用person
的断言事实(给出名称,性别和每个父级,然后使用谓词来建立这些和其他关系,通过登陆事实避免循环,而不是无限循环回到其他谓词。可能是其他类似的方法,但这只是一个例子。