pythonoptapy

java.lang.IllegalStateException: 2 members with a @ValueRangeProvider annotation must not have the same id (timeslotRangeLS)


Trying to generate school timetable with lab hours. Kindly help me to solve this error! Thanks in advance.

Here is my code!

@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")"
        )

Trying to get the 2 timeslots one for lesson(1 hour) and one for lab(2 hour).Here is my @planning_solution.

I defined 2 @planning_entity for both lab & lesson with @value_range_provider.

@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_variable(Base, value_range_provider_refs=['roomRange', 'timeslotRangeLB'],
                            graph_type=PlanningVariableGraphType.CHAINED)
    @planning_id
    def get_id(self):
        return self.id

    
    
    @planning_variable(Timeslot, ["timeslotRangeLB"])
    def get_timeslot1(self):
        return self.timeslot1

    @value_range_provider(range_id = "timeslotRangeLB", value_range_type = Timeslot)
    def get_possible_timeslot_list1(self):
        return self.subject.teacher.student_group.room_list
    
    
    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")"
        )
@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_variable(Base, value_range_provider_refs=['timeslotRangeLS', 'roomRange'],
                            graph_type=PlanningVariableGraphType.CHAINED)
    @planning_id
    def get_id(self):
        return self.id

    @planning_variable(Timeslot, ["timeslotRangeLS"])
    def get_timeslot(self):
        return self.timeslot

    @value_range_provider(range_id = "timeslotRangeLS", value_range_type = Timeslot)
    def get_possible_timeslot_list(self):
        return self.subject.teacher.student_group.room_list
        # return self.course.teacher.department.room_list
    
    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")"
        )

Solution

  • The issue is you defined @value_range_provider(range_id = "timeslotRangeLS") on both your @planning_solution and your @planning_entity. You can only have one; if you want the value range to apply to every entity, do it on the @planning_solution. If you want each planning entity to have it own value range that only applies to it, do it on the @planning_entity. If you want to combine a value range that contains common values for all entities, and a value range that is per entity, use a @value_range_provider on the @planning_solution, and a @value_range_provider on the entity, but give them different ids (ex: @value_range_provider(range_id = "timeslotRangeLSSolution") and @value_range_provider(range_id = "timeslotRangeLSEntity"), and in the @planning_variable, use both range ids in the list (ex: @planning_variable(Room, ["timeslotRangeLSSolution", "timeslotRangeLSEntity"])