在Timefold中建模任意固定数量独立规划变量的方案咨询
我正在开发日程生成器,实现课程与房间的分配功能,当前模型如下:
@PlanningEntity class Lesson { ... @PlanningVariable(allowsUnassigned = true) Room room; Set<String> requiredRoomAttributes; ... } class Room { Set<String> attributes; }
但现在需要调整模型,使每个课程可分配任意但固定数量的房间(用户可在UI中指定某课程需要3个分别对应不同属性要求的房间)。
(由于只要课程时间不冲突,同一房间可分配给多个课程,因此@PlanningListVariable并不适用。)
我想到的一种建模方式如下:
@PlanningEntity class Lesson { ... Set<RoomAssignment> roomAssignments; ... } class RoomAssignment { ... Room room; // null until room has been assigned Set<String> requiredRoomAttributes; ... } class Room { Set<String> attributes; }
但我不确定@PlanningVariable注解应放置在何处,因为只有room是实际变量,而非requiredRoomAttributes。
因此我认为以下建模方式更优:
@PlanningEntity class Lesson { ... @PlanningVariable List<Room> rooms; // 第i个集合对应第i个房间的属性要求 List<Set<String>> requiredAttributes; ... } class Room { Set<String> attributes; }
问题1:这是否是推荐的建模方式?是否有更优方案?
你提出的List<Room>搭配索引对应requiredAttributes的方案不可行,因为Timefold不支持将@PlanningVariable标注在集合类型上。更推荐的方案是将每个房间分配需求拆分为独立的PlanningEntity:
@PlanningEntity class Lesson { // 课程基础信息,无规划变量 ... int id; // 关联该课程的所有房间分配需求 List<RoomAssignment> roomAssignments; ... } @PlanningEntity class RoomAssignment { // 关联所属课程 Lesson lesson; // 该分配的属性要求(固定值,非变量) Set<String> requiredRoomAttributes; @PlanningVariable(allowsUnassigned = true) Room room; ... } class Room { Set<String> attributes; }
该方案的核心优势:
- 每个
RoomAssignment是独立规划单元,Timefold内置求解器可直接处理单个房间的分配调整,无需额外自定义逻辑 - 模型职责清晰,属性匹配等约束可直接绑定到
RoomAssignment,规则编写更直观 - 扩展性强,后续给房间分配添加优先级、特殊规则等需求时,修改成本低
问题2:是否可使用内置移动选择器更新List<Room> rooms中的单个元素,还是需要自定义移动选择器?
首先,@PlanningVariable不能标注在List类型上,这种方案本身不被Timefold识别为合法规划变量。即使强行尝试,内置移动选择器也无法处理集合内的单个元素——内置选择器针对的是单个规划变量实例,而非集合元素。
如果采用独立RoomAssignment实体的方案,内置移动选择器(如ChangeMoveSelector、SwapMoveSelector)可直接作用于每个RoomAssignment的room变量,完全无需自定义移动选择器。
问题3:Timefold内部是否可处理任意但固定数量的独立变量?是否考虑过支持类似如下的注解?
@PlanningEntity class Lesson { @PlanningVariableArray Room[] rooms = new Room[10]; }
Timefold不支持@PlanningVariableArray这类注解,但通过拆分独立PlanningEntity的方式,完全可以实现“固定数量独立变量”的需求——每个数组元素对应一个RoomAssignment实体,效果与你设想的数组方案一致,且更符合Timefold的建模规范。
Timefold的设计逻辑是将每个独立决策点封装为单独的PlanningEntity,这种模式能让求解器更高效地搜索解空间。目前官方没有计划添加@PlanningVariableArray注解,因为拆分实体的方式已经能很好覆盖这类场景,且模型灵活性更高。
内容的提问来源于stack exchange,提问作者aioobe

