別の言い方をすれば、一意の変数の 1 つのリストが他の変数の順列である場合、述語は成功するはずです。に類推してlibrary(ordsets)
、このメタ論理述語を呼びましょう varset_seteq(As, Bs).
とは対照的にord_seteq/2
、この述語は単純にはできないことに注意してくださいAs == Bs
。
別の言い方をすれば、一意の変数の 1 つのリストが他の変数の順列である場合、述語は成功するはずです。に類推してlibrary(ordsets)
、このメタ論理述語を呼びましょう varset_seteq(As, Bs).
とは対照的にord_seteq/2
、この述語は単純にはできないことに注意してくださいAs == Bs
。
私が提案する解決策は、余分な変数がないかどうか、および に表示されない変数がないterm_variables/2
かどうかを確認するために使用します。Bs
As
As
Bs
varset_seteq(As, Bs):-
term_variables(As-Bs, As),
term_variables(Bs-As, Bs).
上記のソリューションは、自由変数のセットではない引数を使用して成功するようにだまされる可能性があります。
| ?- varset_seteq([A], [a]).
A = a
yes
それを避けるために、統一を同等性テストに置き換えることができます。
varset_seteq(As, Bs):-
term_variables(As-Bs, A0),
A0 == As,
term_variables(Bs-As, B0),
B0 == Bs.
別の解決策は、 Tudor の巧妙な解決策よりも効率が悪いため推奨されませんが、複数の場面で使用されているので、ここで言及する価値があります。
varset_seteq(As, Bs) :-
sort(As, Sa), sort(Bs, Sb), Sa == Sb.
別のアプローチ。これらの高次の述語 (それぞれが単独で役立つ) を提供すると、
select_with(_, _, [], []).
select_with(P, X, [Y|Ys], Ys) :- call(P, X, Y), !.
select_with(P, X, [Y|Ys], [Y|Ks]) :-
select_with(P, X, Ys, Ks).
foldl(_,[],Vn,Vn).
foldl(P,[X|Xs],V0,Vn) :-
call(P,X,V0,V1),
foldl_(P,Xs,V1,Vn).
次に、一方のリストの各メンバーが他方のリストに等しい要素を持つ場合に真である述語を簡単に定義できます ( を使用==/2
)。
members_equal(A, B :-
foldl(select_with(==), A, B, []).
着信引数が varset であることを確認すれば、この述語を指定された目的に特化することができます。以下は、その方向で私が思いついた最高のものです(しかし、かなりの数の推論を食い尽くします):
is_varset([]).
is_varset([V|Vs]) :-
var(V),
maplist(\==(V), Vs),
is_varset(Vs).
(少なくとも SWI Prolog では、 usingsort/2
は上記よりも少ない推論しか必要としません。おそらく、これはソートが C で行われるためです。また、この回答はまだアプローチの優雅さに近づいていません。これterm_vars/2
が「セマンティック アセントの力です。 " :)