Reputation: 199
Question
Is it possible to create a dynamic ValueRangeProvider whose range of values depends on the current value of a planning variable? Or is there some other way to achieve this desired effect?
Background
I'm attempting to make a scheduling optimization similar to the nurse roster example. Here are some differences:
The number of planning entities is variable, but that's a different issue. Current workaround is generating as many planning entities as the duration of each shift, but that will quickly create millions of entities which will mostly end up having null assignments.
Attempts
I tried to set up a ValueRangeProvider on the ShiftAssignment (the PlanningEntity), which returns a countable value range based on the available times for the currently assigned Employee, but it seems that this is static to the first Employee that was assigned. My next attempt was to make the ValueRangeProvider return an instance of a @CustomShadowVariable that would change the availability when a new Employee is set, but this does not seem to have any different of an effect than the first way.
Another idea was to create a custom move factory that generates only the valid times when the current Employee can start, but this still wouldn't prevent a change in an Employee from breaking the hard constraints on its time not being valid. It seems more like this approach would need an additional custom move factory for changing Employees, explicitly changing the startTime variable to a valid time for that Employee whenever it changes.
One other attempt is to make the start time a shadow variable that updates to the first available time for an Employee, while having a genuine variable 'offset' that would be a static value range between 0 and the duration of the shift. This seems like it might solve the problem, but assumes that the offset can be reset to 0 whenever the Employee changes, which would need a custom move factory to be able to achieve. This seems like it ends up being the same thing as a custom move factory for just planning the start time as a genuine planning variable, but maybe it would work better than trying to change the ValueRangeProvider dynamically.
Current Solution
For now, I ignore not being able to enforce the constraint within the ValueRangeProvider, and just return a ValueRange set by a shift's start/end time (which is fixed for each different shift). This increases the search space, and generates many solutions with broken hard constraints when an Employee cannot start at the time chosen after being changed. It seems that it can never find a better solution because it doesn't get a chance to improve the start time variable. This might be partially mitigated by changing the solver parameters (which I'm not very adept at), but the search space would still be a lot larger than necessary.
Any help or a point in the right direction would be greatly appreciated. Thanks!
Upvotes: 1
Views: 1454
Reputation: 89
You can refer to the chapter "4.3.5.2.3. ValueRangeProvider on the Planning Entity". The value range could place on solution class or planning entity class. you can create a getter in planning entity class to get the value range base on current planning entity instance, filter the scope to reduce the possible values of a planning variable, to reduce the search space.
Upvotes: 3
Reputation: 199
I ended up creating a new instance of a ShiftAssignment entity for each Employee and each time range that Employee is available for, so that the ValueRangeProvider on each entity would be static, which seems to be working for my purposes. Instead of letting an Employee and the start time both be planning variables, just the start time is a variable now, but nullable to indicate that a specific Employee/Shift/Availability entity isn't assigned to a shift.
Upvotes: 2