-
Notifications
You must be signed in to change notification settings - Fork 30
Refactor and update Cumulative and NoOverlap constraints #694
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
assert is_any_list(start), "start should be a list" | ||
assert is_any_list(duration), "duration should be a list" | ||
assert is_any_list(end), "end should be a list" | ||
|
||
assert demand is not None, "demand should be provided but was None" | ||
assert capacity is not None, "capacity should be provided but was None" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what should be done here, but I am not really a fan of giving them a default value (making them optional) and then not allowing the optional value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I also agree it is quite annoying... For now this is the best I could come up with, as you cannot make an argument in the middle optional...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still troubled by this. So, someone either has to actually use the end var after all, or has to use kwargs to define demand and capacity, which are optional but not that optional after all.
Both minizinc (https://docs.minizinc.dev/en/stable/predicates.html) and essence (https://arxiv.org/pdf/2201.03472) actually do not accept end variables at all, and create them for solvers that need them. Should we stick to having them after all?
The question is what if the user needs the end variables for something else I guess; In this case, if the users define themselves the end = start + duration constraints, it is ok. Common subexpression elimination should capture it during the decomposition if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm yeah, but removing it all together will break every CPMpy model currently out there that uses a Cumulative constraint...
I don't really have too much of an opinion on whether we want to keep the end variables or not, but if we decide to remove them, we should wait a couple of releases and raise a deprecation warning here
I used this PR to add some more changes to the Cumulative and NoOverlap constraints.
This PR now also fixes #685 @Dimosts can you re-review these changes? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly approved. See my first comment on end variables and whether we actually want to have them. Not a required change though, I just think it overcomplicates the code if we keep it.
assert is_any_list(start), "start should be a list" | ||
assert is_any_list(duration), "duration should be a list" | ||
assert is_any_list(end), "end should be a list" | ||
|
||
assert demand is not None, "demand should be provided but was None" | ||
assert capacity is not None, "capacity should be provided but was None" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still troubled by this. So, someone either has to actually use the end var after all, or has to use kwargs to define demand and capacity, which are optional but not that optional after all.
Both minizinc (https://docs.minizinc.dev/en/stable/predicates.html) and essence (https://arxiv.org/pdf/2201.03472) actually do not accept end variables at all, and create them for solvers that need them. Should we stick to having them after all?
The question is what if the user needs the end variables for something else I guess; In this case, if the users define themselves the end = start + duration constraints, it is ok. Common subexpression elimination should capture it during the decomposition if needed.
|
||
cons = [] | ||
cons = [d >= 0 for d in duration] # enforce non-negative durations | ||
cons += [h >= 0 for h in demand] # enforce non-negative demand |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should maybe be in safening? It is defined as a restriction, not as an enforced constraint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels more like safening code than constraining. It is a restriction of the cumulative constraint (https://sofdem.github.io/gccat/aux/pdf/cumulative.pdf) and not something that is enforced.
However, after in person discussion I agree that it will create more problems if we do it in safening instead. Note to revisit this if we encounter more such cases.
Proposal to omit the end variables in scheduling constraints such as Cumulative and NoOverlap.
Makes
end
None by default, and adapts solver behaviour accordingly.It was not possible to make the "dummy" end variables in the constructor, as then they would be added to
user_vars
in the solver interface, which is incorrect.Most solvers don't actually need the
end
variables in their interface either, except for OR-Tools.Added a helper-function
get_end_vars
to create these dummy end variables.