Skip to content

Conversation

IgnaceBleukx
Copy link
Collaborator

@IgnaceBleukx IgnaceBleukx commented Jun 18, 2025

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.

@IgnaceBleukx IgnaceBleukx requested a review from Dimosts June 18, 2025 10:03
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"
Copy link
Collaborator

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.

Copy link
Collaborator Author

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...

Copy link
Collaborator

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.

Copy link
Collaborator Author

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

@IgnaceBleukx IgnaceBleukx changed the title Omit end variables in scheduling constraints Refactor and update Cumulative and NoOverlap constraints Sep 9, 2025
@IgnaceBleukx
Copy link
Collaborator Author

I used this PR to add some more changes to the Cumulative and NoOverlap constraints.
In particular:

  • Refactored .decompose() and .value() functions
  • Specified allowed types for arguments in documentation
  • Allow for negative durations, and ensure consistent solver behaviour
  • Allow for negative demands, and ensure consistent solver behaviour
  • Allow to omit end variables (original scope of this PR...)

This PR now also fixes #685

@Dimosts can you re-review these changes?

@Dimosts Dimosts self-requested a review September 9, 2025 13:00
Copy link
Collaborator

@Dimosts Dimosts left a 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"
Copy link
Collaborator

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
Copy link
Collaborator

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.

Copy link
Collaborator

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants