def test_mapping_for_single_op(self):
        """Test for single register operator."""
        with self.subTest("test +"):
            op = FermionicOp("+", display_format="dense")
            expected = PauliSumOp.from_list([("X", 0.5), ("Y", -0.5j)])
            self.assertEqual(JordanWignerMapper().map(op), expected)

        with self.subTest("test -"):
            op = FermionicOp("-", display_format="dense")
            expected = PauliSumOp.from_list([("X", 0.5), ("Y", 0.5j)])
            self.assertEqual(JordanWignerMapper().map(op), expected)

        with self.subTest("test N"):
            op = FermionicOp("N", display_format="dense")
            expected = PauliSumOp.from_list([("I", 0.5), ("Z", -0.5)])
            self.assertEqual(JordanWignerMapper().map(op), expected)

        with self.subTest("test E"):
            op = FermionicOp("E", display_format="dense")
            expected = PauliSumOp.from_list([("I", 0.5), ("Z", 0.5)])
            self.assertEqual(JordanWignerMapper().map(op), expected)

        with self.subTest("test I"):
            op = FermionicOp("I", display_format="dense")
            expected = PauliSumOp.from_list([("I", 1)])
            self.assertEqual(JordanWignerMapper().map(op), expected)
    def test_mapping(self):
        """Test mapping to qubit operator"""
        driver = HDF5Driver(hdf5_input=self.get_resource_path(
            "test_driver_hdf5.hdf5", "second_q/drivers/hdf5d"))
        driver_result = driver.run()
        fermionic_op = driver_result.second_q_ops()["ElectronicEnergy"]
        mapper = JordanWignerMapper()
        qubit_op = mapper.map(fermionic_op)

        # Note: The PauliSumOp equals, as used in the test below, use the equals of the
        #       SparsePauliOp which in turn uses np.allclose() to determine equality of
        #       coeffs. So the reference operator above will be matched on that basis so
        #       we don't need to worry about tiny precision changes for any reason.

        self.assertEqual(qubit_op, TestJordanWignerMapper.REF_H2)
    def test_z2_symmetry(self):
        """Test mapping to qubit operator with z2 symmetry tapering"""
        z2_sector = [-1, 1, -1]

        def cb_finder(z2_symmetries: Z2Symmetries,
                      converter: QubitConverter) -> Optional[List[int]]:
            return z2_sector if not z2_symmetries.is_empty() else None

        def cb_find_none(_z2_symmetries: Z2Symmetries,
                         converter: QubitConverter) -> Optional[List[int]]:
            return None

        mapper = JordanWignerMapper()
        qubit_conv = QubitConverter(mapper, z2symmetry_reduction="auto")

        with self.subTest(
                "Locator returns None, should be untapered operator"):
            qubit_op = qubit_conv.convert(self.h2_op,
                                          sector_locator=cb_find_none)
            self.assertEqual(qubit_op, TestQubitConverter.REF_H2_JW)

        qubit_op = qubit_conv.convert(self.h2_op, sector_locator=cb_finder)
        self.assertEqual(qubit_op, TestQubitConverter.REF_H2_JW_TAPERED)

        with self.subTest("convert_match()"):
            qubit_op = qubit_conv.convert_match(self.h2_op)
            self.assertEqual(qubit_op, TestQubitConverter.REF_H2_JW_TAPERED)
            self.assertIsNone(qubit_conv.num_particles)
            self.assertListEqual(qubit_conv.z2symmetries.tapering_values,
                                 z2_sector)
    def setUp(self):
        super().setUp()
        algorithm_globals.random_seed = 8
        self.driver = PySCFDriver(
            atom="H .0 .0 .0; H .0 .0 0.75",
            unit=UnitsType.ANGSTROM,
            charge=0,
            spin=0,
            basis="sto3g",
        )

        self.reference_energies = [
            -1.8427016,
            -1.8427016 + 0.5943372,
            -1.8427016 + 0.95788352,
            -1.8427016 + 1.5969296,
        ]
        self.qubit_converter = QubitConverter(JordanWignerMapper())
        self.electronic_structure_problem = ElectronicStructureProblem(
            self.driver)

        solver = NumPyEigensolver()
        self.ref = solver
        self.quantum_instance = QuantumInstance(
            BasicAer.get_backend("statevector_simulator"),
            seed_transpiler=90,
            seed_simulator=12,
        )
    def __init__(
        self,
        transformation_matrix: np.ndarray,
        qubit_converter: Optional[QubitConverter] = None,
        validate: bool = True,
        rtol: float = 1e-5,
        atol: float = 1e-8,
        **circuit_kwargs,
    ) -> None:
        r"""
        Args:
            transformation_matrix: The matrix :math:`W` that specifies the coefficients of the
                new creation operators in terms of the original creation operators.
                Should be either :math:`N \times N` or :math:`N \times 2N`.
            qubit_converter: The qubit converter. The default behavior is to create
                one using the call `QubitConverter(JordanWignerMapper())`.
            validate: Whether to validate the inputs.
            rtol: Relative numerical tolerance for input validation.
            atol: Absolute numerical tolerance for input validation.
            circuit_kwargs: Keyword arguments to pass to the QuantumCircuit initializer.

        Raises:
            ValueError: transformation_matrix must be a 2-dimensional array.
            ValueError: transformation_matrix must have orthonormal rows.
            ValueError: transformation_matrix does not describe a valid transformation
                of fermionic ladder operators. If the transformation matrix is
                :math:`N \times N`, then it should be unitary.
                If the transformation matrix is :math:`N \times 2N`, then it should have the block form
                :math:`(W_1 \quad W_2)` where :math:`W_1 W_1^\dagger + W_2 W_2^\dagger = I` and
                :math:`W_1 W_2^T + W_2 W_1^T = 0`.
            NotImplementedError: Currently, only the Jordan-Wigner Transform is supported.
                Please use
                :class:`qiskit_nature.second_q.mappers.JordanWignerMapper`
                to construct the qubit mapper.
        """
        if validate:
            _validate_transformation_matrix(transformation_matrix,
                                            rtol=rtol,
                                            atol=atol)

        if qubit_converter is None:
            qubit_converter = QubitConverter(JordanWignerMapper())

        n, _ = transformation_matrix.shape
        register = QuantumRegister(n)
        super().__init__(register, **circuit_kwargs)

        if isinstance(qubit_converter.mapper, JordanWignerMapper):
            operations = _bogoliubov_transform_jw(register,
                                                  transformation_matrix)
            for gate, qubits in operations:
                self.append(gate, qubits)
        else:
            raise NotImplementedError(
                "Currently, only the Jordan-Wigner Transform is supported. "
                "Please use "
                "qiskit_nature.second_q.mappers.JordanWignerMapper "
                "to construct the qubit mapper.")
    def test_custom_filter_criterion(self):
        """Test NumPyEigenSolverFactory with ExcitedStatesEigensolver + Custom filter criterion
        for doublet states"""

        driver = PySCFDriver(
            atom="Be .0 .0 .0; H .0 .0 0.75",
            unit=UnitsType.ANGSTROM,
            charge=0,
            spin=1,
            basis="sto3g",
        )

        transformer = ActiveSpaceTransformer(
            num_electrons=(1, 2),
            num_molecular_orbitals=4,
        )
        # We define an ActiveSpaceTransformer to reduce the duration of this test example.

        converter = QubitConverter(JordanWignerMapper(),
                                   z2symmetry_reduction="auto")

        esp = ElectronicStructureProblem(driver, [transformer])

        expected_spin = 0.75  # Doublet states
        expected_num_electrons = 3  # 1 alpha electron + 2 beta electrons

        # pylint: disable=unused-argument
        def custom_filter_criterion(eigenstate, eigenvalue, aux_values):
            num_particles_aux = aux_values["ParticleNumber"][0]
            total_angular_momentum_aux = aux_values["AngularMomentum"][0]

            return np.isclose(expected_spin,
                              total_angular_momentum_aux) and np.isclose(
                                  expected_num_electrons, num_particles_aux)

        solver = NumPyEigensolverFactory(
            filter_criterion=custom_filter_criterion)
        esc = ExcitedStatesEigensolver(converter, solver)
        results = esc.solve(esp)

        # filter duplicates from list
        computed_energies = [results.computed_energies[0]]
        for comp_energy in results.computed_energies[1:]:
            if not np.isclose(comp_energy, computed_energies[-1]):
                computed_energies.append(comp_energy)

        ref_energies = [
            -2.6362023196223254,
            -2.2971398524128923,
            -2.2020252702733165,
            -2.1044859216523752,
            -1.696132447109807,
            -1.6416831059956618,
        ]

        for idx, energy in enumerate(ref_energies):
            self.assertAlmostEqual(computed_energies[idx], energy, places=3)
