我正在 Prolog 中开发一个任务调度程序。首先让我向您展示我的代码的简化版本。它是这样的:
handle_activable(As) :-
reset_flags,
findall(A,catch(activable(A),Exception,flag(marked_activable,A)),As),
activate_all(As).
有两个版本,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)
)?如果没有,您知道任何解决方法吗?
我想问你的第二件事是关于我的算法的正确性。我已经为此工作了很长时间,并且尽我所能来编写高效、健壮和可靠的代码。真正困难的是在一组条件检查中,其中任务的关系发挥了重要作用并产生了复杂的约束。你觉得“寻找可激活任务”的方式好不好?