web-dev-qa-db-ja.com

プロローグは述語が真である回数を数える

カスタム述語が真である回数をカウントしたいと思います。たとえば、次のコードがあります。

is_man(john).
is_man(alex).
?:-is_man(X).

Xはjohnを返し、セミコロンを押すとalexを返し、falseを返します。

私は次のようなものを作りたいです:

count(is_man(X), Count).

そして、これは戻る

Count = 2

どうやってやるの?

24
Victor Blaga

SWI-Prologの場合:

aggregate_all(count, is_man(X), Count).
29
Kaarel

ISO標準のPrologソリューションの場合、findall/を使用してすべてのソリューションのリストを作成し、Countを結果のリストの長さに設定します。 findall/の最初の引数をフォームで作成する必要があるため、これをユーザー定義の述語count/2にラップするのは少し難しいかもしれません。 count/2の最初の引数として渡したいゴール内の自由な(バインドされていない)変数を考慮する方法。

多くのプロローグは、「カウンター」または他の形式の可変グローバル値を提供します。これは、非標準の拡張であり、障害駆動型「ループ」に関連して使用して、同じカウントを行うことができます。少し面倒ですが、Prolog標準の文字に固執する場合は、動的ファクトを調整して、独自の「カウンター」を作成するためにassertおよびretractを使用します。

後者のアプローチの例を以下に示します。 「マルチスレッドセーフ」にするには、追加のロジックが必要になります。

count(Goal,_) :-
    setGoalCount(0),
    call(Goal),
    incGoalCount(1),
    fail.              /* or false in some Prologs */
count(_,Count) :-
    getGoalCount(Count).

setGoalCount(_) :-
    retract(getGoalCount(_)),
    fail.
setGoalCount(X) :-
    assert(getGoalCount(X)).

incGoalCount(Y) :-
    retract(getGoalCount(X)),
    !,
    Z is X + Y,
    assert(getGoalCount(Z)).
11
hardmath

count(P,Count) :-
        findall(1,P,L),
        length(L,Count).
6
尾崎隆大