0

我正在使用答案集编程(Clingo)模拟大学课程时间表。要求是每节课必须分配到特定的星期、日期和开始/结束时间,直到达到总时间。

一天最多8小时,每节课最少2小时。预定的课程也将持续到第 10 周。

week(1..10). time(9,11;11,13;14,16;16,18).  

所以首先我生成了每个分配的课槽

TotalHours { assigned(Week,Day,Start,End,Course,Teacher) : day(Day), time(Start,End), week(Week) } TotalHours :-
lesson(Course,Teacher,TotalHours).

之后,对于其他要求和规则,我需要找到时间表中分配的最后一门课程。我不知道这是否是一个好方法,但我能够找到解决方案

MaxWeek =  #max {Week : assigned(Week,_,_,_,Course,_)},
MaxDay = #max {Day : assigned(MaxWeek,Day,_,_,Course,_)},
MaxStart= #max {Start : assigned(MaxWeek,MaxDay,Start,_,Course,_)},
assigned(_,_,_,_,Course,_).

我是 ASP 的新手,到目前为止,我找不到一个好方法来找到其他时间表要求所需的时间表(周、日、开始、结束)中分配的课程的倒数第二课。

所以举个例子

assigned(1,Monday,9,11,History,John) , assigned(1,Tuesday,11,13,Math,Smith), assigned(4,Tuesday,16,18,History,John),assigned(5,Monday,11,13,History,John)

我想找到历史的倒数第二课,即

分配(4,星期二,16,18)

非常感谢任何提示或解决方案

4

1 回答 1

0

考虑让第二个分配的谓词(具有不同的数量)更绝对,例如:

assigned((Week-1)*7*24+Day+Start,End,Course,Teacher) :- assigned(Week,Day,Start,End,Course,Teacher).

现在,您只有一个字段对所有作业完全排序,即自年初以来的总小时数。

要找到最后一门课程,最后一个聚合的性能很差,可以使用链式约束进行优化:

auxLastCourse(C,T) :- assigned(T,_,C,_).
auxLastCourse(C,T-1) :- auxLastCourse(C,T), T > 0.
lastCourse(C,T) :- auxLastCourse(C,T), not auxLastCourse(C,T+1).

另请注意,在您的示例中,夜间没有任何课程,因此可以通过不那么精细和明确表示每小时,但可能仅在可能的时间表中实际发生的时间来进一步优化。这意味着将辅助代码中的 T-1 替换为几周、几天和几小时内的明确下一个关系。目前我只是懒得添加这样的东西。

对于倒数第二门课程,您可以执行完全相同的操作:

auxSecondLastCourse(C,T) :- assigned(T,_,C,_), not lastCourse(C,T).
auxSecondLastCourse(C,T-1) :- auxSecondLastCourse(C,T), T > 0.
secondLastCourse(C,T) :- auxSecondLastCourse(C,T), not auxSecondLastCourse(C,T+1).

PS:请注意,我假设您的日期以数字 0..6 的形式给出,而不是像您的示例中那样以单词的形式给出,我相信您会弄清楚如何使用另一个谓词来翻译它们。

PPS:我没有测试代码,因为你没有提供 MWE。

于 2021-04-19T11:58:51.210 回答