Contributing to quchip

Contributions from scientists and developers are welcome. Bug reports, physics discrepancies, documentation corrections, and code changes are all useful. Open a GitHub Issue for a concrete problem or model request. Use GitHub Discussions for open-ended questions.

Development setup

quchip requires Python 3.11 or newer.

git clone https://github.com/Quchip/quchip.git
cd quchip
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e '.[dev,test,dynamiqs]'

QuTiP is the default backend. The dynamiqs extra enables JAX-native solver, gradient, and batching tests.

Tests

The test gate is one command:

python -m pytest

The suite can also be run by lane:

python -m pytest -m core
python -m pytest -m physics_sentinel
python -m pytest -m extended
  • core covers analytical behavior and public API contracts.

  • physics_sentinel checks simulation-backed physics invariants.

  • extended contains slower and long-tail coverage.

Tests that require dynamiqs carry the optional_backend marker and call pytest.importorskip("dynamiqs"). The marker labels the test. The import guard makes it skip cleanly when dynamiqs is absent.

Run the following checks before opening a pull request:

python -m pytest
ruff check .
python -m mypy quchip

Ruff uses a 120-character line limit. Public API docstrings use NumPy-style sections and imperative summaries ending with periods. Every test has a one-line docstring stating the invariant under test. Declarative device classes’ if TYPE_CHECKING: __init__ stubs are generated by tools/gen_device_stubs.py and checked for freshness by the test suite.

Physics conventions

Read PHYSICS.md before changing Hamiltonians, frames, approximations, observables, dissipation, or solver assembly.

  • Use ordinary GHz for frequencies and energies, ns for time, and mK for temperature.

  • Keep the single Hamiltonian-assembly conversion in quchip/engine/stage2_assembly.py.

  • Keep traced paths compatible with JAX. Do not call float(), int(), or bool() on traced values or branch on them with Python. Use jax.numpy and JAX control flow.

  • State approximations, omitted terms, and validity regimes through the model’s declared approximation and physics_notes().

  • Derive physics-test tolerances from an analytic limit, truncation error, solver convergence, an independent calculation, or a cited reference. State the basis next to the assertion. Never tune a tolerance only to make a test pass.

Pull requests

Keep pull requests small and focused. Explain the physical or user-visible change, include tests for changed behavior, and update the relevant documentation.

Open an issue before starting a large change. Do the same for a new device, coupling, drive, envelope, or noise model. Include the model Hamiltonian, assumptions, intended use, and a reference when available. Maintainers use these requests to prioritize models with broad demand and will discuss the right scope with you.

Policies

  • There is no CLA or DCO. By opening a pull request you agree that your contribution is provided under the project’s license.

  • If AI assistance was used, disclose it in the pull request description. The contributor remains accountable for every claim and change.

  • Be respectful and constructive in issues, discussions, and reviews. The full covenant is inscribed in CODE_OF_CONDUCT.md.