Skip to main content

Embedded domain-specific combinator library for the abstract assembly and automated synthesis of logical circuits.

PyPI version and link. Read the Docs documentation status. GitHub Actions status. Coveralls test coverage summary.

Purpose

This embedded domain-specific language (DSL) makes it possible to write an algorithm in Python that operates on bit values and/or bit vectors, and then to interpret that algorithm implementation as a circuit definition in order to synthesize automatically a logical circuit represented using the circuit library. Additional background information and examples can be found in a relevant report.

Installation and Usage

This library is available as a package on PyPI:

python -m pip install circuitry

The library can be imported in the usual ways:

import circuitry
from circuitry import *

Examples

This library makes it possible to embed within Python a function that operates on individual bits and/or bit vectors (subject to specific limitations) and then to automatically synthesize a logical circuit that implements that function. In the simple example below, the defined bit equality function takes two bit objects as its inputs and returns one bit object as its output. Because nearly all built-in Python operators are supported by the bit class via appropriate method definitions (e.g., see the __or__ method), the statements and expressions in the function can employ a straightforward and familiar syntax:

>>> from circuitry import *
>>> @synthesize
... def equal(x: bit, y: bit) -> bit:
...     return (x & y) | ((1 - x) & (1 - y))

The function itself can be invoked in the usual manner if the supplied inputs are integers or instances of the bit class:

>>> equal(0, 1)
0
>>> b = equal(bit(0), bit(1))
>>> isinstance(b, bit)
True
>>> int(b)
0

The synthesize decorator automatically synthesizes the corresponding circuit (as an instance of the circuit class defined in the circuit library). The synthesized circuit object is stored within an attribute of the function itself and can be evaluated on two bit values (as specified by the function’s type annotation). See the documentation of the circuit library for more information on how input bit vectors should be structured when evaluating a circuit:

>>> equal.circuit.evaluate([[0], [1]])
[[0]]

The synthesize decorator can also be applied to functions that are defined explicitly as operating on bit vectors (where bit vectors can be represented as lists of integers or as bits objects). Furthermore, functions can be invoked in other functions, making it possible to reuse modular algorithm components. In the example below, the bit vector equality function invokes the bit equality function defined above:

>>> @synthesize
... def equals(xs: bits(8), ys: bits(8)) -> bit:
...     z = 1
...     for i in range(8):
...         z = z & equal(xs[i], ys[i])
...     return z
>>> bs = [0, 1, 1, 0, 1, 0, 1, 0]
>>> equals.circuit.evaluate([bs, bs])
[[1]]
>>> equals.circuit.count() # Number of gates in circuit.
66

Because a circuit is synthesized via standard execution of a decorated Python function, all native Python language features (and even external libraries) can be employed. The most important constraint (which is the responsibility of the programmer to maintain) is that the execution of the function (i.e., the flow of control) should not depend on the values of the inputs bits. The alternative implementation below demonstrates that recursion and higher-order functions can be used within decorated functions:

>>> from functools import reduce
>>> @synthesize
... def equals(xs: bits(8), ys: bits(8)) -> bit:
...     es = [equal(x, y) for (x, y) in zip(xs, ys)]
...     return reduce((lambda e0, e1: e0 & e1), es)
>>> bs = [0, 1, 1, 0, 1, 0, 1, 0]
>>> equals.circuit.evaluate([bs, list(reversed(bs))])
[[0]]
>>> equals.circuit.count() # Number of gates in circuit.
64

A more complex example involving an implementation of SHA-265 that conforms to the FIPS 180-4 specification is found in the testing script that accompanies this library. The SHA-256 example is also described in a relevant report.

Development

All installation and development dependencies are fully specified in pyproject.toml. The project.optional-dependencies object is used to specify optional requirements for various development tasks. This makes it possible to specify additional options (such as docs, lint, and so on) when performing installation using pip:

python -m pip install .[docs,lint]

Documentation

The documentation can be generated automatically from the source files using Sphinx:

python -m pip install .[docs]
cd docs
sphinx-apidoc -f -E --templatedir=_templates -o _source .. && make html

Testing and Conventions

All unit tests are executed and their coverage is measured when using pytest (see the pyproject.toml file for configuration details):

python -m pip install .[test]
python -m pytest

The subset of the unit tests included in the module itself and the documentation examples that appear in the testing script can be executed separately using doctest:

python src/circuitry/circuitry.py -v
python test/test_circuitry.py -v

Style conventions are enforced using Pylint:

python -m pip install .[lint]
python -m pylint src/circuitry test/test_circuitry.py

Contributions

In order to contribute to the source code, open an issue or submit a pull request on the GitHub page for this library.

Versioning

Beginning with version 0.1.0, the version number format for this library and the changes to the library associated with version number increments conform with Semantic Versioning 2.0.0.

Publishing

This library can be published as a package on PyPI by a package maintainer. First, install the dependencies required for packaging and publishing:

python -m pip install .[publish]

Ensure that the correct version number appears in pyproject.toml, and that any links in this README document to the Read the Docs documentation of this package (or its dependencies) have appropriate version numbers. Also ensure that the Read the Docs project for this library has an automation rule that activates and sets as the default all tagged versions. Create and push a tag for this version (replacing ?.?.? with the version number):

git tag ?.?.?
git push origin ?.?.?

Remove any old build/distribution files and package the source into a distribution archive:

rm -rf build dist src/*.egg-info
python -m build --sdist --wheel .

Finally, upload the package distribution archive to PyPI using the twine package:

python -m twine upload dist/*

Metadata

Release files for circuitry 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for circuitry 2.0.0
File Size Uploaded Provenance Actions
circuitry-2.0.0.tar.gz 22.0 kB Without provenance Details for circuitry-2.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for circuitry 2.0.0
File Interpreter ABI Platform Actions
circuitry-2.0.0-py3-none-any.whl Python 3 none any Details for circuitry-2.0.0-py3-none-any.whl

Total release size: 37.2 kB

Release files / circuitry-2.0.0.tar.gz

Download URL circuitry-2.0.0.tar.gz
Size 22.0 kB
Tags Source
SHA-256 checksum
How to use checksums
7d8e02b916ad9a49adf2d622a4f5b122d99ec6a6b81964bbb8e52044682be1f5
BLAKE2b-256 checksum
How to use checksums
11c75ecada48be5eb0b0ef3a32b8409bd0372a8470bcec66dbc2d160a720a2df
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.10.2

Release files / circuitry-2.0.0-py3-none-any.whl

Download URL circuitry-2.0.0-py3-none-any.whl
Size 15.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0216a2833c2386e033608628bca6ecc2231f6b69a3918ef215362561fe0fdb6e
BLAKE2b-256 checksum
How to use checksums
81dd6ed5a56bfce75915e624bd3ca8cc0736520d3dd94c4ac35c5ff4762b6049
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.10.2

Security for circuitry 2.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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