在 swi-prolog 中查找不同事实中的相互元素 [英] Find mutual element in different facts in swi-prolog

查看:13
本文介绍了在 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.

到目前为止写的规则:

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 insidesetof/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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