PennyLane Backend#

Context and Purpose#

The PennyLane backend serves as the canonical bridge between the QuantumBackend abstraction and a real quantum circuit execution layer. It was created to ensure interchangeability across backends while remaining minimal, deterministic, and easy to extend. Unlike traditional wrappers, this adapter enforces a strict one-to-one correspondence between logical outputs and quantum wires, keeping the model mathematically traceable and compatible with symbolic analyses within qmlhc.

By default, the backend initializes the PennyLane device default.mixed to enable lightweight realistic noise. Use default.qubit for ideal simulation or lightning.qubit for faster pure-state execution.

Conceptual Foundations#

  1. Deterministic state projection: Each forward evaluation represents a direct expectation mapping (deterministic when executed in analytic mode, i.e., shots=None), rather than probabilistic post-processing. This allows reproducible gradients and deterministic learning behavior in analytic mode.

  2. Linear entanglement philosophy: The internal circuit uses a nearest-neighbor entanglement pattern to maintain predictable causal flow and bounded circuit depth, which scales linearly with the qubit count.

  3. Output–wire equivalence: The enforced equality between output_dim and num_qubits is not a constraint by accident—it guarantees stable dimensional alignment for tensorized downstream processing and symbolic contraction across different backends.

  4. Future state projection model: project_future() acts as a temporal continuity operator, designed for smooth evolution of latent quantum states. The hyperbolic tangent ensures bounded propagation when generating prospective branches.

Note

Interaction with Non-Stationary Loops

In non-stationary experiments, PennyLaneBackend remains analytic and deterministic (shots=None). Environment drift is applied to the model input before calling forward(...). The backend then recomputes exact expectation values under the new conditions, while the hypercausal controller (e.g., a dynamic feedback gain alpha) adapts based on coherence and consistency losses. This design preserves stable gradients and deterministic learning behavior, yet allows the overall QML-HCS system to react to non-stationary environments.

Integration Guidelines#

  • Use this backend when deterministic expectation vectors are required (e.g., during gradient computation or cross-backend comparisons).

  • Avoid substituting it for high-depth or hardware-specific circuits; it prioritizes stability over expressiveness.

  • Configuration inheritance from BackendConfig allows uniform behavior with other backends (e.g., shot handling, analytic vs sampled execution).

  • All internal validation routines come from QuantumBackend, ensuring consistent error handling and output verification.

Note

Compatibility Note (PennyLane ≥ 0.39) This backend uses the modern API qml.set_shots(...) for shot configuration. Earlier releases (< 0.37) used qml.transforms.set_shots(...), which has been deprecated and removed in current versions.

Installation#

PennyLane is included as an optional dependency of qml-hcs. If you prefer to install it manually, run:

pip install pennylane

Ensure Python ≥ 3.9 and that your environment includes the required pennylane and numpy packages.

Performance & Scaling Notes#

  • Circuit depth grows as \(O(N)\) with the number of qubits.

  • Memory footprint remains constant since expectation results are collapsed to a single vector rather than a full density matrix.

  • When executed with shots=None, the backend operates in analytic mode, bypassing stochastic noise and returning exact expectation values.

Noise model#

When a mixed-state device (e.g., default.mixed) is selected, the internal circuit includes lightweight per-wire noise channels to simulate realistic conditions:

  • DepolarizingChannel (p = 0.0012)

  • PhaseDamping (γ = 0.0020, T2)

  • AmplitudeDamping (γ = 0.0012, T1)

These defaults keep examples realistic while maintaining a compact, low-depth circuit.

Extension Pathways#

Developers can subclass PennyLaneBackend to prototype alternate ansätze, noise models, or topology variants. A typical extension might redefine the circuit body or override capabilities() to advertise custom device features. Subclasses should always preserve the validation flow defined by _validate_state() and _validate_branches().

Interoperability & Testing#

The backend has been validated against multiple PennyLane devices, including analytic simulators (default.qubit) and mixed-state variants (default.mixed). Consistency tests confirm that returned vectors stay within the expected Pauli-Z range \([-1, 1]\). Orthogonality properties depend on the specific encoding and dataset and should be validated per application.

Design Guarantees#

  • Deterministic mapping between encoded vector and observable output

  • Predictable gradient availability via the parameter-shift rule

  • Full compatibility with batch and analytic execution modes

  • Stable projection dynamics via smooth nonlinear propagation

API Reference overview#

PennyLane Backend Adapter#

Adapter for PennyLane-based quantum execution backends that conforms to the QuantumBackend contract.

This wrapper creates a PennyLane device, defines a lightweight variational circuit (RY rotations + nearest-neighbor CNOT entanglement), and exposes run and project_future in the expected interface. The circuit returns per-wire expectation values of Pauli-Z, yielding a vector S_t with dimension equal to the number of qubits (and therefore to output_dim).

