-
Notifications
You must be signed in to change notification settings - Fork 25
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
Decomposable operations #343
Comments
I like the idea of extracting a different class for these numerical globals (or whatever we want to call them). Will clean up the inheritance a lot indeed. Not a big fan of turning them into 'real' global constraints by adding the result-variable to them however. |
I see issue #258 raise the problem that abs should also be decomposable -> we could add it as a decomposable op as min/max/element/count |
We call them 'numeric global constraints', by lack of better name. I only realized later that constraints like 'Element' need special handling in a language like ours, because they are indeed more like operators/functions returning a numeric value.
What is the benefit of creating two separate abstract classes (e.g. GlobalConstraint and smth like NumericGlobalConstraint or any other better name)? One will have 'decompose' as function, the other 'decompose_comparison'; so mostly conceptual? Note that any creation of new classes might require creating new 'elif' statements in many places; which I'm not fond of. |
No. This is some old-school CP thinking where you had to write constraints as part of a Prolog rule. The philosophy of CPMpy is that one can compose constraints in whatever way, shape or form one desires. This composability is crucial. E.g., is I don't care what we call them (constraints, terms, expressions, syntax trees, inductively defined strings...), as long as there is no distinction between them. To me, we have primitively typed terms (built as a term tree). I'd be happy to say that we get an actual constraint when we assert some term to have a fixed value. E.g., Note that thinking of numerical terms as "not-constraints" leads to problems such as "decomposition of circuit behaves weird" (while it behaves the same as decompositions for most numerical terms) or "lets make element undefined until it is part of a comparison" (while this yields inconsistencies as a subterm (!) to negations, xors or counts). So the central argument is that all terms can be a subterm of some other term in CPMpy. As long as we have that (and we should!) we should make no distinction between constraints, and numerical "not-constraints", simply because we can mix-and-match ad infinitum. |
Ok, the above is philosophy. From a practical point of view, I'd be happy to have some code that decomposes the comparison of a numerical term, and re-use that code to decompose the occurrence of a numerical term where it is not part of a comparison. We can definitely use an inheritable interface (with the appropriate methods) for the terms that use this way of decomposing themselves (e.g., min/max, but also circuit!). |
For me, x+y is not a constraint, as it does impact x if y is changed and y if x is changed. There is no concept of satisfiability with x+y. But in the end, CPMpy still requires a constraint to be inputted in the model. You couldn't use x+y as one of the constraints in the model (and should break). One could say that the classical constraints defined in the literature correspond to boolean expression that we want to be evaluated to true. But for me, not all the expressions are constraints. Just Element(arr, var) is not a constraint, it is simply an expression. Same for max, min, count. For your example @JoD, alldiff(x,y, z), ! alldiff(x,y,z), count(! alldiff(x,y,z), p) >= 1 are boolean expressions that can be used as constraints by imposing their value to be true, but count(! alldiff(x,y,z), p) is only an integer expression |
We seem to agree that a constraint is Boolean expression that is asserted to be true. And that CPMpy has Boolean and numeric(integer) expressions. It also also likely that we will split the class currently called And I guess it is exactly those names that Jo is reacting too... The So although the original remark is now mostly-resolved (yes, we will split them reasonably soon), the new question is: what should we call these two classes, such that CP researchers realize what it sometimes represents, but such that we don't confuse new users about what is and is not called a constraint... |
This discussion is dangerous to open, especially not in person, as it can take ages to specify what we call a constraint and what not. I agree with the contept that constraints are boolean expressions that through propagation restrict the domains of variables. So, all boolean expressions can be used as a constraint, but nothing is a constraint by default, unless asserted to be true in a model (which triggers also the propagation). But this would not just affect our definition of global constraints in cpmpy, but also in the whole CP community. I agree on splitting the numeric expressions from the global constraints to a different class (e.g. GlobalFunctions), but the initial GlobalConstraints class should be named as it, as it represents very specific notions of the CP community which would be weird to not include. For anyone in CP, it woulc be very weird to have a CP modelling library that does not mention anything about Global Constraints, just something about boolean expressions. The fact that they can be reified could be explained in the documentation, i.e. that they can also be used as expressions and not only as constraints. I will open a new PR to split the 2 cases, and we can continue the discussion there :) |
Ok, proposal:
Would that make sense? |
In general yes, I agree But, based on this, our GlobalConstraints class should change name, as they are boolean expressions that are not always asserted to be true, they can be used as subexpressions in any other expression too. However, I have strong feelings on keeping the name GlobalConstraints on them, because of the importance of global constraints in CP. Check PR #351 where I did seperate the boolean GlobalConstraints with the numeric ones, and changed the name of the later to GlobalFunctions. |
I agree with Dimos. If we forget about the history of CP, then we should call the two class boolean (global) expressions and numerical (global) expressions. But this can be counterintuitive/weird from the perspective of the people used to CP who may not be cooperative/found it weird not to have a global constraint category. |
for now we decided to keep the name global constraints (even though they can be used as expressions in reifications) and add a separate class named global functions for things like min max abs and element. |
From the discussion of monday 5 June 2023 at noon:
Minimum, Maximum, Element and Count currently inherits from GlobalConstraint. But they are not really constraints, following the classical definition "constraints define a relation between some variables for which a given assignment satisfies or does not satisfy the constraint". They are in fact more close to operations, evaluated as a value.
They are real constraints when used with a comparison.
This creates, from an inheritance point of view, multiple problems (decompose function not defined without a comparison,...).
Two possibilities to clean the inheritance:
solution 1 would probably lead to redundant code since the comparison part would be the same for all. Solution 2 would remove the redundancy.
The text was updated successfully, but these errors were encountered: