0

私は、学生が次の学期に受講するクラスを選択するアドバイザープログラムを書いています。タスクの1つは、学生がすべての前提条件を満たしているかどうかを確認することです。これまでのところ、私は持っています:

hasPrereqs(Student, Class) :-
    (prereq(Pre, Class) -> 
        hasClass(Student, Pre);
    true).

hasClass(Student, Class) :-
    (creditFor(Student, Class);
    currentlyTaking(Student, Class)).

前提条件は次のように宣言されています。

prereq(csc140, csc145).
prereq(csc140, csc180).
prereq(csc140, csc198).
prereq([csc140, csc130], csc201).
prereq(csc145, csc201).

これは、別のクラスに2つのクラスが必要な場合を除いて、すべての可能性で機能します(csc201たとえば、学生がcsc140とcsc130のいずれか、またはcsc140だけを受講できる場合)。リストは道のりだと思いますが、それを実装する方法がわかりません。

私はhasPrereqs次のように別のものを作成しようとしました:

hasPrereqs(Student, Class) :-
forall(prereq(Pre, Class),
(compound(Pre) -> 
    hasClass(Student, Pre)).

Preこれは、ストレートアトムではなくリストであるため機能しません。したがって、次のようになります。

creditFor(somekittens, csc130).
creditFor(somekittens, csc140).
/* Returns false, because I don't have credit for the list, just the two classes */
creditFor(somekittens, [csc130, csc140]).

他のいくつかのクラスを必要とするクラスが正しく機能するようにシステムを設定するにはどうすればよいですか?

4

3 に答える 3

1

私はこのようにします:

hasPrereqs(Student, Class) :-
  prereq(Class, Pres),
  forall(member(Pre, Pres), hasClass(Student, Pre)).

hasClass(Student, Class) :-
  (creditFor(Student, Class);
  currentlyTaking(Student, Class)).

prereq(csc140, []).
prereq(csc145, [csc140]).
prereq(csc180, [csc140]).
prereq(csc198, [csc140]).
prereq(csc201, [csc140, csc130]).
prereq(csc201, [csc145]).

引数の順序を入れ替えて、prereq/2いくつあるかに関係なく前提条件をリストにしました。これにより、使用するコードprereq/2の一貫性が高まり、前提条件のないクラス、つまりprereq(foo, [])

次に、生徒がすべての前提条件を満たしていることを確認するために使用forall/2しました。member/2

于 2012-10-26T23:44:00.343 に答える
0

関数型プログラミングのバックグラウンド(私のように!)から来ている人は誰でもこれをしたいと思っています:

foreach(var i=0;i<Class.length;i++) {
    if(!hasClass(Student, Class[i])) {
         return false;
    }
}
return true;

残念ながら、これは機能しません。(私の知る限り)Prologのリストをトラバースして、trueすべての要素がtrueを返したIFFを返す簡単な方法はありません。むしろ、再帰的な方法を使用してリストをトラバースします。hasClass次のような別の定義を追加します。

hasClass(Student, ClassList) :-
    /* Splits up the list into:
    H = the first element of the list as an atom
    T = The rest of the list elements as a list
    (if there's only one list element, T is equal to []) */
    [H|T] = ClassList,
    hasClass(Student, H),
    /* if T isn't equal to [], recursively check the rest of the list's elements */
    (T \= [] -> hasClass(Student, T);true).
于 2012-10-26T00:06:41.940 に答える
0
hasPrereqs(Student, Class) :-
    (prereq(Pre, Class) -> 
        hasClass(Student, Pre);
    true).

インスタンス化する変数や実際の事実データに関係なく、常に真です。唯一の目的は、prereq/2またはhasClass/2によって実行される何らかの副作用(IOまたはDBの変更など)である可能性がありますが、これはそうではないようです。

今答えに。SWI-prologにはis_list /1とmaplist /2があり、後者は各要素で同じテストを繰り返すことができ、すべての要素でテストが成功した場合にのみtrueになります。

編集クラスは事前であることが意図されていました

hasPrereqs(Student, Class) :-
 forall(prereq(Pre, Class),
   (   is_list(Pre)
   ->  maplist(hasClass(Student), Pre)
   ;   hasClass(Student, Pre)
   )).

テストのためだけにhasClassを再利用することを計画していて、すでに機能しているhasClass / 2を想定している場合は、それ以上です。

hasPrereqs(Student, Class) :-
   forall(prereq(Pre, Class), hasClass(Student, Pre)).

hasClass(Student, Classes) :-
   is_list(Classes) -> maplist(hasClass(Student), Classes).

以下を編集するとバグが発生し、最後の呼び出しでループします...

さらに別の方法。あなたの答えでは、あなたは解決策に近づいていました:

hasClass(Student, ClassList) :-
    (   [H|T] = ClassList
    ->  hasClass(Student, H), hasClass(Student, T)
    ;   hasClass(Student, ClassList)
    ).

ソリューションの編集はもっと簡単なはずです:

hasClass(Student, [Class|ClassList]) :-
    hasClass(Student, Class),
    !, hasClass(Student, ClassList).
hasClass(_Student, []).
于 2012-10-26T08:31:33.147 に答える