Exemplo n.º 7
0
    def test_succd_ansatz(self, num_spin_orbitals, num_particles, expect):
        """Tests the SUCCD Ansatz."""
        converter = QubitConverter(JordanWignerMapper())

        ansatz = SUCCD(
            qubit_converter=converter,
            num_particles=num_particles,
            num_spin_orbitals=num_spin_orbitals,
        )

        assert_ucc_like_ansatz(self, ansatz, num_spin_orbitals, expect)
Exemplo n.º 8
0
    def test_mp2_initial_point_with_real_molecules(
        self,
        atom,
    ):
        """Test MP2InitialPoint with real molecules."""
        from pyscf import gto  # pylint: disable=import-error

        # Compute the PySCF result
        pyscf_mol = gto.M(atom=atom, basis="sto3g", verbose=0)
        pyscf_mp = pyscf_mol.MP2().run(verbose=0)

        driver = PySCFDriver(atom=atom, basis="sto3g")

        problem = ElectronicStructureProblem(driver)
        problem.second_q_ops()
        grouped_property = problem.grouped_property_transformed

        particle_number = grouped_property.get_property(ParticleNumber)
        num_particles = (particle_number.num_alpha, particle_number.num_beta)
        num_spin_orbitals = particle_number.num_spin_orbitals

        qubit_converter = QubitConverter(mapper=JordanWignerMapper())

        initial_state = HartreeFock(
            num_spin_orbitals=num_spin_orbitals,
            num_particles=num_particles,
            qubit_converter=qubit_converter,
        )
        ansatz = UCC(
            num_spin_orbitals=num_spin_orbitals,
            num_particles=num_particles,
            excitations="sd",
            qubit_converter=qubit_converter,
            initial_state=initial_state,
        )

        mp2_initial_point = MP2InitialPoint()
        mp2_initial_point.grouped_property = grouped_property
        mp2_initial_point.ansatz = ansatz

        with self.subTest("Test the MP2 energy correction."):
            np.testing.assert_almost_equal(mp2_initial_point.energy_correction,
                                           pyscf_mp.e_corr,
                                           decimal=4)

        with self.subTest("Test the total MP2 energy."):
            np.testing.assert_almost_equal(mp2_initial_point.total_energy,
                                           pyscf_mp.e_tot,
                                           decimal=4)

        with self.subTest("Test the T2 amplitudes."):
            mp2_initial_point.compute()
            np.testing.assert_array_almost_equal(
                mp2_initial_point.t2_amplitudes, pyscf_mp.t2, decimal=4)
