Search 如何在prolog事实中递归搜索

Search 如何在prolog事实中递归搜索,search,prolog,counter,Search,Prolog,Counter,我有以下事实 %exam(Student,Subject) exam(student1,subject1). exam(student2,subject1). exam(student3,subject1). exam(student1,subject2). exam(student3,subject2). exam(student1,subject3). 我想找到一个学生的科目并把它们列在一个列表中 Subjects(Student,[H|T]):-

我有以下事实

%exam(Student,Subject)

exam(student1,subject1).
exam(student2,subject1).
exam(student3,subject1).

exam(student1,subject2).
exam(student3,subject2).

exam(student1,subject3).
我想找到一个学生的科目并把它们列在一个列表中

Subjects(Student,[H|T]):-
                        exam(Student,Subject),
                        \\+Subject=H,
                        H = Subject,
                        Subjects(Student,T).

我不知道基本情况应该是什么

\+Subject=H
表示“无法证明”
Subject
可以与
H
统一

但由于
H
一开始是不确定的,所以它总是可以与
主题
统一,所以目标总是失败的

此外,要查看以前是否找到了
Subject
,您必须在以前找到的值列表中检查其成员资格。这意味着,从一个调用到另一个调用携带一个附加参数,该参数将以
[]
开头,向其中添加新找到的主题,并使用更新的列表进行下一次调用

只要你能找到一个新的事实,你就把它添加到这个累积列表中,然后继续;但是如果你找不到一个新的事实,你应该停下来。这将是你的基本情况。使用辅助谓词编写代码会更容易,每个谓词执行各自的任务(如
可以找到新的主题(Student、ListSeenSoFar、subject)
等)

这种设置的缺点是它将是二次的。如果没有额外的逻辑工具,如
assert
,或使用内置的
findall
等,就无法使其线性化。

研究
subjects(Student, L):- search_subjects(Student, [], L).

search_subjects(Student, Seen, L):-
  find_new_subject(Student, Seen, Subj)
  search_subjects(Student, [Subj|Seen], L).

search_subjects(Student, Seen, L):-
  \+ find_new_subject(Student, Seen, Subj),
  ... .

find_new_subject( ......
  ....