qlass.utils package
The utils module provides utility functions for executing quantum algorithms, processing measurement results, and computing loss functions for VQE optimization.
Key Features
Loss Functions
loss_function: Standard loss function for sampling-based VQEloss_function_matrix: Loss function for qubit unitary-based VQEloss_function_photonic_unitary: Loss function for photonic unitaries with post-selectionloss_function_bose_hubbard: Sampling-based loss function for Bose-Hubbard Hamiltonianse_vqe_loss_function: Ensemble-VQE loss function supporting multiple states
Utilities
linear_circuit_to_unitary: Converts Perceval linear circuits to unitary matricesrotate_modes: Appends a 50/50 beam splitter for hopping-term measurementsdraw_circuit: Draws or saves Perceval circuits and processors using Perceval renderingDataCollector: Collects and stores energy data during ensemble-VQE optimizationloss_data: List of cost function valuesenergy_data: List of energy values for each state
Submodules
- qlass.utils.compute_energy(pauli_bin: tuple[int, ...], res: dict[tuple[int, ...], float]) float[source]
Compute the expectation value for a given Pauli string and measurement results.
- Parameters:
pauli_bin (Tuple[int, ...]) – A tuple of 0’s and 1’s (0’s are identities, 1’s are non-identities (X or Z))
res (Dict[Tuple[int, ...], float]) – Frequencies of measured qubit bitstrings
- Returns:
The corresponding expectation value
- Return type:
float
- qlass.utils.compute_expectation_value_from_unitary(unitary: ndarray, pauli_matrix: ndarray, initial_state: ndarray | None = None) float[source]
Compute expectation value <ψ|H|ψ> where |ψ> = U|0>.
- Parameters:
unitary (np.ndarray) – Unitary matrix representing the circuit
pauli_matrix (np.ndarray) – Matrix representation of Pauli operator
initial_state (np.ndarray) – Initial state vector (default: |0…0>)
- Returns:
Expectation value
- Return type:
float
- qlass.utils.draw_circuit(circuit_or_processor: Processor | Circuit, output_format: str = 'mpl', skin: str = 'phys', compact: bool = False, save_path: str | None = None, backend: str = 'perceval', **kwargs: Any) None[source]
Draw a linear optical circuit or processor.
- Parameters:
circuit_or_processor (Union[pcvl.Processor, pcvl.Circuit]) – Perceval processor or linear optical circuit to draw.
output_format (str) – Output format. One of
"mpl","html","latex", or"text".skin (str) – Perceval skin to use. One of
"phys","symb", or"debug".compact (bool) – Whether to use compact circuit display.
save_path (Optional[str]) – If provided, save the rendering to this path instead of displaying it interactively.
backend (str) – Drawing backend. Currently only
"perceval"is supported.**kwargs (Any) – Additional keyword arguments forwarded to Perceval’s display function.
- Raises:
NotImplementedError – If
backendis not"perceval".TypeError – If
circuit_or_processoris not a PercevalProcessororCircuit.ValueError – If
output_formatorskinis invalid.
- qlass.utils.e_vqe_loss_function(lp: ndarray, H: dict[str, float], executor: Any, energy_collector: DataCollector, weight_option: str = 'weighted', mitigator: Any | None = None) float[source]
Compute the loss function for the ensemble Variational Quantum Eigensolver (VQE).
Each Pauli term is measured with its own executor call, which returns one sampling result per ensemble state.
The function works with executors that return, per ensemble state, either: 1. Fock states (from linear optical circuits) - exqalibur.FockState objects 2. Bitstring tuples (from regular qubit-based circuits) 3. Bitstring strings (from Qiskit Sampler)
The executor should return a list with one entry per ensemble state, each in one of these formats: - Dict with ‘results’ key: {‘results’: [samples]} - Direct list of samples: [samples] - Qiskit-style format with bitstrings or counts
- Parameters:
lp (np.ndarray) – Array of variational circuit parameters. Typically optimized to minimize the expectation value of the Hamiltonian.
H (dict of {str: float}) – Hamiltonian represented as a dictionary mapping Pauli strings (e.g.,
'XZ','IZ') to their coefficients.executor (callable) – Function or callable object that executes the quantum circuit and returns measurement samples. Must accept arguments
(lp, pauli_string)and return a list of sampling results, one per ensemble state.energy_collector (DataCollector) – Object responsible for tracking or logging the energy convergence history. Must implement a method
energies_convergence(energies, n_ensembles, total_loss).weight_option ({'weighted', 'equi', 'ground_state_only'}) – Scheme for assigning ensemble weights: -
'weighted'(default): Linearly decreasing weights with index, i.e., w_i < w_j for i > j. -'equi': Equal weights for all occupied orbitals, w_i = w_j. -'ground_state_only': Only the ground state contributes, w_0 = 1, others 0.mitigator (object, optional) – Mitigator object (e.g., M3Mitigator) applied to each ensemble state’s measured counts, as in
loss_function.
- Returns:
loss – The computed ensemble VQE loss value, equal to the weighted sum of ensemble energies.
- Return type:
float
- qlass.utils.get_probabilities(samples: list[FockState | tuple[int, ...] | str]) dict[FockState | tuple[int, ...], float][source]
Get the probabilities of sampled states.
This function now handles: - Fock states: List[exqalibur.FockState] -> Dict[exqalibur.FockState, float] - Bitstring tuples: List[Tuple[int, …]] -> Dict[Tuple[int, …], float] - Bitstring strings (from Qiskit): List[str] -> Dict[Tuple[int, …], float]
- Parameters:
samples (List[Union[exqalibur.FockState, Tuple[int, ...], str]]) – Sampled states (Fock states, bitstring tuples, or bitstring strings)
- Returns:
Probabilities of sampled states
- Return type:
Dict[Union[exqalibur.FockState, Tuple[int, …]], float]
- qlass.utils.is_qubit_state(state: FockState) tuple[int, ...] | None[source]
Check if a given Fock state is a valid dual-rail qubit state.
- Parameters:
state (exqalibur.FockState) – The Fock state to check
- Returns:
The corresponding qubit state if valid, None otherwise
- Return type:
Optional[Tuple[int, …]]
- qlass.utils.linear_circuit_to_unitary(circuit: Circuit) ndarray[source]
Convert a linear optical circuit to a unitary matrix.
- Parameters:
circuit (pcvl.Circuit) – Linear optical circuit
- Returns:
Unitary matrix representation of the circuit
- Return type:
np.ndarray
- qlass.utils.logical_state_to_modes(logical_state: int, m: int, mode_map: list[int] | None = None) list[int][source]
Convert a logical qubit state to the set of occupied photon modes.
Parameters:
- logical_stateint
Integer representing the logical state (0 to 2^m - 1)
- mint
Number of qubits
- mode_mapOptional[List[int]]
Physical mode index for each of the 2m dual-rail rails. If None, qubit k uses physical modes 2k and 2k+1 directly.
Returns:
- List[int]
List of occupied mode indices (0-indexed)
- qlass.utils.loss_function(lp: ndarray, H: dict[str, float], executor: Any, mitigator: Any | None = None) float[source]
Compute the loss function for the VQE algorithm.
Each Pauli term is measured with its own executor call. (Grouping commuting terms is available via
qlass.quantum_chemistry.group_commuting_pauli_termsbut is not applied here, since terms are measured individually either way.)The function works with executors that return either: 1. Fock states (from linear optical circuits) - exqalibur.FockState objects 2. Bitstring tuples (from regular qubit-based circuits) 3. Bitstring strings (from Qiskit Sampler)
The executor should return samples in one of these formats: - Dict with ‘results’ key: {‘results’: [samples]} - Direct list of samples: [samples] - Qiskit-style format with bitstrings or counts
- Parameters:
lp (np.ndarray) – Array of parameter values
H (Dict[str, float]) – Hamiltonian dictionary
executor – A callable function that executes the quantum circuit.
mitigator – Optional mitigator object (e.g., M3Mitigator) to correct measurement errors.
- Returns:
The computed loss value
- Return type:
float
- qlass.utils.loss_function_bose_hubbard(lp: ndarray, H: BosonOperator, executor: Callable, mitigator: Any | None = None) float[source]
Compute the expectation value of a Bose-Hubbard Hamiltonian from samples.
- Parameters:
lp (np.ndarray) – Variational parameters passed to the executor.
H (BosonOperator) – Bose-Hubbard Hamiltonian represented as an OpenFermion
BosonOperator.executor (Callable) – Sampling executor. It is called as
executor(lp, "identity")for diagonal terms andexecutor(lp, "hop", p, q)for hopping terms.mitigator (Any, optional) – Optional mitigator object used to correct sampled counts.
- Returns:
Estimated Bose-Hubbard energy.
- Return type:
float
- Raises:
TypeError – If
His not aBosonOperator.ValueError – If
Hcontains unsupported non-Bose-Hubbard terms.
- qlass.utils.loss_function_matrix(params: ndarray, H: dict[str, float], unitary_executor: Callable) float[source]
Compute loss function using unitary matrices directly.
- Parameters:
params (np.ndarray) – Variational parameters
H (Dict[str, float]) – Hamiltonian dictionary
unitary_executor – Function that returns unitary matrix given params
- Returns:
Energy expectation value
- Return type:
float
- qlass.utils.loss_function_photonic_unitary(params: ndarray, H: dict[str, float], photonic_unitary_executor: Callable, initial_state: ndarray | None = None, ancillary_modes: list[int] | None = None) float[source]
Computes the loss function for a photonic VQE using the efficient, matrix-free state vector approach for post-selection.
This version accepts a full state vector for the initial state, allowing for superposition states, and allows for post-selection on ancillary modes.
- Parameters:
params – Variational parameters for the ansatz.
H – Hamiltonian dictionary.
photonic_unitary_executor – A function that takes params and returns the M x M photonic unitary U, where M is the total number of modes (logical + ancillary).
initial_state – The initial qubit state as a 2^m dimensional numpy vector. If None, defaults to the |00…0> state.
ancillary_modes – A list of mode indices to be treated as ancillary. Post-selection is performed by assuming these modes are 0 (vacuum) for both input and output.
- Returns:
The computed energy expectation value.
- qlass.utils.normalize_samples(samples: Any) list[FockState | tuple[int, ...]][source]
Normalize samples from different executor formats to a consistent format.
Handles: - Qiskit bitstring format: [‘00’, ‘01’, ‘11’] -> [(0,0), (0,1), (1,1)] - Already normalized tuples: [(0,0), (0,1)] -> [(0,0), (0,1)] - ExQalibur FockStates: [FockState, …] -> [FockState, …]
- Parameters:
samples – Raw samples in various formats
- Returns:
Normalized samples
- Return type:
List[Union[exqalibur.FockState, Tuple[int, …]]]
- qlass.utils.permanent(matrix: ndarray) complex[source]
Calculate the permanent of a matrix.
The permanent is like a determinant but without alternating signs: Perm(A) = Σ_{σ∈Sₘ} Π_{i=1 to m} A_{i,σ(i)}
Parameters:
- matrixnp.ndarray
Square matrix to calculate permanent of
Returns:
- complex
The permanent of the matrix
- qlass.utils.photon_to_qubit_unitary(U_photon: ndarray) ndarray[source]
Convert a photon unitary to the effective qubit unitary via post-selection.
Parameters:
- U_photonnp.ndarray
The 2m × 2m unitary matrix acting on photon modes
Returns:
- np.ndarray
The 2^m × 2^m effective qubit unitary matrix
- qlass.utils.qubit_state_marginal(prob_dist: dict[FockState | tuple[int, ...], float]) dict[tuple[int, ...], float][source]
Calculate the frequencies of measured qubit states from a probability distribution.
This function now handles both Fock states and bitstring inputs: - If input contains Fock states, converts them to qubit states using is_qubit_state - If input already contains bitstrings (tuples), passes them through directly
- Parameters:
prob_dist (Dict[Union[exqalibur.FockState, Tuple[int, ...]], float]) – Probability distribution of either Fock states or bitstrings
- Returns:
Frequencies of measured qubit states
- Return type:
Dict[Tuple[int, …], float]
- qlass.utils.rotate_modes(circuit_or_processor: Circuit | Processor, mode_1: int, mode_2: int) Circuit | Processor[source]
Append a 50/50 beam splitter across two photonic modes before measurement.
- Parameters:
circuit_or_processor (Union[pcvl.Circuit, pcvl.Processor]) – Perceval circuit or processor to rotate.
mode_1 (int) – First mode index.
mode_2 (int) – Second mode index.
- Returns:
The input circuit or processor with the beam splitter appended.
- Return type:
Union[pcvl.Circuit, pcvl.Processor]
- Raises:
ValueError – If both mode indices are identical or either index is negative.
- qlass.utils.rotate_qubits(pauli_string: str, vqe_circuit: Circuit | QuantumCircuit) Circuit | QuantumCircuit[source]
Apply the correct rotations on corresponding qubits for expectation value computation.
Note: the circuit is modified in place and also returned; pass a copy if the original must stay unchanged.
- Parameters:
pauli_string (str) – A string representation of Pauli operators
vqe_circuit (Union[pcvl.Circuit, qiskit.QuantumCircuit]) – The VQE circuit to modify
- Returns:
The modified VQE circuit with applied rotations (same type as the input)
- Return type:
Union[pcvl.Circuit, qiskit.QuantumCircuit]