givens_decomposition_slater
givens_decomposition_slater(orbital_coeffs)
Decomposes the occupied orbitals of a Slater determinant into Givens rotations.
This is the rectangular counterpart of givens_decomposition(), specialized for Slater determinant state preparation. Given the coefficient matrix of the occupied orbitals of a Slater determinant, it returns a sequence of Givens rotations that, applied to the reference configuration (the first orbitals occupied), prepares the Slater determinant. Here orbital_coeffs is an matrix whose rows are the occupied orbitals expressed in a basis of spatial orbitals (); its rows are assumed to be orthonormal.
Unlike givens_decomposition(), this decomposition only needs to realize the occupied orbitals rather than a full orbital rotation, so it uses at most Givens rotations arranged in a diamond-shaped pattern (versus the brick-wall of the square decomposition). The decomposition contains no diagonal phases, because a global phase and any rotation within the occupied space leave the prepared Slater determinant unchanged.
Each Givens rotation is defined by a 4-tuple, (c, s, i, j), with:
c: the real-valued cosines: the complex-valued sinei: the first indexj: the second (adjacent) index
which result in a matrix of the form:
Parameters
orbital_coeffs – the matrix of occupied-orbital coefficients.
Returns
The sequence of Givens rotations represented as 4-tuples as explained above.
The occupied orbitals are recovered by applying the returned rotations, in order, to the columns of the reference , where each rotation acting on indices and sends
The result spans the same occupied space as orbital_coeffs (they define the same Slater determinant), so the squared overlap between the reconstructed orbitals and the target is one.
>>> import numpy as np
>>> from qiskit_fermions.linalg import givens_decomposition_slater
>>> # two occupied orbitals in a basis of three, with orthonormal rows
>>> base = np.array([[0.8, 0.6, 0.0], [-0.48, 0.64, 0.6]])
>>> orbital_coeffs = (base * np.array([[1.0], [1j]])).astype(complex)
>>> rotations = givens_decomposition_slater(orbital_coeffs)
>>> m, n = orbital_coeffs.shape
>>> reconstructed = np.eye(m, n, dtype=complex)
>>> for c, s, i, j in rotations:
... col_i, col_j = reconstructed[:, i].copy(), reconstructed[:, j].copy()
... reconstructed[:, i] = c * col_i + s.conjugate() * col_j
... reconstructed[:, j] = c * col_j - s * col_i
>>> overlap = abs(np.linalg.det(reconstructed @ orbital_coeffs.conj().T)) ** 2
>>> bool(np.isclose(overlap, 1.0))
True
givens_decomposition() for the square (full orbital rotation) decomposition.