You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Prolog的考试排期需求:利用attends谓词生成最优3周考试调度

Prolog 考试日程最优调度实现

嘿,我来帮你搞定这个Prolog考试调度的问题!咱们的目标是基于现有的attends/2选修关系,生成一个分三周(A、B、C三个课程列表)的考试日程,核心是最优调度——通常来说,最优的标准是避免同一学生在同一周有多场考试,同时让每周的考试数量尽可能均衡。

首先,先把你提供的attends/2谓词实例放出来,方便后续使用:

% 学生选修课程的关系:attends(Student_ID, Course_ID)
attends(476, c216).
attends(478, c216).
attends(484, c216).
attends(487, c216).
attends(491, c216).

第一步:定义合法调度的约束

首先,一个合法的调度必须满足两个核心条件:

  • 每门课程恰好被分配到A、B、C中的一个周列表
  • 任何学生的所有选修课程不能集中在同一个周列表里(避免冲突)

咱们先实现基础的合法调度谓词:

% 主谓词:生成合法的考试日程A、B、C
exam_schedule(A, B, C) :-
    % 获取所有独特的课程(去重)
    findall(Course, attends(_, Course), AllCourses),
    sort(AllCourses, UniqueCourses),
    % 将所有课程分配到A、B、C三个列表(无重叠,覆盖全部)
    partition_courses(UniqueCourses, A, B, C),
    % 检查所有学生都没有周内考试冲突
    forall(attends(Student, _), no_student_conflict(Student, A, B, C)).

% 辅助谓词:将课程列表分配到三个周列表
partition_courses([], [], [], []).
partition_courses([Course|Rest], [Course|A], B, C) :-
    partition_courses(Rest, A, B, C).
partition_courses([Course|Rest], A, [Course|B], C) :-
    partition_courses(Rest, A, B, C).
partition_courses([Course|Rest], A, B, [Course|C]) :-
    partition_courses(Rest, A, B, C).

% 辅助谓词:检查单个学生是否有周内冲突
no_student_conflict(Student, A, B, C) :-
    % 获取该学生的所有选修课程
    findall(Course, attends(Student, Course), StudentCourses),
    % 确保这些课程不全在A、不全在B、不全在C
    \+ subset(StudentCourses, A),
    \+ subset(StudentCourses, B),
    \+ subset(StudentCourses, C).

% 辅助谓词:判断列表X是否是列表Y的子集
subset([], _).
subset([X|Xs], Y) :-
    member(X, Y),
    subset(Xs, Y).

第二步:实现最优调度筛选

现在我们已经能生成合法调度了,但还需要选出最优的。这里我们把“最优”定义为每周考试数量最均衡(即三个列表长度的方差最小)。

咱们可以扩展主谓词,生成所有合法调度,然后筛选出方差最小的:

% 最优调度谓词:返回最优的考试日程
optimal_exam_schedule(BestA, BestB, BestC) :-
    % 生成所有合法调度
    findall((A,B,C,variance(A,B,C)), exam_schedule(A,B,C), AllSchedules),
    % 按方差从小到大排序,取第一个(方差最小的)
    sort(AllSchedules, SortedSchedules),
    SortedSchedules = [(BestA, BestB, BestC, _)|_].

% 辅助谓词:计算三个列表长度的方差
variance(A, B, C) :-
    length(A, LenA),
    length(B, LenB),
    length(C, LenC),
    Mean is (LenA + LenB + LenC)/3,
    Variance is ((LenA-Mean)^2 + (LenB-Mean)^2 + (LenC-Mean)^2)/3.

测试使用

你可以直接在Prolog解释器中查询:

?- optimal_exam_schedule(A, B, C).

对于你提供的示例数据(只有c216一门课),输出会是该课程被分配到任意一个周列表,另外两个周为空——因为只有一门课,不存在冲突,均衡性的话单周1门,另外两周0门是唯一可能的结果。

扩展说明

如果后续添加更多课程和学生选修关系,这个代码依然适用:

  • 比如如果有学生同时选修c216和c317,调度器会自动把这两门课分到不同的周
  • 最优调度会优先选择每周课程数量最接近的方案

内容的提问来源于stack exchange,提问作者DIMITRIOS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:00:25