Ejemplo n.º 1
0
def fidelity(nn_state, target_psi, space, **kwargs):
    r"""Calculates the square of the overlap (fidelity) between the reconstructed
    wavefunction and the true wavefunction (both in the computational basis).

    .. math:: F = \vert \langle \psi_{RBM} \vert \psi_{target} \rangle \vert ^2

    :param nn_state: The neural network state (i.e. complex wavefunction or
                     positive wavefunction).
    :type nn_state: qucumber.nn_states.WaveFunctionBase
    :param target_psi: The true wavefunction of the system.
    :type target_psi: torch.Tensor
    :param space: The basis elements of the Hilbert space of the system :math:`\mathcal{H}`.
                  The ordering of the basis elements must match with the ordering of the
                  coefficients given in `target_psi`.
    :type space: torch.Tensor
    :param \**kwargs: Extra keyword arguments that may be passed. Will be ignored.

    :returns: The fidelity.
    :rtype: float
    """
    Z = nn_state.compute_normalization(space)
    target_psi = target_psi.to(nn_state.device)
    psi = nn_state.psi(space) / Z.sqrt()
    F = cplx.inner_prod(target_psi, psi)
    return cplx.absolute_value(F).pow_(2).item()
Ejemplo n.º 2
0
def fidelity(nn_state, target, space=None, **kwargs):
    r"""Calculates the square of the overlap (fidelity) between the reconstructed
    state and the true state (both in the computational basis).

    .. math::

        F = \vert \langle \psi_{RBM} \vert \psi_{target} \rangle \vert ^2
          = \left( \tr \lbrack \sqrt{ \sqrt{\rho_{RBM}} \rho_{target} \sqrt{\rho_{RBM}} } \rbrack \right) ^ 2

    :param nn_state: The neural network state.
    :type nn_state: qucumber.nn_states.NeuralStateBase
    :param target: The true state of the system.
    :type target: torch.Tensor
    :param space: The basis elements of the Hilbert space of the system :math:`\mathcal{H}`.
                  The ordering of the basis elements must match with the ordering of the
                  coefficients given in `target`. If `None`, will generate them using
                  the provided `nn_state`.
    :type space: torch.Tensor
    :param \**kwargs: Extra keyword arguments that may be passed. Will be ignored.

    :returns: The fidelity.
    :rtype: float
    """
    space = space if space is not None else nn_state.generate_hilbert_space()
    Z = nn_state.normalization(space)
    target = target.to(nn_state.device)

    if isinstance(nn_state, WaveFunctionBase):
        assert target.dim() == 2, "target must be a complex vector!"

        psi = nn_state.psi(space) / Z.sqrt()
        F = cplx.inner_prod(target, psi)
        return cplx.absolute_value(F).pow_(2).item()
    else:
        assert target.dim() == 3, "target must be a complex matrix!"

        rho = nn_state.rho(space, space) / Z
        rho_rbm_ = cplx.numpy(rho)
        target_ = cplx.numpy(target)

        sqrt_rho_rbm = sqrtm(rho_rbm_)
        prod = np.matmul(sqrt_rho_rbm, np.matmul(target_, sqrt_rho_rbm))

        # Instead of sqrt'ing then taking the trace, we compute the eigenvals,
        #  sqrt those, and then sum them up. This is a bit more efficient.
        eigvals = np.linalg.eigvals(
            prod).real  # imaginary parts should be zero
        eigvals = np.abs(eigvals)
        trace = np.sum(np.sqrt(eigvals))

        return trace**2
Ejemplo n.º 3
0
def fidelity(nn_state, target_psi, space, **kwargs):
    r"""Calculates the square of the overlap (fidelity) between the reconstructed
    wavefunction and the true wavefunction (both in the computational basis).

    :param nn_state: The neural network state (i.e. complex wavefunction or
                     positive wavefunction).
    :type nn_state: WaveFunction
    :param target_psi: The true wavefunction of the system.
    :type target_psi: torch.Tensor
    :param space: The hilbert space of the system.
    :type space: torch.Tensor
    :param \**kwargs: Extra keyword arguments that may be passed. Will be ignored.

    :returns: The fidelity.
    :rtype: float
    """
    Z = nn_state.compute_normalization(space)
    target_psi = target_psi.to(nn_state.device)
    psi = nn_state.psi(space) / Z.sqrt()
    F = cplx.inner_prod(target_psi, psi)
    return cplx.absolute_value(F).pow_(2).item()
Ejemplo n.º 4
0
 def test_vector_inner_prod(self):
     vector = torch.tensor([[1, 2], [3, 4]], dtype=torch.double)
     expect = torch.tensor([30, 0], dtype=torch.double)
     self.assertTensorsEqual(
         cplx.inner_prod(vector, vector), expect, msg="Vector inner product failed!"
     )
Ejemplo n.º 5
0
 def test_scalar_inner_prod(self):
     scalar = torch.tensor([1, 2], dtype=torch.double)
     expect = torch.tensor([5, 0], dtype=torch.double)
     self.assertTensorsEqual(
         cplx.inner_prod(scalar, scalar), expect, msg="Scalar inner product failed!"
     )