Exemplo n.º 9
0
    def test_puccd_ansatz_generalized(self, num_spin_orbitals, num_particles,
                                      expect):
        """Tests the generalized PUCCD Ansatz."""
        converter = QubitConverter(JordanWignerMapper())

        ansatz = PUCCD(
            qubit_converter=converter,
            num_particles=num_particles,
            num_spin_orbitals=num_spin_orbitals,
            generalized=True,
        )

        assert_ucc_like_ansatz(self, ansatz, num_spin_orbitals, expect)
Exemplo n.º 10
0
    def test_ucc_ansatz(self, excitations, num_spin_orbitals, num_particles,
                        expect):
        """Tests the UCC Ansatz."""
        converter = QubitConverter(JordanWignerMapper())

        ansatz = UCC(
            qubit_converter=converter,
            num_particles=num_particles,
            num_spin_orbitals=num_spin_orbitals,
            excitations=excitations,
        )

        assert_ucc_like_ansatz(self, ansatz, num_spin_orbitals, expect)
Exemplo n.º 11
0
    def test_succd_ansatz_with_singles(self, num_spin_orbitals, num_particles,
                                       include_singles, expect):
        """Tests the SUCCD Ansatz with included single excitations."""
        converter = QubitConverter(JordanWignerMapper())

        ansatz = SUCCD(
            qubit_converter=converter,
            num_particles=num_particles,
            num_spin_orbitals=num_spin_orbitals,
            include_singles=include_singles,
        )

        assert_ucc_like_ansatz(self, ansatz, num_spin_orbitals, expect)
