0

私はプロローグで抱えているこの問題に頭を悩ませることができません。まだ始まったばかりですが、オブジェクトが一意であるかどうかを確認する方法が見つからないようです。これが私のコードです:

/* (Student Name, Student Number)*/
Student(stuart, 11234).
Student(ross, 11235).
Student(rose, 11236).
Student(stuart, 11237).

生徒がユニークかどうかを確認するにはどうすればよいですか。スチュアートを例にとると、スチュアートという名前の2人の学生がいるので、スチュアートはユニークではありません。別の学生がスチュアートと呼ばれるかどうかを判断する手順をどのように書くことができますか。

私はこれに多くの時間を費やしてみましたが、他のスチュアートではなく元のスチュアートを扱うことに頭を悩ませているようには見えません。 。

助けてくれてありがとう。

4

3 に答える 3

2

この問題を解決する方法はおそらくかなりありますが、私は次のようにします。

% a student has a name and a number
student(stuart, 11234).
student(ross, 11235).
student(rose, 11236).
student(stuart, 11237).

このコードは、「名前を持つ学生の数と同じ長さのリストを検索する」、次に「カウントをリストの長さと同じにする」と言います。

% for every student name there is an associated count of how many times 
%   that name appears
number_students(Name, Count) :-
    findall(_, student(Name, _), Students),
    length(Students, Count).

この述語は、number_studentsが1の場合にのみ真になります。

% a student name is unique (appears once and only once) is the 
%  number_students count is 1
unique_student(Name) :-
    number_students(Name, 1).

テスト:

12 ?- unique_student(ross).
true.

13 ?- unique_student(rose).
true.

14 ?- unique_student(bob).
false.

15 ?- unique_student(stuart).
false.

これは問題を解決する簡単な方法ですが、「一意の学生名を教えて」などと言ってすべての一意の名前のリストを取得することはできないため、Prologの優れた解決策ではありません。

于 2013-03-09T20:26:14.440 に答える
2

あなたのデータベースの例では、これは

unique(S) :-
    student(S, N), \+ (student(S, M), M \= N).

それがもたらすように

?- unique(S).
S = ross ;
S = rose ;
false.

一般的に、Prologはソリューションの存在を対象としています。次に、カーディナリティに関する予測には、言語の「不純な」部分からのサポートが必要です。nb_setargカーディナリティを効率的に追跡する必要がある場合、現在、これは私たちの親友です。

次のようなメタ述語を使用します。

%%  count_solutions(+Goal, ?C)
%
%   adapted from call_nth/2 for http://stackoverflow.com/a/14280226/874024
%
count_solutions(Goal, C) :-
    State = count(0, _), % note the extra argument which remains a variable
    (   Goal,
        arg(1, State, C1),
        C2 is C1 + 1,
        nb_setarg(1, State, C2),
        fail
    ;   arg(1, State, C)
    ).

:- meta_predicate count_solutions(0, ?).

2番目の引数を考慮せずに問題を解決できます

unique(S) :-
    student(S, _), count_solutions(student(S, _), 1).

同じ述語でlibrary(aggregate)のaggregate_all(count、student(S、_)、1)を使用できますが、そのようなライブラリは現在内部でリストを作成しているため、Peterからの回答は実装が簡単であると考えることができます。

于 2013-03-10T10:00:18.577 に答える
1

あなたが持っているコードに関するいくつかのコメント。これは事実ではありません:

Student(Ross).

これらは2つの異なる事実です(少なくともSWI-Prologでは):

student(ross).
student('Ross').

つまり、述語名は小文字で始まる必要があり、大文字で始まる識別子はアトムではなく変数を示します。任意の文字列を一重引用符で囲んで、有効なアトムにすることができます。

さて、これは邪魔にならないので、あなたが何を目指しているのかは明確ではありません。あなたはあなたのユニークな学生と何をするつもりですか?最初のものがあなたが探しているものであり、2番目のものではないことをどうやって知っていますか?そして、そのために学生番号を使用してみませんか(少なくともあなたの例では、2つのスチュアートは異なる番号を持っているようです)?

于 2013-03-09T16:15:46.317 に答える