试图找到prolog课程的所有先决条件

时间:2013-04-25 06:55:07

标签: recursion prolog

几个小时一直困在问题上,此时我真的需要帮助。

目标是创建一个谓词 all_prereqs(C,L),它返回课程的所有直接和直接先决条件的列表。我们获得了一系列与其先决条件列表相关的课程。

prereqs(cse115, []).
prereqs(cse116, [cse115]).
prereqs(cse191, [cse115]).
prereqs(cse241, [cse116,cse191]).
prereqs(cse250, [cse116,cse191]).
prereqs(cse305, [cse250]).
prereqs(cse321, [cse341]).
prereqs(cse331, [cse250,mth142]).
prereqs(cse341, [cse241]).
prereqs(cse379, [cse241]).
prereqs(cse380, [cse241]).
prereqs(cse396, [cse250]).
prereqs(cse411, [cse241]).
prereqs(cse421, [cse305]).
prereqs(cse422, [cse421]).
prereqs(cse431, [cse331]).
prereqs(cse435, [cse250,mth309]).

我知道应该有一个帮助类,我尝试了类似

的东西
prereq1(C1,C2):- prereqs(C1,L),prereq1(member(C2,L),C3).

当然会返回“否”。 我已经在纸上写下了必须对这些价值观做些什么,但是我对Prolog的经验不足使我无法做到这一点。

任何帮助将不胜感激。

修改

好的,谢谢你提供的信息。有一次我确实有这个想法,但不知道如何在列表为空时终止递归。

prereq1(C1,C2):-prereqs(C1,L),member(T,L),prereq1(T,C3). prereq1(C1,C2):-T\==[].

这只返回true,当prereq列表为空时,我无法理解递归调用的终止。

1 个答案:

答案 0 :(得分:1)

您在功能数据模型中编写代码,但Prolog却是关系数据模型。那你的规则应该是

prereq1(C1,C2) :- prereqs(C1,L),member(C2,L),prereq1(C2,C3).

但这也不会成功,因为在使用 empty 先决条件列表的课程中,递归调用将始终失败。注意,初始部分没问题:

prereq2(C1,C2) :- prereqs(C1,L), member(C2,L).

给出所有立即先决条件,然后我们应该通过递归为每个立即添加一个闭包。

prereq2(C1,C2) :- prereqs(C1,L), member(T,L), ...

请自己完成,你会得到

?- prereq2(cse331, L).
L = cse250 ;
L = mth142 ;
L = cse116 ;
L = cse191 ;
L = cse115 ;
L = cse115 ;
false.

请注意副本。 Prolog有一种惯用的方法来处理这个问题:

?- setof(C, prereq2(cse331, C), L).
L = [cse115, cse116, cse191, cse250, mth142].

编辑您的Prolog应警告您规则中的单身人士:

prereq1(C1,C2):-prereqs(C1,L),member(T,L),prereq1(T,C3).

C3必须成为C2。有了这个,你应该完成你的任务。当成员被给予空列表时,终止将被“隐式”处理 - 这将在我给出的示例中多次发生。