Examples

>>> import numpy as np
>>> from qmlhc.core.backend import BackendConfig
>>> from qmlhc.backends.pennylane_backend import PennyLaneBackend
>>> cfg = BackendConfig(output_dim=4, shots=None)
>>> be = PennyLaneBackend(cfg, num_qubits=4, device_name="default.qubit")
>>> be.encode(np.array([0.1, 0.2, 0.3, 0.4]))
>>> s_t = be.run()
>>> fut = be.project_future(s_t, branches=5)
>>> X = np.stack([np.zeros(4), np.ones(4)*0.1], axis=0)      # Example: batch execution
>>> be.run_batch(X).shape  # (B, D)
(2, 4)
>>> caps = be.capabilities()                          # Check device and backend capabilities (values depend on your device/config)
>>> caps["using_shots"], caps["supports_noise"]
(False, False)
class qmlhc.backends.pennylane_backend.PennyLaneBackend(config, num_qubits, device_name='default.mixed', shots=None, supports_noise=None)[source]#

Bases: QuantumBackend

Wrap a PennyLane device and variational circuit into the QuantumBackend API.

Parameters:
  • config (BackendConfig) – Backend configuration (e.g., output_dim, shots).

  • num_qubits (int) – Number of qubits / wires. Must equal config.output_dim.

  • device_name (str, optional) – PennyLane device name, by default "default.qubit".

  • shots (int or None, optional) – Number of device shots (None for analytic mode). If None, falls back to config.shots.

  • supports_noise (bool or None, optional) – Manual override for noise support in capabilities(). If None (default), a heuristic is used based on the device; if True/False the reported capability is forced accordingly.

Raises:

ValueError – If output_dim does not match num_qubits.

Notes

API usage in brief (details in the RST): - Call encode(x) with shape (D,) before run. - D must match num_qubits and config.output_dim. - Analytic mode is deterministic (shots=None); sampling mode (shots>0) introduces variance. - run_batch(X) expects shape (B, D) and returns (B, D). - supports_noise (init arg) lets you override noise reporting in capabilities().

capabilities()[source]#

Report merged capabilities (base + PennyLane device).

Returns:

Capability dictionary including device version, qubit count, shot/noise support, batching, and gradient method.

Return type:

Capabilities

Notes

  • max_qubits: number of qubits configured for this instance.

  • supports_shots: device family accepts finite shots (capability).

  • using_shots: this instance currently samples (shots is not None).

  • supports_noise: noise support (override takes precedence).

  • supports_batch: batch API is available via run_batch.

project_future(s_t, branches=2)[source]#

Generate future projections around s_t using smooth additive deltas followed by tanh for numeric stability.

Parameters:
  • s_t (np.ndarray) – Current state vector.

  • branches (int, optional) – Number of future branches (K), by default 2.

Returns:

Future states matrix of shape (K, D).

Return type:

Array

Note

This is a device-agnostic, low-cost projection utility. It does not change circuit parameters nor implement physical time evolution.

run(params=None)[source]#

Execute the PennyLane circuit on the last encoded input.

Parameters:

params (dict or None, optional) – Unused in this minimal adapter; reserved for future extensions.

Note

encode(x) must be called beforehand. The base class enforces this via _require_input() and raises if the input is missing.

Returns:

Validated state vector S_t of shape (D,).

Return type:

Array

run_batch(X)[source]#

Execute a batch of inputs with shape (B, D) and return a matrix of shape (B, D). Requires D == num_qubits. Validation of the batch result is delegated to the base class.

Note

The batch must contain at least one row; empty batches are not supported.

Return type:

ndarray

See Also#

External and Internal Dependencies#

Third-Party Libraries

pennylane This backend is built on top of PennyLane, which provides the quantum device layer and the main tools for creating and running parametrized circuits and QNodes. See the official documentation or source repository for implementation details.

numpy NumPy is used throughout the backend for numerical operations and array management, including utilities such as asarray, tanh, linspace, and stack. Refer to the NumPy documentation or repository to explore its numerical capabilities and integration with this backend.

Python Standard Library

__future__ Used to enable forward-compatible annotations (from __future__ import annotations).

typing Provides standard type hints such as typing.Any, typing.Mapping, and typing.Optional.

QML-HCS Internal Modules

qmlhc.core.backend Implements the shared backend contract through qmlhc.core.backend.QuantumBackend and qmlhc.core.backend.BackendConfig, which this adapter extends.

qmlhc.core.types Defines internal data structures like qmlhc.core.types.Array, qmlhc.core.types.Capabilities, and qmlhc.core.types.GradientKind.

Together, these components make the PennyLane backend modular, reproducible, and consistent, combining the analytical precision of PennyLane and NumPy with the architectural stability of the QML-HCS core system.