-
Notifications
You must be signed in to change notification settings - Fork 159
Description
Current Situation
If a filter, join or any other constraintstream construct only depends on non-variable fields, we still execute the relevant lambda despite knowing that nothing will change while solving.
Inefficiency / Problem
Instead of re-calculating the same things over and over again, we could introduce a new mechanism which, when used correctly, will only execute the relevant code once.
Consider this hypothetical situation:
.forEach(Shift.class)
.join(Shift.class, lessThanOrEqual(Shift::getEnd, Shift::getStart))
.filter((firstShift, secondShift) -> Duration.between(firstShift.getEnd(), secondShift.getStart()).toHours() < 10)
- Initially, all shifts would go through the node network
- they all execute the join node
- they all execute the filter node
However, assuming shift.start and shift.end are facts (non-variables), then this entire block will never change during solving, yet they are executed each time something changes.
Current Workaround
You can work around this by creating a new class (SolverShift, GroupedShifts) which already does some of this constraint stream action.
Typically, you could work around this if users of the Solver de-couple their regular domain classes from the Solver Domain classes, which is good practice anyway. However, if Domain vs Solver model become radically different, this increases cognitive load.
Potential Implementation Ideas
- Create a static node in the network which will only be executed once, potentially trading off memory usage for performance (explicitly)
Linked Issues
- this mechanism is implemented for filters: Add
filterStatic
(vs.filter
) to ConstraintStreams #1806