题
我有大量的事实我的计划之内,上市开发人员和设计人员在一家公司,以及以前的项目,像这样..
% project(Project Name,Year)
project(efnet, 2007).
% designer(Project Name, Name, Role)
designer(efnet, jane_cole, lead).
% developer(Project Name, Name, Role)
developer(efnet, alex_tobbs, architect).
我也建立了一个定义显示器工作的一个项目无论是设计师或开发人员的名单
% employees(Single Project, List of Employees
employees(Project, E)
我要的是创造采取任何设计师或开发人员,并显示所有他们都在(P)工作的项目名称的列表列表的新定义;像这样..
% projects_of_all(List of Staff, List of Projects)
projects_of_all(S,P):- ...
我可以很容易地的findall(或bagof)这样做,如果我必须找到一个人的电影,但我不知道我会如何与员工列表做到这一点。有人可以给我伸出援助之手这件事?
解决方案
考虑不依赖于所有的解决方案,内置插件一样findall
,setof
或bagof
以下内容:
% employees(Single Project, List of Employees
employees(Project, Employees) :-
employees(Project, [], Employees).
employees(Project, Acc, Employees) :-
( designer(Project, Employee, _)
; developer(Project, Employee, _)
),
\+ member(Employee, Acc), !,
employees(Project, [Employee|Acc], Employees).
employees(_Project, Employees, Employees).
该版本积累的一个项目工作的员工的唯一列表。类似地,你的谓词projects_of_all/2
的实施方式可以是这样:
% projects_of_all(List of Staff, List of Projects)
projects_of_all(Employees, Projects):-
projects_of_all(Employees, [], Projects).
projects_of_all(Employees, Acc, Projects):-
\+ var(Employees),
member(Employee, Employees),
( designer(Project, Employee, _)
; developer(Project, Employee, _)
),
\+ member(Project, Acc), !,
projects_of_all(Employees, [Project|Acc], Projects).
projects_of_all(_Employees, Projects, Projects).
请注意保护子目标\+ var(Employees)
,因为我们不希望这两个参数来调用member(Employee, Employees)
是完全绑定,这可能会导致变量的无限递归扩展在不断增加长度的名单。一旦我们选择Employee
,任何相关Project
通过designer/3
检索的或的developer/3
(离开choicepoints),直到没有积累新的Project
被发现,此时我们去寻找更多;直到没有任何更多的,在这种情况下,我们停止(第2章的基础情况)。
虽然这是相对于任何内部(即,天然的,非解释的)实现findall
,setof
或bagof
的,它用来说明其旨在帮助您使用累加器方法了解该溶液的方法。大概低效p>
如果您需要使用内置的全解决方案,您可以实现projects_of_all/2
这样:
% projects_of_all(List of Staff, List of Projects)
projects_of_all(Employees, Projects):-
findall(Project,
( member(Employee, Employees),
( designer(Project, Employee, _)
; developer(Project, Employee, _)
)
), ProjectsBag),
sort(ProjectsBag, Projects).
请注意setof
和bagof
会原路返回给你的选择,但要在积累了清单,这是findall
的行为的所有项目。据推测,但是,你不想重复,如删除重复给你一套这样呼吁的结果sort/2
。
修改强>改变(澄清)的我写此之后讨论的OP,即要求完全不同的答案(解释如下):
% projects_of_all(List of Staff, List of Projects)
projects_of_all(Employees, CommonProjects):-
% find the projects of every employee in the input list
employee_projects(Employees, EmployeeProjects),
% find the intersection of all projects (common projects)
recursive_val_intersect(EmployeeProjects, CommonProjects).
employee_projects([], []).
employee_projects([Employee|Employees], [Projects|Rem]) :-
findall(Project,
( designer(Project, Employee, _)
; developer(Project, Employee, _)
),
ProjectsBag),
sort(ProjectsBag, Projects),
employee_projects(Employees, Rem).
recursive_val_intersect([L|Ls], Intersect) :-
recursive_val_intersect(Ls, L, Intersect).
recursive_val_intersect([], Acc, Acc).
recursive_val_intersect([L0|Ls], L1, Intersect) :-
intersection(L0, L1, NewL),
recursive_val_intersect(Ls, NewL, Intersect).
employee_projects/2
用于构建的项目是,在输入列表中的每个Employee
了关于工作列表的列表。注意,它使用了我以前用过的findall/3
解决策略。第二谓词,recursive_val_intersect/2,3
,确定是否所有的项目列表的交集,因为这表明项目,每个雇员拥有的制作一起即可。这是刚刚寻求所有项目输入列表中,这是我想针对工作的所有员工将上述溶液不同。
注意,以上recursive_val_intersect/3
依赖于SWI-PROLOG组相交谓词 intersection/3
,该取列表,没有重复(因此使用sort/2
的构建在employee_projects/2
输入列表)。
其他提示
尝试与此类似,其中Es
是员工的名单:
setof(P, E^(member(E, Es), employee(P, E)), Projects)
在E^
是存在量词。