Metadata-Version: 2.4
Name: qcoherence
Version: 1.0.0
Summary: A native pytest plugin for testing and verifying quantum circuits - Qiskit, Cirq, PennyLane (via OpenQASM), simulators and real hardware.
Author-email: Peruri Bhuvan Satwik <bhu1satwik@gmail.com>, Bala Chandu <kotabalachandu23@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/bhu1satwik/qcoherence
Keywords: quantum,qiskit,cirq,pennylane,pytest,testing,verification,openqasm
Classifier: Framework :: Pytest
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pytest>=7.0
Requires-Dist: qiskit>=1.0
Requires-Dist: qiskit-aer>=0.14
Requires-Dist: qiskit-qasm3-import>=0.4
Requires-Dist: numpy>=1.24
Requires-Dist: scipy>=1.10
Provides-Extra: cirq
Requires-Dist: cirq-core>=1.3; extra == "cirq"
Provides-Extra: pennylane
Requires-Dist: pennylane>=0.35; extra == "pennylane"
Provides-Extra: hardware
Requires-Dist: qiskit-ibm-runtime>=0.20; extra == "hardware"
Provides-Extra: all
Requires-Dist: cirq-core>=1.3; extra == "all"
Requires-Dist: pennylane>=0.35; extra == "all"
Requires-Dist: qiskit-ibm-runtime>=0.20; extra == "all"
Dynamic: license-file

# qcoherence

A native **pytest plugin** for testing and verifying quantum circuits — across **Qiskit, Cirq, and PennyLane** (via OpenQASM), on **simulators and real IBM Quantum hardware**.

## Why this exists

Only **31% of quantum developers use any quantum-specific testing tooling** — most still debug with print statements and circuit visualizations, because observing a quantum state collapses it, so classical debugging habits don't transfer. Several academic tools have tried to close this gap (Muskit, QuCAT, Quito, MorphQ, QuCheck, QUTest), but each requires writing tests as custom classes inheriting from a project-specific runner, each is tied to Qiskit only, and none validates against real hardware.

`qcoherence` is different on all three counts:

1. **Native pytest.** Install it, write `def test_x():`, run `pytest`. No base class, no custom runner.
2. **Cross-framework.** Accepts Qiskit `QuantumCircuit`s, OpenQASM 2/3 strings/files, Cirq circuits, and PennyLane circuits (via QASM export).
3. **Real hardware, opt-in.** Re-run your golden tests on actual IBM Quantum devices with `--qc-hardware`, with noise-realistic tolerances.

## Install

```bash
pip install qcoherence            # core (Qiskit + Aer)
pip install qcoherence[cirq]      # + Cirq ingestion
pip install qcoherence[pennylane] # + PennyLane examples
pip install qcoherence[hardware]  # + IBM Quantum real-device validation
pip install qcoherence[all]       # everything
```

## Quickstart

```python
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qcoherence import assert_state_equal, assert_entangled, run_statevector

def bell_circuit():
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    return qc

def test_bell_state():
    expected = Statevector(np.array([1, 0, 0, 1]) / np.sqrt(2))
    actual = run_statevector(bell_circuit())
    assert_state_equal(actual, expected)
    assert_entangled(actual, qubits=[0])
```

Run it like any other test suite: `pytest`.

### From Cirq or PennyLane

```python
from qcoherence import to_qiskit, run_statevector

# Cirq: pass the circuit object directly
qc = to_qiskit(my_cirq_circuit)

# PennyLane: export to OpenQASM, pass the string
qasm = qml.workflow.construct_tape(my_qnode)().to_openqasm(measure_all=False)
qc = to_qiskit(qasm)
```

## What's proven, not just claimed

`tests/test_bug_demo.py` demonstrates the core value proposition: a Bell-state
circuit missing its entangling gate is a bug that looks completely fine under
naive inspection (it's a valid, normalized quantum state) but is caught
immediately by `assert_entangled` and `assert_state_equal`:

```bash
pytest tests/test_bug_demo.py -v
```

## Assertion API

| Function | Checks |
|---|---|
| `assert_state_equal(actual, expected, tol=1e-6)` | State fidelity ≈ 1 (equal up to global phase) |
| `assert_distribution_close(counts, probs, tol=0.05)` | Total variation distance, simple tolerance |
| `assert_distribution_fits(counts, probs, alpha=0.01)` | Chi-square goodness-of-fit with a real p-value |
| `assert_entangled(state, qubits)` | Reduced-state purity < 1 |
| `assert_separable(state, qubits)` | Reduced-state purity ≈ 1 |
| `holm_bonferroni(pvalues, alpha)` | Family-wise error control across a suite of statistical tests |

## pytest integration

- `pytest -m quantum_test` — run only qcoherence-marked tests.
- `pytest --qc-hardware` — also run `@pytest.mark.hardware` tests on real IBM Quantum devices (requires a free IBM Quantum account; skipped by default so CI stays green).
- `--qc-shots N` / `--qc-seed N` — shot count and reproducibility seed.

## Real-hardware validation

```python
import pytest
from qcoherence.hardware import run_counts_on_hardware, assert_hardware_distribution_close

@pytest.mark.hardware
def test_bell_on_real_device():
    counts = run_counts_on_hardware(bell_circuit(), shots=4096)
    assert_hardware_distribution_close(counts, {"00": 0.5, "11": 0.5})  # tol=0.15, NISQ-realistic
```

## Extending qcoherence

Register custom assertions/backends programmatically or from a separate pip
package via entry points — see `qcoherence/registry.py`:

```python
from qcoherence.registry import register_assertion

@register_assertion("assert_w_state_like")
def assert_w_state_like(state, *, tol=1e-6):
    ...
```

```toml
# in another package's pyproject.toml
[project.entry-points."qcoherence.assertions"]
assert_my_thing = "mypkg.assertions:assert_my_thing"
```

## Golden benchmarks

`tests/golden/` contains verified reference circuits used as both examples
and a regression suite: **Bell state**, **GHZ state** (3-qubit entanglement),
and a **VQE ground-state search** checked against exact `numpy`
diagonalization computed in-test.

## Prior art

This project builds on ideas published in the quantum software testing
research literature, particularly Muskit (mutation testing), QuCAT
(combinatorial testing), Quito (coverage-guided generation), MorphQ
(metamorphic testing), QuCheck (property-based testing and the statistical
multiple-testing insight), and QUTest (native assertion testing). Its
contribution is a native pytest integration layer with cross-framework
ingestion and opt-in hardware validation, not a new testing paradigm.

## License

MIT
