Excitations for tapered Hamiltonian

Is there a way to obtain double and single excitations for tapered Hamiltonian and tapered hf state?

Hi @Roux. The function excitations generates the single and double excitations for a Hartree-Fock state using the number of electrons and spin orbitals. This function, in principle, can be applied to a tapered state but constructing a circuit based on such excitations might not be always trivial when the state is tapered. Please feel free to let us know if you have any further questions.

1 Like

Hi @sjahangiri!
Yes, the problem is that these excitations generated by the function excitations cannot be used with a tapered hf state, because the wires in a tapered hf state don’t match with the wires inside single and double excitations. I just tried to find the same functionality as in qiskit, where you can pass a tapered initial state and a tapered Hamiltonian to UCC ansatz constructor class.

Hi @Roux, unfortunately we don’t have a functionality to do what you need. It doesn’t seem to be something that is easily doable for exactly the reason that you mention.

If you do get to implement this it would be a great contribution to PennyLane.

1 Like

Hi @Roux

A colleague of mine took a look at your question and he mentioned that you should be able to get the excitation operators for the tapered state, but if you want to use them for building the UCCSD or K-UpCCGSD templates then that wouldn’t be possible since these templates are hardcoded.

If you have the operators though, you should be able to build the UCC ansatz yourself (and escape using the template) by defining a function to build a circuit to exponentiate Pauli observable [1].

Please let me know if this helps!

1 Like

Hi @CatalinaAlbornoz! Thank you for your answers and sorry for the late reply.
Could you show some sample code, please, to make it clear, how I can get the excitation operators?

symbols = ["H", "H", "H"]
geometry = np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 1], [0.0, 0.0, 2]])
mol = qml.hf.Molecule(symbols, geometry, charge=0,mult = 1)
H = qml.hf.generate_hamiltonian(mol)(geometry)
generators, paulix_ops = qml.hf.generate_symmetries(H, len(H.wires))
opt_sector = qml.hf.optimal_sector(H, generators, mol.n_electrons)
H_tapered = qml.hf.transform_hamiltonian(H, generators, paulix_ops, opt_sector)
n_elec = mol.n_electrons
n_qubits = mol.n_orbitals * 2

hf_tapered = qml.hf.transform_hf(generators, paulix_ops, opt_sector, n_elec, n_qubits)
orbitals = len(H_tapered.wires)
singles, doubles = qchem.excitations(n_elec, orbitals)

The last line of this code throws an error.

Hi @Roux! Thank you for your update.
The idea behind obtaining operators for the tapered state is to use the operators from the untapered HF states and taper them using the symmetries we find using the Hamiltonian.
Therefore, in this case, we can do something as follows:

symbols = ["H", "H", "H"]
geometry = np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 1], [0.0, 0.0, 2]])
mol = qml.qchem.Molecule(symbols, geometry, charge=0,mult = 1)
n_elec, n_qubits = mol.n_electrons, mol.n_orbitals * 2

H = qml.hf.generate_hamiltonian(mol)(geometry)
generators = qml.symmetry_generators(H)
paulix_ops = qml.paulix_ops(generators, n_qubits)
opt_sector = qml.qchem.optimal_sector(H, generators, n_elec)

excitations = []
singles, doubles = qml.qchem.excitations(n_elec, n_qubits)
for excitation in singles+doubles:
    op_coeffs, op_terms = qml.qchem.observable_hf.jordan_wigner(excitation)
    excitation_op = qml.Hamiltonian(np.array(op_coeffs), op_terms)
    excitation_tapered_op = qml.taper(excitation_op, generators, paulix_ops, opt_sector)

Hope this helps!