setof/3 里面的 setof/3 不起作用,但为什么呢? [英] setof/3 inside setof/3 not working, but why?

查看:61
本文介绍了setof/3 里面的 setof/3 不起作用,但为什么呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

灵感来自

在 swi-prolog 中查找不同事实中的相互元素

我想尝试一下Prolog 中的 RDBMS 操作"(实际上,这或多或少是 Datalog)

问题说明

给定一个电影演员"数据库:

starsin(a,bob).星星(c,鲍勃).星星(a,玛丽亚).星星(b,玛丽亚).星星(c,玛丽亚).星星(a,乔治).星星(b,乔治).星星(c,乔治).星星(d,乔治).

在给定电影集的情况下,找出在该集的所有电影中出演的演员.

我一开始有一个丑陋的解决方案,但后来...

很好的解决方案

澄清问题:

集合由没有重复的列表表示,可能是有序的.

<块引用>

  1. 给定一组电影 MovIn
  2. ... 找到演员集 ActOut
  3. ... ... 这样:ActOut 中的每个 Actor 都出现在(至少)MovIn 中的所有电影中立>
  4. ... ... 重新制定:ActOut 的任何演员 Ax电影集 MovAxMovIn 的超集.

setof/3 似乎是正确的顶层谓词.第 1 点和第 2 点的 Ansatz 是:

setof(Ax, (... MovIn ...) , ActOut).

如果MovAxAx出现的电影集,我们可以使用

让我们使用 subset/2.

第 4 点似乎让我们写:

setof(Ax, (..., subnet(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 中,但为什么??

?- actor_appearing_in_movies([a,b],ActOut).ActOut = [玛丽亚];ActOut = [乔治].

完成,拿两个

以下确实有效:

subselect(Ax,MovIn) :-setof(Mx,starsin(Mx,Ax),MovAx),子集(MovIn,MovAx).actor_appearing_in_movies(MovIn,ActOut) :-setof(Ax, subselect(Ax,MovIn) , ActOut).

?- actor_appearing_in_movies([a,b],ActOut).ActOut = [乔治,玛丽亚].

测试

测试只是为了实现几个目标.

请注意,对于空集的电影,我们获得了所有演员.这可以说是正确的:每个演员都出演了空场的所有电影.

actors_appearing_in_movies([],ActOut),permutation([bob, george, maria],ActOut),!.actor_appearing_in_movies([a],ActOut),permutation([bob, george, maria],ActOut),!.actor_appearing_in_movies([a,b],ActOut),permutation([george, maria],ActOut),!.actor_appearing_in_movies([a,b,c],ActOut),permutation([george, maria],ActOut),!.actor_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) :-设置(斧头,MovAx^(setof(Mx,starsin(Mx,Ax),MovAx),subset(MovIn,MovAx)),行动).

无需对 MovAx 变量进行存在性限定,每个变量的绑定都会得到一个解决方案.

示例调用:

?- actor_appearing_in_movies([a,b],ActOut).ActOut = [乔治,玛丽亚].

Inspired by

Find mutual element in different facts in swi-prolog

I wanted to try my hand at "RDBMS operations in Prolog" (actually, this is more or less Datalog)

Problem statement

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).

And given set of movies, find those actors that starred in all the movies of said set.

I first had an ugly solution, but then...

Solution that is nice

Clarify the problem:

Sets are represented by lists without duplicates, possibly ordered.

  1. Given a Set of Movies MovIn
  2. ... Find the Set of Actors ActOut
  3. ... ... Such that: Every Actor in ActOut appeared in (at least) all the movies in MovIn
  4. ... ... Reformulated: The Set of Movies MovAx for any actor Ax of ActOut is a superset of MovIn.

setof/3 seems to be the correct toplevel predicate. An Ansatz for points 1 and 2 is:

setof(Ax, (... MovIn ...) , ActOut).

If MovAx is the Set of Movies that Ax appeared in, we can use

Let's use the subset/2.

Point 4 seems to make us write:

setof(Ax, (..., subset(MovAx, MovIn)) , ActOut).

Develop the ... ...

setof(Ax, ( setof(Mx,starsin(Mx,Ax),MovAx) , subset(MovIn, MovAx) ) , ActOut).

This seems to be it already!

The feel when there are λ Expressions but there is no λ on the keyboard or in the syntax.

Done!

Wrap up into predicate:

actors_appearing_in_movies(MovIn,ActOut) :-
   setof(Ax, ( setof(Mx,starsin(Mx,Ax),MovAx) , subset(MovIn, MovAx) ) , ActOut).

Unfortunately the above doesn't work.

There is backtracking going on, apparently I need to wrap everything into another setof/3, but why??

?- actors_appearing_in_movies([a,b],ActOut).
ActOut = [maria] ;
ActOut = [george].

Done, take two

The following does work:

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].

Testing

Testing is just running a few goals.

Note that for the empty set of movies, we get all the actors. This is arguably correct: every actors stars in all the movies of the empty set.

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),!.

Question

What did I miss in

actors_appearing_in_movies(MovIn,ActOut) :-
   setof(Ax, ( setof(Mx,starsin(Mx,Ax),MovAx) , subset(MovIn, MovAx) ) , ActOut).

解决方案

Try:

actors_appearing_in_movies(MovIn,ActOut) :-
    setof(
        Ax,
        MovAx^(setof(Mx,starsin(Mx,Ax),MovAx), subset(MovIn,MovAx)),
        ActOut
    ).

Without existentially qualifying the MovAx variable, you get a solution per each binding of the variable.

Sample call:

?- actors_appearing_in_movies([a,b],ActOut).
ActOut = [george, maria].

这篇关于setof/3 里面的 setof/3 不起作用,但为什么呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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