Skip to main content

Python bindings for the D4 model counter and compiler

Project description

py-d4

Python bindings for the D4 compiler and model counter, supporting option structures, CNF files, custom clause vectors, logic circuits, weighted model counting, and d-DNNF queries. Built with nanobind and scikit-build-core.


🚀 Users Guide

1. Installation

Install the package directly from your GitLab PyPI package registry (typically configured in your CI or local .pip/pip.conf):

pip install d4Solver --extra-index-url https://gitlab.univ-artois.fr/api/v4/projects/<PROJECT_ID>/packages/pypi/simple

2. Usage Examples

2.1 Basic Model Counting

You can instantiate a Solver using a CNF filepath or raw Python clause structures (list of lists/tuples of literals, 1-based indexing):

import py_d4

# 1. Option A: Load from a DIMACS CNF file
solver = py_d4.Solver("path/to/formula.cnf")

# 2. Option B: Pass raw Python clauses and total variable count
# Formula: (x1 or x2) and (not x2 or x3)
clauses = [
    [1, 2],
    [-2, 3]
]
nb_vars = 3
solver = py_d4.Solver(clauses, nb_vars)

# Run model counting
count_res = solver.count()
print(f"Number of models: {count_res.getResult()}")     # Large integer as string (GMP support)
print(f"As Python integer: {count_res.getIntResult()}")  # Safe python int

2.2 Compilation to d-DNNF

py-d4 can compile CNF formulas and circuits into Decision Diagram / Deterministic Decomposable Negation Normal Form (d-DNNF):

import py_d4

clauses = [[1, 2], [-2, 3]]
solver = py_d4.Solver(clauses, 3)

# Compile
compile_res = solver.compile()

# Access compiled graph statistics
print(f"Nodes in d-DNNF: {compile_res.getNbNodes()}")
print(f"Edges in d-DNNF: {compile_res.getNbEdges()}")

# Get the compiled NNF circuit string (in standard d-DNNF format)
nnf_str = compile_res.getNNFString()
print("NNF String:\n", nnf_str)

2.3 Querying the Compiled d-DNNF

Once compiled, you can run multiple queries (SAT checks or model counting) under different literal assumptions:

# Check if the formula is satisfiable (no assumptions)
is_sat = compile_res.isSAT([])  # True/False

# Check satisfiability assuming x1 is True (1) and x2 is False (-2)
is_sat_under_assumptions = compile_res.isSAT([1, -2])

# Count models under literal assumptions
# E.g., model count assuming x1 is True
count_under_x1 = compile_res.count([1])
print(f"Models satisfying x1: {count_under_x1}")

2.4 Weighted Model Counting (WMC)

You can assign weights to literals for exact weighted model counting:

import py_d4

# Formula: (x1 or x2)
solver = py_d4.Solver([[1, 2]], nb_vars=2)

# Define weights for literals (keys are 1-based literals, values are string representations)
weights = {
    1: "0.3",
    -1: "0.7",
    2: "0.4",
    -2: "0.6"
}
# Set weights (WeightType can be FLOAT or GMP)
solver.setWeights(weights, py_d4.WeightType.FLOAT)

# Compute WMC directly
count_res = solver.count()
print("WMC Result:", float(count_res.getResult()))  # Output: 0.58

# Or compile and query WMC under assumptions
compile_res = solver.compile()
print("WMC under x1=True:", float(compile_res.count([1])))  # Output: 0.3

2.5 Logic Gates / Circuit Compilation

Instead of CNF, you can initialize the solver with logic gates to compile or count structured circuits:

import py_d4

# Create a gate representing: x3 = x1 AND (not x2)
gate = py_d4.Gate()
gate.gateType = py_d4.GateType.AND
gate.inputs = [1, -2]
gate.output = 3

# Instantiate solver from gate specifications
solver = py_d4.Solver([gate], nb_vars=3)
print("Models for circuit:", solver.count().getIntResult())

2.6 Solver Configuration & Options

Fine-tune the behavior of D4 by mutating native C++ option structures. Documentation and description of settings are exposed natively as Python docstrings:

import py_d4

# Instantiate default options
opt = py_d4.OptionDpllStyleMethod()

# 1. Read Option Descriptions (C++ docstrings exposed to Python)
print(py_d4.OptionDpllStyleMethod.exploitModel.__doc__)
# Output: "If we exploit model during search"

# 2. Modify properties directly (with type safety)
opt.precision = 30
opt.exploitModel = False
opt.optionSolver.solverName = 0  # 0: glucose, 1: minisat

# 3. Modify nested option group settings
opt.optionBranchingHeuristic.freqDecay = 98

# 4. Pass options to the Solver
solver = py_d4.Solver("formula.cnf", opt)

# 5. Serialize options to/from standard Python Dictionaries
config_dict = py_d4.dump_options_to_dict(opt)
opt_restored = py_d4.load_options_from_dict(config_dict)

# 6. Serialize options to/from raw JSON Strings (via native C++ bindings)
json_str = py_d4._py_d4.dump_options_to_json(opt)
opt_restored_json = py_d4._py_d4.load_options_from_json(json_str)

🛠️ Developers Guide

1. Requirements

Before building locally, ensure the following system-level dependencies are installed on your host:

  • C++20 compatible compiler (e.g. GCC >= 10, Clang >= 10)
  • CMake (>= 3.15)
  • GMP development headers (libgmp-dev / gmp-devel)
  • Zlib development headers (zlib1g-dev / zlib-devel)

2. Local Build Pipeline

To compile the C++ extension module and deploy it directly inside your local Python package tree, run:

# 1. Provide your GitLab access token to clone the D4 dependency
export GITLAB_TOKEN_LOGICAL="your_gitlab_token"

# 2. Configure, generate bindings, compile, and deploy shared library
./build.sh

Alternatively, you can install the package in editable mode via pip:

pip install -e .

3. Re-Generating Bindings

If D4 option headers change, you can automatically parse the new C++ classes and inline constructor descriptions to rebuild the nanobind bindings:

python3 scripts/generate_bindings.py /path/to/local/d4

(If /path/to/local/d4 is omitted, the script automatically searches the CMake FetchContent directory).

4. Running Tests

To execute the test suite and verify the integrity of the wrapper:

LD_PRELOAD=$(gcc -print-file-name=libstdc++.so.6) PYTHONPATH=. python3 tests/test_options.py

5. GitLab CI/CD Pipeline

The project includes an automated multi-stage .gitlab-ci.yml pipeline:

  • Build Stage: Uses cibuildwheel to compile optimized, standalone Linux wheels for Python 3.8 to 3.13. It automatically routes the group-level GITLAB_TOKEN_LOGICAL CI variable to authenticate both the py-d4 and internal d4/optree sub-project checkouts.
  • Deploy Stage: Triggered on pushing Git tags. Automatically publishes the generated wheel packages directly to the GitLab project PyPI package registry using twine.

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

d4solver-1.0.0.tar.gz (27.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

d4solver-1.0.0-cp313-cp313-win_amd64.whl (6.0 MB view details)

Uploaded CPython 3.13Windows x86-64

d4solver-1.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

d4solver-1.0.0-cp312-cp312-win_amd64.whl (6.0 MB view details)

Uploaded CPython 3.12Windows x86-64

d4solver-1.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

d4solver-1.0.0-cp311-cp311-win_amd64.whl (6.0 MB view details)

Uploaded CPython 3.11Windows x86-64

d4solver-1.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

d4solver-1.0.0-cp310-cp310-win_amd64.whl (6.0 MB view details)

Uploaded CPython 3.10Windows x86-64

d4solver-1.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

d4solver-1.0.0-cp39-cp39-win_amd64.whl (6.0 MB view details)

Uploaded CPython 3.9Windows x86-64

d4solver-1.0.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

File details

Details for the file d4solver-1.0.0.tar.gz.

File metadata

  • Download URL: d4solver-1.0.0.tar.gz
  • Upload date:
  • Size: 27.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for d4solver-1.0.0.tar.gz
Algorithm Hash digest
SHA256 a7e8349283035145dfc4a3ecedc90405c35cb27468307334f81d393c712416fe
MD5 ad35db2aaae623bbb6a01f949f5eaf70
BLAKE2b-256 f2c02408a8403f140e36a2ad05e132f27f5b0ccf53f112da673f5d26bd44232e

See more details on using hashes here.

File details

Details for the file d4solver-1.0.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: d4solver-1.0.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 6.0 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for d4solver-1.0.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 ac67ea2c5f8e9e87f131b8d0d9f4679eb84bfced3bad1be74fdaddbf5d05c2e2
MD5 d985390eb6c09402b669311e20718f2b
BLAKE2b-256 1ff76f3fc1b407e50dc78c67ccac44f04bf0ac742ec7596eda19f92cbd076097

See more details on using hashes here.

File details

Details for the file d4solver-1.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for d4solver-1.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a739370542a2385c33c94a58b6d54a73178e7691932aa504e2383be85158c9dd
MD5 2623a3564417bd0ae315d6efe78d69e7
BLAKE2b-256 eacef82d1e833c25c9c085e2cca7790cbfc7cd759cc664aa73ff9c30099bea2b

See more details on using hashes here.

File details

Details for the file d4solver-1.0.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: d4solver-1.0.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 6.0 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for d4solver-1.0.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 12fc3415175cb6d4f563e2b905328f14e52bbb978f293252bf9eef4dcf9a86ff
MD5 ab239aec4b7a83f2efedc83560918fc1
BLAKE2b-256 d9e16432a7f52e86e8036ea41bc42985eb39c9c46bcad8fd977c57fa74f36950

See more details on using hashes here.

File details

Details for the file d4solver-1.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for d4solver-1.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 20f2b817f9d2fd3256d52353c9a5b41f2d2754f27dc0d17af67791638b033e9b
MD5 9082b69285413b7f08e5a252e56c32c7
BLAKE2b-256 c418582ea5b35421396b208af8cabcfdca03be5bacc91167d55dff8c775cb481

See more details on using hashes here.

File details

Details for the file d4solver-1.0.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: d4solver-1.0.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 6.0 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for d4solver-1.0.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 56e11a933a715a18196e12c334dd4bf4192f61bdb62a427a697ffd1a09a15147
MD5 e2060b0c6fb63b6a041d4ca399abd539
BLAKE2b-256 682c5a6fa46097d1d45ea3ddf192a84df280bc650b5a952c93907366e749ebc1

See more details on using hashes here.

File details

Details for the file d4solver-1.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for d4solver-1.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 20337c105ed77a1d0ad905f0ff0862f4e9c98e161444d743eb8f48c54e29ef60
MD5 440f737965d703ae42bea3e457ab3c2c
BLAKE2b-256 2685765b7cf369050adea22f150bbdee8c643706a79d52593e476c567d7b2fe5

See more details on using hashes here.

File details

Details for the file d4solver-1.0.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: d4solver-1.0.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 6.0 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for d4solver-1.0.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 a301ce5666bb7492776cf078616bca51c693ad6ddc7192ebfdf03c76561452f1
MD5 a447acb90846086baa485f86a1febe0d
BLAKE2b-256 f81c3355a82853c5a4658f1a15622499ef9a8f62a374761ebf9f9db0574fc1ff

See more details on using hashes here.

File details

Details for the file d4solver-1.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for d4solver-1.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 160d110f12da7a99fa2e95746c77a560d3bce16ead017517de9ba3c29af3c85e
MD5 162035ac0a7107ec9cb22dc2d5d56750
BLAKE2b-256 89609b1585f2d48fcca7767b0245b10cca01103f164d4d3df14f3d311756af9f

See more details on using hashes here.

File details

Details for the file d4solver-1.0.0-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: d4solver-1.0.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 6.0 MB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for d4solver-1.0.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 be53ae05db839a90c0acac3c7c529ea0619ccd76f5f8677d670ab5e0f08cb71f
MD5 6ac7c0167038072dec32aad7e7841a92
BLAKE2b-256 9c5e61fa9ecc78ac6e4891e12f8ae311e117bb1eac00c7394161562cc1c73d07

See more details on using hashes here.

File details

Details for the file d4solver-1.0.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for d4solver-1.0.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 904eac7851eb072a22885526113b9a137c47dee6508accf02da331e616e42cf0
MD5 7d5fb3cc57de33cc25bd002a33385bfd
BLAKE2b-256 bbcfdffbad8211955b2acd0001001fa3ff2132d929913228d61a90da85e84fa3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page