Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
n_spatial_orbitals = n_qubits // 2
n_occupied = int(numpy.ceil(n_electrons / 2))
n_virtual = n_spatial_orbitals - n_occupied
# Unpack amplitudes
n_single_amplitudes = n_occupied * n_virtual
# Single amplitudes
t1 = packed_amplitudes[:n_single_amplitudes]
# Double amplitudes associated with one spatial occupied-virtual pair
t2_1 = packed_amplitudes[n_single_amplitudes:2 * n_single_amplitudes]
# Double amplitudes associated with two spatial occupied-virtual pairs
t2_2 = packed_amplitudes[2 * n_single_amplitudes:]
# Initialize operator
generator = FermionOperator()
# Generate excitations
spin_index_functions = [up_index, down_index]
# Generate all spin-conserving single and double excitations derived
# from one spatial occupied-virtual pair
for i, (p, q) in enumerate(
itertools.product(range(n_virtual), range(n_occupied))):
# Get indices of spatial orbitals
virtual_spatial = n_occupied + p
occupied_spatial = q
for spin in range(2):
# Get the functions which map a spatial orbital index to a
# spin orbital index
this_index = spin_index_functions[spin]
evolution for a single Trotter step.
Notes: follows Equation 9 of Poulin et al.'s work in "The Trotter Step
Size Required for Accurate Quantum Simulation of Quantum Chemistry",
applied to the "stagger"-based Trotter step for detailed in
Kivlichan et al., "Quantum Simulation of Electronic Structure with
Linear Depth and Connectivity", arxiv:1711.04789.
"""
more_info = bool(indices)
n_terms = len(terms)
if verbose:
import time
start = time.time()
error_operator = FermionOperator.zero()
for beta in range(n_terms):
if verbose and beta % (n_terms // 30) == 0:
print('%4.3f percent done in' % (
(float(beta) / n_terms) ** 3 * 100), time.time() - start)
for alpha in range(beta + 1):
for alpha_prime in range(beta):
# If we have pre-computed info on indices, use it to determine
# trivial double commutation.
if more_info:
if (not
trivially_double_commutes_dual_basis_using_term_info(
indices[alpha], indices[beta],
indices[alpha_prime], is_hopping_operator[alpha],
is_hopping_operator[beta],
is_hopping_operator[alpha_prime], jellium_only)):
Args:
n_spatial_orbitals: number of spatial orbitals (n_qubits + 1 // 2).
Returns:
operator (FermionOperator): corresponding to the s+ operator over
n_spatial_orbitals.
Note:
The indexing convention used is that even indices correspond to
spin-up (alpha) modes and odd indices correspond to spin-down (beta)
modes.
"""
if not isinstance(n_spatial_orbitals, int):
raise TypeError("n_orbitals must be specified as an integer")
fermion_identity = FermionOperator(())
operator = (s_minus_operator(n_spatial_orbitals) *
s_plus_operator(n_spatial_orbitals))
operator += (sz_operator(n_spatial_orbitals) *
(sz_operator(n_spatial_orbitals) + fermion_identity))
return operator
# to put it into the form we want
n = p // 2
for i in range(1, n, 2):
swap_rows(canonical, i, n + i - 1)
swap_columns(canonical, i, n + i - 1)
swap_columns(orthogonal, i, n + i - 1)
if n % 2 != 0:
swap_rows(canonical, n - 1, n + i)
swap_columns(canonical, n - 1, n + i)
swap_columns(orthogonal, n - 1, n + i)
# Now we permute so that the upper right block is non-negative
for i in range(n):
if canonical[i, n + i] < 0.0:
swap_rows(canonical, i, n + i)
swap_columns(canonical, i, n + i)
swap_columns(orthogonal, i, n + i)
# Now we permute so that the nonzero entries are ordered by magnitude
# We use insertion sort
diagonal = canonical[range(n), range(n, 2 * n)]
for i in range(n):
# Insert the smallest element from the unsorted part of the list into
# index i
arg_min = numpy.argmin(diagonal[i:]) + i
if arg_min != i:
# Permute the upper right block
swap_rows(canonical, i, arg_min)
swap_columns(canonical, n + i, n + arg_min)
swap_columns(orthogonal, n + i, n + arg_min)
# Permute the lower left block
swap_rows(canonical, n + i, n + arg_min)
raise ValueError('The input matrix must be antisymmetric.')
# Compute Schur decomposition
canonical, orthogonal = schur(antisymmetric_matrix, output='real')
# The returned form is block diagonal; we need to permute rows and columns
# to put it into the form we want
n = p // 2
for i in range(1, n, 2):
swap_rows(canonical, i, n + i - 1)
swap_columns(canonical, i, n + i - 1)
swap_columns(orthogonal, i, n + i - 1)
if n % 2 != 0:
swap_rows(canonical, n - 1, n + i)
swap_columns(canonical, n - 1, n + i)
swap_columns(orthogonal, n - 1, n + i)
# Now we permute so that the upper right block is non-negative
for i in range(n):
if canonical[i, n + i] < 0.0:
swap_rows(canonical, i, n + i)
swap_columns(canonical, i, n + i)
swap_columns(orthogonal, i, n + i)
# Now we permute so that the nonzero entries are ordered by magnitude
# We use insertion sort
diagonal = canonical[range(n), range(n, 2 * n)]
for i in range(n):
# Insert the smallest element from the unsorted part of the list into
# index i
arg_min = numpy.argmin(diagonal[i:]) + i
if arg_min != i:
if not numpy.isclose(maxval, 0.0):
raise ValueError('The input matrix must be antisymmetric.')
# Compute Schur decomposition
canonical, orthogonal = schur(antisymmetric_matrix, output='real')
# The returned form is block diagonal; we need to permute rows and columns
# to put it into the form we want
n = p // 2
for i in range(1, n, 2):
swap_rows(canonical, i, n + i - 1)
swap_columns(canonical, i, n + i - 1)
swap_columns(orthogonal, i, n + i - 1)
if n % 2 != 0:
swap_rows(canonical, n - 1, n + i)
swap_columns(canonical, n - 1, n + i)
swap_columns(orthogonal, n - 1, n + i)
# Now we permute so that the upper right block is non-negative
for i in range(n):
if canonical[i, n + i] < 0.0:
swap_rows(canonical, i, n + i)
swap_columns(canonical, i, n + i)
swap_columns(orthogonal, i, n + i)
# Now we permute so that the nonzero entries are ordered by magnitude
# We use insertion sort
diagonal = canonical[range(n), range(n, 2 * n)]
for i in range(n):
# Insert the smallest element from the unsorted part of the list into
# index i
arg_min = numpy.argmin(diagonal[i:]) + i
# Check that input matrix is antisymmetric
matrix_plus_transpose = antisymmetric_matrix + antisymmetric_matrix.T
maxval = numpy.max(numpy.abs(matrix_plus_transpose))
if not numpy.isclose(maxval, 0.0):
raise ValueError('The input matrix must be antisymmetric.')
# Compute Schur decomposition
canonical, orthogonal = schur(antisymmetric_matrix, output='real')
# The returned form is block diagonal; we need to permute rows and columns
# to put it into the form we want
n = p // 2
for i in range(1, n, 2):
swap_rows(canonical, i, n + i - 1)
swap_columns(canonical, i, n + i - 1)
swap_columns(orthogonal, i, n + i - 1)
if n % 2 != 0:
swap_rows(canonical, n - 1, n + i)
swap_columns(canonical, n - 1, n + i)
swap_columns(orthogonal, n - 1, n + i)
# Now we permute so that the upper right block is non-negative
for i in range(n):
if canonical[i, n + i] < 0.0:
swap_rows(canonical, i, n + i)
swap_columns(canonical, i, n + i)
swap_columns(orthogonal, i, n + i)
# Now we permute so that the nonzero entries are ordered by magnitude
# We use insertion sort
diagonal = canonical[range(n), range(n, 2 * n)]
for i in range(n):
# Check that input matrix is antisymmetric
matrix_plus_transpose = antisymmetric_matrix + antisymmetric_matrix.T
maxval = numpy.max(numpy.abs(matrix_plus_transpose))
if not numpy.isclose(maxval, 0.0):
raise ValueError('The input matrix must be antisymmetric.')
# Compute Schur decomposition
canonical, orthogonal = schur(antisymmetric_matrix, output='real')
# The returned form is block diagonal; we need to permute rows and columns
# to put it into the form we want
n = p // 2
for i in range(1, n, 2):
swap_rows(canonical, i, n + i - 1)
swap_columns(canonical, i, n + i - 1)
swap_columns(orthogonal, i, n + i - 1)
if n % 2 != 0:
swap_rows(canonical, n - 1, n + i)
swap_columns(canonical, n - 1, n + i)
swap_columns(orthogonal, n - 1, n + i)
# Now we permute so that the upper right block is non-negative
for i in range(n):
if canonical[i, n + i] < 0.0:
swap_rows(canonical, i, n + i)
swap_columns(canonical, i, n + i)
swap_columns(orthogonal, i, n + i)
# Now we permute so that the nonzero entries are ordered by magnitude
# We use insertion sort
diagonal = canonical[range(n), range(n, 2 * n)]
maxval = numpy.max(numpy.abs(matrix_plus_transpose))
if not numpy.isclose(maxval, 0.0):
raise ValueError('The input matrix must be antisymmetric.')
# Compute Schur decomposition
canonical, orthogonal = schur(antisymmetric_matrix, output='real')
# The returned form is block diagonal; we need to permute rows and columns
# to put it into the form we want
n = p // 2
for i in range(1, n, 2):
swap_rows(canonical, i, n + i - 1)
swap_columns(canonical, i, n + i - 1)
swap_columns(orthogonal, i, n + i - 1)
if n % 2 != 0:
swap_rows(canonical, n - 1, n + i)
swap_columns(canonical, n - 1, n + i)
swap_columns(orthogonal, n - 1, n + i)
# Now we permute so that the upper right block is non-negative
for i in range(n):
if canonical[i, n + i] < 0.0:
swap_rows(canonical, i, n + i)
swap_columns(canonical, i, n + i)
swap_columns(orthogonal, i, n + i)
# Now we permute so that the nonzero entries are ordered by magnitude
# We use insertion sort
diagonal = canonical[range(n), range(n, 2 * n)]
for i in range(n):
# Insert the smallest element from the unsorted part of the list into
# index i
# The returned form is block diagonal; we need to permute rows and columns
# to put it into the form we want
n = p // 2
for i in range(1, n, 2):
swap_rows(canonical, i, n + i - 1)
swap_columns(canonical, i, n + i - 1)
swap_columns(orthogonal, i, n + i - 1)
if n % 2 != 0:
swap_rows(canonical, n - 1, n + i)
swap_columns(canonical, n - 1, n + i)
swap_columns(orthogonal, n - 1, n + i)
# Now we permute so that the upper right block is non-negative
for i in range(n):
if canonical[i, n + i] < 0.0:
swap_rows(canonical, i, n + i)
swap_columns(canonical, i, n + i)
swap_columns(orthogonal, i, n + i)
# Now we permute so that the nonzero entries are ordered by magnitude
# We use insertion sort
diagonal = canonical[range(n), range(n, 2 * n)]
for i in range(n):
# Insert the smallest element from the unsorted part of the list into
# index i
arg_min = numpy.argmin(diagonal[i:]) + i
if arg_min != i:
# Permute the upper right block
swap_rows(canonical, i, arg_min)
swap_columns(canonical, n + i, n + arg_min)
swap_columns(orthogonal, n + i, n + arg_min)
# Permute the lower left block