Ejemplo n.º 1
0
    def setUp(self):
        super().setUp()
        # np.random.seed(50)
        self.seed = 50
        algorithm_globals.random_seed = self.seed
        try:
            self.driver = PySCFDriver(atom='H .0 .0 .0; H .0 .0 0.735',
                                      unit=UnitsType.ANGSTROM,
                                      basis='sto3g')
        except QiskitNatureError:
            self.skipTest('PYSCF driver does not appear to be installed')
            return

        molecule = self.driver.run()
        self.num_particles = molecule.num_alpha + molecule.num_beta
        self.num_spin_orbitals = molecule.num_orbitals * 2
        fer_op = FermionicOperator(h1=molecule.one_body_integrals,
                                   h2=molecule.two_body_integrals)
        map_type = 'PARITY'
        qubit_op = fer_op.mapping(map_type)
        self.qubit_op = TwoQubitReduction(
            num_particles=self.num_particles).convert(qubit_op)
        self.num_qubits = self.qubit_op.num_qubits
        self.init_state = HartreeFock(self.num_spin_orbitals,
                                      self.num_particles)
        self.var_form_base = None
Ejemplo n.º 2
0
 def test_with_two_qubit_reduction(self):
     """Test the VQE using TwoQubitReduction."""
     qubit_op = PauliSumOp.from_list([
         ("IIII", -0.8105479805373266),
         ("IIIZ", 0.17218393261915552),
         ("IIZZ", -0.22575349222402472),
         ("IZZI", 0.1721839326191556),
         ("ZZII", -0.22575349222402466),
         ("IIZI", 0.1209126326177663),
         ("IZZZ", 0.16892753870087912),
         ("IXZX", -0.045232799946057854),
         ("ZXIX", 0.045232799946057854),
         ("IXIX", 0.045232799946057854),
         ("ZXZX", -0.045232799946057854),
         ("ZZIZ", 0.16614543256382414),
         ("IZIZ", 0.16614543256382414),
         ("ZZZZ", 0.17464343068300453),
         ("ZIZI", 0.1209126326177663),
     ])
     tapered_qubit_op = TwoQubitReduction(num_particles=2).convert(qubit_op)
     for simulator in [self.qasm_simulator, self.statevector_simulator]:
         with self.subTest(f"Test for {simulator}."):
             vqe = VQE(
                 self.ry_wavefunction,
                 SPSA(maxiter=300, last_avg=5),
                 quantum_instance=simulator,
             )
             result = vqe.compute_minimum_eigenvalue(tapered_qubit_op)
             energy = -1.868 if simulator == self.qasm_simulator else self.h2_energy
             self.assertAlmostEqual(result.eigenvalue.real,
                                    energy,
                                    places=2)
Ejemplo n.º 3
0
    def _map_fermionic_operator_to_qubit(
            fer_op: FermionicOperator, qubit_mapping: str,
            num_particles: List[int], two_qubit_reduction: bool) -> PauliSumOp:
        """

        Args:
            fer_op: Fermionic Operator
            qubit_mapping: fermionic to qubit mapping
            num_particles: number of particles
            two_qubit_reduction: two qubit reduction

        Returns:
            qubit operator
        """

        qubit_op = fer_op.mapping(map_type=qubit_mapping, threshold=0.00000001)
        if qubit_mapping == 'parity' and two_qubit_reduction:
            qubit_op = TwoQubitReduction(
                num_particles=num_particles).convert(qubit_op)
        return qubit_op
