setof/3 inside setof/3 不工作,但为什么?
setof/3 inside setof/3 not working, but why?
灵感来自
Find mutual element in different facts in swi-prolog
我想试试"RDBMS operations in Prolog"(实际上,这或多或少是Datalog)
问题陈述
给定 "actors starring in movies" 的数据库:
starsin(a,bob).
starsin(c,bob).
starsin(a,maria).
starsin(b,maria).
starsin(c,maria).
starsin(a,george).
starsin(b,george).
starsin(c,george).
starsin(d,george).
然后给定一组电影,找出出演该组所有电影的演员。
我首先有一个丑陋的解决方案,但后来...
很好的解决方案
澄清问题:
集合由没有重复的列表表示,可能是有序的。
- Given a Set of Movies
MovIn
- ... Find the Set of Actors
ActOut
- ... ... Such that: Every Actor in
ActOut
appeared in (at least) all the movies in MovIn
- ... ... Reformulated: The Set of Movies
MovAx
for any actor Ax
of ActOut
is a superset of MovIn
.
setof/3 似乎是正确的顶级谓词。第 1 点和第 2 点的 Ansatz 是:
setof(Ax, (... MovIn ...) , ActOut).
如果MovAx
是Ax
出现的电影集,我们可以使用
- subset/2 的
library(lists) 或
- ord_subset/2 的
library(ordset) ...如果我们能确保一切都是一个 ordset。
让我们使用 subset/2
。
第 4 点似乎让我们写:
setof(Ax, (..., subset(MovAx, MovIn)) , ActOut).
发展 ...
...
setof(Ax, ( setof(Mx,starsin(Mx,Ax),MovAx) , subset(MovIn, MovAx) ) , ActOut).
好像已经这样了!
有λ表达式但是有的时候的感觉
键盘或语法中没有 λ。
完成!
总结成谓词:
actors_appearing_in_movies(MovIn,ActOut) :-
setof(Ax, ( setof(Mx,starsin(Mx,Ax),MovAx) , subset(MovIn, MovAx) ) , ActOut).
不幸的是,上面的方法不起作用。
正在进行回溯,显然我需要将所有内容包装到另一个 setof/3
,
但为什么??
?- actors_appearing_in_movies([a,b],ActOut).
ActOut = [maria] ;
ActOut = [george].
完成,拿两个
以下有效:
subselect(Ax,MovIn) :-
setof(Mx,starsin(Mx,Ax),MovAx), subset(MovIn, MovAx).
actors_appearing_in_movies(MovIn,ActOut) :-
setof(Ax, subselect(Ax,MovIn) , ActOut).
?- actors_appearing_in_movies([a,b],ActOut).
ActOut = [george, maria].
测试
测试只是运行几个目标。
请注意,对于空的电影集,我们得到了所有演员。这可以说是正确的:
空集所有电影演员皆出演
actors_appearing_in_movies([],ActOut),permutation([bob, george, maria],ActOut),!.
actors_appearing_in_movies([a],ActOut),permutation([bob, george, maria],ActOut),!.
actors_appearing_in_movies([a,b],ActOut),permutation([george, maria],ActOut),!.
actors_appearing_in_movies([a,b,c],ActOut),permutation([george, maria],ActOut),!.
actors_appearing_in_movies([a,b,c,d],ActOut),permutation([george],ActOut),!.
问题
我错过了什么
actors_appearing_in_movies(MovIn,ActOut) :-
setof(Ax, ( setof(Mx,starsin(Mx,Ax),MovAx) , subset(MovIn, MovAx) ) , ActOut).
尝试:
actors_appearing_in_movies(MovIn,ActOut) :-
setof(
Ax,
MovAx^(setof(Mx,starsin(Mx,Ax),MovAx), subset(MovIn,MovAx)),
ActOut
).
如果不对 MovAx
变量进行存在性限定,您将获得每个变量绑定的解决方案。
调用示例:
?- actors_appearing_in_movies([a,b],ActOut).
ActOut = [george, maria].
灵感来自
Find mutual element in different facts in swi-prolog
我想试试"RDBMS operations in Prolog"(实际上,这或多或少是Datalog)
问题陈述
给定 "actors starring in movies" 的数据库:
starsin(a,bob).
starsin(c,bob).
starsin(a,maria).
starsin(b,maria).
starsin(c,maria).
starsin(a,george).
starsin(b,george).
starsin(c,george).
starsin(d,george).
然后给定一组电影,找出出演该组所有电影的演员。
我首先有一个丑陋的解决方案,但后来...
很好的解决方案
澄清问题:
集合由没有重复的列表表示,可能是有序的。
- Given a Set of Movies
MovIn
- ... Find the Set of Actors
ActOut
- ... ... Such that: Every Actor in
ActOut
appeared in (at least) all the movies inMovIn
- ... ... Reformulated: The Set of Movies
MovAx
for any actorAx
ofActOut
is a superset ofMovIn
.
setof/3 似乎是正确的顶级谓词。第 1 点和第 2 点的 Ansatz 是:
setof(Ax, (... MovIn ...) , ActOut).
如果MovAx
是Ax
出现的电影集,我们可以使用
- subset/2 的 library(lists) 或
- ord_subset/2 的 library(ordset) ...如果我们能确保一切都是一个 ordset。
让我们使用 subset/2
。
第 4 点似乎让我们写:
setof(Ax, (..., subset(MovAx, MovIn)) , ActOut).
发展 ...
...
setof(Ax, ( setof(Mx,starsin(Mx,Ax),MovAx) , subset(MovIn, MovAx) ) , ActOut).
好像已经这样了!
有λ表达式但是有的时候的感觉 键盘或语法中没有 λ。
完成!
总结成谓词:
actors_appearing_in_movies(MovIn,ActOut) :-
setof(Ax, ( setof(Mx,starsin(Mx,Ax),MovAx) , subset(MovIn, MovAx) ) , ActOut).
不幸的是,上面的方法不起作用。
正在进行回溯,显然我需要将所有内容包装到另一个 setof/3
,
但为什么??
?- actors_appearing_in_movies([a,b],ActOut).
ActOut = [maria] ;
ActOut = [george].
完成,拿两个
以下有效:
subselect(Ax,MovIn) :-
setof(Mx,starsin(Mx,Ax),MovAx), subset(MovIn, MovAx).
actors_appearing_in_movies(MovIn,ActOut) :-
setof(Ax, subselect(Ax,MovIn) , ActOut).
?- actors_appearing_in_movies([a,b],ActOut).
ActOut = [george, maria].
测试
测试只是运行几个目标。
请注意,对于空的电影集,我们得到了所有演员。这可以说是正确的: 空集所有电影演员皆出演
actors_appearing_in_movies([],ActOut),permutation([bob, george, maria],ActOut),!.
actors_appearing_in_movies([a],ActOut),permutation([bob, george, maria],ActOut),!.
actors_appearing_in_movies([a,b],ActOut),permutation([george, maria],ActOut),!.
actors_appearing_in_movies([a,b,c],ActOut),permutation([george, maria],ActOut),!.
actors_appearing_in_movies([a,b,c,d],ActOut),permutation([george],ActOut),!.
问题
我错过了什么
actors_appearing_in_movies(MovIn,ActOut) :-
setof(Ax, ( setof(Mx,starsin(Mx,Ax),MovAx) , subset(MovIn, MovAx) ) , ActOut).
尝试:
actors_appearing_in_movies(MovIn,ActOut) :-
setof(
Ax,
MovAx^(setof(Mx,starsin(Mx,Ax),MovAx), subset(MovIn,MovAx)),
ActOut
).
如果不对 MovAx
变量进行存在性限定,您将获得每个变量绑定的解决方案。
调用示例:
?- actors_appearing_in_movies([a,b],ActOut).
ActOut = [george, maria].