Prolog中的动态编程调度程序

时间:2011-05-31 23:01:40

标签: prolog dynamic-programming

我正在尝试在Prolog中创建一个简单的调度程序,它包含一系列课程以及他们提供的学期和用户对课程的排名。这些输入变成了诸如

之类的事实
course('CS 4812','Quantum Information Processing',1.0882353,s2012).
course('Math 6110','Real Analysis I',0.5441176,f2011).

其中第三个条目是分数。目前,我的数据库大约有60个类,但我希望该程序最终能够处理更多。我无法让我的DP实现工作在一个非常重要的输入上。答案是正确的,但花费的时间与蛮力算法的顺序相同。我使用动态谓词来处理memoization:

:- dynamic(stored/6).
memo(Result,Schedule,F11,S12,F12,S13) :-
  stored(Result,Schedule,F11,S12,F12,S13) -> true;
  dpScheduler(Result,Schedule,F11,S12,F12,S13),
  assertz(stored(Result,Scheduler,F11,S12,F12,S13)).

dpScheduler的参数是最佳时间表(类列表及其分数的元组),到目前为止选择的类,以及2011年秋季2012年春季剩余的课程数量,2012年秋季和2013年春季学期。一旦调度程序具有竞争计划,它就会得到evalSchedule的分数,它只是总结了类的分数。

dpScheduler((Acc,X),Acc,0,0,0,0) :- 
  !, evalSchedule(X,Acc).

我在每个学期分手了dpScheduler,但他们看起来几乎一样。以下是2011年秋季选择的第一个学期的条款。

dpScheduler(Answer,Acc,N,B,C,D) :-
  !, M is N - 1,
  getCourses(Courses,f2011,Acc),
  lemma([Head|Tail],Courses,Acc,M,B,C,D),
  findBest(Answer,Tail,Head).

lemma谓词计算所有子目标。

lemma(Results,Courses,Acc,F11,S12,F12,S13) :-
  findall(Result, 
    (member(Course,Courses), memo(Result,[Course|Acc],F11,S12,F12,S13)),
    Results).

我的表现非常可怕,我对如何改进它表示感谢。另外,我是一个新的Prolog程序员,我没有花太多时间阅读别人的Prolog代码,所以我的程序可能是单一的。对此的任何建议都将受到高度赞赏。

1 个答案:

答案 0 :(得分:2)

表现不佳有几个原因:
首先,断言/ 3不是很快,所以如果有很多断言,你会花很多时间在那里。

然后,prolog使用基于第一个参数的哈希表来匹配子句。在你的情况下,第一个参数是结果,当它被调用时未被实例化,所以我认为你会因此而受到性能损失。你可以解决这个问题,重新排序论证。我认为你可以改变哈希表所基于的参数但我不知道如何在swi-prolog手册中:/

此外,prolog并不是出色的表现xd

我建议使用提供自动备忘录的XSB(如果可能)(制表);你只是写 :-table(my_predicate / 42),它可以处理所有事情。我认为它也比swipl快一点。

除此之外,您可以尝试使用包含所有计算值的列表并传递它;也许是association list

编辑:我真的没有看到你在哪里调用memoization谓词