教培系统课表生成的约束求解方案从回溯算法到OR-Tools的实战演进
背景教培机构的排课问题是一个经典的约束满足问题CSP。一个中型机构可能有50个老师、200个班级、10间教室、5个时间段需要在满足各种约束条件下生成一份无冲突的课表。我们最初用回溯算法实现了一版排课引擎在小规模数据下运行良好。但当机构学员超过500人时排课耗时从几秒飙升到几分钟甚至超时。今天分享我们从回溯算法迁移到Google OR-Tools约束求解器的过程和踩坑经验。一、回溯算法的瓶颈最初的排课引擎使用经典的回溯加剪枝策略。核心数据结构是一个三维矩阵// timeslot[teacher][class][room] true/false// 表示老师t在教室r给班级c上课是否可行class ScheduleBacktracker:def __init__(self, teachers, classes, rooms, timeslots):self.teachers teachersself.classes classesself.rooms roomsself.timeslots timeslotsself.assignment {} # {class_id: (teacher_id, room_id, timeslot_id)}def is_valid(self, class_id, teacher_id, room_id, timeslot_id):# 检查教师时间冲突for cid, (tid, rid, ts) in self.assignment.items():if tid teacher_id and ts timeslot_id:return False# 检查教室时间冲突if rid room_id and ts timeslot_id:return False# 检查教师跨校区通勤时间teacher self.teachers[teacher_id]for cid, (tid, rid, ts) in self.assignment.items():if tid teacher_id:time_diff abs(ts - timeslot_id)if time_diff 1:room1 self.rooms[rid]room2 self.rooms[room_id]if room1.campus ! room2.campus:return False # 相邻时段不同校区不可行return Truedef backtrack(self, class_ids):if not class_ids:return Trueclass_id class_ids[0]for teacher_id in self.teachers:for room_id in self.rooms:for timeslot_id in self.timeslots:if self.is_valid(class_id, teacher_id, room_id, timeslot_id):self.assignment[class_id] (teacher_id, room_id, timeslot_id)if self.backtrack(class_ids[1:]):return Truedel self.assignment[class_id]return False这个实现在50个班级以内时大约2到3秒出结果。但到了200个班级时搜索空间爆炸运行10分钟也排不完。即使加了MRV最小剩余值和LCV最少约束值启发式策略改善也有限。二、迁移到OR-Tools CP-SAT求解器Google OR-Tools的CP-SAT求解器是我们找到的最佳替代方案。它内部使用了高效的约束传播和Lazy Clause Generation技术处理大规模CSP问题的能力远超手写回溯。核心思路是把排课问题建模为布尔变量矩阵from ortools.sat.python import cp_modelclass ScheduleOptimizer:def __init__(self, teachers, classes, rooms, timeslots):self.model cp_model.CpModel()self.teachers teachersself.classes classesself.rooms roomsself.timeslots timeslotsself.vars {} # {class_id: {teacher_id: {room_id: {timeslot_id: BoolVar}}}}def build_model(self):# 创建布尔变量for c in self.classes:self.vars[c.id] {}for t in c.available_teachers:self.vars[c.id][t] {}for r in self.rooms:if r.type c.required_room_type:self.vars[c.id][t][r] {}for ts in c.available_timeslots:self.vars[c.id][t][r][ts] self.model.NewBoolVar(fc{c.id}_t{t}_r{r.id}_ts{ts})# 约束1每个班级恰好分配一个老师教室时间段for c in self.classes:all_vars []for t in self.vars[c.id]:for r in self.vars[c.id][t]:for ts in self.vars[c.id][t][r]:all_vars.append(self.vars[c.id][t][r][ts])self.model.AddExactlyOne(all_vars)# 约束2同一老师同一时间段只能上一门课for t in self.teachers:for ts in self.timeslots:conflict_vars []for c in self.classes:if t.id in self.vars.get(c.id, {}) and ts.id in self.vars[c.id][t.id].get(next(iter(self.vars[c.id][t.id])), {}):for r in self.vars[c.id][t.id]:if ts in self.vars[c.id][t.id][r]:conflict_vars.append(self.vars[c.id][t.id][r][ts])if len(conflict_vars) 1:self.model.AddAtMostOne(conflict_vars)# 约束3同一教室同一时间段只能有一门课for r in self.rooms:for ts in self.timeslots:conflict_vars []for c in self.classes:if c.id in self.vars:for t in self.vars[c.id]:if r.id in self.vars[c.id][t] and ts.id in self.vars[c.id][t][r.id]:conflict_vars.append(self.vars[c.id][t][r.id][ts])if len(conflict_vars) 1:self.model.AddAtMostOne(conflict_vars)# 约束4教师跨校区通勤约束for t in self.teachers:for ts_idx in range(len(self.timeslots) - 1):ts1 self.timeslots[ts_idx]ts2 self.timeslots[ts_idx 1]for r1 in self.rooms:for r2 in self.rooms:if r1.campus ! r2.campus:for c1 in self.classes:for c2 in self.classes:if c1.id ! c2.id and t.id in self.vars.get(c1.id, {}) and t.id in self.vars.get(c2.id, {}):v1 self.vars[c1.id][t.id].get(r1.id, {}).get(ts1.id)v2 self.vars[c2.id][t.id].get(r2.id, {}).get(ts2.id)if v1 and v2:self.model.Add(v1 v2 1)迁移过程中最大的坑是变量数量爆炸。200个班级乘以50个老师乘以10间教室乘以5个时间段布尔变量数量达到50万个。OR-Tools虽然能处理这个规模但内存占用很高。解决方案是预处理阶段做激进的变量剪枝。对于每个班级只保留真正可用的老师、教室和时间段组合把不可能的组合直接从变量空间里剔除。实际操作后变量数量降到了5万左右求解时间从超时降到8到12秒。三、优化目标与软约束排课不只是找到一份可行解还要找到一份好的课表。比如老师不希望一天跑三个校区教室不希望频繁切换热门时间段应该优先分给大班课。这些是软约束不能硬性排除但可以设为优化目标。OR-Tools支持通过AddHint和Minimize来实现# 目标函数最小化教师跨校区次数cross_campus_count []for t in self.teachers:for ts_idx in range(len(self.timeslots) - 1):ts1 self.timeslots[ts_idx]ts2 self.timeslots[ts_idx 1]for r1 in self.rooms:for r2 in self.rooms:if r1.campus ! r2.campus:for c1 in self.classes:for c2 in self.classes:if c1.id ! c2.id:v1 self.vars[c1.id][t.id].get(r1.id, {}).get(ts1.id)v2 self.vars[c2.id][t.id].get(r2.id, {}).get(ts2.id)if v1 and v2:cross_campus self.model.NewBoolVar(fcc_{t.id}_{ts_idx})self.model.Add(v1 v2 1 cross_campus)cross_campus_count.append(cross_campus)self.model.Minimize(sum(cross_campus_count))加入优化目标后求解时间增加到15到20秒但生成的课表质量明显提升。教师跨校区次数平均减少了60%。四、总结从回溯算法迁移到OR-Tools的核心收获1. 约束满足问题不要自己写求解器CP-SAT已经做了大量优化性能远超手写方案。2. 变量预处理比求解器优化更重要减少变量数量是最有效的性能提升手段。3. 软约束和优化目标的设计需要跟业务方反复对齐不同机构对好课表的定义不同。4. 求解时间控制在15秒以内是用户可接受的边界超过这个时间需要加进度提示。

