2011-12-14 6 views
4

私は私の知識ベースでのこのようなものを持っている:プロローグカウント知識ベース

countnumbers(X). 
X = 6. 
:今

number(1). 
number(3). 
number(6). 
number(8). 
number(9). 
number(12). 

、私は知識ベースに、例がいくつあるかの数字を評価述語が必要

どうすればいいですか? 、私はプロローグとの新たなんだと私はあなたのデータベースからすべての事実を得るために

答えて

8

使用findall/3をこれを理解し、リストの長さを取得することはできませんしてください。

countnumbers(X) :- 
    findall(N, number(N), Ns), 
    length(Ns, X). 

は注意してください:number/1組み込み述語であってもよい。

+0

ありがとう、それは完全に働いた – nosmirck

8

Xがいくつかの述語を満たした回数を知る必要がある場合は、それらのすべてを知る必要はありません。 findall/3の使用は本当にそのようなタスクでは冗長です。あなたが6人か606人いるときにはX - これは大したことではありません。しかし、あなたが本当に大きくて重いジェネレータを持っている場合、あなたはリスト内のすべての値を保持し、それからその長さを数える必要はありません。

numberr(1). 
numberr(3). 
numberr(6). 
numberr(8). 
numberr(9). 
numberr(12). 

countNumbers(Numbers) :- 
    aggregate(count, X^numberr(X), Numbers). 

X^は "Xが存在する" という意味なので、全体の式は、その数Numbersを数値X numberr(X)をカウントして呼び出す」のようなものを意味しそう

Aggregate

はよくこの問題を解決します。

+1

あなたが私を見ていたらnto aggregate.plを実行すると、 'aggregate/3'は' bagof/3'を呼び出し、次に 'length/2'を呼び出します。では、実行速度に関しては、正確に何が得られましたか? – twinterer

+1

@twinterer、あなたは特定の実装を指しています、Dimitriiはインターフェイスを参照しています。インターフェイスを変更せずに実装が改善される可能性があります。しかし、リストを明示的に使用するプログラムは、より良い実装から利益を得る機会はありません。ライブラリが使用されていないため、できるだけ多くのものを改善しない理由の1つです。代わりに、人々はすべてを改革する。 – false

+1

@false:かなり真です。しかし、私はこれを大幅に速くする唯一のチャンスは、現在行われているように、Prologの組み込み関数を使わずにライブラリを実装することだと思います。スリムな希望、私は思う。現在、 'findall/3' +' length/2'のために 'aggregate/3'を使う議論は成立しません。私が実際にランタイムを心配していたのであれば、グローバル変数をカウンタとして使用して '(n(_)、incval(count)、fail; getvalカウント、C)) '。これは私が考えることができる唯一の方法であり、実際にはどのリストも取り除くことができます。 – twinterer