This clarification makes a lot of sense to me, but if I try and apply the reasoning to the code below (which is based on the employee scheduling example available in optapy) I would have expected set_timeslot_list
to be called when set_task
is called but it does not look like it is.
The optimisation runs OK and finds a suitable set of tasks to assign to the list of time slots that I have available, but each task.timeslot_list
remains empty, and looks like the set_timeslot_list
method is never called.
I believe I am missing something..Can you please help me understand what is wrong with how I modified the example in the code below or with I am interpreting how shadow vars work?
I can provide longer snippets, or the @planning_solution
class if this is not sufficient.
@planning_entity(pinning_filter=timeslot_pinning_filter)
class Timeslot:
def __init__(self, start: datetime.datetime = None, end: datetime.datetime = None,
location: str = None, required_skill: str = None, task: object = None):
self.start = start
self.end = end
self.location = location
self.required_skill = required_skill
self.task = task
@planning_id
def get_id(self):
return self.id
# The type of the planning variable is Task, but we cannot use it because task refers to Timeslot below.
@planning_variable(object, value_range_provider_refs=['task_range'], nullable=False)
def get_task(self):
return self.task
def set_task(self, task):
self.task = task
@planning_entity
class Task:
def __init__(self, name: str = None, duration: int = None, skill_set: list = None):
self.name = name
self.duration = duration
self.skill_set = skill_set
self.timeslot_list = [] #The shadow property, which is a list, can never be None. If no genuine variable references that shadow entity, then it is an empty list
@inverse_relation_shadow_variable(Timeslot, source_variable_name = "task")
def get_timeslot_list(self):
return self.timeslot_list
def set_timeslot_list(self, ts):
self.timeslot_list = ts