Skip to content

Commit

Permalink
Update code for single excitation
Browse files Browse the repository at this point in the history
  • Loading branch information
chmwzc committed Aug 20, 2024
1 parent f1cf698 commit 5a9acd4
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 6 deletions.
29 changes: 26 additions & 3 deletions src/qibochem/ansatz/givens_excitation.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""
Module documentation
Circuit ansatz for representing a fermionic excitation as a Givens rotation by Arrazola et al.
Reference: https://doi.org/10.22331/q-2022-06-20-742
"""

from qibo import Circuit, gates
Expand All @@ -10,6 +11,28 @@
# Helper functions


def single_excitation_gate(sorted_orbitals, theta):
"""
Decomposition of a Givens single excitation gate into single qubit rotations and CNOTs. In principle, should be
identical to gates.GIVENS(qubit0, qubit1, theta)
Args:
sorted_orbitals (list): Sorted list of orbitals involved in the excitation
theta (float): Rotation angle
Returns:
(list): List of gates representing the decomposition of the Givens' single excitation gate
"""
result = []
result.append(gates.CNOT(sorted_orbitals[0], sorted_orbitals[1]))
result.append(gates.RY(sorted_orbitals[0], 0.5 * theta))
result.append(gates.CNOT(sorted_orbitals[1], sorted_orbitals[0]))
result.append(gates.RY(sorted_orbitals[0], -0.5 * theta))
result.append(gates.CNOT(sorted_orbitals[1], sorted_orbitals[0]))
result.append(gates.CNOT(sorted_orbitals[0], sorted_orbitals[1]))
return result


def double_excitation_gate(sorted_orbitals, theta):
"""
Decomposition of a Givens double excitation gate into single qubit rotations and CNOTs
Expand Down Expand Up @@ -56,7 +79,7 @@ def double_excitation_gate(sorted_orbitals, theta):
# Main function
def givens_excitation_circuit(n_qubits, excitation, theta=None):
"""
Circuit ansatz corresponding to the Givens rotation excitation from Arrazola et al. (https://doi.org/10.22331/q-2022-06-20-742) for a single excitation.
Circuit ansatz corresponding to the Givens rotation excitation from Arrazola et al.
Args:
n_qubits: Number of qubits in the circuit
Expand All @@ -76,7 +99,7 @@ def givens_excitation_circuit(n_qubits, excitation, theta=None):

circuit = Circuit(n_qubits)
if len(excitation) == 2:
circuit.add(gates.GIVENS(excitation[0], excitation[1], theta))
circuit.add(single_excitation_gate(sorted_orbitals, theta))
elif len(excitation) == 4:
circuit.add(double_excitation_gate(sorted_orbitals, theta))
else:
Expand Down
28 changes: 25 additions & 3 deletions tests/test_givens_excitation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,33 @@
double_excitation_gate,
givens_excitation_ansatz,
givens_excitation_circuit,
single_excitation_gate,
)
from qibochem.ansatz.util import generate_excitations, mp2_amplitude, sort_excitations
from qibochem.driver import Molecule


def test_single_excitation_gate():
# Hardcoded test
theta = 0.1

control_gates = [
gates.CNOT(0, 1),
gates.RY(0, 0.5 * theta),
gates.CNOT(1, 0),
gates.RY(0, -0.5 * theta),
gates.CNOT(1, 0),
gates.CNOT(0, 1),
]
test_list = single_excitation_gate([0, 1, 2, 3], 0.1)

# Check gates are correct
assert all(
control.name == test.name and control.target_qubits == test.target_qubits
for control, test in zip(control_gates, test_list)
)


def test_double_excitation_gate():
# Hardcoded test
theta = 0.0
Expand Down Expand Up @@ -62,7 +84,7 @@ def test_double_excitation_gate():
@pytest.mark.parametrize(
"excitation,expected",
[
([0, 2], [gates.GIVENS(0, 2, 0.0)]),
([0, 2], single_excitation_gate([0, 2], 0.0)),
([0, 1, 2, 3], double_excitation_gate([0, 1, 2, 3], 0.0)),
],
)
Expand Down Expand Up @@ -106,8 +128,8 @@ def test_givens_excitation_ansatz_h2():
# Then check that the circuit parameters are the MP2 guess parameters
# Get the MP2 amplitudes first, then expand the list based on the excitation type
mp2_guess_amplitudes = [mp2_amplitude([0, 1, 2, 3], mol.eps, mol.tei) for _ in range(8)] # Doubles
mp2_guess_amplitudes += [0.0, 0.0] # Singles
coeffs = np.array([-0.125, 0.125, -0.125, 0.125, 0.125, -0.125, 0.125, -0.125, 1.0, 1.0])
mp2_guess_amplitudes += [0.0, 0.0, 0.0, 0.0] # Singles
coeffs = np.array([-0.125, 0.125, -0.125, 0.125, 0.125, -0.125, 0.125, -0.125, 1.0, 1.0, 1.0, 1.0])
mp2_guess_amplitudes = coeffs * np.array(mp2_guess_amplitudes)
# Need to flatten the output of circuit.get_parameters() to compare it to mp2_guess_amplitudes
test_parameters = np.array([_x for _tuple in test_circuit.get_parameters() for _x in _tuple])
Expand Down

0 comments on commit 5a9acd4

Please sign in to comment.