QHack 2023: 4 week prep challenge, day 5, Triple excitation Givens rotation

Continuing on the Quantum Chemistry track, the next exercise. According to the designers, it is more difficult than the last ones, but it suited me very well. With the knowledge of the previous days, I could solve the task by merely looking at it.

The task is to prepare the state

\[ |\psi(\alpha, \beta, \gamma)\rangle = \cos{\frac{\alpha}{2}} \cos{\frac{\beta}{2}} \left[ \cos{\frac{\gamma}{2}} |111000\rangle – \sin{\frac{\gamma}{2}}|000111\rangle \right] – \cos{\frac{\alpha}{2}} \sin{\frac{\beta}{2}}|001011\rangle – \sin{\frac{\alpha}{2}} |011001\rangle \]

using a single excitation, a double excitation and a triple excitation, the latter one should be constructed from a matrix.

Constructing a triple excitation Givens rotation

This is a really straight forward task. The transformation rules are analogous to the single and double excitations

\[ G^{(3)}(\gamma)|000111\rangle = \cos{\frac{\gamma}{2}} | 000111\rangle + \sin{\frac{\gamma}{2}} |111000\rangle \\ G^{(3)}(\gamma)|111000\rangle = \cos{\frac{\gamma}{2}} | 111000\rangle – \sin{\frac{\gamma}{2}} |000111\rangle \]

and the realization, that the decimal representations of the states provide you with the target indices in the transformation matrix

\[ |000111\rangle = |7\rangle, \\ |111000\rangle = |56\rangle \]

yields the implementation

def triple_excitation_matrix(gamma):
    """The matrix representation of a triple-excitation Givens rotation.
https://github.com/XanaduAI/QHack2022/tree/master/Coding_Challenges/qchem_400_TripleGivens_template 
    Args:
        - gamma (float): The angle of rotation

    Returns:
        - (np.ndarray): The matrix representation of a triple-excitation
    """

    dim = 2**6
    res = np.identity(dim)
    
    # |000111> = |7>
    # G3(theta)|7> = cos(theta/2)|7> + sin(theta/2)|56>
    row7 = np.zeros(dim)
    row7[7] = np.cos(gamma/2)
    row7[56] = -np.sin(gamma/2)
    
    # |111000> = |56>
    # G3(theta)|56> = cos(theta/2)|56> - sin(theta/2)|7>
    row56 = np.zeros(dim)
    row56[7] = np.sin(gamma/2)
    row56[56] = np.cos(gamma/2)
    
    res[7] = row7
    res[56] = row56
    
    return res

Preparing the target state

This was solved by looking at the states and the pre-factors. The basis-states with a single pre-factor underwent only a single Givens rotation…

@qml.qnode(dev)
def circuit(angles):
    """Prepares the quantum state in the problem statement and returns qml.probs

    Args:
        - angles (list(float)): The relevant angles in the problem statement in this order:
        [alpha, beta, gamma]

    Returns:
        - (np.tensor): The probability of each computational basis state
    """

    # QHACK #
    qml.BasisState(np.array([1, 1, 1, 0, 0, 0]), wires=[0, 1, 2, 3, 4, 5])
    qml.SingleExcitation(angles[0], wires=[0, 5])
    qml.DoubleExcitation(angles[1], wires=[0,1,4,5])
    qml.QubitUnitary(triple_excitation_matrix(angles[2]), wires=[0,1,2,3,4,5])
    # QHACK #

    return qml.probs(wires=range(NUM_WIRES))

The provided test datasets yield the correct results, success!