1

私のプログラムの場合、ナレッジベースには次のようなアトミックステートメントとルールがあります

store(itemName, ProductType)

ex: 店舗(iPhone5, phone)

manufacturer(itemName, Company)

ex: メーカー(iPhone5、apple)

クエリは、2 つ以上の異なる製品タイプを製造している会社があるかどうかを調べるためのものです。したがって、Apple の場合、Macbook、iPad、および iPhone があります。

クエリは次のとおりです。

?- store(ItemID1, ProductType1), manufacturer(ItemID1, Company), store(ItemID2, ProductType2), manufacturer(ItemID2, Company), store(ItemID3, ProductType3), manufacturer(ItemID3, Company), not ProductType1 = ProductType2, not ProductType1 = ProductType3, not ProductType2 = ProductType3.

アップル製品を 3 つリストアップすると正解が出ますが、さらに押すと同じ答えが何度も出てきます。これを止める方法はありますか?

注: このサイトにある他の質問に対する他の回答は知っていますが、Prolog に関する知識が限られているため、それらの回答を実装する方法がわかりません。また、それらの回答がこの質問に当てはまるかどうかもわかりません。

注:この質問では! ->、 and;演算子の使用は許可されていません

4

2 に答える 2

1

JBさんのお勧め以外にも解決方法はいくつかあると思います。ProductTypeN安っぽいトリックの 1 つは、これをクエリの最後に追加して順序付けを強制することです。

ProductType1 @> ProductType2, 
ProductType2 @> ProductType3.

これにより、3 つの製品タイプの 1 つの順列が得られ、見ている組み合わせの爆発がなくなります。

より洗練された手法は、setof/3ソリューションを列挙するために使用することです。すべての回答をセットとして生成するため、値をソートする必要があります。これにより、安っぽいトリックと基本的に同じ方法で重複が削除されます。

more_than_two_product_types(Manufacturer) :-
    setof(Manufacturer, T^manufacturer(T,Manufacturer), Manufacturers),
    member(Manufacturer, Manufacturers),
    setof(Type, Thing^(manufacturer(Thing, Manufacturer), store(Thing, Type)), [_,_,_|_]).

これはかなり複雑なので、分解してみましょう。まず、この条件はメーカーのリストを生成します。

setof(Manufacturer, T^manufacturer(T,Manufacturer), Manufacturers),

メタsetof/3述語は、コンストラクター式、テンプレート式を受け取り、結果のリストを返します。これは、すべてのソリューションをmanufacturer(T, Manufacturer)まとめてリストにまとめます。関心があるのは製造元の名前だけなので、テンプレートの引数はManufacturer. T^構文はがsetof/3自由T変数でmanufacturer(T, Manufacturer)あることを示しているので、それが何にインスタンス化されるかは気にしません。これは不可欠setof/3です。そうしないと、タイプごとに 1 つのソリューションが生成されますが、これは私たちが望んでいるものではありません。

この行は、製造元の新しいリストを繰り返します。

member(Manufacturer, Manufacturers),

この複雑な行は、メーカーが製造したすべてのタイプの製品を見つけます。

setof(Type, Thing^(manufacturer(Thing, Manufacturer), store(Thing, Type)), [_,_,_|_]).

ここでのゴール式は sequence(manufacturer(Thing, Manufacturer), store(Thing, Type))です。これは、Thingこのメーカーの製品を見つけてType、その製品の製品を見つけることを意味します。繰り返しになりますが、Thing^構文は、物事が何であるかはあまり気にしないことを示しているため、すべてのTypeソリューションを一度に取得します。これを処理するためにリストにバインドする代わりに、テンプレート[_,_,_|_]は少なくとも 3 つの項目を持つ任意のリストと統合します。それらのアイテムが何であるかはあまり気にしないので、それらはすべて空白です。コンソールでテストして、何が統合されるかを確認します。

?- [1,2,3] = [_,_,_|_].
true.

?- [1,2] = [_,_,_|_].
false.

?- [1,2,3,4] = [_,_,_|_].
true.

これは、少なくとも 3 つのソリューションを生成し、それらを破棄して成功するか、それより少ない場合は失敗します。

ご覧のとおり、Prolog で猫の皮を剥ぐ方法は複数あります。:)

于 2013-09-24T04:46:32.073 に答える
1

パフォーマンスの問題を割り引いて、あなたの中心的な問題は、異なる製品タイプを探しているようですが、製品自体に変数があるようです. したがって、たとえば、仮想の異なる製品タイプ T1、T2、T3、およびタイプ T1 の製品 P1a P1b P1c、タイプ T2 の P2、およびタイプ T3 の P3 の場合、(P1a,P2,P3)、(P1b、 P2,P3) と (P1C,P2,P3) は、あなたの観点からはすべて同等です。

これを回避するには、 (type,product) ペアをタイプごとに 1 つに融合する必要があります。

追伸: コードを問題が露呈する最小限 (たとえば、そのprice述語は不要と思われる) まで切り詰めて、実際の出力を提供すると、より良い回答が得られます。

于 2013-09-23T19:04:54.147 に答える