Exemplo n.º 12
0
    def test_diagonalizing_bogoliubov_transform(self):
        """Test diagonalizing Bogoliubov transform."""
        hermitian_part = np.array(
            [[0.0, 1.0, 0.0], [1.0, 0.0, 1.0], [0.0, 1.0, 0.0]], dtype=complex)
        antisymmetric_part = np.array(
            [[0.0, 1.0j, 0.0], [-1.0j, 0.0, 1.0j], [0.0, -1.0j, 0.0]],
            dtype=complex)
        quad_ham = QuadraticHamiltonian(hermitian_part, antisymmetric_part)
        (
            transformation_matrix,
            orbital_energies,
            transformed_constant,
        ) = quad_ham.diagonalizing_bogoliubov_transform()

        # test that the transformation diagonalizes the Hamiltonian
        left = transformation_matrix[:, :3]
        right = transformation_matrix[:, 3:]
        full_transformation_matrix = np.block([[left, right],
                                               [right.conj(),
                                                left.conj()]])
        eye = np.eye(3, dtype=complex)
        majorana_basis = np.block([[eye, eye], [1j * eye, -1j * eye]
                                   ]) / np.sqrt(2)
        basis_change = majorana_basis @ full_transformation_matrix @ majorana_basis.T.conj(
        )
        majorana_matrix, majorana_constant = quad_ham.majorana_form()
        canonical = basis_change @ majorana_matrix @ basis_change.T

        zero = np.zeros((3, 3))
        diagonal = np.diag(orbital_energies)
        expected = np.block([[zero, diagonal], [-diagonal, zero]])

        np.testing.assert_allclose(orbital_energies, np.sort(orbital_energies))
        np.testing.assert_allclose(canonical, expected, atol=1e-7)
        np.testing.assert_allclose(
            transformed_constant,
            majorana_constant - 0.5 * np.sum(orbital_energies))

        # confirm eigenvalues match with Jordan-Wigner transformed Hamiltonian
        hamiltonian_jw = (QubitConverter(mapper=JordanWignerMapper()).convert(
            quad_ham.to_fermionic_op()).primitive.to_matrix())
        eigs, _ = np.linalg.eigh(hamiltonian_jw)
        expected_eigs = np.array([
            np.sum(orbital_energies[list(occupied_orbitals)]) +
            transformed_constant for occupied_orbitals in [(), (0, ), (
                1, ), (2, ), (0, 1), (0, 2), (1, 2), (0, 1, 2)]
        ])
        np.testing.assert_allclose(np.sort(eigs),
                                   np.sort(expected_eigs),
                                   atol=1e-7)
Exemplo n.º 13
0
    def _run_driver(
        driver: ElectronicStructureDriver,
        converter: QubitConverter = QubitConverter(JordanWignerMapper()),
        transformers: Optional[List[BaseTransformer]] = None,
    ):

        problem = ElectronicStructureProblem(driver, transformers)

        solver = NumPyMinimumEigensolver()

        gsc = GroundStateEigensolver(converter, solver)

        result = gsc.solve(problem)
        return result
Exemplo n.º 14
0
    def test_transpile_no_parameters(self):
        """Test transpilation without parameters"""

        num_spin_orbitals = 8
        num_particles = (2, 2)
        qubit_converter = QubitConverter(mapper=JordanWignerMapper())

        ansatz = UCC(
            num_spin_orbitals=num_spin_orbitals,
            num_particles=num_particles,
            qubit_converter=qubit_converter,
            excitations="s",
        )

        ansatz = transpile(ansatz, optimization_level=3)
        self.assertEqual(ansatz.num_qubits, 8)
    def setUp(self):
        super().setUp()
        self.driver = HDF5Driver(
            self.get_resource_path("test_driver_hdf5.hdf5",
                                   "second_q/drivers/hdf5d"))
        self.seed = 56
        algorithm_globals.random_seed = self.seed

        self.reference_energy = -1.1373060356951838

        self.qubit_converter = QubitConverter(JordanWignerMapper())
        self.electronic_structure_problem = ElectronicStructureProblem(
            self.driver)

        self.num_spin_orbitals = 4
        self.num_particles = (1, 1)
