Пример #1
0
    def test_one_body_square_decomposition(self):

        # Initialize H2 InteractionOperator.
        n_qubits = 4
        n_orbitals = 2
        filename = os.path.join(THIS_DIRECTORY, 'data',
                                'H2_sto-3g_singlet_0.7414')
        molecule = MolecularData(filename=filename)
        molecule_interaction = molecule.get_molecular_hamiltonian()
        fermion_operator = get_fermion_operator(molecule_interaction)

        two_body_coefficients = molecule_interaction.two_body_tensor

        # Decompose.
        eigenvalues, one_body_squares, one_body_correction, error = (
            low_rank_two_body_decomposition(two_body_coefficients))
        rank = eigenvalues.size
        for l in range(rank):
            one_body_operator = FermionOperator()
            for p, q in itertools.product(range(n_qubits), repeat=2):
                term = ((p, 1), (q, 0))
                coefficient = one_body_squares[l, p, q]
                one_body_operator += FermionOperator(term, coefficient)
            one_body_squared = one_body_operator**2

            # Get the squared one-body operator via one-body decomposition.
            if abs(eigenvalues[l]) < 1e-6:
                with self.assertRaises(ValueError):
                    prepare_one_body_squared_evolution(one_body_squares[l])
                continue
            else:
                density_density_matrix, basis_transformation_matrix = (
                    prepare_one_body_squared_evolution(one_body_squares[l]))
            two_body_operator = FermionOperator()
            for p, q in itertools.product(range(n_qubits), repeat=2):
                term = ((p, 1), (p, 0), (q, 1), (q, 0))
                coefficient = density_density_matrix[p, q]
                two_body_operator += FermionOperator(term, coefficient)

            # Confirm that the rotations diagonalize the one-body squares.
            hopefully_diagonal = basis_transformation_matrix.dot(
                numpy.dot(
                    one_body_squares[l],
                    numpy.transpose(
                        numpy.conjugate(basis_transformation_matrix))))
            diagonal = numpy.diag(hopefully_diagonal)
            difference = hopefully_diagonal - numpy.diag(diagonal)
            self.assertAlmostEqual(0., numpy.amax(numpy.absolute(difference)))
            density_density_alternative = numpy.outer(diagonal, diagonal)
            difference = density_density_alternative - density_density_matrix
            self.assertAlmostEqual(0., numpy.amax(numpy.absolute(difference)))

            # Test spectra.
            one_body_squared_spectrum = eigenspectrum(one_body_squared)
            two_body_spectrum = eigenspectrum(two_body_operator)
            difference = two_body_spectrum - one_body_squared_spectrum
            self.assertAlmostEqual(0., numpy.amax(numpy.absolute(difference)))
Пример #2
0
    def __init__(self,
                 hamiltonian: InteractionOperator,
                 truncation_threshold: Optional[float]=None,
                 final_rank: Optional[int]=None) -> None:

        self.truncation_threshold = truncation_threshold
        self.final_rank = final_rank

        # Get the chemist matrix.
        (self.constant,
         self.one_body_coefficients,
         chemist_two_body_coefficients) = (
                 get_chemist_two_body_coefficients(hamiltonian))

        # Perform the low rank decomposition of two-body operator.
        self.eigenvalues, self.one_body_squares, _ = (
            low_rank_two_body_decomposition(
                chemist_two_body_coefficients,
                truncation_threshold=self.truncation_threshold,
                final_rank=self.final_rank))

        # Get scaled density-density terms and basis transformation matrices.
        self.scaled_density_density_matrices = []  # type: List[numpy.ndarray]
        self.basis_change_matrices = []            # type: List[numpy.ndarray]
        for j in range(len(self.eigenvalues)):
            density_density_matrix, basis_change_matrix = (
                prepare_one_body_squared_evolution(self.one_body_squares[j]))
            self.scaled_density_density_matrices.append(
                    numpy.real(self.eigenvalues[j] * density_density_matrix))
            self.basis_change_matrices.append(basis_change_matrix)

        super().__init__(hamiltonian)