相关新闻

Onekey Steam清单下载器:5分钟快速掌握游戏清单获取的终极指南

Onekey Steam清单下载器:5分钟快速掌握游戏清单获取的终极指南

Onekey Steam清单下载器:5分钟快速掌握游戏清单获取的终极指南 【免费下载链接】Onekey Onekey Steam Depot Manifest Downloader 项目地址: https://gitcode.com/gh_mirrors/one/Onekey Onekey Steam清单下载器是一款专门为Steam游戏玩家设计的免费开源工具…

2026/8/14 2:21:16 阅读更多 →
QwenPaw工具注册

QwenPaw工具注册

## 工具插件是如何工作的### 插件的 type 字段决定了能力在 plugin.json 中把 type 设为 "tool",插件安装后会自动把工具注册给 Agent 调用:json {"id": "my-custom-tool","name": "我的自定义工具",…

2026/8/14 2:21:16 阅读更多 →
稻百年胖东来研学实体门店感悟:深耕服务,长期主义方能稳步成长

稻百年胖东来研学实体门店感悟:深耕服务,长期主义方能稳步成长

陕西 流行美加盟店 加盟商 杨旭洲这是我第二次参与门店经营专项学习。当下实体行业市场环境多变,行业竞争日趋激烈,门店传统拓客、锁客模式逐渐失效,业绩增长遭遇明显瓶颈。长期沿用固有经营思路,很难突破现有经营困境&#xff0c…

2026/8/14 2:21:16 阅读更多 →

最新新闻

非线性最小二乘与无源定位:从夹角观测到无人机轨迹估计

非线性最小二乘与无源定位:从夹角观测到无人机轨迹估计

1. 项目概述:从一道赛题到一套方法论 去年带学生打数模,B题“夹角观测条件下无人机无源定位”这道题给我留下了挺深的印象。它不像一些纯理论推导题那么“飘”,也不像一些数据处理题那么“糙”,而是把一个非常典型的工程问题——如…