Ejemplo n.º 4
0
    def _build_single_hopping_operator(index, num_particles, num_orbitals,
                                       qubit_mapping, two_qubit_reduction,
                                       z2_symmetries):

        h_1 = np.zeros((num_orbitals, num_orbitals), dtype=complex)
        h_2 = np.zeros(
            (num_orbitals, num_orbitals, num_orbitals, num_orbitals),
            dtype=complex)
        if len(index) == 2:
            i, j = index
            h_1[i, j] = 4.0
        elif len(index) == 4:
            i, j, k, m = index
            h_2[i, j, k, m] = 16.0
        fer_op = FermionicOperator(h_1, h_2)
        qubit_op = fer_op.mapping(qubit_mapping)
        if qubit_mapping == 'parity' and two_qubit_reduction:
            qubit_op = TwoQubitReduction(
                num_particles=num_particles).convert(qubit_op)

        commutativities = []
        if not z2_symmetries.is_empty():
            for symmetry in z2_symmetries.symmetries:
                symmetry_op = PauliSumOp.from_list([(symmetry.to_label(), 1.0)
                                                    ])
                commuting = qubit_op.primitive.table.commutes_with_all(
                    symmetry_op.primitive.table)
                anticommuting = qubit_op.primtive.table.anticommutes_with_all(
                    symmetry_op.primitive.table)

                if commuting != anticommuting:  # only one of them is True
                    if commuting:
                        commutativities.append(True)
                    elif anticommuting:
                        commutativities.append(False)
                else:
                    raise QiskitNatureError(
                        "Symmetry {} is nor commute neither anti-commute "
                        "to exciting operator.".format(symmetry.to_label()))

        return qubit_op, commutativities
    def test_convert(self):
        """ convert test """

        qubit_op = PauliSumOp.from_list([
            ("IIII", -0.8105479805373266),
            ("IIIZ", 0.17218393261915552),
            ("IIZZ", -0.22575349222402472),
            ("IZZI", 0.1721839326191556),
            ("ZZII", -0.22575349222402466),
            ("IIZI", 0.1209126326177663),
            ("IZZZ", 0.16892753870087912),
            ("IXZX", -0.045232799946057854),
            ("ZXIX", 0.045232799946057854),
            ("IXIX", 0.045232799946057854),
            ("ZXZX", -0.045232799946057854),
            ("ZZIZ", 0.16614543256382414),
            ("IZIZ", 0.16614543256382414),
            ("ZZZZ", 0.17464343068300453),
            ("ZIZI", 0.1209126326177663),
        ])
        tapered_qubit_op = TwoQubitReduction(num_particles=2).convert(qubit_op)
        self.assertIsInstance(tapered_qubit_op, TaperedPauliSumOp)

        primitive = SparsePauliOp.from_list([
            ("II", -1.052373245772859),
            ("ZI", -0.39793742484318007),
            ("IZ", 0.39793742484318007),
            ("ZZ", -0.01128010425623538),
            ("XX", 0.18093119978423142),
        ])
        symmetries = [Pauli("IIZI"), Pauli("ZIII")]
        sq_paulis = [Pauli("IIXI"), Pauli("XIII")]
        sq_list = [1, 3]
        tapering_values = [-1, 1]
        z2_symmetries = Z2Symmetries(symmetries, sq_paulis, sq_list,
                                     tapering_values)
        expected_op = TaperedPauliSumOp(primitive, z2_symmetries)
        self.assertEqual(tapered_qubit_op, expected_op)
