解决java.lang.IllegalStateException:重复@ValueRangeProvider ID问题
问题原因与修复方案
错误根源
报错java.lang.IllegalStateException: 2 members with a @ValueRangeProvider annotation must not have the same id (timeslotRangeLS)是因为:
- 在
TimeTable类和Lesson类中,同时定义了id为timeslotRangeLS的@value_range_provider - 在
TimeTable类和Lab类中,同时定义了id为timeslotRangeLB的@value_range_provider
OptaPlanner要求全局范围内的value_range_provider id必须唯一,重复定义会触发该异常。
另外代码中还存在两个次要问题:
Lesson和Lab类错误地将id标记为planning_variable(id是实体唯一标识,不需要被规划分配值)TimeTable类中get_lab_list方法拼写错误:return self.Lab_list应为return self.lab_list
修正后的代码
1. 修正TimeTable类
@planning_solution class TimeTable: timeslot_list: list[Timeslot] timeslot_list1: list[Timeslot] room_list: list[Room] lesson_list: list[Lesson] lab_list: list[Lab] score: HardSoftScore def __init__(self, timeslot_list, timeslot_list1, room_list, lesson_list, lab_list, score=None): self.timeslot_list = timeslot_list self.timeslot_list1 = timeslot_list1 self.room_list = room_list self.lesson_list = lesson_list self.lab_list = lab_list self.score = score @problem_fact_collection_property(Timeslot) @value_range_provider("timeslotRangeLS") def get_timeslot_list(self): return self.timeslot_list @problem_fact_collection_property(Timeslot) @value_range_provider("timeslotRangeLB") def get_timeslot_list1(self): return self.timeslot_list1 @problem_fact_collection_property(Room) @value_range_provider("roomRange") def get_room_list(self): return self.room_list @planning_entity_collection_property(Lesson) def get_lesson_list(self): return self.lesson_list @planning_entity_collection_property(Lab) def get_lab_list(self): return self.lab_list # 修正拼写错误 @planning_score(HardSoftScore) def get_score(self): return self.score def set_score(self, score): self.score = score def __str__(self): return ( f"TimeTable(" f"timeslot_list={format_list(self.timeslot_list)},\n" f"timeslot_list1={format_list(self.timeslot_list1)},\n" f"room_list={format_list(self.room_list)},\n" f"lesson_list={format_list(self.lesson_list)},\n" f"lab_list={format_list(self.lab_list)},\n" f"score={str(self.score.toString()) if self.score is not None else 'None'}" f")" )
2. 修正Lab类
@planning_entity class Lab(Base): id: int subject: str teacher: str student_group: str timeslot1: Timeslot room: Room def __init__(self, id, subject, teacher, student_group, timeslot1=None, room=None): self.id = id self.subject = subject self.teacher = teacher self.student_group = student_group self.timeslot1 = timeslot1 self.room = room @planning_id # 仅保留标识注解,移除错误的规划变量注解 def get_id(self): return self.id @planning_variable(Timeslot, ["timeslotRangeLB"]) def get_timeslot1(self): return self.timeslot1 def set_timeslot1(self, new_timeslot): self.timeslot1 = new_timeslot @planning_variable(Room, ["roomRange"]) def get_room(self): return self.room def set_room(self, new_room): self.room = new_room def __str__(self): return ( f"Lab(" f"id={self.id}, " f"timeslot1={self.timeslot1}, " f"room={self.room}, " f"teacher={self.teacher}, " f"subject={self.subject}, " f"student_group={self.student_group}" f")" )
3. 修正Lesson类
@planning_entity class Lesson(Base): id: int subject: str teacher: str student_group: str timeslot: Timeslot room: Room def __init__(self, id, subject, teacher, student_group, timeslot=None, room=None): self.id = id self.subject = subject self.teacher = teacher self.student_group = student_group self.timeslot = timeslot self.room = room @planning_id # 仅保留标识注解,移除错误的规划变量注解 def get_id(self): return self.id @planning_variable(Timeslot, ["timeslotRangeLS"]) def get_timeslot(self): return self.timeslot def set_timeslot(self, new_timeslot): self.timeslot = new_timeslot @planning_variable(Room, ["roomRange"]) def get_room(self): return self.room def set_room(self, new_room): self.room = new_room def __str__(self): return ( f"Lesson(" f"id={self.id}, " f"timeslot={self.timeslot}, " f"room={self.room}, " f"teacher={self.teacher}, " f"subject={self.subject}, " f"student_group={self.student_group}" f")" )
核心修改点说明
- 删除
Lesson和Lab类中重复的@value_range_provider注解及对应方法,直接引用TimeTable中定义的全局范围即可 - 移除实体类中错误标记的
@planning_variable(Base, ...)注解,id仅作为实体标识,不需要参与规划分配 - 修正
TimeTable类中get_lab_list的拼写错误,确保实体集合能正确加载
内容的提问来源于stack exchange,提问作者VijiS
相关产品推荐
相关产品推荐

