Repository navigation
Unit tests of the constraints Maximum and Minimum, and fixes of #244 to #251 - #243
Merged
Merged
Conversation
This was referenced Oct 19, 2026
Maximum() and Minimum() of a single term with the parameter condition: a constraint on one term
#245
Closed
…um and Minimum tests
This was referenced Oct 19, 2026
Closed
… the marks of the Maximum and Minimum tests Tests of #250 (a term given several times is kept once): test_xcsp3_extremum_with_a_repeated_term and test_xcsp3_extremum_of_a_single_repeated_term.
The condition given by the parameter condition is built by Condition.build_condition(), as for Sum(),
instead of being written as it is (eq 2); an empty set of values gives false with in, and true with notin.
Condition.build_condition() now reports an operator that cannot be applied to its operand, as ('in', 2)
or ('eq', {1, 2}), instead of an assert without message.
Fixes #244
…imum()
As XCSP3-core requires at least two terms, the condition given to Maximum() or Minimum() of a single term is
applied to this term, as for Sum() (Maximum(x[0], condition=('ge', 2)) gives x[0] >= 2).
Fixes #245
Maximum() and Minimum() of no term (as Maximum([]) or Maximum(None)) fail with the message "Maximum() requires at least one term", instead of an assert without message. Fixes #246
…nd Minimum() A Boolean among the terms fails with "Maximum() does not accept Booleans as terms, which is the case of True" (instead of a message about the values of a domain), and a symbolic variable with "Maximum() requires integer variables (or expressions), which is not the case of s[0]" (instead of being accepted), as for Sum(). Fixes #247
The extremum of integers only is a constant (Maximum(3, 1) == y gives y == 3, and minimize(Maximum(3, 1)) is refused, there being nothing to optimize); with other terms, the integers are reduced to the largest one (the smallest one for Minimum()), replaced by a single auxiliary variable. A constant term (as Sum([]), or x >= x simplified into 1) is an integer, instead of being written in the list. Fixes #248
As the maximum and the minimum do not depend on repetitions, each term is kept once (variables compared by identity, expressions by their text, identical components being replaced by the same auxiliary variable), as for NotAllEqual() (#134); a single remaining term gives an expression (Maximum(x[0], x[0]) == 2 gives x[0] == 2). Then ACE no longer finds wrong solutions for maximum on [x[0] x[0]], and cosoco no longer refuses a repeated variable in minimum. Fixes #250
…Arg() and MinimumArg() The terms were given by list(term) when the first argument is a generator, the other terms being ignored (Maximum((x[i] for i in range(2)), x[2]) gave a maximum of x[0] and x[1]): they are now given by flatten(term, others), which handles generators, as for Sum(). Fixes #251
The values of a condition in (or notin) of a constraint (maximum, minimum, sum, count, nValues, element,
cumulative, binPacking, flow, ...) must be integers: Condition.build_condition() reports a variable (or an
expression) among them, instead of writing it in the condition (Maximum(x) in {y, 2} gave (in,{y,2}), which is
not XCSP3), also for the parameter condition. A list (or a tuple) of values with a variable, as in
Maximum(x) in [y, 2] or Sum(x) in [y, z], is given to the condition, so as to be reported when the constraint is
posted, instead of failing with an assert without message or of being accepted. In intension, variables remain
accepted among the values (x[0] in {y, 2}); a variable with a coefficient (x[0] * 2 not in {y, z, 1}) gives a sum
of one term (#208) only with integers, and an expression in intension otherwise.
Fixes #249
The values of a condition in (or notin) must be integers: Condition.build_condition() now reports any other
value (a float, a symbol, None, a tuple, ...), not only a variable or an expression (Sum(x) in {1.5, 2} gave
(in,{1.5,2}), and s[i] in {'a', 'b'} gave (in,{a,b}), which the parser of XCSP3 does not accept); a list (or a
tuple) of such values with a constraint is given to the condition, instead of failing with an assert without
message (Sum(x) in ['a', 2]).
Refs #249
…and on demand The builds were run for each commit of a pull request (event pull_request without types). They are now run at each push on master (so when a pull request is merged) and when a tag is pushed; on a pull request, only when the label run-tests is added (as for the tests); and on demand from the tab Actions (workflow_dispatch). The section about the continuous integration of the README of the tests is updated (Windows, label run-tests).
With occurrences={0: z, 7: z}, cosoco writes out of an array on the heap (xcsp3team/cosoco#98): the corruption
is detected by the allocator of glibc on Linux (crash, hence the strict mark), but not on macOS, where cosoco may
give the right solutions (XPASS(strict) in the run of the tests at the merge of #226). The case is skipped for
cosoco outside Linux, the result being undefined there; the strict mark is kept on Linux.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Unit tests of the constraints Maximum and Minimum of the section Constraints (Global) of the API (https://pycsp.org/documentation/api/constraints-global/#Maximum), written as for the previous global constraints (#66, #130, #135, #141, #148, #156, #169, #213, #226), in a single file: each test is run for
Maximum()(its solutions compared withmax()) and forMinimum()(compared withmin()), and fixes of the issues found (#244 to #251).Tests
pycsp3/tests/test_constraints_global_maximum_minimum.py: conditions given by operators (==,!=,<, ...,in,not in, with integers, variables, expressions, ranges, sets, empty sets) or by the parametercondition; forms of the terms (lists, generators, several arrays, matrices, arrays with holes); sizes and domains (holes, negative values); expressions (generalized form), integers and components (Sum,Count,NValues, nested extremums) among the terms; single and repeated terms; extremums as terms of expressions; groups, functions,Slide; logical contexts (|,&,~,imply,iff,xor,If,either,both, ...); meta-constraints; objectives (minimize,maximize, with expressions, integers, components); examples of the documentation; XCSP3 files; invalid arguments; variables among the values ofinwith all the constraints having a condition, and in intension. The constraints maximum and minimum are not part of the mini-tracks, so there is no test with-mini.Whole suite at 117dd3d: 11135 passed, 471 skipped, 622 xfailed, 0 failed. Each fix comes with tests that fail without it. PyCSP3-models (one instance per model): at 2812f37, 412 of 415 XCSP3 files identical to master (414 of 415 identical between 2812f37 and 117dd3d), compilation 236.0 s on master and 230.7 s with the fixes; the 3 differences: AccordionMini (MemoryError on both sides, with a cap of 3 GB), League13 (25 auxiliary variables instead of 80, the zeros of
rankings[j] * (x[j] == i)being reduced to one, #248), OPD (Maximum(x[i] * x[j] for ...)now gives the same XCSP3 file as the list form, #251; on a reduced version, ACE and CHOCO find the solutions of brute force with both files).Issues of PyCSP3
conditionofMaximum()andMinimum()was written as it is (eq 2), neither built nor checked;Condition.build_condition()now also reports an operator that cannot be applied to its operand (('in', 2))conditiongave a constraint on one term; the condition is now applied to the termMaximumArg()andMinimumArg())in/not inwith any constraint having a condition (Maximum(),Sum(),Count(),NValues(),MaximumArg(), element,Cumulative(),BinPacking(),Flow(), ...) is reported by an explicit error; intension remains permissive (x[0] in {y, 2}), andx[0] * 2 not in {y, z, 1}no longer gives a sum with variables in its conditionNone, a tuple) is reported too (Sum(x) in {1.5, 2}gave(in,{1.5,2}),s[i] in {'a', 'b'}gave(in,{a,b}), not accepted by the parser of XCSP3)The last column gives the number of tests of the commit that fail on the code of the previous commit.
Other changes
build-linux.yml,build-macos.yml,build-windows.yml) were run for each commit of a pull request; they are now run at each push on master (so when a pull request is merged), when a tag is pushed, on a pull request only when the labelrun-testsis added (as the tests), and on demand (workflow_dispatch). The section about the continuous integration ofpycsp3/tests/README.mdis updated.test_cardinality_occurrences_given_by_variables[COSOCO-{0: z, 7: z}]gaveXPASS(strict), the heap overflow of cosoco (xcsp3team/cosoco#98) being detected by the allocator of glibc on Linux (crash) but not on macOS (right solutions by chance). The case is now skipped for cosoco outside Linux, the strict mark being kept on Linux.Problems of the solvers
maximumandminimumwith(ne,k):! ERROR(AssertionError: NE is not implementedinExtremumCst.buildFrom())maximumandminimum:(ne,k)posted as(eq,k);(lt|le|gt|ge,y)posted asop(y,max(X)); intervals with swapped bounds andnotinposted asin; sets handled as intervals; segmentation fault ofmaximumwith(eq,y)(null sentinel inMaximumVariableEQ)maximumandminimumwith(in,a..b)and(notin,a..b): wrong solutions with 4.10.15-beta (embedded in PyCSP3) and 6.0.2, fixed in the develop version (859fdde)Maximum(x) in set())maximumon a list made of a single variable given several times (x[0] x[0]) with(eq,k)behaves as(le,k)Cases not handled by the solvers (skipped)
maximumandminimumon expressions, except with(eq,y)s UNSUPPORTED): 23 testsThe 7 other skipped tests are the parameter
conditionofMaximumArg(),MinimumArg()and element, which have no such parameter or do not build it yet (to be tested with these constraints).Found, to be handled with the next constraints
conditionofMaximumArg()andMinimumArg()is not built (as The parameter condition of Maximum() and Minimum() is written as it is (neither built nor checked) #244).Knapsack(...) in {1, 3}fails with an assert without message, andm[i][j] in {1, 3}(element on a matrix) with "Problem with an indexing expression".elementwithout index (member), generated for a variable or a component in a list of four variables or more: ACE gives wrong solutions, CHOCO gives solutions twice, and cosoco does not handle it (s UNSUPPORTED); to be reported with the tests of Element.Decisions
A. Repeated terms: (a) each term is kept once by PyCSP3, as for
NotAllEqual()(#134); the problem of ACE is then not reported (#250).B. Extremum of integers (#248): (a) evaluated by PyCSP3:
Maximum(3, 1) == ygivesy == 3, an objective made of integers only is refused (with the message of #221, as forNValues()of a single term, orSum()andCount()of no term), and, with variables, the integers are reduced to the largest one (the smallest one forMinimum()), replaced by a single auxiliary variable. (The question said "as forSum()", which was wrong:Sum(3, 5)also gives an auxiliary variable for each integer.)C. Single term with the parameter
condition(#245): (a) the condition applied to the term, asSum()does.D. Variable among the values of
in(#249): (a) an explicit error, for all the constraints having a condition, the values of a conditionin/notinbeing integers (any other value is refused); lists of variables are refused too; intension remains permissive.E. ACE and
(ne,k): (a) reported (xcsp3team/ACE#34).F. Issues of the solvers: created (xcsp3team/ACE#34, xcsp3team/cosoco#99).