2026/8/14 6:18:03 阅读更多 →
Service服务发现(四层流量负载均衡)

Service服务发现(四层流量负载均衡)

一,核心背景Pod IP是动态的,重建/漂移后IP会发生变化,无法直接作为固定访问地址。Service提供稳定虚拟IP(ClusterIP)DNS域名,统一接入一组Pod,实现四层负载均衡,屏蔽Pod动态变化。1.Service底层…

2026/8/14 6:18:03 阅读更多 →
AI与大模型新闻日报 | 2026-08-13

AI与大模型新闻日报 | 2026-08-13

AI与大模型新闻日报20260813大模型技术共 14 条新闻1. 国产具身智能创全球新纪录!以30%成本跑赢 Figure AI 45%效率,聪明的具身大脑成关键来源: 量子位时间: 2026-08-12 13:10摘要: 具身模型一小时狂拣1816件异形包裹2. 紫东太初推出GMC核心集剪枝方法&a…

2026/8/14 6:18:03 阅读更多 →
机器人技术演进:从本体性能到通用智能的范式转移

机器人技术演进:从本体性能到通用智能的范式转移

1. 从“跑赢”到“想赢”:一场关于机器人进化的深度思考最近几年,机器人领域最吸睛的新闻,往往与“速度”和“体能”有关。波士顿动力的Atlas后空翻、人形机器人百米冲刺、四足机器狗负重攀爬……这些视频一次次刷新我们对机械极限的认知。然…

2026/8/14 6:18:03 阅读更多 →
DeepSeek 涨价你换了吗

DeepSeek 涨价你换了吗

DeepSeek 涨价你换了吗 —— 主流国产大模型优缺点分析2026 年 AI 行业最具戏剧性的事件之一,莫过于 DeepSeek 从 “价格屠夫” 转向预告涨价。短短数月内,DeepSeek V4 Pro 刚宣布永久降价,随后推出峰谷定价、高峰时段价格翻倍,再…

2026/8/14 6:18:03 阅读更多 →
网站建设书籍推荐:从零基础到精通的全方位指南,助你打造极致用户体验的官方网站

网站建设书籍推荐:从零基础到精通的全方位指南,助你打造极致用户体验的官方网站

在这个数字化浪潮席卷全球的今天,无论是传统企业转型还是个人创业者起步,拥有一座专业、美观且功能完善的网站,已经不再是“加分项”,而是生存的“必选项”。然而,许多朋友在面对网站建设时,往往会陷入一种困惑:代码看得懂但写不出,设计图很惊艳但做不出来,或者好不容…

2026/8/14 6:17:02 阅读更多 →

日新闻

临沂网站建设铭镇:深耕本土数字生态,以匠心铸就企业品牌核心竞争力

临沂网站建设铭镇:深耕本土数字生态,以匠心铸就企业品牌核心竞争力

在这个流量为王、视觉至上的互联网时代,对于临沂乃至整个山东乃至全国的传统中小企业来说,拥有一张精美的“数字名片”早已不再是可选项,而是生存的必答题。每当夜幕降临,沂河两岸灯火辉煌,物流之都的喧嚣逐渐沉淀为对未来的思考。我们常常听到老板们在茶余饭后探讨:为什…

2026/8/14 0:00:26 阅读更多 →
Flutter与OpenHarmony实现剧本杀组队表单开发实战

Flutter与OpenHarmony实现剧本杀组队表单开发实战

1. 项目概述在移动应用开发领域,跨平台框架Flutter因其高效的开发体验和出色的性能表现,已经成为众多开发者的首选。而OpenHarmony作为新兴的操作系统平台,其开放性和灵活性为开发者提供了全新的可能性。本文将聚焦于一个实际应用场景——剧本…

2026/8/14 0:00:26 阅读更多 →
大连网站建设找简维科技:为您打造懂业务更懂用户的数字化转型引擎

大连网站建设找简维科技:为您打造懂业务更懂用户的数字化转型引擎

在这个数字化浪潮席卷全球的今天,企业想要在激烈的市场竞争中站稳脚跟,拥有一张好看的“数字名片”已经远远不够了。很多老板在刚开始接触互联网业务时,都有一个共同的困惑:为什么我花了钱建的网站,就像是在真空中自嗨?访客进来转了两圈就跑了,线索石沉大海,甚至连客服…

2026/8/14 0:01:27 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/13 2:38:34 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/13 10:41:52 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/13 10:41:51 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/13 10:41:50 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/13 10:41:49 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/13 10:41:49 阅读更多 →