3

に触発された

swi-prologで異なる事実の相互要素を見つける

「Prolog での RDBMS 操作」を試してみたかった (実際、これは多かれ少なかれ Datalog です)

問題文

「映画に出演している俳優」のデータベースが与えられた場合:

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

与えられた映画のセットから、そのセットのすべての映画に出演した俳優を見つけます。

私は最初は醜い解決策を持っていましたが、その後...

素敵な解決策

問題を明確にします。

セットは重複のないリストで表され、場合によっては順序付けられます。

  1. 映画のセットが与えられた場合 MovIn
  2. ...アクターのセットを見つける ActOut
  3. ... ... そのような: のすべての俳優ActOutが (少なくとも) すべての映画に出演MovIn
  4. ... ... 再定式化: のアクターの映画のセット は のスーパーセットです。MovAxAxActOutMovIn

setof/3は正しいトップレベル述語のようです。ポイント 1 と 2のAnsatzは次のとおりです。

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

に登場する映画MovAxセットである場合Ax、使用できます

を使いましょう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].

完了、2 つ取ります

以下機能します:

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

1 に答える 1