Exemplo n.º 16
0
    def test_custom_excitations(self, num_spin_orbitals, num_particles,
                                excitations):
        """Tests if an error is raised when the excitations have a wrong format"""
        converter = QubitConverter(JordanWignerMapper())

        # pylint: disable=unused-argument
        def custom_excitations(num_spin_orbitals, num_particles):
            return excitations

        with self.assertRaises(QiskitNatureError):
            ansatz = UCC(
                qubit_converter=converter,
                num_particles=num_particles,
                num_spin_orbitals=num_spin_orbitals,
                excitations=custom_excitations,
            )
            ansatz.excitation_ops()
    def test_molecular_problem_sector_locator_z2_symmetry(self):
        """Test mapping to qubit operator with z2 symmetry tapering and two qubit reduction"""

        driver = HDF5Driver(hdf5_input=self.get_resource_path(
            "test_driver_hdf5.hdf5", "second_q/drivers/hdf5d"))
        problem = ElectronicStructureProblem(driver)

        mapper = JordanWignerMapper()
        qubit_conv = QubitConverter(mapper,
                                    two_qubit_reduction=True,
                                    z2symmetry_reduction="auto")
        main_op, _ = problem.second_q_ops()
        qubit_op = qubit_conv.convert(
            main_op,
            self.num_particles,
            sector_locator=problem.symmetry_sector_locator,
        )
        self.assertEqual(qubit_op, TestQubitConverter.REF_H2_JW_TAPERED)
Exemplo n.º 18
0
    def setUp(self):
        super().setUp()

        self.converter = QubitConverter(JordanWignerMapper())

        self.seed = 50
        self.quantum_instance = QuantumInstance(
            BasicAer.get_backend("statevector_simulator"),
            shots=1,
            seed_simulator=self.seed,
            seed_transpiler=self.seed,
        )
        self.quantum_instance_2 = QuantumInstance(
            BasicAer.get_backend("statevector_simulator"),
            shots=2,
            seed_simulator=self.seed,
            seed_transpiler=self.seed,
        )

        self._vqe_ucc_factory = VQEUCCFactory(
            quantum_instance=self.quantum_instance)
    def test_mapping_basic(self):
        """Test mapping to qubit operator"""
        mapper = JordanWignerMapper()
        qubit_conv = QubitConverter(mapper)
        qubit_op = qubit_conv.convert(self.h2_op)

        self.assertIsInstance(qubit_op, PauliSumOp)

        # Note: The PauliSumOp equals, as used in the test below, use the equals of the
        #       SparsePauliOp which in turn uses np.allclose() to determine equality of
        #       coeffs. So the reference operator above will be matched on that basis so
        #       we don't need to worry about tiny precision changes for any reason.

        self.assertEqual(qubit_op, TestQubitConverter.REF_H2_JW)

        with self.subTest("Re-use test"):
            qubit_op = qubit_conv.convert(self.h2_op)
            self.assertEqual(qubit_op, TestQubitConverter.REF_H2_JW)

        with self.subTest("convert_match()"):
            qubit_op = qubit_conv.convert_match(self.h2_op)
            self.assertEqual(qubit_op, TestQubitConverter.REF_H2_JW)

        with self.subTest("Re-use with different mapper"):
            qubit_conv.mapper = ParityMapper()
            qubit_op = qubit_conv.convert(self.h2_op)
            self.assertEqual(qubit_op, TestQubitConverter.REF_H2_PARITY)

        with self.subTest(
                "Set two qubit reduction - no effect without num particles"):
            qubit_conv.two_qubit_reduction = True
            qubit_op = qubit_conv.convert_match(self.h2_op)
            self.assertEqual(qubit_op, TestQubitConverter.REF_H2_PARITY)

        with self.subTest("Force match set num particles"):
            qubit_conv.force_match(self.num_particles)
            qubit_op = qubit_conv.convert_match(self.h2_op)
            self.assertEqual(qubit_op,
                             TestQubitConverter.REF_H2_PARITY_2Q_REDUCED)
 def test_slater_determinant(self):
     """Test preparing Slater determinants."""
     n_orbitals = 5
     converter = QubitConverter(JordanWignerMapper())
     quad_ham = random_quadratic_hamiltonian(n_orbitals,
                                             num_conserving=True,
                                             seed=8839)
     (
         transformation_matrix,
         orbital_energies,
         transformed_constant,
     ) = quad_ham.diagonalizing_bogoliubov_transform()
     fermionic_op = quad_ham.to_fermionic_op()
     qubit_op = converter.convert(fermionic_op)
     matrix = qubit_op.to_matrix()
     for n_particles in range(n_orbitals + 1):
         circuit = SlaterDeterminant(transformation_matrix[:n_particles],
                                     qubit_converter=converter)
         final_state = np.array(Statevector(circuit))
         eig = np.sum(orbital_energies[:n_particles]) + transformed_constant
         np.testing.assert_allclose(matrix @ final_state,
                                    eig * final_state,
                                    atol=1e-7)
 def test_bogoliubov_transform(self, n_orbitals, num_conserving):
     """Test Bogoliubov transform."""
     converter = QubitConverter(JordanWignerMapper())
     hamiltonian = random_quadratic_hamiltonian(
         n_orbitals, num_conserving=num_conserving, seed=5740)
     (
         transformation_matrix,
         orbital_energies,
         transformed_constant,
     ) = hamiltonian.diagonalizing_bogoliubov_transform()
     matrix = converter.map(hamiltonian.to_fermionic_op()).to_matrix()
     bog_circuit = BogoliubovTransform(transformation_matrix,
                                       qubit_converter=converter)
     for initial_state in range(2**n_orbitals):
         state = Statevector.from_int(initial_state, dims=2**n_orbitals)
         final_state = np.array(state.evolve(bog_circuit))
         occupied_orbitals = [
             i for i in range(n_orbitals) if initial_state >> i & 1
         ]
         eig = np.sum(
             orbital_energies[occupied_orbitals]) + transformed_constant
         np.testing.assert_allclose(matrix @ final_state,
                                    eig * final_state,
                                    atol=1e-8)
