1

私はPrologでタスクスケジューラを開発しています。まず、私のコードの簡略化されたバージョンを紹介します。こんなふうになります:

handle_activable(As) :-
    reset_flags,
    findall(A,catch(activable(A),Exception,flag(marked_activable,A)),As),
    activate_all(As).

には2つのバージョンがありますactivable/1が、最も関連性の高いものは(ここでも簡略化されています):

activable(T) :-
    task(T),        /* T is a task */
    inactive(T),    /* The task is currently inactive */
    (\+checked(T) ->
        mark_checked(T),
        !,
        /* 
           Here would go the set of conditions 
           and  statements to determine if task T 
           is activable or not. They may internally 
           call activable/1.
        */
        asserta(flag(marked_activable,T))
    ;   
        /* 
           This task was already checked and the 
           result is stored in flag(marked_activable,T) 
           fact. 
        */
        throw(exception(already_checked,T))
    ). 

問題は、「条件セットチェック」内で、activable/1間接的に呼び出される可能性があるということです。そのchecked/1ため、不要なループを回避するために、を使用する必要があります。私の使い方findall/3は大丈夫だと思いましたが、As常に空のリストとしてインスタンス化されているので、[]何か問題があると思い始めています。

最初にお願いしたいのは、catch(...)呼び出しです。それが正しいか?つまり、activable/1呼び出し中に、タスクがすでにチェックされているためにプログラムが例外をスローした場合Aでも、インスタンス化されます(で使用できるようにflag(marked_activable,A))?そうでない場合は、その回避策を知っていますか?

次にお聞きしたいのは、私のアルゴリズムの正しさです。私はこれに長い間取り組んできましたが、効率的で堅牢で信頼性の高いコードを作成するために最善を尽くしました。本当に難しいのは、条件セットのチェックの範囲内です。ここでは、タスクの関係が大きな役割を果たし、複雑な制約を作成します。「アクティブなタスクを見つける」方法は良いと思いますか?

4

1 に答える 1

0

組み込みのcatch/3述語を使用して情報を渡す正しい方法は、Catcher用語を使用することです。

catch(:Goal, +Catcher, :Recover)

SWI-Prolog doc によると、はの引数と統合するGoal最も内側のゴールであり、 によって生成されたすべての選択ポイントがカットされ、システムはスローされた例外項を保持しながらの先頭に戻ります。したがって、次のようなルールがあります。Catcherthrow/1Goal catch/3

generate(info1).
generate(info2).
generate(info3).
generate(info4).
rule(D) :-
    generate(D),
    ...
    throw(error_info(D)).

このルールをキャッチした結果は次のようになります。

?- catch(rule(D), Exception, write(Exception)).
error_info(info1).
Exception = error_info(info1).

?- catch(rule(_), error_info(E), write(E)).
info1.
E = info1.
于 2013-03-25T11:49:52.040 に答える