Explanation tools for PyCSP3 constraint models
Project description
PyCSP3-Explain
Explanation tools for PyCSP3 constraint models. Find minimal unsatisfiable subsets (MUS), maximal satisfiable subsets (MSS), and minimal correction sets (MCS) to debug and understand infeasible constraint problems.
Features
- MUS (Minimal Unsatisfiable Subset): Find the minimal set of conflicting constraints
mus()- Assumption-based using ACE core extractionmus_naive()- Deletion-based (works with any solver)quickxplain_naive()- Preferred MUS based on constraint ordering
- Optimal MUS (SMUS/OCUS): Prefer smaller or lower-weight explanations
smus()- Smallest MUS (fewest constraints)optimal_mus()- Minimum total weight MUSocus()- OCUS with subset constraints/predicatesocus_naive()- Naive OCUS (alias for weighted MUS)
Note: IHS uses a small CP model in PyCSP3 and falls back to enumeration if needed.
- MSS (Maximal Satisfiable Subset): Find the maximum satisfiable portion
mss()- Assumption-based with core extractionmss_naive()- Greedy growing algorithm
- Weighted MSS/MCS: Optimize which constraints to keep/remove
mss_opt()- Maximize total weight of kept constraintsmcs_opt()- Minimize total weight of removed constraints
- MCS (Minimal Correction Set): Find the minimal changes needed to restore satisfiability
mcs()- Via assumption-based MSS complementmcs_naive()- Via naive MSS complement
- MARCO: Enumerate all MUSes and MCSes
marco()- Generator over MUS/MCSmarco_naive()- Naive MARCO implementationall_mus()/all_mcs()- Convenience wrappersall_mus_naive()- Naive MUS enumeration
Installation
# Clone the repository
git clone https://github.com/sohaibafifi/pycsp3-explain.git
cd pycsp3-explain
# Install dependencies
pip install -e .
Requirements
- Python 3.10+
- PyCSP3 (>= 2.5)
- lxml (>= 4.9)
- Java runtime (for ACE/Choco)
Quick Start
Using satisfy() with Explain Tools
from pycsp3 import *
from pycsp3_explain import *
x = VarArray(size=2, dom=range(10))
satisfy( [
x[0] == 5,
x[0] == 7, # conflicts with x[0] == 5
x[1] >= 3,
])
constraints = flatten_constraints(posted())
if solve() == UNSAT:
print("MUS:", mus(constraints))
print("Optimal MUS:", optimal_mus(constraints, weights=[1, 1, 1]))
for kind, subset in marco(constraints):
print(kind, subset)
# or use the helper function
mus_result = explain_unsat("mus", soft=constraints, check=False)
print("MUS:", mus_result)
optimal = explain_unsat("optimal_mus", soft=constraints, check=False, weights=[1] * len(constraints))
print("Optimal MUS:", optimal)
for kind, subset in explain_unsat("marco", soft=constraints, check=False):
print(kind, subset)
Notes
mus()andmss()use ACE core extraction for efficiency; they fall back to naive versions for non-ACE solvers.- MCS is the complement of MSS:
MCS = Soft \ MSS - Removing MCS constraints from soft constraints leaves MSS, which is satisfiable.
How It Works
Constraint Explanation Problem
Given an infeasible constraint satisfaction problem (CSP), explanation tools help identify:
| Concept | Question | Description |
|---|---|---|
| MUS | Why is it infeasible? | Minimal Unsatisfiable Subset - the smallest set of constraints that conflict |
| MSS | What can be satisfied? | Maximal Satisfiable Subset - the largest set of constraints that can hold together |
| MCS | What to fix? | Minimal Correction Set - the smallest set of constraints to remove for satisfiability |
Relationships
- Every MUS and every MCS share at least one constraint (hitting set duality)
MCS = Soft \ MSS(MCS is the complement of MSS)- Multiple MUSes/MSSes/MCSes may exist for a given problem
API Reference
MUS Functions
mus(soft, hard=None, solver="ace")- Assumption-based MUSmus_naive(soft, hard=None, solver="ace")- Deletion-based MUSquickxplain_naive(soft, hard=None, solver="ace")- Preferred MUSis_mus(subset, hard=None, solver="ace")- Verify MUS validityall_mus_naive(soft, hard=None, solver="ace")- Enumerate MUSes (naive)optimal_mus(soft, hard=None, weights=None, solver="ace")- Minimum-weight MUSoptimal_mus_naive(soft, hard=None, weights=None, solver="ace")- Naive minimum-weight MUSsmus(soft, hard=None, solver="ace")- Smallest MUS (fewest constraints)ocus(soft, hard=None, weights=None, solver="ace", ...)- OCUS with subset constraintsocus_naive(soft, hard=None, weights=None, solver="ace")- Naive OCUSOCUSException- Exception for optimal MUS/OCUS routines
MSS/MCS Functions
mss(soft, hard=None, solver="ace")- Assumption-based MSSmss_naive(soft, hard=None, solver="ace")- Greedy growing MSSmss_opt(soft, hard=None, weights=None, solver="ace")- Weighted MSSis_mss(subset, soft, hard=None, solver="ace")- Verify MSS validitymcs(soft, hard=None, solver="ace")- Assumption-based MCSmcs_naive(soft, hard=None, solver="ace")- Naive MCSmcs_opt(soft, hard=None, weights=None, solver="ace")- Weighted MCSmcs_from_mss(mss, soft)- Complement of MSSis_mcs(subset, soft, hard=None, solver="ace")- Verify MCS validity
MARCO Enumeration
marco(soft, hard=None, solver="ace")- Generator over MUS/MCSmarco_naive(soft, hard=None, solver="ace")- Naive MARCOall_mus(soft, hard=None, solver="ace")- Collect all MUSesall_mcs(soft, hard=None, solver="ace")- Collect all MCSes
License
MIT License
References
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pycsp3_explain-0.1.2.tar.gz.
File metadata
- Download URL: pycsp3_explain-0.1.2.tar.gz
- Upload date:
- Size: 91.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7053d4b926fc62e85383f325c3e64fdea077a49d46f2a645e892f22014ca8701
|
|
| MD5 |
ef4d1aab5670b7c04ac90d57705769b0
|
|
| BLAKE2b-256 |
101ebab9b48e146b1884273ebcc8c019d715306804eb15a086f3ece861708b58
|
Provenance
The following attestation bundles were made for pycsp3_explain-0.1.2.tar.gz:
Publisher:
publish.yml on sohaibafifi/pycsp3-explain
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycsp3_explain-0.1.2.tar.gz -
Subject digest:
7053d4b926fc62e85383f325c3e64fdea077a49d46f2a645e892f22014ca8701 - Sigstore transparency entry: 829310692
- Sigstore integration time:
-
Permalink:
sohaibafifi/pycsp3-explain@856f47be28c86221851d0f5aafb708353444668b -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/sohaibafifi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@856f47be28c86221851d0f5aafb708353444668b -
Trigger Event:
push
-
Statement type:
File details
Details for the file pycsp3_explain-0.1.2-py3-none-any.whl.
File metadata
- Download URL: pycsp3_explain-0.1.2-py3-none-any.whl
- Upload date:
- Size: 24.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
268dce12ea4321fba16aff881429bdf7e95d5e2f2ae7adab8a879bd7e3acdae1
|
|
| MD5 |
2320d8829edefb3a6217757d077c9985
|
|
| BLAKE2b-256 |
e969bd3b684a8c5078c62466351fc08d510aa43234de36794ee19207edcce99a
|
Provenance
The following attestation bundles were made for pycsp3_explain-0.1.2-py3-none-any.whl:
Publisher:
publish.yml on sohaibafifi/pycsp3-explain
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycsp3_explain-0.1.2-py3-none-any.whl -
Subject digest:
268dce12ea4321fba16aff881429bdf7e95d5e2f2ae7adab8a879bd7e3acdae1 - Sigstore transparency entry: 829310694
- Sigstore integration time:
-
Permalink:
sohaibafifi/pycsp3-explain@856f47be28c86221851d0f5aafb708353444668b -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/sohaibafifi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@856f47be28c86221851d0f5aafb708353444668b -
Trigger Event:
push
-
Statement type: