Skip to main content

A lattice polynomial is a term built from variables and constants using only the lattice operations meet and join. Over a bounded distributive lattice \((K, \vee, \wedge, \bot, \top)\) every such term has a normal form, and the functions they denote are exactly the monotone functions generated by the lattice operations. pollywog represents these functions canonically as multi-terminal binary decision diagrams (MTBDDs), so equal polynomials are equal objects, and provides the operations you would expect on them: meet, join, dual (on De Morgan algebras), and substitution.

The diagrams are CUDD ADDs, so the variable order can be reordered dynamically or imposed by hand. There is a C++ core with Python bindings on top of it.

Lattices

Leaves are double. A lattice is a small trait supplying bottom, top, meet, and join; a De Morgan algebra adds dual. Two are built in:

  • MaxMinExtendedReal - the extended reals with \(\wedge = \min\), \(\vee = \max\), \(\bot = -\infty\), \(\top = +\infty\), and \(\neg a = -a\).

  • MaxMinUnitInterval - the unit interval \([0, 1]\) with \(\wedge = \min\), \(\vee = \max\), \(\bot = 0\), \(\top = 1\), and the fuzzy negation \(\neg a = 1 - a\), giving a Kleene algebra.

Each lattice carries its polynomial type as a nested Polynomial class.

Example

>>> from pollywog import Context, Var, MaxMinExtendedReal
>>> ctx = Context[str]()
>>> K = ctx.over(MaxMinExtendedReal)
>>> x, y = K.var("x"), K.var("y")
>>> # (x AND y) OR 3.0
>>> f = x.meet(y).join(K.terminal(3.0))
>>> ctx.support(f) == {"x", "y"}
True
>>> bottom = K.lattice.bottom()
>>> f.let({Var(0): bottom, Var(1): bottom}).leaf_value()
3.0

Context maps arbitrary hashables to the integer indices CUDD keys its tables on, so you can name variables with states, atomic predicates or formula subterms. Substitution is keyed by Var, not by the bare index.

ctx.over fixes the lattice and the manager, which are constant across any stretch of code working in one lattice, so the constructors take only what varies. The context underneath stays lattice-agnostic: views over different lattices share its variable naming, so their polynomials share a support and a variable order.

Also in the Box

  • Manager - owns the unique table, operation cache and variable order. There is no global runtime to start; construct one and build diagrams from it.

  • BooleanFunction - BDDs, for the ordinary Boolean reasoning the polynomials omit: complementation, quantifiers, cube and prime-implicant enumeration.

  • AlgebraicFunction - ADDs under CUDD’s own arithmetic, with conversions to and from BDDs.

Why not dd?

If what you want is BDDs in Python, use dd. It wraps CUDD, Sylvan and BuDDy, it has ZDDs, an expression parser and quantifiers, and it has a pure-Python backend that installs anywhere. pollywog is not trying to replace it.

The difference is at the leaves. A dd function is Boolean-valued, \(f : \mathbb{B}^n \to \mathbb{B}\), and its API is the Boolean connectives. A pollywog polynomial is lattice-valued, \(f : K^n \to K\), and its API is the lattice: meet, join, dual, substitution. CUDD has ADDs underneath, but dd does not expose them, so there is no multi-terminal diagram in it to build this on.

A finite lattice can of course be encoded as a family of Boolean functions, one BDD per cut \(\{ \mathbf{a} : f(\mathbf{a}) \ge c \}\). What that costs:

  • One object instead of \(k\). Equality, hashing, node counts and substitution apply to the function itself, and sharing between the cuts is CUDD’s problem rather than yours.

  • Real leaves. MaxMinExtendedReal has continuum-many values and no finite family of cuts.

  • The normal form. A node is read as \(f = f_\bot \vee (x \wedge f_\top)\) under the invariant \(f_\bot \le f_\top\), so there is no complement anywhere and substitution is one meet and one join per node. Encoded into Shannon-expanded BDDs, monotonicity is an invariant you maintain by hand.

The Boolean side is still there when you want it: BooleanFunction lives in the same manager and the same variable order as the polynomials, so a skeleton and the polynomial over it share nodes instead of crossing a library boundary.

So: Boolean functions, dd. Functions valued in a lattice — fuzzy truth values, min-max robustness, weights ordered by \(\le\)pollywog.

Building

The project builds with scikit-build-core and nanobind. With pixi:

pixi install
pixi run python -c "import pollywog"

C++ tests:

ctest --test-dir build

Documentation (needs Doxygen and Sphinx, both in the docs dependency group):

cmake --build build --target docs

The rendered output lands in build/docs/html.

Documentation

docs/ is split by audience. The concept pages — the representation and its normalization invariant, variables and ordering, managers and lifetimes — carry the long-form prose. docs/api/ documents the end-user surface of each language binding, deliberately selectively.

Internals are documented in the source rather than in the manual, so read the headers for the custom CUDD operators and the reference-counting.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

pollywog-0.1.1-cp312-abi3-musllinux_1_2_x86_64.whl (976.9 kB view details)

Uploaded CPython 3.12+musllinux: musl 1.2+ x86-64

pollywog-0.1.1-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (496.7 kB view details)

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

File details

Details for the file pollywog-0.1.1-cp312-abi3-musllinux_1_2_x86_64.whl.

File metadata

  • Download URL: pollywog-0.1.1-cp312-abi3-musllinux_1_2_x86_64.whl
  • Upload date:
  • Size: 976.9 kB
  • Tags: CPython 3.12+, musllinux: musl 1.2+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"42","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pollywog-0.1.1-cp312-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 f858d538a0a05c638805f5507a5fbffb1b920f728a2ce002ba2d2e8bacf15b23
MD5 ef16537c2607d34a320ddc5589be5394
BLAKE2b-256 e97102e2cbacbc72357acdadc046370764cee9b6a7b7992e605315752616ac82

See more details on using hashes here.

File details

Details for the file pollywog-0.1.1-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

  • Download URL: pollywog-0.1.1-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 496.7 kB
  • Tags: CPython 3.12+, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"42","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pollywog-0.1.1-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 766b7ce87c87e49e6c886e67638da3959f72f2c9ff9a833882c74ea716d1d3d2
MD5 d80c839887df482aedd52d9a8562271b
BLAKE2b-256 a9adb4b0c7ffc2a5367d3ca162ca9de7fd7c15415af72de952ac59b7338a47d7

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page