Ejemplo n.º 6
0
    def _build_hopping_operator(index,
                                num_orbitals,
                                num_particles,
                                qubit_mapping,
                                two_qubit_reduction,
                                z2_symmetries,
                                skip_commute_test=False):
        """
        Builds a hopping operator given the list of indices (index) that is a single or a double
        excitation.

        Args:
            index (list): a single or double excitation (e.g. double excitation [0,1,2,3] for a 4
                          spin-orbital system)
            num_orbitals (int): number of spin-orbitals
            num_particles (int): number of electrons
            qubit_mapping (str): qubit mapping type
            two_qubit_reduction (bool): reduce the number of qubits by 2 if
                                        parity qubit mapping is used
            z2_symmetries (Z2Symmetries): class that contains the symmetries
                                          of hamiltonian for tapering
            skip_commute_test (bool): when tapering excitation operators we test and exclude any
                                that do not commute with symmetries. This test can be skipped to
                                include all tapered excitation operators whether they commute
                                or not.
        Returns:
            PauliSumOp: qubit_op
            list: index
        """
        h_1 = np.zeros((num_orbitals, num_orbitals))
        h_2 = np.zeros(
            (num_orbitals, num_orbitals, num_orbitals, num_orbitals))
        if len(index) == 2:
            i, j = index
            h_1[i, j] = 1.0
            h_1[j, i] = -1.0
        elif len(index) == 4:
            i, j, k, m = index
            h_2[i, j, k, m] = 1.0
            h_2[m, k, j, i] = -1.0

        dummpy_fer_op = FermionicOperator(h1=h_1, h2=h_2)
        qubit_op = dummpy_fer_op.mapping(qubit_mapping)
        if two_qubit_reduction:
            qubit_op = TwoQubitReduction(
                num_particles=num_particles).convert(qubit_op)

        if not z2_symmetries.is_empty():
            symm_commuting = True
            for symmetry in z2_symmetries.symmetries:
                symmetry_op = PauliSumOp.from_list([(symmetry.to_label(), 1.0)
                                                    ])
                symm_commuting = qubit_op.primitive.table.commutes_with_all(
                    symmetry_op.primitive.table)
                if not symm_commuting:
                    break
            if not skip_commute_test:
                qubit_op = z2_symmetries.taper(
                    qubit_op) if symm_commuting else None
            else:
                qubit_op = z2_symmetries.taper(qubit_op)

        if qubit_op is None:
            logger.debug(
                'Excitation (%s) is skipped since it is not commuted '
                'with symmetries', ','.join([str(x) for x in index]))
        return qubit_op, index
Ejemplo n.º 7
0
    def test_readme_sample(self):
        """ readme sample test """

        # pylint: disable=import-outside-toplevel,redefined-builtin

        def print(*args):
            """ overloads print to log values """
            if args:
                self.log.debug(args[0], *args[1:])

        # --- Exact copy of sample code ----------------------------------------

        from qiskit_nature import FermionicOperator
        from qiskit_nature.drivers import PySCFDriver, UnitsType
        from qiskit.opflow import TwoQubitReduction

        # Use PySCF, a classical computational chemistry software
        # package, to compute the one-body and two-body integrals in
        # molecular-orbital basis, necessary to form the Fermionic operator
        driver = PySCFDriver(atom='H .0 .0 .0; H .0 .0 0.735',
                             unit=UnitsType.ANGSTROM,
                             basis='sto3g')
        molecule = driver.run()
        num_particles = molecule.num_alpha + molecule.num_beta
        num_spin_orbitals = molecule.num_orbitals * 2

        # Build the qubit operator, which is the input to the VQE algorithm
        ferm_op = FermionicOperator(h1=molecule.one_body_integrals,
                                    h2=molecule.two_body_integrals)
        map_type = 'PARITY'
        qubit_op = ferm_op.mapping(map_type)
        qubit_op = TwoQubitReduction(
            num_particles=num_particles).convert(qubit_op)
        num_qubits = qubit_op.num_qubits

        # setup a classical optimizer for VQE
        from qiskit.algorithms.optimizers import L_BFGS_B
        optimizer = L_BFGS_B()

        # setup the initial state for the variational form
        from qiskit_nature.circuit.library import HartreeFock
        init_state = HartreeFock(num_spin_orbitals, num_particles)

        # setup the variational form for VQE
        from qiskit.circuit.library import TwoLocal
        var_form = TwoLocal(num_qubits, ['ry', 'rz'], 'cz')

        # add the initial state
        var_form.compose(init_state, front=True)

        # set the backend for the quantum computation
        from qiskit import Aer
        backend = Aer.get_backend('statevector_simulator')

        # setup and run VQE
        from qiskit.algorithms import VQE
        algorithm = VQE(var_form,
                        optimizer=optimizer,
                        quantum_instance=backend)

        result = algorithm.compute_minimum_eigenvalue(qubit_op)
        print(result.eigenvalue.real)

        # ----------------------------------------------------------------------

        self.assertAlmostEqual(result.eigenvalue.real,
                               -1.8572750301938803,
                               places=6)