Source code for psipose.ansatze.base

"""Base ansatz class for parameterized quantum circuits.

An ansatz (German for "approach" or "guess") is a parameterized quantum
circuit whose parameters are optimized during training. In variational
quantum algorithms (VQAs), the ansatz serves as the learnable component
that processes encoded data.

The choice of ansatz architecture involves trade-offs:
- Expressibility: ability to approximate arbitrary quantum states
- Trainability: avoiding barren plateaus in the optimization landscape
- Hardware efficiency: compatibility with quantum device connectivity

See Cerezo et al. (2021), "Variational Quantum Algorithms" (arXiv:2012.12265)
for a comprehensive review of ansatz design considerations.
"""

import abc

import numpy as np


[docs] class BaseAnsatz(abc.ABC): """Abstract base class for quantum ansatze. An ansatz is a parameterized quantum circuit that can be trained by adjusting its parameters (weights). In variational quantum algorithms, the ansatz works in concert with a feature map to learn from data. Subclasses must implement :meth:`circuit` and :meth:`weight_shape`. Parameters ---------- n_qubits : int Number of qubits in the circuit. Attributes ---------- n_qubits : int Number of qubits. n_params : int, optional Total number of parameters (set by subclasses if applicable). """ def __init__(self, n_qubits): self.n_qubits = n_qubits self.n_params = None
[docs] @abc.abstractmethod def circuit(self, weights, wires): """Build the parameterized quantum circuit. Parameters ---------- weights : array-like Trainable parameters for the ansatz. Shape depends on the ansatz. wires : Iterable[int] Qubit wires to apply the circuit to. """ pass
[docs] def weight_shape(self, n_qubits): """Return the shape of the weight array needed. Parameters ---------- n_qubits : int Number of qubits. Returns ------- tuple[int, ...] or int Shape of the weight array. Can be a single integer (total params) or a tuple (e.g., (n_layers, n_qubits, 3) for layered ansatze). """ raise NotImplementedError("Subclasses must implement weight_shape")
[docs] def initialize_weights(self, seed=None): """Initialize random weights. Parameters ---------- seed : int, optional Random seed for reproducibility. Returns ------- ndarray Randomly initialized weights with the correct shape. """ rng = np.random.default_rng(seed) shape = self.weight_shape(self.n_qubits) return rng.uniform(0, 2 * np.pi, shape)