Пример #3
0
    def __init__(self,
                 hamiltonian: InteractionOperator,
                 truncation_threshold: Optional[float] = 1e-8,
                 final_rank: Optional[int] = None,
                 spin_basis=True) -> None:

        self.truncation_threshold = truncation_threshold
        self.final_rank = final_rank

        # Perform the low rank decomposition of two-body operator.
        self.eigenvalues, self.one_body_squares, one_body_correction, _ = (
            low_rank_two_body_decomposition(
                hamiltonian.two_body_tensor,
                truncation_threshold=self.truncation_threshold,
                final_rank=self.final_rank,
                spin_basis=spin_basis))
        self.one_body_coefficients = (hamiltonian.one_body_tensor +
                                      one_body_correction)
        self.constant = hamiltonian.constant

        # Get scaled density-density terms and basis transformation matrices.
        self.scaled_density_density_matrices = []  # type: List[numpy.ndarray]
        self.basis_change_matrices = []  # type: List[numpy.ndarray]
        for j in range(len(self.eigenvalues)):
            density_density_matrix, basis_change_matrix = (
                prepare_one_body_squared_evolution(self.one_body_squares[j]))
            self.scaled_density_density_matrices.append(
                numpy.real(self.eigenvalues[j] * density_density_matrix))
            self.basis_change_matrices.append(basis_change_matrix)

        super().__init__(hamiltonian)
Пример #4
0
    def test_one_body_square_decomposition(self):

        # Initialize a random two-body FermionOperator.
        n_qubits = 4
        random_operator = get_fermion_operator(
            random_interaction_operator(n_qubits, seed=17004))

        # Convert to chemist tensor.
        constant, one_body_coefficients, chemist_tensor = (
            get_chemist_two_body_coefficients(random_operator))

        # Perform decomposition.
        eigenvalues, one_body_squares, trunc_error = (
            low_rank_two_body_decomposition(chemist_tensor))

        # Build back two-body component.
        for l in range(n_qubits**2):

            # Get the squared one-body operator.
            one_body_operator = FermionOperator()
            for p, q in itertools.product(range(n_qubits), repeat=2):
                term = ((p, 1), (q, 0))
                coefficient = one_body_squares[l, p, q]
                one_body_operator += FermionOperator(term, coefficient)
            one_body_squared = one_body_operator**2

            # Get the squared one-body operator via one-body decomposition.
            density_density_matrix, basis_transformation_matrix = (
                prepare_one_body_squared_evolution(one_body_squares[l]))
            two_body_operator = FermionOperator()
            for p, q in itertools.product(range(n_qubits), repeat=2):
                term = ((p, 1), (p, 0), (q, 1), (q, 0))
                coefficient = density_density_matrix[p, q]
                two_body_operator += FermionOperator(term, coefficient)

            # Confirm that the rotations diagonalize the one-body squares.
            hopefully_diagonal = basis_transformation_matrix.dot(
                numpy.dot(
                    one_body_squares[l],
                    numpy.transpose(
                        numpy.conjugate(basis_transformation_matrix))))
            diagonal = numpy.diag(hopefully_diagonal)
            difference = hopefully_diagonal - numpy.diag(diagonal)
            self.assertAlmostEqual(0., numpy.amax(numpy.absolute(difference)))
            density_density_alternative = numpy.outer(diagonal, diagonal)
            difference = density_density_alternative - density_density_matrix
            self.assertAlmostEqual(0., numpy.amax(numpy.absolute(difference)))

            # Test spectra.
            one_body_squared_spectrum = eigenspectrum(one_body_squared)
            two_body_spectrum = eigenspectrum(two_body_operator)
            difference = two_body_spectrum - one_body_squared_spectrum
            self.assertAlmostEqual(0., numpy.amax(numpy.absolute(difference)))