Ejemplo n.º 1
0
def test_excitations(electrons, orbitals, delta_sz, n_singles, n_doubles,
                     singles_exp, doubles_exp):
    r"""Test the correctness of the generated configurations"""

    singles, doubles = qchem.excitations(electrons, orbitals, delta_sz)

    assert len(singles) == len(singles_exp)
    assert len(doubles) == len(doubles_exp)
    assert singles == singles_exp
    assert doubles == doubles_exp
class TestSparseExpvalQChem:
    """Tests for the expval function with qchem workflow"""

    symbols = ["Li", "H"]
    geometry = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 2.969280527])

    H, qubits = qchem.molecular_hamiltonian(
        symbols,
        geometry,
    )
    H_sparse = qml.utils.sparse_hamiltonian(H)

    active_electrons = 1

    hf_state = qchem.hf_state(active_electrons, qubits)

    singles, doubles = qchem.excitations(active_electrons, qubits)
    excitations = singles + doubles

    @pytest.fixture(params=[np.complex64, np.complex128])
    def dev(self, request):
        return qml.device("lightning.qubit", wires=12, c_dtype=request.param)

    @pytest.mark.parametrize(
        "qubits, wires, H_sparse, hf_state, excitations",
        [
            [qubits,
             np.arange(qubits), H_sparse, hf_state, excitations],
            [
                qubits,
                np.random.permutation(np.arange(qubits)),
                H_sparse,
                hf_state,
                excitations,
            ],
        ],
    )
    def test_sparse_Pauli_words(self, qubits, wires, H_sparse, hf_state,
                                excitations, tol, dev):
        """Test expval of some simple sparse Hamiltonian"""
        @qml.qnode(dev, diff_method="parameter-shift")
        def circuit():
            qml.BasisState(hf_state, wires=range(qubits))

            for i, excitation in enumerate(excitations):
                if len(excitation) == 4:
                    qml.DoubleExcitation(1, wires=excitation)
                elif len(excitation) == 2:
                    qml.SingleExcitation(1, wires=excitation)

            return qml.expval(qml.SparseHamiltonian(H_sparse, wires=wires))

        dev_default = qml.device("default.qubit", wires=qubits)

        @qml.qnode(dev_default, diff_method="parameter-shift")
        def circuit_default():
            qml.BasisState(hf_state, wires=range(qubits))

            for i, excitation in enumerate(excitations):
                if len(excitation) == 4:
                    qml.DoubleExcitation(1, wires=excitation)
                elif len(excitation) == 2:
                    qml.SingleExcitation(1, wires=excitation)

            return qml.expval(qml.SparseHamiltonian(H_sparse, wires=wires))

        assert np.allclose(circuit(), circuit_default(), atol=tol, rtol=0)
Ejemplo n.º 3
0
def test_inconsistent_excitations(electrons, orbitals, delta_sz,
                                  message_match):
    r"""Test that an error is raised if a set of inconsistent arguments is input"""

    with pytest.raises(ValueError, match=message_match):
        qchem.excitations(electrons, orbitals, delta_sz)
Ejemplo n.º 4
0
# :func:`~.pennylane.templates.subroutines.SingleExcitationUnitary` and
# :func:`~.pennylane.templates.subroutines.DoubleExcitationUnitary` functions.
#
# Now, we demonstrate how to use PennyLane functionalities to build up the UCCSD
# ansatz for VQE simulations. First, we use the :func:`~.pennylane_qchem.qchem.excitations`
# function to generate the whole set of single- and double-excitations for :math:`N_e`
# ``electrons`` populating ``qubits`` spin orbitals. Furthermore, we can define the selection rules
# :math:`s_{z_p} - s_{z_r} = \Delta s_z` and
# :math:`s_{z_p} + s_{z_q} - s_{z_r} - s_{z_s}= \Delta s_z` for the spin-projection of the
# molecular orbitals involved in the single and double excitations
# using the keyword argument ``delta_sz``. This allows us to prepare a
# correlated state whose total-spin projection :math:`S_z` is different from the one of
# the Hartree-Fock state by the quantity ``delta_sz``. Therefore, we choose ``delta_sz = 0`` to
# prepare the ground state of the :math:`\mathrm{H}_2` molecule.

singles, doubles = qchem.excitations(electrons, qubits, delta_sz=0)
print(singles)
print(doubles)

##############################################################################
# The output lists ``singles`` and ``doubles`` contain the indices representing the single and
# double excitations. For the hydrogen molecule in a minimal basis set we have two single
# and one double excitations. The latter means that in preparing the UCCSD ansatz the
# :func:`~.pennylane.templates.subroutines.SingleExcitationUnitary` function has to be called
# twice to exponentiate the two single-excitation operators while the
# :func:`~.pennylane.templates.subroutines.DoubleExcitationUnitary` function is invoked once to
# exponentiate the double excitation.
#
# We use the function
# :func:`~.pennylane_qchem.qchem.excitations_to_wires` to generate the set of wires that the UCCSD
# circuit will act on. The inputs to this function are the indices stored in the