2

次のようなリストを連結するプロローグ プログラムがあるとします。

concat([],X,X).
concat([Head|Tail],X,[Head|R]) :- concat(Tail,X,R).

どの質問が有限数の回答を返すかを知るにはどうすればよいですか? たとえば、

concat(X,Y,[1,2,3,4]).

有限解セットを返します:

X = [],
Y = [1, 2, 3, 4] ;
X = [1],
Y = [2, 3, 4] ;
X = [1, 2],
Y = [3, 4] ;
X = [1, 2, 3],
Y = [4] ;
X = [1, 2, 3, 4],
Y = [] ;
false.

質問をしながら

concat(X,[2,3],Z).

解の無限セットを返します。

X = [],
Z = [1, 2, 3] ;
X = [_G24],
Z = [_G24, 1, 2, 3] ;
X = [_G24, _G30],
Z = [_G24, _G30, 1, 2, 3] ;
X = [_G24, _G30, _G36],
Z = [_G24, _G30, _G36, 1, 2, 3] ;
X = [_G24, _G30, _G36, _G42],
Z = [_G24, _G30, _G36, _G42, 1, 2, 3] ;
X = [_G24, _G30, _G36, _G42, _G48],
Z = [_G24, _G30, _G36, _G42, _G48, 1, 2, 3] ;
X = [_G24, _G30, _G36, _G42, _G48, _G54],
Z = [_G24, _G30, _G36, _G42, _G48, _G54, 1, 2, 3]

など (基本的に、[1,2,3] で終わる可能性のあるすべてのリスト。

では、論理プログラムでどの質問が終了するか、または終了しないかをどのように判断できますか?

4

3 に答える 3

2

私は通常、次のルールを使用します。

  1. それぞれの新鮮な述語は、異なるパラメーターの方向/タイプでテストする必要があります。あなたの場合、方向は (+, +, -), (+, -, +), (-, +, +), (-, -, +), (-, +, -), (+, - , -), (-, -, -)。「-」はバインドされていない変数を意味し、+ - 一部のメンバーが既にバインドされている変数を意味します。同じ場所に「-」があるケースが機能する場合、「+」のケースは常に機能します。したがって、実際には 4 つのテストしか実行できません。(-, -, ...) モードで動作する述語はないと思います。インタプリタのコマンド ラインからテストを実行するだけです。まだ単体テストを記述する必要はありません。

  2. 不適切な結果が見つかった場合は、述語を再設計してください。例えば

    con_fin([],X,X).
    con_fin(A,X,[Head|R]) :- nonvar(A), A=[Head|Tail], con_fin(Tail,X,R).
    

    常に有限の回答セットを返します。完全な 2 行の述語を一度に書くことができない場合 (完璧な述語とは、考えられるすべての方向で効果的に機能する述語です)、さまざまなモード/型に対して複数の行を記述し、var、nonvar、、is_set などの型チェックをX = [_|_]行います。 /1 などを友達にしましょう。

  3. そのテストの後、明確なコメントをしてください。可能なタイプと引数の方向を常に言及し、一部のモードでは det、semidet、または nondet として述語を定義する必要があります。あなたの問題は「(-, +, -) nondet」の場合の無限の解決策ではないと思いますが、無限再帰の可能性についてユーザーに警告されません

    B=[1, 2], con(A, B, C), A=[0].
    

    次のケースと比較してください

    B=[1,2], con(A, B, C), proper_length(C, 4), !.
    

    効果的ではありませんが、正確で決定論的です。

  4. モードと型のチェックを追加します。不適切な使用に対して例外をスローします。ISO 標準には、場合によっては事前定義された例外があります ( http://www.deransart.fr/prolog/exceptions.html )。優れた設計は、ISO の推奨事項に従う必要があります。

  5. 考えられるすべての使用法をカバーする単体テストを作成します (通常は 15 分以上かかりませんが、将来的にはさらに節約できます)。

  6. あなたの人生を楽しんでください

  7. より良い解決策 (Eureka!) を見つけた場合は、述語を書き直すだけです。単体テストは今ではあなたの親友です。

通常、Prolog は非常にコンパクトでスマートなコードを書くことができますが、他の言語に比べてより多くの作業を必要とします。俳句のように、年月を重ねるごとに一行ずつ改善していくことができます。しかし、Prolog で実験を行うのは非常に簡単なので、言語の実際の性質は、try->test->use->redesign の原則です。

于 2013-10-01T22:04:21.230 に答える