Exemplo n.º 22
0
 def test_qubits_4_jw_h2(self):
     """qubits 4 jw h2 test"""
     state = HartreeFock(4, (1, 1), QubitConverter(JordanWignerMapper()))
     ref = QuantumCircuit(4)
     ref.x([0, 2])
     self.assertEqual(state, ref)
 def test_vqe_mes_jw_auto(self):
     """Test VQEUCCSDFactory with QEOM + Jordan Wigner mapping + auto symmetry"""
     converter = QubitConverter(JordanWignerMapper(),
                                z2symmetry_reduction="auto")
     self._solve_with_vqe_mes(converter)
 def test_vqe_mes_jw(self):
     """Test VQEUCCSDFactory with QEOM + Jordan Wigner mapping"""
     converter = QubitConverter(JordanWignerMapper())
     self._solve_with_vqe_mes(converter)
 def test_allows_two_qubit_reduction(self):
     """Test this returns False for this mapper"""
     mapper = JordanWignerMapper()
     self.assertFalse(mapper.allows_two_qubit_reduction)
Exemplo n.º 26
0
    def test_build_ucc(self):
        """Test building UCC"""
        ucc = UCC()

        with self.subTest("Check defaulted construction"):
            self.assertIsNone(ucc.num_particles)
            self.assertIsNone(ucc.num_spin_orbitals)
            self.assertIsNone(ucc.excitations)
            self.assertIsNone(ucc.qubit_converter)
            self.assertIsNone(ucc.operators)
            self.assertIsNone(ucc.excitation_list)
            self.assertEqual(ucc.num_qubits, 0)
            with self.assertRaises(ValueError):
                _ = ucc.data

        with self.subTest("Set num particles"):
            ucc.num_particles = (1, 1)
            self.assertEqual(ucc.num_particles, (1, 1))
            self.assertIsNone(ucc.operators)
            with self.assertRaises(ValueError):
                _ = ucc.data

        with self.subTest("Set num spin orbitals"):
            ucc.num_spin_orbitals = 4
            self.assertEqual(ucc.num_spin_orbitals, 4)
            self.assertIsNone(ucc.operators)
            with self.assertRaises(ValueError):
                _ = ucc.data

        with self.subTest("Set excitations"):
            ucc.excitations = "sd"
            self.assertEqual(ucc.excitations, "sd")
            self.assertIsNone(ucc.operators)
            with self.assertRaises(ValueError):
                _ = ucc.data

        with self.subTest("Set qubit converter to complete build"):
            converter = QubitConverter(JordanWignerMapper())
            ucc.qubit_converter = converter
            self.assertEqual(ucc.qubit_converter, converter)
            self.assertIsNotNone(ucc.operators)
            self.assertEqual(len(ucc.operators), 3)
            self.assertEqual(ucc.num_qubits, 4)
            self.assertIsNotNone(ucc.data)

        with self.subTest("Set custom operators"):
            self.assertEqual(len(ucc.operators), 3)
            ucc.operators = ucc.operators[:2]
            self.assertEqual(len(ucc.operators), 2)
            self.assertEqual(ucc.num_qubits, 4)

        with self.subTest("Reset operators back to as per UCC"):
            ucc.operators = None
            self.assertEqual(ucc.num_qubits, 4)
            self.assertIsNotNone(ucc.operators)
            self.assertEqual(len(ucc.operators), 3)

        with self.subTest("Set num particles to include 0"):
            ucc.num_particles = (1, 0)
            self.assertEqual(ucc.num_particles, (1, 0))
            self.assertIsNotNone(ucc.operators)
            self.assertEqual(len(ucc.operators), 1)

        with self.subTest("Change num particles"):
            ucc.num_particles = (1, 1)
            self.assertIsNotNone(ucc.operators)
            self.assertEqual(len(ucc.operators), 3)

        with self.subTest("Change num spin orbitals"):
            ucc.num_spin_orbitals = 6
            self.assertIsNotNone(ucc.operators)
            self.assertEqual(len(ucc.operators), 8)

        with self.subTest("Change excitations"):
            ucc.excitations = "s"
            self.assertIsNotNone(ucc.operators)
            self.assertEqual(len(ucc.operators), 4)

        with self.subTest("Change qubit converter"):
            ucc.qubit_converter = QubitConverter(ParityMapper(),
                                                 two_qubit_reduction=True)
            # Has not been used to convert so we need to force it to do two qubit reduction
            ucc.qubit_converter.force_match(ucc.num_particles)
            self.assertIsNotNone(ucc.operators)
            self.assertEqual(ucc.num_qubits, 4)
