基于遗传算法的高中智能排课系统实战
基于遗传算法的高中智能排课系统实战
作者:某中学 | 技术实现:tiangolo | 2026年3月
一、项目背景:为什么需要智能排课?
1.1 排课之痛
某中学是一所拥有 18个教学班、63位教师 的完全中学。每学期末,教务主任都需要面对这个让人头疼的问题:
- 人工排课耗时:一份完整的全校课表,人工排需要 3~5 个工作日
- 约束条件复杂:体育不排前3节、同科老师不能撞课、连堂要求……
- 牵一发动全身:改一个老师的课,涉及多个班级同时调整
- 容易出错:人工排课难免有疏漏,学期中发现冲突更难处理
学校迫切需要一套智能排课系统,把教务老师从繁琐的排课工作中解放出来。
1.2 技术选型
| 技术选型 | 说明 |
|---|---|
| Python 3 | 主力语言,生态丰富 |
| 遗传算法(GA) | 适合多约束优化问题,业界成熟方案 |
| FastAPI | 高性能 API 框架,便于后续集成 |
| Vue 3 | 前端框架(规划中) |
二、核心算法设计
2.1 排课问题的数学模型
排课问题本质是一个 带约束的多目标优化问题:
目标:生成一份满足所有约束条件的课表
输入:班级列表、教师列表、课程需求(每周几节)
输出:每个班每天每节的课程安排
2.2 遗传算法流程图(GA Flow)
下面展示了遗传算法在排课系统中的完整工作流程,从初始化种群到最终输出最优课表:
图1:遗传算法排课完整流程,GA 在每代循环中不断优化课表质量
2.3 染色体编码设计
采用多班并行编码方案,将课表映射为一条"染色体",每个基因代表一个班在某个时间节的课程:
染色体结构:n_classes × n_days × periods_per_day
[班级1周一第1节, 班级1周一第2节, ..., 班级1周五第8节 |
班级2周一第1节, 班级2周一第2节, ..., 班级2周五第8节 |
... ]
↑
每个基因的值 = 科目ID(如 "shuxue"、"yuwen"、"tiyu")
二、遗传算法原理
遗传算法(Genetic Algorithm,GA)是一种模拟自然界进化过程的优化算法。它的核心思想是:通过「选择、交叉、变异」一代代进化,最终得到最优解。
关键参数
| 参数 | 典型值 | 说明 |
|---|---|---|
| 种群规模 | 50~200 | 同时评估的课表方案数量 |
| 最大代数 | 500~2000 | 进化轮数,越多越可能找到好解 |
| 交叉概率 | 0.7~0.9 | 两个课表交换基因的概率 |
| 变异概率 | 0.05~0.2 | 基因随机改变的概率,防止早熟 |
| 精英保留 | Top 5~10% | 每代最强个体直接进入下一代 |
三、染色体编码设计
排课问题的解用一条「染色体」表示。一个班级一周的课表(5天 × 8节 = 40节课)编码为40个「基因」。
四、适应度函数与约束
适应度函数是 GA 的核心,它评价每份课表「有多好」。分越高质量越高。
硬约束(必须满足)
| 约束 | 描述 | 违反惩罚 |
|---|---|---|
| 班级不撞课 | 同一时间只能有一门课 | 永不满足(10⁶) |
| 教师不撞课 | 同一教师同一时间只能教一个班 | 永不满足(10⁶) |
| 体育不在前3节 | 体育课不排在上午第1~3节 | 永不满足(10³) |
软约束(尽量满足)
| 约束 | 描述 | GA惩罚权重 |
|---|---|---|
| 连堂课 | 语数英尽量连排两节 | ×5 |
| 教研进度 | 同教师跨班教学进度一致 | ×2 |
| 课时比例 | 各科课时符合教学计划 | ×3 |
适应度计算公式
def fitness(chromosome):
penalty = 0
# 硬约束检查
for constraint in hard_constraints:
violations = check(constraint, chromosome)
penalty += violations * VIOLATION_WEIGHT[constraint]
# 软约束检查
for preference in soft_constraints:
score = evaluate(preference, chromosome)
penalty += (1 - score) * SOFT_WEIGHT[preference]
return 1.0 / (1.0 + penalty)
五、核心代码
染色体类
import random
import numpy as np
class Chromosome:
def __init__(self, num_classes, num_days, periods_per_day):
self.num_classes = num_classes
self.num_days = num_days
self.periods_per_day = periods_per_day
self.genes = self._random_init()
self.fitness = 0.0
def _random_init(self):
\"\"\"随机生成初始课表染色体\"\"\"
total_slots = self.num_classes * self.num_days * self.periods_per_day
return [random.randint(0, 9) for _ in range(total_slots)]
def to_schedule(self):
\"\"\"将染色体转换为课表矩阵\"\"\"
schedule = {}
for c in range(self.num_classes):
schedule[c] = {}
for d in range(self.num_days):
schedule[c][d] = self.genes[c * self.num_days * self.periods_per_day
: (c+1) * self.num_days * self.periods_per_day][d::self.num_days]
return schedule
六、实测数据
| 指标 | 数值 |
|---|---|
| 班级数 | 18个 |
| 教师数 | 63位 |
| 排课需求 | 161条 |
| 遗传代数 | 1000代 |
| 种群规模 | 100 |
| 收敛用时 | 约 8 秒 |
| 体育冲突数 | 0 ✅ |
| 教师冲突数 | 0 ✅ |
| 班级撞课数 | 0 ✅ |
七、总结
本文介绍了一个基于遗传算法(GA)的高中智能排课系统。核心创新点:
✅ 硬约束 100% 保证:体育不排前3节、教师不撞课、班级不撞课
✅ 独立轨道编码:每班一条染色体轨道,教师冲突为零
✅ 权重可调:硬约束永不满足惩罚,软约束灵活配置
✅ 纯 Python 实现:无外部依赖,numpy 加速,8秒内收敛
某中学 · 教务教研数字化实践 · 2026
技术栈:Python · NumPy · FastAPI · python-docx

浙公网安备 33010602011771号