Prolog中的动态规划调度器

Prolog中的动态规划调度器,prolog,dynamic-programming,Prolog,Dynamic Programming,我正试图在Prolog中创建一个简单的调度器,该调度器包含一系列课程,以及它们提供的学期和用户对课程的排名。这些输入被转化为如下事实 course('CS 4812','Quantum Information Processing',1.0882353,s2012). course('Math 6110','Real Analysis I',0.5441176,f2011). 其中第三个条目是分数。目前,我的数据库大约有60个类,但我希望这个程序最终能够处理更多的类。我很难让我的DP实现在一个

我正试图在Prolog中创建一个简单的调度器,该调度器包含一系列课程,以及它们提供的学期和用户对课程的排名。这些输入被转化为如下事实

course('CS 4812','Quantum Information Processing',1.0882353,s2012).
course('Math 6110','Real Analysis I',0.5441176,f2011).
其中第三个条目是分数。目前,我的数据库大约有60个类,但我希望这个程序最终能够处理更多的类。我很难让我的DP实现在一个非平凡的输入上工作。答案是正确的,但花费的时间与暴力算法的顺序相同。我使用动态谓词处理记忆:

:- 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).
我每学期都会分手,但他们看起来都差不多。这是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(Results,Courses,Acc,F11,S12,F12,S13) :-
  findall(Result, 
    (member(Course,Courses), memo(Result,[Course|Acc],F11,S12,F12,S13)),
    Results).

我的表现非常糟糕,如果有人能给我指点如何改进我会很感激的。另外,我是一名新的Prolog程序员,我没有花太多时间阅读其他人的Prolog代码,所以我的程序可能很不规范。如果您对此有任何建议,我们将不胜感激。

性能不佳的原因有两个:
首先,assert/3不是很快,所以如果有很多assert,那么您会在那里花费很多时间

然后,prolog使用基于第一个参数的哈希表来匹配子句。在你的例子中,第一个参数是结果,当调用它时,它是未经证明的,所以我认为你会因此受到性能惩罚。您可以通过重新排列参数来解决此问题。我认为您可以更改哈希表所基于的参数,但在swi prolog手册中我看不到如何更改:

此外,prolog并不以出色的性能xd而闻名

我建议使用(如果可能的话)提供自动记录(表格);你只要写 :-表(my_谓词/42),它处理所有事情。我觉得它也比游泳快一点

除此之外,您可以尝试使用包含所有计算值的列表,并将其传递给其他人;也许是一个


编辑:我真的看不出在哪里调用备忘录谓词

好问题:我在删除备忘录进行调试后进行了复制/粘贴。它是
lemma
dpScheduler
的替代品。我将参数重新排序到
memo
,而且速度已经快了。我还将尝试XSB(或者干脆放弃并用其他东西重写:D)。谢谢