Exemplo n.º 27
0
    def __init__(
        self,
        transformation_matrix: np.ndarray,
        occupied_orbitals: Optional[Sequence[int]] = None,
        qubit_converter: QubitConverter = None,
        validate: bool = True,
        rtol: float = 1e-5,
        atol: float = 1e-8,
        **circuit_kwargs,
    ) -> None:
        r"""
        Args:
            transformation_matrix: The matrix :math:`W` that specifies the coefficients of the
                new creation operators in terms of the original creation and annihilation operators.
                This matrix must satisfy special constraints, as detailed above.
            occupied_orbitals: The pseudo-particle orbitals to fill. These refer to the indices
                of the operators :math:`\{b^\dagger_j\}` from the main body of the docstring
                of this function. The default behavior is to use the empty set of orbitals,
                which corresponds to a state with zero pseudo-particles.
            qubit_converter: The qubit converter. The default behavior is to create
                one using the call `QubitConverter(JordanWignerMapper())`.
            validate: Whether to validate the inputs.
            rtol: Relative numerical tolerance for input validation.
            atol: Absolute numerical tolerance for input validation.
            circuit_kwargs: Keyword arguments to pass to the QuantumCircuit initializer.

        Raises:
            ValueError: transformation_matrix must be a 2-dimensional array.
            ValueError: transformation_matrix must have shape (n_orbitals, 2 * n_orbitals).
            ValueError: transformation_matrix does not describe a valid transformation
                of fermionic ladder operators. A valid matrix has the block form
                :math:`(W_1 \quad W_2)` where :math:`W_1 W_1^\dagger + W_2 W_2^\dagger = I` and
                :math:`W_1 W_2^T + W_2 W_1^T = 0`.

            NotImplementedError: Currently, only the Jordan-Wigner Transform is supported.
                Please use
                :class:`qiskit_nature.second_q.mappers.JordanWignerMapper`
                to construct the qubit mapper used to construct `qubit_converter`.
        """
        if validate:
            _validate_transformation_matrix(transformation_matrix,
                                            rtol=rtol,
                                            atol=atol)

        if occupied_orbitals is None:
            occupied_orbitals = []
        if qubit_converter is None:
            qubit_converter = QubitConverter(JordanWignerMapper())

        n, _ = transformation_matrix.shape
        register = QuantumRegister(n)
        super().__init__(register, **circuit_kwargs)

        if isinstance(qubit_converter.mapper, JordanWignerMapper):
            operations = _prepare_fermionic_gaussian_state_jw(
                register, transformation_matrix, occupied_orbitals)
            for gate, qubits in operations:
                self.append(gate, qubits)
        else:
            raise NotImplementedError(
                "Currently, only the Jordan-Wigner Transform is supported. "
                "Please use "
                "qiskit_nature.second_q.mappers.JordanWignerMapper "
                "to construct the qubit mapper used to construct qubit_converter."
            )