Today, I’m heading again for a prepared exercise, the next exercise in the QHack 2022 Quantum Chemistry track. It requires slightly more preparation, than the previous two, but again very doable.
The challenge, invites to get more acquainted with Givens rotations, i.e. operations that allow to transform states, while preserving the hamming weight (the number of ones and zeros). They are the basic building blocks of quantum chemistry and “can be used to construct any kind of particle-conserving circuit”.
The goal is to find the correct rotation angles to transform a start state to a target state, with a quantum circuit with three Givens rotations,
Getting to know Givens rotations
Givens rotations, describe transitions of electrons from a starting state to an excited state. In Pennylane, these rotations can be used via the classes qml.SingleExcitation and qml.DoubleExcitation. The linked tutorial is very recommendable.

Solving the exercise
To solve this exercise, I used the rotations’ transformation rules to reach an expression that associated trigonometric functions with the target factors. Further, I used the fact, that states are normalized at any time during the calculation. Key for me to solve it, was to apply only the first two rotations and used the normalization property of the state, from this I obtained the first angle. Then I went on to apply the remaining rotation and easily expressed the missing two angles.
import numpy as np
def givens_rotations(a, b, c, d):
"""Calculates the angles needed for a Givens rotation to out put the state with amplitudes a,b,c and d
Args:
- a,b,c,d (float): real numbers which represent the amplitude of the relevant basis states (see problem statement). Assume they are normalized.
Returns:
- (list(float)): a list of real numbers ranging in the intervals provided in the challenge statement, which represent the angles in the Givens rotations,
in order, that must be applied.
"""
theta1 = 2.*np.arccos(np.sqrt(1-b**2-c**2))
theta2 = 2.*np.arcsin(c/np.sin(theta1/2.))
theta3 = 2.*np.arccos(a/np.cos(theta1/2.))
return [theta1, theta2, theta3]
Test
Defining the circuit…
import pennylane as qml
dev = qml.device('default.qubit', wires=6)
@qml.qnode(dev)
def circuit(x, y, z):
qml.BasisState(np.array([1, 1, 0, 0, 0, 0]), wires=[i for i in range(6)])
qml.DoubleExcitation(x, wires=[0, 1, 2, 3])
qml.DoubleExcitation(y, wires=[2, 3, 4, 5])
# single excitation controlled on qubit 0
qml.ctrl(qml.SingleExcitation, control=0)(z, wires=[1, 3])
return qml.state()
and executing the circuit …
[x, y, z] = givens_rotations(0.8062,-0.5,-0.1,-0.3)
circuit(x,y,z)
yields the correct amplitudes, success!