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()
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
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()
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!" )
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!" )