一个基于 Google OR-Tools 的演出规划工具,可根据用户指定的艺人观看需求,从候选演出列表中筛选出最优方案,支持「最小观看场数」和「最低总票价」两种优化目标,并自动检测日期冲突、生成详细报告。
| 核心功能 | 说明 |
|---|---|
| 双优化目标 | 支持「最小观看场数」(优先少跑路)和「最低总票价」(优先省钱)两种模式 |
| 数据兼容性 | 支持外部 CSV 数据导入,同时内置测试用例,开箱即用 |
| 智能筛选 | 自动过滤不包含目标艺人的演出,避免无效方案 |
| 冲突检测 | 自动识别同一日期的多场演出,提示时间冲突 |
| 多方案输出 | 生成「最优」「次优」「次次优」多级方案,提供选择灵活性 |
| 详细报告 | 输出包含「艺人覆盖情况」「日期冲突提示」「观看总结」的可视化报告,并自动保存到文件 |
| 数据校验 | 自动验证日期格式(支持 YYYY-MM-DD 和 YYYY/MM/DD),避免格式错误导致的运行失败 |
本工具依赖 Google OR-Tools(用于求解整数规划问题),安装命令如下:
pip install ortools- 推荐使用 Python 3.8 及以上版本(兼容 OR-Tools 最新版本,避免语法兼容性问题)
工具支持两种数据输入方式:外部 CSV 文件(推荐,灵活定制需求)和 内置测试用例(快速体验功能)。
需在脚本同级目录下创建两个 CSV 文件,格式如下:
存储所有候选演出的信息,必须包含以下 4 列(列名不可修改):
| 列名 | 数据类型 | 说明 | 示例 |
|---|---|---|---|
name |
文本 | 演出名称(唯一标识) | 演出 A、Livehouse 专场 |
date |
日期 | 演出日期,支持 YYYY-MM-DD 或 YYYY/MM/DD |
2025-11-11、2025/12/01 |
price |
数字 | 演出单价(支持整数 / 小数) | 400、380.5 |
artist_list |
文本 | 演出艺人列表,多个艺人用 分号 ; 分隔 |
艺人 A; 青木阳菜;小林由依 |
示例内容:
name,date,price,artist_list
演出A,2025-11-11,400,艺人A;青木阳菜;小林由依
演出B,2025-11-12,500,艺人B;Mirror, Mirror;艺人C
演出C,2025-11-15,400,艺人B;Mirror, Mirror;青木阳菜
演出D,2025-12-01,100,艺人X;艺人Y;艺人Z存储用户需要观看的艺人及次数,必须包含以下 2 列(列名不可修改):
| 列名 | 数据类型 | 说明 | 示例 |
|---|---|---|---|
artist |
文本 | 目标艺人名称(需与 show_list.csv 中的艺人名称完全匹配,大小写不敏感) |
青木阳菜、Mirror, Mirror |
count |
整数 | 需要观看该艺人的最少次数 | 1、2 |
示例内容:
artist,count
青木阳菜,1
小林由依,1
Mirror, Mirror,1sample-data文件夹下已包含两个样例,可以直接试用。
若未创建上述两个 CSV 文件,脚本会自动生成内置测试数据(即上述示例内容),无需手动配置,可直接体验功能。
在脚本同级目录下执行命令:
python solver.py脚本启动后,会提示选择优化目标:
请选择优化目标:
1. 最小场数
2. 最低总价
请输入选项 (1 或 2):
- 输入
1:优先减少观看场数(适合时间紧张的用户) - 输入
2:优先降低总花费(适合预算有限的用户)
脚本会先显示用户需求和候选演出列表,然后计算并输出最优方案,例如:
已找到 2 个最优方案,都需要观看 2 场演出:
方案 1 (总场数: 2, 总票价: 900.00):
- 演出A (2025-11-11) [覆盖艺人: 青木阳菜, 小林由依]
- 演出B (2025-11-12) [覆盖艺人: Mirror, Mirror]
--------------------------------------------------
观看总结: {Mirror, Mirror: 1次, 青木阳菜: 1次, 小林由依: 1次}
方案 2 (总场数: 2, 总票价: 800.00):
- 演出A (2025-11-11) [覆盖艺人: 青木阳菜, 小林由依]
- 演出C (2025-11-15) [覆盖艺人: Mirror, Mirror, 青木阳菜]
--------------------------------------------------
观看总结: {Mirror, Mirror: 1次, 青木阳菜: 2次, 小林由依: 1次}
操作选择:
1. 寻找下一级别的次优方案
2. 结束并保存方案
请输入选项 (1 或 2):
- 输入
1:继续计算次优方案(例如最优方案需 2 场,次优方案需 3 场) - 输入
2:结束计算并将所有方案保存到文件
选择「结束并保存方案」后,脚本会在同级目录下生成一个 方案报告文件,文件名格式为 plan_YYYYMMDD_HHMMSS.txt(例如 plan_20250520_143025.txt)。
报告内容包含:
- 生成时间
- 各级方案(最优、次优、次次优)
- 每个方案的演出列表、覆盖艺人、日期冲突提示
- 观看总结(各目标艺人的实际观看次数)
报告示例片段:
==================================================
演出规划方案
生成时间: 2025-05-20 14:30:25
==================================================
--- 最优方案 (总场数: 2) ---
方案 1 (总场数: 2, 总票价: 900.00):
- 演出A (2025-11-11) [覆盖艺人: 青木阳菜, 小林由依]
- 演出B (2025-11-12) [覆盖艺人: Mirror, Mirror]
--------------------------------------------------
观看总结: {Mirror, Mirror: 1次, 青木阳菜: 1次, 小林由依: 1次}
方案 2 (总场数: 2, 总票价: 800.00):
- 演出A (2025-11-11) [覆盖艺人: 青木阳菜, 小林由依]
- 演出C (2025-11-15) [覆盖艺人: Mirror, Mirror, 青木阳菜]
--------------------------------------------------
观看总结: {Mirror, Mirror: 1次, 青木阳菜: 2次, 小林由依: 1次}
--- 次优方案 (总场数: 3) ---
方案 1 (总场数: 3, 总票价: 1000.00):
- 演出A (2025-11-11) [覆盖艺人: 青木阳菜, 小林由依]
- 演出B (2025-11-12) [覆盖艺人: Mirror, Mirror]
- 演出D (2025-12-01) [覆盖艺人: ]
--------------------------------------------------
! 日期冲突警告:
! - 2025-11-11 有 2 场演出: 演出A, 演出X
--------------------------------------------------
观看总结: {Mirror, Mirror: 1次, 青木阳菜: 1次, 小林由依: 1次}
| 错误提示 | 原因 | 解决方法 |
|---|---|---|
未找到 Google OR-Tools 库 |
未安装 OR-Tools 依赖 | 执行 pip install ortools 安装 |
演出 'XXX' 日期格式无效 |
show_list.csv 中日期格式错误 |
将日期改为 YYYY-MM-DD 或 YYYY/MM/DD(例如 2025-11-11) |
找不到任何可行的方案 |
候选演出无法满足所有目标艺人的观看次数 | 1. 检查 artist_list 中艺人名称是否与 user_target.csv 匹配;2. 增加候选演出;3. 降低目标艺人的观看次数 |
CSV 读取错误 |
CSV 文件列名缺失或格式错误 | 确保 show_list.csv 包含 name/date/price/artist_list,user_target.csv 包含 artist/count |
- 艺人名称匹配:
user_target.csv中的艺人名称与show_list.csv中的艺人名称 大小写不敏感(例如「青木阳菜」和「青木陽菜」视为不同艺人,需完全匹配)。 - 日期冲突:脚本会自动提示同一日期的多场演出,但不会主动排除(需用户根据实际时间选择)。
- 方案数量:若候选演出较多,次优方案可能会非常多,建议找到满足需求的最优方案后即可停止计算。
- 价格精度:脚本内部使用「分」作为价格单位(避免浮点数误差),最终显示时自动转为「元」。