Skip to content

Commit 0d6d82e

Browse files
Update from upstream CPMpy (#2)
1 parent 9bb9a23 commit 0d6d82e

55 files changed

Lines changed: 2704 additions & 723 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/python-test.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,17 @@ jobs:
66
steps:
77
- uses: actions/checkout@v3
88
- name: Set up Python 3.10
9-
uses: actions/setup-python@v4
9+
uses: actions/setup-python@v5
1010
with:
1111
python-version: '3.10'
1212
- name: Install dependencies
1313
run: |
1414
python -m pip install --upgrade pip
15-
pip install flake8 pytest pytest-xdist requests pandas
1615
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
17-
pip install python-sat[pblib]
18-
pip install z3-solver
19-
pip install exact
20-
pip install pysdd
21-
pip install pychoco
16+
pip install ".[test, z3, choco, exact, pysat, pysdd, choco, minizinc]"
17+
pip install pypblib # dependency of pysat for PB constraints
18+
pip install pytest-xdist
2219
sudo snap install minizinc --classic
23-
pip install minizinc
2420
- name: Test with pytest
2521
run: |
2622
python -m pytest -n 4 tests/

changelog.md

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,242 @@
11
# Change log
22

3+
## 0.9.25
4+
5+
### Added
6+
* **New solver**: IBM CP Optimizer [#576](https://github.com/CPMpy/cpmpy/pull/576)
7+
* **New global**: `ShortTable` [#469](https://github.com/CPMpy/cpmpy/pull/469)
8+
* `model.add()` as new default to add constraints to model (same behaviour as `+=`) [#640](https://github.com/CPMpy/cpmpy/pull/640)
9+
* Easy install of all solvers through the `"all"` optional dependency, i.e. `pip install cpmpy[all]` [#665](https://github.com/CPMpy/cpmpy/pull/665)
10+
* More complex variants of the Sudoku puzzle (in examples) [#577](https://github.com/CPMpy/cpmpy/pull/577)
11+
* API summery sheet [#629](https://github.com/CPMpy/cpmpy/pull/629)
12+
13+
* Linearisation for `div`, `abs` and `mod` [#516](https://github.com/CPMpy/cpmpy/pull/516)
14+
* Linearisation for subtraction [#639](https://github.com/CPMpy/cpmpy/pull/639)
15+
* `div` linearisation for Gurobi [#593](https://github.com/CPMpy/cpmpy/pull/593)
16+
* Native cardinality constraints for PySAT [#588](https://github.com/CPMpy/cpmpy/pull/588)
17+
* `wsum` support for PySAT
18+
19+
* Support for constants in `Element` global function [#630](https://github.com/CPMpy/cpmpy/pull/630)
20+
21+
* `SolverLookup` now has `.supported()` and `.print_status()` to get information on the available solvers on the current system [#641](https://github.com/CPMpy/cpmpy/pull/641)
22+
* `solveAll()` now accepts solver-specific kwargs, just like `solve()` [#582](https://github.com/CPMpy/cpmpy/pull/582)
23+
24+
* Optional dependencies for solvers and tools (setup.py) [#599](https://github.com/CPMpy/cpmpy/pull/599)
25+
* Documentation for all CPMpy exceptions [#622](https://github.com/CPMpy/cpmpy/pull/622)
26+
27+
28+
29+
### Changed
30+
* Bumped minimal Python version from 3.7 to 3.8 [#575](https://github.com/CPMpy/cpmpy/pull/575)
31+
* `mod` and `div` now default to integer division
32+
* Improved reading of DIMACS formatted files [#587](https://github.com/CPMpy/cpmpy/pull/587)
33+
* Avoid max-based decomposition for `abs` if possible [#595](https://github.com/CPMpy/cpmpy/pull/595)
34+
* Cleanup semantics of Boolean Python builtins [#602](https://github.com/CPMpy/cpmpy/pull/602)
35+
* Performance optimisation of `simplify_bool` [#592](https://github.com/CPMpy/cpmpy/pull/592)
36+
* Ensure `AllDifferent` decomposition is linear [#614](https://github.com/CPMpy/cpmpy/pull/614)
37+
* Much improved README
38+
* Improved docs formatting, especially for the Python API docstrings [#603](https://github.com/CPMpy/cpmpy/pull/603)
39+
* Improved API documentation of explanation tools [#512](https://github.com/CPMpy/cpmpy/pull/512)
40+
* Better exceptions for explanation tools [#512](https://github.com/CPMpy/cpmpy/pull/512)
41+
* Improve documentation of non-standard solver args passing for Exact [#616](https://github.com/CPMpy/cpmpy/pull/616)
42+
* General documentation improvements [#619](https://github.com/CPMpy/cpmpy/pull/619), [#633](https://github.com/CPMpy/cpmpy/pull/633), [#634](https://github.com/CPMpy/cpmpy/pull/634)
43+
* Skip subset of `PySAT` tests when optional dependency `pblib` is not available [#668](https://github.com/CPMpy/cpmpy/pull/668)
44+
45+
### Fixed
46+
* Linearisation with boolean constants [#581](https://github.com/CPMpy/cpmpy/pull/581)
47+
* Linearisation of `AllDifferent` with integer constants [#547](https://github.com/CPMpy/cpmpy/pull/547)
48+
* Side conditions for `Precedence` global [#589](https://github.com/CPMpy/cpmpy/pull/589)
49+
* `simplify_bool` on non-CPMpy expressions [#626](https://github.com/CPMpy/cpmpy/pull/626)
50+
* Handling of negative variables in objective during linearisation [#495](https://github.com/CPMpy/cpmpy/pull/495)
51+
* Integers in `GCC` global for Choco-solver [#646](https://github.com/CPMpy/cpmpy/pull/646)
52+
* `NValueExceptN` for single value range [#645](https://github.com/CPMpy/cpmpy/pull/645)
53+
* Handling of empty clauses in GCS [#662](https://github.com/CPMpy/cpmpy/pull/662)
54+
* Missing user vars when calling `solveAll()`, resulting in incorrect number of solutions [#609](https://github.com/CPMpy/cpmpy/pull/609)
55+
* Consistent handling of non-positive `time_limit` [#642](https://github.com/CPMpy/cpmpy/pull/642)
56+
* Added `setuptools` to required dependencies (can be missing on some installs) [#664](https://github.com/CPMpy/cpmpy/pull/664)
57+
* DIMACS tempfiles on Windows [#601](https://github.com/CPMpy/cpmpy/pull/601)
58+
59+
### Removed
60+
61+
* Removed support for Python version 3.7 [#575](https://github.com/CPMpy/cpmpy/pull/575)
62+
63+
**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.24...v0.9.25
64+
65+
<!-- ---------------------------------- - ---------------------------------- -->
66+
67+
## 0.9.24
68+
69+
### Release Notes
70+
71+
#### Enhancements and Features
72+
- **Safening of partial functions**: New transformation to safen partial function. [#515](https://github.com/CPMpy/cpmpy/pull/515)
73+
- **Update Choco interface with native reification**: Improved the Choco solver interface with native reification support. [#526](https://github.com/CPMpy/cpmpy/pull/526)
74+
- **Reals in objective function**: Added support for real numbers in the objective function. [#529](https://github.com/CPMpy/cpmpy/pull/529)
75+
- **Better naive grow**: Enhanced the "naive grow" strategy for better performance. [#528](https://github.com/CPMpy/cpmpy/pull/528)
76+
- **Blocks world**: Introduced a "blocks world" example for demonstration purposes. [#533](https://github.com/CPMpy/cpmpy/pull/533)
77+
- **Examples Colab links**: Added direct Colab links to examples for easier experimentation. [#553](https://github.com/CPMpy/cpmpy/pull/553)
78+
- **Circuit decomposition for all ranges**: Extended circuit decomposition to handle all ranges. [#424](https://github.com/CPMpy/cpmpy/pull/424)
79+
- **Global function in Z3 objective**: Introduced global functions in Z3 solver objectives. [#560](https://github.com/CPMpy/cpmpy/pull/560)
80+
- **Z3 auto subsolver**: Implemented automatic subsolver selection for Z3 when solving optimization problems. [#567](https://github.com/CPMpy/cpmpy/pull/567)
81+
- **Parametrize solver tests**: Streamlined solver test cases using parameterization. [#572](https://github.com/CPMpy/cpmpy/pull/572)
82+
- **Linearize power**: Added linearization for power operations. [#538](https://github.com/CPMpy/cpmpy/pull/538)
83+
- **Improve Boolean normalization for PySAT**: Enhanced normalization of Boolean terms for PySAT. [#569](https://github.com/CPMpy/cpmpy/pull/569)
84+
85+
#### Performance Improvements
86+
- **Has subexpr optimization**: Skip transformations of leaf expressions for improved efficiency. [#532](https://github.com/CPMpy/cpmpy/pull/532)
87+
- **Only implied speedup**: Optimized "only implied" handling for significant speedups. [#541](https://github.com/CPMpy/cpmpy/pull/541)
88+
- **Distribute tests over CPUs**: Distributed tests over 4 CPUs, reducing runtime from `21m30s` to `8m45s`. [#571](https://github.com/CPMpy/cpmpy/pull/571)
89+
- **ndvar_getitem optimization**: Improved `ndvar_getitem` by moving fetch casts to initialization. [#550](https://github.com/CPMpy/cpmpy/pull/550)
90+
- **Remove inline imports**: Instead use `import as x` at top of file. [#542](https://github.com/CPMpy/cpmpy/pull/542)
91+
92+
#### Bug Fixes
93+
- **Remove broadcast in min/max**: Fixed issues when forwarding to built-in min/max functions. [#536](https://github.com/CPMpy/cpmpy/pull/536)
94+
- **Convert numpy array in Table constraint**: Ensured proper conversion of NumPy arrays to lists in Table constraints. [#540](https://github.com/CPMpy/cpmpy/pull/540)
95+
- **Clear values on UNSAT**: Added functionality to clear variable values when UNSAT is detected. [#523](https://github.com/CPMpy/cpmpy/pull/523)
96+
- **Fix cpm_array with order='F'**: Resolved issues with `cpm_array()` when using column-major order. [#555](https://github.com/CPMpy/cpmpy/pull/555)
97+
- **Car sequencing index fix**: Corrected indexing issues in the car sequencing problem. [#565](https://github.com/CPMpy/cpmpy/pull/565)
98+
99+
#### Code Quality and Maintenance
100+
- **Improve exception messages**: Enhanced clarity of exception messages and removed unused imports. [#539](https://github.com/CPMpy/cpmpy/pull/539)
101+
- **Edits to the docs**: Updated documentation for clarity and completeness. [#530](https://github.com/CPMpy/cpmpy/pull/530)
102+
- **Gurobi license check**: Separated Gurobi license checks into a distinct process. [#566](https://github.com/CPMpy/cpmpy/pull/566)
103+
- **Standardize solver version checks**: Unified approach to checking solver version compatibility. [#568](https://github.com/CPMpy/cpmpy/pull/568)
104+
- **Update requirements**: Upped our minimal python requirement from 3.6 to 3.7. [#573](https://github.com/CPMpy/cpmpy/pull/573)
105+
106+
**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.23...v0.9.24
107+
108+
<!-- ---------------------------------- - ---------------------------------- -->
109+
110+
## 0.9.23
111+
112+
Quick release, because we want the updated tools to be available.
113+
114+
### What's Changed
115+
* Extension to tools: MARCO and SMUS
116+
* Added tests for incremental solving and fixed incemental solving with objective in Exact
117+
* Cumulative decomposition fix when capacity was numpy integer.
118+
119+
**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.22...v0.9.23
120+
121+
<!-- ---------------------------------- - ---------------------------------- -->
122+
123+
## 0.9.22
124+
125+
### What's New
126+
* New solver: GlasgowConstraintSolver (GCS)
127+
* Upgraded to Exact 2
128+
* Minizinc print: easily extract MiniZinc and FlatZinc text from CPMpy model.
129+
* Update TEMPLATE.py to make it clearer how to add new solvers.
130+
* SolverLookup gives clear error message in stead of returning None
131+
* allow kwargs in Model.solve()
132+
* call python builtins for sum, abs, min and max without expressions in the arguments.
133+
* All solvers now have a native_model() function, to allow native solver access.
134+
* It's now possible to name multiple new variables at once, by providing the names in a list.
135+
* Linearize transformation can now rewrite modulo (if multiplication is supported)
136+
* Fix behaviour of "all", "any", "max", "min", "sum", "prod" on higher dimensional NDVarArrays (maintain dimensionality)
137+
* Value function of expressions now always returns a python integer, where it could sometimes be a numpy integer.
138+
* Fixed performance issue where all solver vars where seen as user vars when solving with MiniZinc
139+
140+
### Documentation
141+
* Overall improvement of documentation
142+
* update documentation of 'comparison' transformation
143+
144+
### New Contributors
145+
Thanks to 2 new contributors!
146+
* [@ThomSerg](https://github.com/ThomSerg) and [@sin3000x](https://github.com/sin3000x)
147+
148+
**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.21...v0.9.22
149+
150+
<!-- ---------------------------------- - ---------------------------------- -->
151+
152+
## 0.9.21
153+
154+
### New Global constraints:
155+
* Increasing, Decreasing, IncreasingStrict, DecreasingStrict
156+
* Lexicographical ordering constraints: LexLess, LexLessEq, LexChainLess, LexChainLessEq
157+
* Scheduling constraints Precedence and NoOverlap
158+
* Closed version of GCC
159+
* AllDiffExceptN, AllEqualExceptN
160+
* Nvalues except n
161+
* Negative table
162+
* Among
163+
164+
### Bug Fixes:
165+
* count nested in a wsum crashed MiniZinc [#461](https://github.com/CPMpy/cpmpy/issues/461)
166+
* AllDifferentExcept0 now correctly works with MiniZinc
167+
* User variables that get simplified away during transformation steps are now saved.
168+
* Add missing case in simplify bool transformation.
169+
170+
### Quality of life
171+
* Removed type restriction for InDomain
172+
* Extending automatic testsuite
173+
* Check if minizinc executable is installed
174+
175+
**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.20...v0.9.21
176+
177+
<!-- ---------------------------------- - ---------------------------------- -->
178+
179+
## 0.9.20
180+
181+
### What's Changed
182+
* Choco is now a tier 2 solver, available to use after installing the pychoco package!
183+
* new DIMACS parser and writer
184+
* SolverLookup is now a classmethod for easier use of custom solvers.
185+
* Fixed a bug where expression bounds didn't get rounded to integers when creating an intvar
186+
* Added a warning when expressions have non-integer bounds, as these will be rounded
187+
* Fixed a bug in our helper function is_bool, now also recognises our BoolVal objects
188+
* Updated our ortools and minizinc version requirements.
189+
190+
**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.19..v0.9.20
191+
192+
<!-- ---------------------------------- - ---------------------------------- -->
193+
194+
## 0.9.19
195+
196+
### What's Changed
197+
* Update on tools/subsets, add mcs and mss tools with grow-variants.
198+
* Full propagation with exact
199+
* Adding NValue global constraint
200+
* Minizinc result now saved in solver object, this allows to access the solver statistics.
201+
202+
### Documentation
203+
* Update docs for tools.
204+
* Docs on solver statistics
205+
* Format solver api, and add missing links in docs
206+
* Update version and copyright date
207+
* Remove bug where python comment (#) got interpreted as a header.
208+
209+
### Bug Fixes
210+
* Properly handle reified global constraints for Minizinc
211+
* Correctly handle global constraints with list-arguments of length 1
212+
* Add missing edge case in flatten
213+
* Type check table constraint first argument, cannot be a constant.
214+
215+
**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.18...v0.9.19
216+
217+
<!-- ---------------------------------- - ---------------------------------- -->
218+
219+
## 0.9.18
220+
Minor release with some bugfixes, we are trying to do monthly releases now, so they will be more concise.
221+
222+
### What's new?
223+
* get_bounds() helper function now works on arrays and lists, returning arrays (lists) of bounds
224+
* Pysdd added to our automated GitHub tests
225+
* Pysdd does not support Xor anymore.
226+
227+
### Bugfixes
228+
* Fixed Cumulative bug when capacity was a numpy int.
229+
* Cumulative now works in Minizinc with only one task.
230+
* Docs look good again
231+
* Corrected default parameter value in docs
232+
* Fixed visualisations in Nonogram and Room assignment notebook examples
233+
* Adopted the new ORtools 9.8 names of tuneable parameters.
234+
235+
## New Contributors
236+
* [@KennyVDV](https://github.com/KennyVDV) made their first contribution by adding a new example: chess_position
237+
238+
<!-- ---------------------------------- - ---------------------------------- -->
239+
3240
## 0.9.17
4241
Some new solvers supported at tier 3, update to our transformations and bugfixes.
5242

cpmpy/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
- `solvers`: CPMpy classes that translate a model into approriate calls of a solver's API
1313
- `transformations`: common methods for transforming expressions into other expressions, used by `solvers` modules to simplify/rewrite expressions
1414
"""
15-
# Tias Guns, 2019-2024
15+
# Tias Guns, 2019-2025
1616

17-
__version__ = "0.9.24"
17+
__version__ = "0.9.25"
1818

1919

2020
from .expressions import *

cpmpy/expressions/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from .globalconstraints import AllDifferent, AllDifferentExcept0, AllDifferentExceptN, AllEqual, AllEqualExceptN, Circuit, Inverse, Table, ShortTable, Xor, Cumulative, \
2525
IfThenElse, GlobalCardinalityCount, DirectConstraint, InDomain, Increasing, Decreasing, IncreasingStrict, DecreasingStrict, \
2626
LexLess, LexLessEq, LexChainLess, LexChainLessEq, Precedence, NoOverlap, \
27-
NegativeTable
27+
NegativeTable, Regular
2828
from .globalconstraints import alldifferent, allequal, circuit # Old, to be deprecated
2929
from .globalfunctions import Maximum, Minimum, Abs, Element, Count, NValue, NValueExcept, Among
3030
from .core import BoolVal

cpmpy/expressions/core.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,10 @@ def __invert__(self):
430430
raise TypeError("Not operator is only allowed on boolean expressions: {0}".format(self))
431431
return Operator("not", [self])
432432

433+
def __bool__(self):
434+
raise ValueError(f"__bool__ should not be called on a CPMPy expression {self} as it will always return True\n"
435+
"Do not use an expression as argument in an `if` statement and use cpmpy.any, cpmpy.max instead of python builtins\n"
436+
"If you think this is an error, please report on github")
433437

434438
class BoolVal(Expression):
435439
"""
@@ -551,6 +555,12 @@ def __repr__(self):
551555
return "({}) {} ({})".format(self.args[0], self.name, self.args[1])
552556
# if not: prettier printing without braces
553557
return "{} {} {}".format(self.args[0], self.name, self.args[1])
558+
559+
def __bool__(self):
560+
# will be called when comparing elements in a container, but always with `==`
561+
if self.name == "==":
562+
return repr(self.args[0]) == repr(self.args[1])
563+
super().__bool__() # default to exception
554564

555565
# return the value of the expression
556566
# optional, default: None

0 commit comments

Comments
 (0)