Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
659f18a
Parameters to exact (#616)
IgnaceBleukx Apr 16, 2025
db3999e
Discussing whether we support constants for Element decomposition (#630)
hbierlee Apr 16, 2025
357059f
Missing user vars for solveAll (#609)
ThomSerg Apr 16, 2025
e56b66d
Rework (start of) docs of solvers API (#633)
tias Apr 16, 2025
8c7eda2
Docs api quickstart page (#629)
kostis-init Apr 16, 2025
926e9e7
Use optional dependencies in CI and other minor improvements (#636)
hbierlee Apr 16, 2025
1594ecc
Linearize subtraction (#639)
IgnaceBleukx Apr 16, 2025
7fb6f60
rework (start of) transformations docs (#634)
tias Apr 16, 2025
2de7df3
add add() function, will use as default (#640)
tias Apr 16, 2025
03a53dc
Handle non-positive time limit consistently (#642)
Dimosts Apr 17, 2025
9df4926
Pass gurobi env params on construction
ThomSerg Apr 18, 2025
8154c97
SolverLookup: add supported() and print_status() (#641)
tias Apr 18, 2025
e49b871
Fix BoolVal in canonical comparison
ThomSerg Apr 18, 2025
585dbba
Undefault `pypblib` dependency for `pysat` (#649)
hbierlee Apr 18, 2025
7826a14
linearize objectives (#495)
Wout4 Apr 18, 2025
6ed4537
Convert ints to vars in GCC first argument for Choco (#646)
Dimosts Apr 21, 2025
f501f15
Fix in NValueExceptN for 1 value range (#645)
Dimosts Apr 24, 2025
5574948
fix empty clause in gcs (#662)
IgnaceBleukx May 2, 2025
1595192
Changelog recovery (#666)
ThomSerg May 5, 2025
251171f
Optional dependency 'all' solvers (#665)
ThomSerg May 7, 2025
88d867a
Skip tests on missing pblib (#668)
ThomSerg May 7, 2025
a339522
Setup fixes (#664)
ThomSerg May 7, 2025
313bcd1
Last changes before release 0.9.25 (#670)
ThomSerg May 7, 2025
028219d
Bump version number
ThomSerg May 7, 2025
49df2d9
release 0.9.25
ThomSerg May 7, 2025
dab22cc
Fix inverse decomposition (#673)
IgnaceBleukx May 7, 2025
2409ab7
remove 3.9 syntax for setup (#675)
ThomSerg May 12, 2025
25c2fec
Check for bool conversion on Expressions (#660)
IgnaceBleukx May 16, 2025
428dca3
update docs and error messages for canonical comparison (#678)
IgnaceBleukx May 16, 2025
f4140fd
expr/utils: no need for copy (from pumpkin branch)
tias May 20, 2025
ff0bdb4
Regular constraint (#677)
IgnaceBleukx May 20, 2025
dbfc858
CPO: Special setting for 0 duration (#681)
ThomSerg May 21, 2025
e7405de
Consistent state reporting (#545)
ThomSerg May 21, 2025
1ea0ec5
CPO solution callback (#682)
ThomSerg May 21, 2025
f120579
Remove accidental inclusion of gcs
ThomSerg May 21, 2025
bd0ee48
only_implies: avoid retransform if no subexpressions (#680)
tias May 21, 2025
2828276
cherry pick incremental_assumption test
IgnaceBleukx Feb 14, 2025
f33dbd7
CSE in flattening and decompose (#679)
IgnaceBleukx May 22, 2025
5767b32
Fix eval comparison (#683)
IgnaceBleukx May 23, 2025
0253437
Merge branch 'master' of github.com:CPMpy/cpmpy into CPMpy-master
maartenflippo May 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,17 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.10
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest pytest-xdist requests pandas
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install python-sat[pblib]
pip install z3-solver
pip install exact
pip install pysdd
pip install pychoco
pip install ".[test, z3, choco, exact, pysat, pysdd, choco, minizinc]"
pip install pypblib # dependency of pysat for PB constraints
pip install pytest-xdist
sudo snap install minizinc --classic
pip install minizinc
- name: Test with pytest
run: |
python -m pytest -n 4 tests/
237 changes: 237 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,242 @@
# Change log

## 0.9.25

### Added
* **New solver**: IBM CP Optimizer [#576](https://github.com/CPMpy/cpmpy/pull/576)
* **New global**: `ShortTable` [#469](https://github.com/CPMpy/cpmpy/pull/469)
* `model.add()` as new default to add constraints to model (same behaviour as `+=`) [#640](https://github.com/CPMpy/cpmpy/pull/640)
* Easy install of all solvers through the `"all"` optional dependency, i.e. `pip install cpmpy[all]` [#665](https://github.com/CPMpy/cpmpy/pull/665)
* More complex variants of the Sudoku puzzle (in examples) [#577](https://github.com/CPMpy/cpmpy/pull/577)
* API summery sheet [#629](https://github.com/CPMpy/cpmpy/pull/629)

* Linearisation for `div`, `abs` and `mod` [#516](https://github.com/CPMpy/cpmpy/pull/516)
* Linearisation for subtraction [#639](https://github.com/CPMpy/cpmpy/pull/639)
* `div` linearisation for Gurobi [#593](https://github.com/CPMpy/cpmpy/pull/593)
* Native cardinality constraints for PySAT [#588](https://github.com/CPMpy/cpmpy/pull/588)
* `wsum` support for PySAT

* Support for constants in `Element` global function [#630](https://github.com/CPMpy/cpmpy/pull/630)

* `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)
* `solveAll()` now accepts solver-specific kwargs, just like `solve()` [#582](https://github.com/CPMpy/cpmpy/pull/582)

* Optional dependencies for solvers and tools (setup.py) [#599](https://github.com/CPMpy/cpmpy/pull/599)
* Documentation for all CPMpy exceptions [#622](https://github.com/CPMpy/cpmpy/pull/622)



### Changed
* Bumped minimal Python version from 3.7 to 3.8 [#575](https://github.com/CPMpy/cpmpy/pull/575)
* `mod` and `div` now default to integer division
* Improved reading of DIMACS formatted files [#587](https://github.com/CPMpy/cpmpy/pull/587)
* Avoid max-based decomposition for `abs` if possible [#595](https://github.com/CPMpy/cpmpy/pull/595)
* Cleanup semantics of Boolean Python builtins [#602](https://github.com/CPMpy/cpmpy/pull/602)
* Performance optimisation of `simplify_bool` [#592](https://github.com/CPMpy/cpmpy/pull/592)
* Ensure `AllDifferent` decomposition is linear [#614](https://github.com/CPMpy/cpmpy/pull/614)
* Much improved README
* Improved docs formatting, especially for the Python API docstrings [#603](https://github.com/CPMpy/cpmpy/pull/603)
* Improved API documentation of explanation tools [#512](https://github.com/CPMpy/cpmpy/pull/512)
* Better exceptions for explanation tools [#512](https://github.com/CPMpy/cpmpy/pull/512)
* Improve documentation of non-standard solver args passing for Exact [#616](https://github.com/CPMpy/cpmpy/pull/616)
* 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)
* Skip subset of `PySAT` tests when optional dependency `pblib` is not available [#668](https://github.com/CPMpy/cpmpy/pull/668)

### Fixed
* Linearisation with boolean constants [#581](https://github.com/CPMpy/cpmpy/pull/581)
* Linearisation of `AllDifferent` with integer constants [#547](https://github.com/CPMpy/cpmpy/pull/547)
* Side conditions for `Precedence` global [#589](https://github.com/CPMpy/cpmpy/pull/589)
* `simplify_bool` on non-CPMpy expressions [#626](https://github.com/CPMpy/cpmpy/pull/626)
* Handling of negative variables in objective during linearisation [#495](https://github.com/CPMpy/cpmpy/pull/495)
* Integers in `GCC` global for Choco-solver [#646](https://github.com/CPMpy/cpmpy/pull/646)
* `NValueExceptN` for single value range [#645](https://github.com/CPMpy/cpmpy/pull/645)
* Handling of empty clauses in GCS [#662](https://github.com/CPMpy/cpmpy/pull/662)
* Missing user vars when calling `solveAll()`, resulting in incorrect number of solutions [#609](https://github.com/CPMpy/cpmpy/pull/609)
* Consistent handling of non-positive `time_limit` [#642](https://github.com/CPMpy/cpmpy/pull/642)
* Added `setuptools` to required dependencies (can be missing on some installs) [#664](https://github.com/CPMpy/cpmpy/pull/664)
* DIMACS tempfiles on Windows [#601](https://github.com/CPMpy/cpmpy/pull/601)

### Removed

* Removed support for Python version 3.7 [#575](https://github.com/CPMpy/cpmpy/pull/575)

**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.24...v0.9.25

<!-- ---------------------------------- - ---------------------------------- -->

## 0.9.24

### Release Notes

#### Enhancements and Features
- **Safening of partial functions**: New transformation to safen partial function. [#515](https://github.com/CPMpy/cpmpy/pull/515)
- **Update Choco interface with native reification**: Improved the Choco solver interface with native reification support. [#526](https://github.com/CPMpy/cpmpy/pull/526)
- **Reals in objective function**: Added support for real numbers in the objective function. [#529](https://github.com/CPMpy/cpmpy/pull/529)
- **Better naive grow**: Enhanced the "naive grow" strategy for better performance. [#528](https://github.com/CPMpy/cpmpy/pull/528)
- **Blocks world**: Introduced a "blocks world" example for demonstration purposes. [#533](https://github.com/CPMpy/cpmpy/pull/533)
- **Examples Colab links**: Added direct Colab links to examples for easier experimentation. [#553](https://github.com/CPMpy/cpmpy/pull/553)
- **Circuit decomposition for all ranges**: Extended circuit decomposition to handle all ranges. [#424](https://github.com/CPMpy/cpmpy/pull/424)
- **Global function in Z3 objective**: Introduced global functions in Z3 solver objectives. [#560](https://github.com/CPMpy/cpmpy/pull/560)
- **Z3 auto subsolver**: Implemented automatic subsolver selection for Z3 when solving optimization problems. [#567](https://github.com/CPMpy/cpmpy/pull/567)
- **Parametrize solver tests**: Streamlined solver test cases using parameterization. [#572](https://github.com/CPMpy/cpmpy/pull/572)
- **Linearize power**: Added linearization for power operations. [#538](https://github.com/CPMpy/cpmpy/pull/538)
- **Improve Boolean normalization for PySAT**: Enhanced normalization of Boolean terms for PySAT. [#569](https://github.com/CPMpy/cpmpy/pull/569)

#### Performance Improvements
- **Has subexpr optimization**: Skip transformations of leaf expressions for improved efficiency. [#532](https://github.com/CPMpy/cpmpy/pull/532)
- **Only implied speedup**: Optimized "only implied" handling for significant speedups. [#541](https://github.com/CPMpy/cpmpy/pull/541)
- **Distribute tests over CPUs**: Distributed tests over 4 CPUs, reducing runtime from `21m30s` to `8m45s`. [#571](https://github.com/CPMpy/cpmpy/pull/571)
- **ndvar_getitem optimization**: Improved `ndvar_getitem` by moving fetch casts to initialization. [#550](https://github.com/CPMpy/cpmpy/pull/550)
- **Remove inline imports**: Instead use `import as x` at top of file. [#542](https://github.com/CPMpy/cpmpy/pull/542)

#### Bug Fixes
- **Remove broadcast in min/max**: Fixed issues when forwarding to built-in min/max functions. [#536](https://github.com/CPMpy/cpmpy/pull/536)
- **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)
- **Clear values on UNSAT**: Added functionality to clear variable values when UNSAT is detected. [#523](https://github.com/CPMpy/cpmpy/pull/523)
- **Fix cpm_array with order='F'**: Resolved issues with `cpm_array()` when using column-major order. [#555](https://github.com/CPMpy/cpmpy/pull/555)
- **Car sequencing index fix**: Corrected indexing issues in the car sequencing problem. [#565](https://github.com/CPMpy/cpmpy/pull/565)

#### Code Quality and Maintenance
- **Improve exception messages**: Enhanced clarity of exception messages and removed unused imports. [#539](https://github.com/CPMpy/cpmpy/pull/539)
- **Edits to the docs**: Updated documentation for clarity and completeness. [#530](https://github.com/CPMpy/cpmpy/pull/530)
- **Gurobi license check**: Separated Gurobi license checks into a distinct process. [#566](https://github.com/CPMpy/cpmpy/pull/566)
- **Standardize solver version checks**: Unified approach to checking solver version compatibility. [#568](https://github.com/CPMpy/cpmpy/pull/568)
- **Update requirements**: Upped our minimal python requirement from 3.6 to 3.7. [#573](https://github.com/CPMpy/cpmpy/pull/573)

**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.23...v0.9.24

<!-- ---------------------------------- - ---------------------------------- -->

## 0.9.23

Quick release, because we want the updated tools to be available.

### What's Changed
* Extension to tools: MARCO and SMUS
* Added tests for incremental solving and fixed incemental solving with objective in Exact
* Cumulative decomposition fix when capacity was numpy integer.

**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.22...v0.9.23

<!-- ---------------------------------- - ---------------------------------- -->

## 0.9.22

### What's New
* New solver: GlasgowConstraintSolver (GCS)
* Upgraded to Exact 2
* Minizinc print: easily extract MiniZinc and FlatZinc text from CPMpy model.
* Update TEMPLATE.py to make it clearer how to add new solvers.
* SolverLookup gives clear error message in stead of returning None
* allow kwargs in Model.solve()
* call python builtins for sum, abs, min and max without expressions in the arguments.
* All solvers now have a native_model() function, to allow native solver access.
* It's now possible to name multiple new variables at once, by providing the names in a list.
* Linearize transformation can now rewrite modulo (if multiplication is supported)
* Fix behaviour of "all", "any", "max", "min", "sum", "prod" on higher dimensional NDVarArrays (maintain dimensionality)
* Value function of expressions now always returns a python integer, where it could sometimes be a numpy integer.
* Fixed performance issue where all solver vars where seen as user vars when solving with MiniZinc

### Documentation
* Overall improvement of documentation
* update documentation of 'comparison' transformation

### New Contributors
Thanks to 2 new contributors!
* [@ThomSerg](https://github.com/ThomSerg) and [@sin3000x](https://github.com/sin3000x)

**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.21...v0.9.22

<!-- ---------------------------------- - ---------------------------------- -->

## 0.9.21

### New Global constraints:
* Increasing, Decreasing, IncreasingStrict, DecreasingStrict
* Lexicographical ordering constraints: LexLess, LexLessEq, LexChainLess, LexChainLessEq
* Scheduling constraints Precedence and NoOverlap
* Closed version of GCC
* AllDiffExceptN, AllEqualExceptN
* Nvalues except n
* Negative table
* Among

### Bug Fixes:
* count nested in a wsum crashed MiniZinc [#461](https://github.com/CPMpy/cpmpy/issues/461)
* AllDifferentExcept0 now correctly works with MiniZinc
* User variables that get simplified away during transformation steps are now saved.
* Add missing case in simplify bool transformation.

### Quality of life
* Removed type restriction for InDomain
* Extending automatic testsuite
* Check if minizinc executable is installed

**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.20...v0.9.21

<!-- ---------------------------------- - ---------------------------------- -->

## 0.9.20

### What's Changed
* Choco is now a tier 2 solver, available to use after installing the pychoco package!
* new DIMACS parser and writer
* SolverLookup is now a classmethod for easier use of custom solvers.
* Fixed a bug where expression bounds didn't get rounded to integers when creating an intvar
* Added a warning when expressions have non-integer bounds, as these will be rounded
* Fixed a bug in our helper function is_bool, now also recognises our BoolVal objects
* Updated our ortools and minizinc version requirements.

**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.19..v0.9.20

<!-- ---------------------------------- - ---------------------------------- -->

## 0.9.19

### What's Changed
* Update on tools/subsets, add mcs and mss tools with grow-variants.
* Full propagation with exact
* Adding NValue global constraint
* Minizinc result now saved in solver object, this allows to access the solver statistics.

### Documentation
* Update docs for tools.
* Docs on solver statistics
* Format solver api, and add missing links in docs
* Update version and copyright date
* Remove bug where python comment (#) got interpreted as a header.

### Bug Fixes
* Properly handle reified global constraints for Minizinc
* Correctly handle global constraints with list-arguments of length 1
* Add missing edge case in flatten
* Type check table constraint first argument, cannot be a constant.

**Full Changelog**: https://github.com/CPMpy/cpmpy/compare/v0.9.18...v0.9.19

<!-- ---------------------------------- - ---------------------------------- -->

## 0.9.18
Minor release with some bugfixes, we are trying to do monthly releases now, so they will be more concise.

### What's new?
* get_bounds() helper function now works on arrays and lists, returning arrays (lists) of bounds
* Pysdd added to our automated GitHub tests
* Pysdd does not support Xor anymore.

### Bugfixes
* Fixed Cumulative bug when capacity was a numpy int.
* Cumulative now works in Minizinc with only one task.
* Docs look good again
* Corrected default parameter value in docs
* Fixed visualisations in Nonogram and Room assignment notebook examples
* Adopted the new ORtools 9.8 names of tuneable parameters.

## New Contributors
* [@KennyVDV](https://github.com/KennyVDV) made their first contribution by adding a new example: chess_position

<!-- ---------------------------------- - ---------------------------------- -->

## 0.9.17
Some new solvers supported at tier 3, update to our transformations and bugfixes.

Expand Down
4 changes: 2 additions & 2 deletions cpmpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
- `solvers`: CPMpy classes that translate a model into approriate calls of a solver's API
- `transformations`: common methods for transforming expressions into other expressions, used by `solvers` modules to simplify/rewrite expressions
"""
# Tias Guns, 2019-2024
# Tias Guns, 2019-2025

__version__ = "0.9.24"
__version__ = "0.9.25"


from .expressions import *
Expand Down
2 changes: 1 addition & 1 deletion cpmpy/expressions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from .globalconstraints import AllDifferent, AllDifferentExcept0, AllDifferentExceptN, AllEqual, AllEqualExceptN, Circuit, Inverse, Table, ShortTable, Xor, Cumulative, \
IfThenElse, GlobalCardinalityCount, DirectConstraint, InDomain, Increasing, Decreasing, IncreasingStrict, DecreasingStrict, \
LexLess, LexLessEq, LexChainLess, LexChainLessEq, Precedence, NoOverlap, \
NegativeTable
NegativeTable, Regular
from .globalconstraints import alldifferent, allequal, circuit # Old, to be deprecated
from .globalfunctions import Maximum, Minimum, Abs, Element, Count, NValue, NValueExcept, Among
from .core import BoolVal
Expand Down
10 changes: 10 additions & 0 deletions cpmpy/expressions/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,10 @@ def __invert__(self):
raise TypeError("Not operator is only allowed on boolean expressions: {0}".format(self))
return Operator("not", [self])

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

class BoolVal(Expression):
"""
Expand Down Expand Up @@ -551,6 +555,12 @@ def __repr__(self):
return "({}) {} ({})".format(self.args[0], self.name, self.args[1])
# if not: prettier printing without braces
return "{} {} {}".format(self.args[0], self.name, self.args[1])

def __bool__(self):
# will be called when comparing elements in a container, but always with `==`
if self.name == "==":
return repr(self.args[0]) == repr(self.args[1])
super().__bool__() # default to exception

# return the value of the expression
# optional, default: None
Expand Down
Loading
Loading