在swi-prolog中找到不同事实中的相互元素 [英] Find mutual element in different facts in swi-prolog
问题描述
我正在尝试输入电影列表并找到在同一部电影中扮演的演员.问题:给定一个电影列表,使用递归显示一组明星的链接.这些是事实的例子:
i am trying to have an input of a list of movies and find the actors who play at the same movies. Question : Given a list of movies, display their link by a set of stars using recursion. these are an example of facts :
fact(movie,actor).
starsin(a,bob).
starsin(b,bob).
starsin(c,bob).
starsin(a,maria).
starsin(b,maria).
starsin(c,maria).
starsin(a,george).
starsin(b,george).
starsin(c,george).
输入输出示例:
?- sameActors([a,b,c],Y).
Y = bob,maria,george.
到目前为止编写的规则:
Rule written so far :
sameActors(Actors,Movies) :-
findall(Stars,(member(movie,Actors),starsin(movie,Stars)),Name),
sum_list(Name,Movies).
我是新手,在网上找不到针对我的问题的任何类似解决方案,我不明白我做错了什么,或者我需要添加什么.
I am quite new and can't find any similar solution online for my problem, i don't understand what i am doing wrong , or what i need to add.
推荐答案
这里还有一个(我终于找到方法了)
Here is another one (I finally found a way)
没有递归,只是findall的一个亲戚,setof/3
:
No recursion, just a relative of findall, setof/3
:
给定一个电影演员"数据库:
Given a database of "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).
我们做了一些反思(在setof/3里面有描述setof/3 不起作用,但为什么?),然后:
We do some reflection (described in setof/3 inside setof/3 not working, but why?), and then:
subselect(Ax,MovIn) :-
setof(Mx,starsin(Mx,Ax),MovAx), subset(MovIn, MovAx).
actors_appearing_in_movies(MovIn,ActOut) :-
setof(Ax, subselect(Ax,MovIn) , ActOut).
这是一个 RDBMS 操作的正确感觉!
This has the right feel of being an RDBMS operation!
测试!
请注意,对于空的电影集,我们获得了所有演员.这有点正确:所有演员出演空场的所有电影.
Note that for the empty set of movies, we get all the actors. This is marginally right: all the actors star in all the movies of the empty set.
测试包括运行这些目标并观察它们是否成功:
Testing consists in running these goals and observing that they succeed:
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),!.
奖金回合:在 R
完全不相关,但我想过如何在 R 中做到这一点.
Bonus Round: In R
Completely unrelated, but I thought about how to do that in R.
经过一番摸索:
# Load tidyverse dplyr
library(dplyr)
# Create a data frame ("tibble") with our raw data using `tribble`
t <- tribble(
~movie, ~actor
,"a" , "bob"
,"c" , "bob"
,"a" , "maria"
,"b" , "maria"
,"c" , "maria"
,"a" , "george"
,"b" , "george"
,"c" , "george"
,"d" , "george")
# The function!
actors_appearing_in_movies <- function(data, movies_must) {
# (movie,actor) pairs of actors active in movies we are interested in
t1 <- data %>% filter(is.element(movie, movies_must))
# (actor, (movies)) pairs of actors and the movies they appear in
# for movies we are interested in
t2 <- t1 %>% group_by(actor) %>% summarize(movies = list(unique(movie)))
# Retain only those which appear in all movies
t3 <- t2 %>% rowwise() %>% filter(setequal(movies_must,movies))
# Select only the actor column
# ("Select" works columnwise, not rowwise as in SQL)
t4 <- t3 %>% select(actor)
return(t4)
}
结果?
上述方法对于空电影集中的人有不同的看法:
The above approach has a different opinion on who is in the empty movie set:
> actors_appearing_in_movies(t, c())
# A tibble: 0 x 1
# … with 1 variable: actor <chr>
但是:
> actors_appearing_in_movies(t, c("a"))
# A tibble: 3 x 1
actor
<chr>
1 bob
2 george
3 maria
> actors_appearing_in_movies(t, c("a","b"))
# A tibble: 2 x 1
actor
<chr>
1 george
2 maria
> actors_appearing_in_movies(t, c("a","b","c"))
# A tibble: 2 x 1
actor
<chr>
1 george
2 maria
> actors_appearing_in_movies(t, c("a","b","c","d"))
# A tibble: 1 x 1
actor
<chr>
1 george
这篇关于在swi-prolog中找到不同事实中的相互元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!