Пример #1
0
 def setUp(self):
     self.fermion_term = FermionOperator('1^ 2^ 3 4', -3.17)
     self.fermion_operator = self.fermion_term + hermitian_conjugated(
         self.fermion_term)
     self.boson_term = BosonOperator('1^ 2^ 3 4', -3.17)
     self.boson_operator = self.boson_term + hermitian_conjugated(
         self.boson_term)
     self.quad_term = QuadOperator('q0 p0 q1 p0 p0', -3.17)
     self.quad_operator = self.quad_term + hermitian_conjugated(
         self.quad_term)
     self.qubit_operator = jordan_wigner(self.fermion_operator)
 def test_ccr_onsite(self):
     c1 = FermionOperator(((1, 1),))
     a1 = hermitian_conjugated(c1)
     self.assertTrue(normal_ordered(c1 * a1) ==
         FermionOperator(()) - normal_ordered(a1 * c1))
     self.assertTrue(jordan_wigner(c1 * a1) ==
         QubitOperator(()) - jordan_wigner(a1 * c1))
Пример #3
0
def number_nonconserving_fop(rank: int, norb: int) -> FermionOperator:
    # TODO: Complete docstring.
    """Returns a FermionOperator Hamiltonian which...

    Args:
        rank:
        norb:
    """
    hamil = FermionOperator()

    if rank >= 0:
        hamil += FermionOperator("", 6.0)

    if rank >= 2:
        for i in range(0, 2 * norb, 2):
            for j in range(0, 2 * norb, 2):
                opstring = str(i) + " " + str(j + 1)
                hamil += FermionOperator(
                    opstring,
                    (i + 1 + j * 2) * 0.1 - (i + 1 + 2 * (j + 1)) * 0.1j,
                )
                opstring = str(i) + "^ " + str(j + 1) + "^ "
                hamil += FermionOperator(opstring, (i + 1 + j) * 0.1 +
                                         (i + 1 + j) * 0.1j)
                opstring = str(i + 1) + " " + str(j)
                hamil += FermionOperator(opstring, (i + 1 + j) * 0.1 -
                                         (i + 1 + j) * 0.1j)
                opstring = str(i + 1) + "^ " + str(j) + "^ "
                hamil += FermionOperator(
                    opstring,
                    (i + 1 + j * 2) * 0.1 + (i + 1 + 2 * (j + 1)) * 0.1j,
                )

    return (hamil + hermitian_conjugated(hamil)) / 2.0
Пример #4
0
 def fermion_generator(self) -> 'openfermion.FermionOperator':
     """The FermionOperator G such that the gate's unitary is exp(-i t G)
     with exponent t using the Jordan-Wigner transformation."""
     half_generator = sum(
         (w * G
          for w, G in zip(self.weights, self.fermion_generator_components())
          ), ops.FermionOperator())
     return half_generator + hermitian_conjugated(half_generator)
    def test_jordan_wigner_interaction_op_with_zero_term(self):
        test_op = FermionOperator('1^ 2^ 3 4')
        test_op += hermitian_conjugated(test_op)

        interaction_op = get_interaction_operator(test_op)
        interaction_op.constant = 0.0

        retransformed_test_op = reverse_jordan_wigner(
            jordan_wigner(interaction_op))
Пример #6
0
def get_dressed_operator(dress_operator, operator2dress):
    """ Return a QubitOperator modified as U^HU
    Args:
        dress_operator: U
        operator2dress: H
    """
    new_operator = hermitian_conjugated(dress_operator) * operator2dress
    new_operator = new_operator * dress_operator
    return new_operator
Пример #7
0
    def test_jordan_wigner_twobody_interaction_op_allunique(self):
        test_op = FermionOperator('1^ 2^ 3 4')
        test_op += hermitian_conjugated(test_op)

        retransformed_test_op = reverse_jordan_wigner(
            jordan_wigner(get_interaction_operator(test_op)))

        self.assertTrue(
            normal_ordered(retransformed_test_op) == normal_ordered(test_op))
Пример #8
0
def s_matrix(operators, state):
    l = len(operators)
    s = numpy.empty((l, l), dtype=numpy.complex128)
    for i in range(l):
        for j in range(i + 1):
            o = hermitian_conjugated(operators[i])
            o *= operators[j]
            e = expectation_value(o, state)
            s[i, j] = e
            if i != j: s[j, i] = e.conjugate()
    return s
Пример #9
0
    def test_uccsd_anti_hermitian(self):
        """Test operators are anti-Hermitian independent of inputs"""
        test_orbitals = 4

        single_amplitudes = randn(*(test_orbitals, ) * 2)
        double_amplitudes = randn(*(test_orbitals, ) * 4)

        generator = uccsd_generator(single_amplitudes, double_amplitudes)
        conj_generator = hermitian_conjugated(generator)

        self.assertEqual(generator, -1. * conj_generator)
Пример #10
0
    def test_jordan_wigner_one_body(self):
        # Make sure it agrees with jordan_wigner(FermionTerm).
        for p in range(self.n_qubits):
            for q in range(self.n_qubits):
                # Get test qubit operator.
                test_operator = jordan_wigner_one_body(p, q)

                # Get correct qubit operator.
                fermion_term = FermionOperator(((p, 1), (q, 0)))
                correct_op = jordan_wigner(fermion_term)
                hermitian_conjugate = hermitian_conjugated(fermion_term)
                if not fermion_term == hermitian_conjugate:
                    correct_op += jordan_wigner(hermitian_conjugate)

                self.assertTrue(test_operator == correct_op)
Пример #11
0
    def get_qubit_excitation_generator(qubits_1, qubits_2):

        assert len(qubits_2) == len(qubits_1)

        term_1 = QubitOperator('')

        for qubit_1, qubit_2 in zip(qubits_1, qubits_2):
            term_1 *= (QubitOperator('X{}'.format(qubit_1), 0.5) +
                       QubitOperator('Y{}'.format(qubit_1), 0.5j))
            term_1 *= (QubitOperator('X{}'.format(qubit_2), 0.5) -
                       QubitOperator('Y{}'.format(qubit_2), 0.5j))

        term_2 = hermitian_conjugated(term_1)

        return term_1 - term_2
Пример #12
0
def test_qubitop_to_qiskitpauli():
    """
    Conversion of QubitOperator; accuracy test
    """
    hop_term = FermionOperator(((2, 1), (0, 0)))
    term = hop_term + hermitian_conjugated(hop_term)

    pauli_term = jordan_wigner(term)

    qiskit_op = qubitop_to_qiskitpauli(pauli_term)

    ground_truth = WeightedPauliOperator([[0.5, Pauli.from_label("XZX")],
                                          [0.5, Pauli.from_label("YZY")]])

    assert ground_truth == qiskit_op
Пример #13
0
def test_qubitop_to_paulisum():
    """
    Conversion of QubitOperator; accuracy test
    """
    hop_term = FermionOperator(((2, 1), (0, 0)))
    term = hop_term + hermitian_conjugated(hop_term)

    pauli_term = jordan_wigner(term)

    forest_term = qubitop_to_pyquilpauli(pauli_term)
    ground_truth = PauliTerm("X", 0) * PauliTerm("Z", 1) * PauliTerm("X", 2)
    ground_truth += PauliTerm("Y", 0) * PauliTerm("Z", 1) * PauliTerm("Y", 2)
    ground_truth *= 0.5

    assert ground_truth == forest_term
Пример #14
0
        def add_singles(occ_idx, vir_idx):
            for i in occ_idx:
                for a in vir_idx:
                    single = FermionOperator(((a, 1), (i, 0)))
                    # 1. build Fermion anti-Hermitian operator
                    single -= hermitian_conjugated(single)
                    # 2. JW transformation to qubit operator
                    jw_single = jordan_wigner(single)
                    h_single_commutator = commutator(self.h_qubit_OF, jw_single)
                    # 3. qforte.build_from_openfermion(OF_qubitop)
                    qf_jw_single = qforte.build_from_openfermion(jw_single)
                    qf_commutator = qforte.build_from_openfermion(h_single_commutator)

                    self.fermion_ops.append((i,a))
                    self.jw_ops.append(qf_jw_single)
                    self.jw_commutators.append(qf_commutator)
Пример #15
0
    def test_uccsd_singlet_anti_hermitian(self):
        """Test that the singlet version is anti-Hermitian"""
        test_orbitals = 8
        test_electrons = 4

        packed_amplitude_size = uccsd_singlet_paramsize(
            test_orbitals, test_electrons)

        packed_amplitudes = randn(int(packed_amplitude_size))

        generator = uccsd_singlet_generator(packed_amplitudes, test_orbitals,
                                            test_electrons)

        conj_generator = hermitian_conjugated(generator)

        self.assertEqual(generator, -1. * conj_generator)
Пример #16
0
        def add_doubles(occ_idx_pairs, vir_idx_pairs):
            for ji in occ_idx_pairs:
                for ba in vir_idx_pairs:
                    j, i = ji
                    b, a = ba

                    double = FermionOperator(F'{a}^ {b}^ {i} {j}')
                    double -= hermitian_conjugated(double)
                    jw_double = jordan_wigner(double)
                    h_double_commutator = commutator(self.h_qubit_OF, jw_double)

                    qf_jw_double = qforte.build_from_openfermion(jw_double)
                    qf_commutator = qforte.build_from_openfermion(
                    h_double_commutator)

                    self.fermion_ops.append((j,i,b,a))
                    self.jw_ops.append(qf_jw_double)
                    self.jw_commutators.append(qf_commutator)
Пример #17
0
def conv_anti(hamiltonian_list):
    """
    str型にしたフェルミ演算子から
    反エルミートな演算子を作る
    """
    op = 0 * QubitOperator("")
    for i in range(len(hamiltonian_list)):
        fop = FermionOperator(hamiltonian_list[i][1])
        anti_fop = fop - hermitian_conjugated(fop)
        anti_tmp = str(jordan_wigner(anti_fop)).replace("]", "")
        anti_list = [
            x.strip().split("[") for x in anti_tmp.split("+")
            # anti_tmp.strip()ではなくx.strip()では?
            #if not anti_tmp.strip() == ""]
            if not x.strip() == ""
        ]
        # 1以上ではない?
        if len(anti_list) > 1:
            for j in range(len(anti_list)):
                qop = QubitOperator(anti_list[j][1])
                op += qop
    return op
Пример #18
0
    def test_jordan_wigner_two_body(self):
        # Make sure it agrees with jordan_wigner(FermionTerm).
        for p in range(self.n_qubits):
            for q in range(self.n_qubits):
                for r in range(self.n_qubits):
                    for s in range(self.n_qubits):
                        # Get test qubit operator.
                        test_operator = jordan_wigner_two_body(p, q, r, s)

                        # Get correct qubit operator.
                        fermion_term = FermionOperator(
                            ((p, 1), (q, 1), (r, 0), (s, 0)))
                        correct_op = jordan_wigner(fermion_term)
                        hermitian_conjugate = hermitian_conjugated(
                            fermion_term)
                        if not fermion_term == hermitian_conjugate:
                            if p == r and q == s:
                                pass
                            else:
                                correct_op += jordan_wigner(
                                    hermitian_conjugate)

                        self.assertTrue(test_operator == correct_op,
                                        str(test_operator - correct_op))
Пример #19
0
 def setUp(self):
     self.fermion_term = FermionOperator('1^ 2^ 3 4', -3.17)
     self.fermion_operator = self.fermion_term + hermitian_conjugated(
         self.fermion_term)
     self.qubit_operator = jordan_wigner(self.fermion_operator)
Пример #20
0
 def test_jordan_wigner_twobody_interaction_op_reversal_symmetric(self):
     test_op = FermionOperator('1^ 2^ 2 1')
     test_op += hermitian_conjugated(test_op)
     self.assertTrue(
         jordan_wigner(test_op) == jordan_wigner(
             get_interaction_operator(test_op)))
Пример #21
0
def _hubbard(parity,
             x_dimension,
             y_dimension,
             tunneling,
             local_interaction,
             coulomb,
             chemical_potential=0.,
             magnetic_field=0.,
             periodic=True,
             spinless=False,
             particle_hole_symmetry=False):
    r"""Returns a generic Hubbard-style Hamiltonian, to be used
    by the bose_hubbard and fermi_hubbard wrapper functions.

    See the corresponding bose_hubbard and fermi_hubbard for descriptions
    of the various arguments.

    Args:
        parity (int): parity=-1 returns the output as an instance
            of the FermionOperator class. Alternatively, parity=1
            returns the output as an instance of the BosonOperator
            class

    Returns:
        hubbard_model: An instance of the FermionOperator or
            BosonOperator class.
    """
    tunneling = float(tunneling)
    local_interaction = float(local_interaction)
    coulomb = float(coulomb)
    chemical_potential = float(chemical_potential)
    magnetic_field = float(magnetic_field)

    if parity == -1:
        Op = FermionOperator
    elif parity == 1:
        Op = BosonOperator

    # Initialize operator class.
    n_sites = x_dimension * y_dimension
    n_spin_orbitals = n_sites

    if not spinless:
        n_spin_orbitals *= 2

    hubbard_model = Op.zero()

    # Select particle-hole symmetry
    if particle_hole_symmetry:
        coulomb_shift = Op((), 0.5)
    else:
        coulomb_shift = Op.zero()

    # Loop through sites and add terms.
    for site in range(n_sites):
        # Add chemical potential to the spinless case. The magnetic field
        # doesn't contribute.
        if spinless and chemical_potential:
            hubbard_model += number_operator(n_spin_orbitals,
                                             site,
                                             -chemical_potential,
                                             parity=parity)

        # no Pauli-Exclusion principle, spinless particles interact on-site
        if parity == 1:
            int_op = number_operator(
                n_sites, site, local_interaction, parity=1) \
                * (number_operator(n_sites, site, parity=1)
                   - Op.identity())
            hubbard_model += int_op

        # With spin, add the chemical potential and magnetic field terms.
        elif not spinless:
            hubbard_model += number_operator(n_spin_orbitals,
                                             up_index(site),
                                             -chemical_potential -
                                             magnetic_field,
                                             parity=parity)
            hubbard_model += number_operator(n_spin_orbitals,
                                             down_index(site),
                                             -chemical_potential +
                                             magnetic_field,
                                             parity=parity)

            # Add local pair interaction terms.
            operator_1 = number_operator(
                n_spin_orbitals, up_index(site), parity=parity) \
                - coulomb_shift
            operator_2 = number_operator(
                n_spin_orbitals, down_index(site), parity=parity) \
                - coulomb_shift
            hubbard_model += coulomb * operator_1 * operator_2

        # Index coupled orbitals.
        right_neighbor = site + 1
        bottom_neighbor = site + x_dimension

        # Account for periodic boundaries.
        if periodic:
            if (x_dimension > 2) and ((site + 1) % x_dimension == 0):
                right_neighbor -= x_dimension
            if (y_dimension > 2) and (site + x_dimension + 1 > n_sites):
                bottom_neighbor -= x_dimension * y_dimension

        # Add transition to neighbor on right.
        if (right_neighbor) % x_dimension or (periodic and x_dimension > 2):
            if spinless:
                # Add Coulomb term.
                operator_1 = number_operator(
                    n_spin_orbitals, site, 1.0, parity=parity) - coulomb_shift
                operator_2 = number_operator(
                    n_spin_orbitals, right_neighbor, 1.0, parity=parity) \
                    - coulomb_shift
                hubbard_model += coulomb * operator_1 * operator_2

                # Add hopping term.
                operators = ((site, 1), (right_neighbor, 0))

            else:
                # Add hopping term.
                operators = ((up_index(site), 1), (up_index(right_neighbor),
                                                   0))
                hopping_term = Op(operators, -tunneling)
                hubbard_model += hopping_term
                hubbard_model += hermitian_conjugated(hopping_term)

                operators = ((down_index(site), 1),
                             (down_index(right_neighbor), 0))

            hopping_term = Op(operators, -tunneling)
            hubbard_model += hopping_term
            hubbard_model += hermitian_conjugated(hopping_term)

        # Add transition to neighbor below.
        if site + x_dimension + 1 <= n_sites or (periodic and y_dimension > 2):
            if spinless:
                # Add Coulomb term.
                operator_1 = number_operator(
                    n_spin_orbitals, site, parity=parity) - coulomb_shift
                operator_2 = number_operator(
                    n_spin_orbitals, bottom_neighbor, parity=parity) \
                    - coulomb_shift
                hubbard_model += coulomb * operator_1 * operator_2

                # Add hopping term.
                operators = ((site, 1), (bottom_neighbor, 0))

            else:
                # Add hopping term.
                operators = ((up_index(site), 1), (up_index(bottom_neighbor),
                                                   0))
                hopping_term = Op(operators, -tunneling)
                hubbard_model += hopping_term
                hubbard_model += hermitian_conjugated(hopping_term)

                operators = ((down_index(site), 1),
                             (down_index(bottom_neighbor), 0))

            hopping_term = Op(operators, -tunneling)
            hubbard_model += hopping_term
            hubbard_model += hermitian_conjugated(hopping_term)

    return hubbard_model
Пример #22
0
def fermi_hubbard(x_dimension,
                  y_dimension,
                  tunneling,
                  coulomb,
                  chemical_potential=0.,
                  magnetic_field=0.,
                  periodic=True,
                  spinless=False,
                  particle_hole_symmetry=False):
    """Return symbolic representation of a Fermi-Hubbard Hamiltonian.

    The idea of this model is that some fermions move around on a grid and the
    energy of the model depends on where the fermions are.
    The Hamiltonians of this model live on a grid of dimensions
    `x_dimension` x `y_dimension`.
    The grid can have periodic boundary conditions or not.
    In the standard Fermi-Hubbard model (which we call the "spinful" model),
    there is room for an "up" fermion and a "down" fermion at each site on the
    grid. In this model, there are a total of `2N` spin-orbitals,
    where `N = x_dimension * y_dimension` is the number of sites.
    In the spinless model, there is only one spin-orbital per site
    for a total of `N`.

    The Hamiltonian for the spinful model has the form

    .. math::

        \\begin{align}
        H = &- t \sum_{\langle i,j \\rangle} \sum_{\sigma}
                     (a^\dagger_{i, \sigma} a_{j, \sigma} +
                      a^\dagger_{j, \sigma} a_{i, \sigma})
             + U \sum_{i} a^\dagger_{i, \\uparrow} a_{i, \\uparrow}
                         a^\dagger_{j, \downarrow} a_{j, \downarrow}
            \\\\
            &- \mu \sum_i \sum_{\sigma} a^\dagger_{i, \sigma} a_{i, \sigma}
             - h \sum_i (a^\dagger_{i, \\uparrow} a_{i, \\uparrow} -
                       a^\dagger_{i, \downarrow} a_{i, \downarrow})
        \\end{align}

    where

        - The indices :math:`\langle i, j \\rangle` run over pairs
          :math:`i` and :math:`j` of sites that are connected to each other
          in the grid
        - :math:`\sigma \in \\{\\uparrow, \downarrow\\}` is the spin
        - :math:`t` is the tunneling amplitude
        - :math:`U` is the Coulomb potential
        - :math:`\mu` is the chemical potential
        - :math:`h` is the magnetic field

    One can also construct the Hamiltonian for the spinless model, which
    has the form

    .. math::

        H = - t \sum_{k=1}^{N-1} (a_k^\dagger a_{k + 1} + a_{k+1}^\dagger a_k)
            + U \sum_{k=1}^{N-1} a_k^\dagger a_k a_{k+1}^\dagger a_{k+1}
            - \mu \sum_{k=1}^N a_k^\dagger a_k.

    Args:
        x_dimension (int): The width of the grid.
        y_dimension (int): The height of the grid.
        tunneling (float): The tunneling amplitude :math:`t`.
        coulomb (float): The attractive local interaction strength :math:`U`.
        chemical_potential (float, optional): The chemical potential
            :math:`\mu` at each site. Default value is 0.
        magnetic_field (float, optional): The magnetic field :math:`h`
            at each site. Default value is 0. Ignored for the spinless case.
        periodic (bool, optional): If True, add periodic boundary conditions.
            Default is True.
        spinless (bool, optional): If True, return a spinless Fermi-Hubbard
            model. Default is False.
        particle_hole_symmetry (bool, optional): If False, the repulsion
            term corresponds to:

            .. math::

                U \sum_{k=1}^{N-1} a_k^\dagger a_k a_{k+1}^\dagger a_{k+1}

            If True, the repulsion term is replaced by:

            .. math::

                U \sum_{k=1}^{N-1} (a_k^\dagger a_k - \\frac12)
                                   (a_{k+1}^\dagger a_{k+1} - \\frac12)

            which is unchanged under a particle-hole transformation.
            Default is False

    Returns:
        hubbard_model: An instance of the FermionOperator class.
    """
    tunneling = float(tunneling)
    coulomb = float(coulomb)
    chemical_potential = float(chemical_potential)
    magnetic_field = float(magnetic_field)

    # Initialize fermion operator class.
    n_sites = x_dimension * y_dimension
    n_spin_orbitals = n_sites

    if not spinless:
        n_spin_orbitals *= 2

    hubbard_model = FermionOperator.zero()

    # Select particle-hole symmetry
    if particle_hole_symmetry:
        coulomb_shift = FermionOperator((), 0.5)
    else:
        coulomb_shift = FermionOperator.zero()

    # Loop through sites and add terms.
    for site in range(n_sites):
        # Add chemical potential to the spinless case. The magnetic field
        # doesn't contribute.
        if spinless and chemical_potential:
            hubbard_model += number_operator(n_spin_orbitals, site,
                                             -chemical_potential)

        # With spin, add the chemical potential and magnetic field terms.
        elif not spinless:
            hubbard_model += number_operator(
                n_spin_orbitals, up_index(site),
                -chemical_potential - magnetic_field)
            hubbard_model += number_operator(
                n_spin_orbitals, down_index(site),
                -chemical_potential + magnetic_field)

            # Add local pair interaction terms.
            operator_1 = number_operator(n_spin_orbitals,
                                         up_index(site)) - coulomb_shift
            operator_2 = number_operator(n_spin_orbitals,
                                         down_index(site)) - coulomb_shift
            hubbard_model += coulomb * operator_1 * operator_2

        # Index coupled orbitals.
        right_neighbor = site + 1
        bottom_neighbor = site + x_dimension

        # Account for periodic boundaries.
        if periodic:
            if (x_dimension > 2) and ((site + 1) % x_dimension == 0):
                right_neighbor -= x_dimension
            if (y_dimension > 2) and (site + x_dimension + 1 > n_sites):
                bottom_neighbor -= x_dimension * y_dimension

        # Add transition to neighbor on right.
        if (right_neighbor) % x_dimension or (periodic and x_dimension > 2):
            if spinless:
                # Add Coulomb term.
                operator_1 = number_operator(n_spin_orbitals, site,
                                             1.0) - coulomb_shift
                operator_2 = number_operator(n_spin_orbitals, right_neighbor,
                                             1.0) - coulomb_shift
                hubbard_model += coulomb * operator_1 * operator_2

                # Add hopping term.
                operators = ((site, 1), (right_neighbor, 0))

            else:
                # Add hopping term.
                operators = ((up_index(site), 1), (up_index(right_neighbor),
                                                   0))
                hopping_term = FermionOperator(operators, -tunneling)
                hubbard_model += hopping_term
                hubbard_model += hermitian_conjugated(hopping_term)

                operators = ((down_index(site), 1),
                             (down_index(right_neighbor), 0))

            hopping_term = FermionOperator(operators, -tunneling)
            hubbard_model += hopping_term
            hubbard_model += hermitian_conjugated(hopping_term)

        # Add transition to neighbor below.
        if site + x_dimension + 1 <= n_sites or (periodic and y_dimension > 2):
            if spinless:
                # Add Coulomb term.
                operator_1 = number_operator(n_spin_orbitals,
                                             site) - coulomb_shift
                operator_2 = number_operator(n_spin_orbitals,
                                             bottom_neighbor) - coulomb_shift
                hubbard_model += coulomb * operator_1 * operator_2

                # Add hopping term.
                operators = ((site, 1), (bottom_neighbor, 0))

            else:
                # Add hopping term.
                operators = ((up_index(site), 1), (up_index(bottom_neighbor),
                                                   0))
                hopping_term = FermionOperator(operators, -tunneling)
                hubbard_model += hopping_term
                hubbard_model += hermitian_conjugated(hopping_term)

                operators = ((down_index(site), 1),
                             (down_index(bottom_neighbor), 0))

            hopping_term = FermionOperator(operators, -tunneling)
            hubbard_model += hopping_term
            hubbard_model += hermitian_conjugated(hopping_term)

    return hubbard_model
def apply_constraints(operator, n_fermions):
    """Function to use linear programming to apply constraints.

    Args:
        operator(FermionOperator): FermionOperator with only 1- and 2-body
            terms that we wish to vectorize.
        n_fermions(int): The number of particles in the simulation.

    Returns:
        modified_operator(FermionOperator): The operator with reduced norm
            that has been modified with equality constraints.
    """
    # Get constraint matrix.
    n_orbitals = count_qubits(operator)
    constraints = constraint_matrix(n_orbitals, n_fermions)
    n_constraints, n_terms = constraints.get_shape()

    # Get vectorized operator.
    vectorized_operator = operator_to_vector(operator)
    initial_bound = numpy.sum(numpy.absolute(vectorized_operator[1::])) ** 2
    print('Initial bound on measurements is %f.' % initial_bound)

    # Get linear programming coefficient vector.
    n_variables = n_constraints + n_terms
    lp_vector = numpy.zeros(n_variables, float)
    lp_vector[-n_terms:] = 1.

    # Get linear programming constraint matrix.
    lp_constraint_matrix = scipy.sparse.dok_matrix((2 * n_terms, n_variables))
    for (i, j), value in constraints.items():
        if j:
            lp_constraint_matrix[j, i] = value
            lp_constraint_matrix[n_terms + j, i] = -value
    for i in range(n_terms):
        lp_constraint_matrix[i, n_constraints + i] = -1.
        lp_constraint_matrix[n_terms + i, n_constraints + i] = -1.

    # Get linear programming constraint vector.
    lp_constraint_vector = numpy.zeros(2 * n_terms, float)
    lp_constraint_vector[:n_terms] = vectorized_operator
    lp_constraint_vector[-n_terms:] = -vectorized_operator

    # Perform linear programming.
    print('Starting linear programming.')
    options = {'maxiter': int(1e6)}
    bound = n_constraints * [(None, None)] + n_terms * [(0, None)]
    solution = scipy.optimize.linprog(c=lp_vector,
                                      A_ub=lp_constraint_matrix.toarray(),
                                      b_ub=lp_constraint_vector,
                                      bounds=bound,
                                      options=options)

    # Analyze results.
    print(solution['message'])
    assert solution['success']
    solution_vector = solution['x']
    objective = solution['fun'] ** 2
    print('Program terminated after %i iterations.' % solution['nit'])

    # Alternative bound.
    residuals = solution_vector[-n_terms:]
    alternative_bound = numpy.sum(numpy.absolute(residuals[1::])) ** 2
    print('Bound implied by solution vector is %f.' % alternative_bound)

    # Make sure residuals are positive.
    for residual in residuals:
        assert residual > -1e-6

    # Get bound on updated Hamiltonian.
    weights = solution_vector[:n_constraints]
    final_vectorized_operator = (vectorized_operator -
                                 constraints.transpose() * weights)
    final_bound = numpy.sum(
        numpy.absolute(final_vectorized_operator[1::])) ** 2
    print('Actual bound determined is %f.' % final_bound)

    # Return modified operator.
    modified_operator = vector_to_operator(
        final_vectorized_operator, n_orbitals)
    return (modified_operator +
            hermitian_conjugated(modified_operator)) / 2.
Пример #24
0
def mean_field_dwave(x_dimension,
                     y_dimension,
                     tunneling,
                     sc_gap,
                     chemical_potential=0.,
                     periodic=True):
    r"""Return symbolic representation of a BCS mean-field d-wave Hamiltonian.

    The Hamiltonians of this model live on a grid of dimensions
    `x_dimension` x `y_dimension`.
    The grid can have periodic boundary conditions or not.
    Each site on the grid can have an "up" fermion and a "down" fermion.
    Therefore, there are a total of `2N` spin-orbitals,
    where `N = x_dimension * y_dimension` is the number of sites.

    The Hamiltonian for this model has the form

    .. math::

        \begin{align}
        H = &- t \sum_{\langle i,j \rangle} \sum_\sigma
                (a^\dagger_{i, \sigma} a_{j, \sigma} +
                 a^\dagger_{j, \sigma} a_{i, \sigma})
            - \mu \sum_i \sum_{\sigma} a^\dagger_{i, \sigma} a_{i, \sigma}
            \\
            &- \sum_{\langle i,j \rangle} \Delta_{ij}
              (a^\dagger_{i, \uparrow} a^\dagger_{j, \downarrow} -
               a^\dagger_{i, \downarrow} a^\dagger_{j, \uparrow} +
               a_{j, \downarrow} a_{i, \uparrow} -
               a_{j, \uparrow} a_{i, \downarrow})
        \end{align}

    where

        - The indices :math:`\langle i, j \rangle` run over pairs
          :math:`i` and :math:`j` of sites that are connected to each other
          in the grid
        - :math:`\sigma \in \{\uparrow, \downarrow\}` is the spin
        - :math:`t` is the tunneling amplitude
        - :math:`\Delta_{ij}` is equal to :math:`+\Delta/2` for
          horizontal edges and :math:`-\Delta/2` for vertical edges,
          where :math:`\Delta` is the superconducting gap.
        - :math:`\mu` is the chemical potential

    Args:
        x_dimension (int): The width of the grid.
        y_dimension (int): The height of the grid.
        tunneling (float): The tunneling amplitude :math:`t`.
        sc_gap (float): The superconducting gap :math:`\Delta`
        chemical_potential (float, optional): The chemical potential
            :math:`\mu` at each site. Default value is 0.
        periodic (bool, optional): If True, add periodic boundary conditions.
            Default is True.

    Returns:
        mean_field_dwave_model: An instance of the FermionOperator class.
    """
    # Initialize fermion operator class.
    n_sites = x_dimension * y_dimension
    n_spin_orbitals = 2 * n_sites
    mean_field_dwave_model = FermionOperator()

    # Loop through sites and add terms.
    for site in range(n_sites):
        # Add chemical potential
        mean_field_dwave_model += number_operator(n_spin_orbitals,
                                                  up_index(site),
                                                  -chemical_potential)
        mean_field_dwave_model += number_operator(n_spin_orbitals,
                                                  down_index(site),
                                                  -chemical_potential)

        # Index coupled orbitals.
        right_neighbor = site + 1
        bottom_neighbor = site + x_dimension
        # Account for periodic boundaries.
        if periodic:
            if (x_dimension > 2) and ((site + 1) % x_dimension == 0):
                right_neighbor -= x_dimension
            if (y_dimension > 2) and (site + x_dimension + 1 > n_sites):
                bottom_neighbor -= x_dimension * y_dimension

        # Add transition to neighbor on right
        if (site + 1) % x_dimension or (periodic and x_dimension > 2):
            # Add spin-up hopping term.
            operators = ((up_index(site), 1), (up_index(right_neighbor), 0))
            hopping_term = FermionOperator(operators, -tunneling)
            mean_field_dwave_model += hopping_term
            mean_field_dwave_model += hermitian_conjugated(hopping_term)
            # Add spin-down hopping term
            operators = ((down_index(site), 1), (down_index(right_neighbor),
                                                 0))
            hopping_term = FermionOperator(operators, -tunneling)
            mean_field_dwave_model += hopping_term
            mean_field_dwave_model += hermitian_conjugated(hopping_term)

            # Add pairing term
            operators = ((up_index(site), 1), (down_index(right_neighbor), 1))
            pairing_term = FermionOperator(operators, sc_gap / 2.)
            operators = ((down_index(site), 1), (up_index(right_neighbor), 1))
            pairing_term += FermionOperator(operators, -sc_gap / 2.)
            mean_field_dwave_model -= pairing_term
            mean_field_dwave_model -= hermitian_conjugated(pairing_term)

        # Add transition to neighbor below.
        if site + x_dimension + 1 <= n_sites or (periodic and y_dimension > 2):
            # Add spin-up hopping term.
            operators = ((up_index(site), 1), (up_index(bottom_neighbor), 0))
            hopping_term = FermionOperator(operators, -tunneling)
            mean_field_dwave_model += hopping_term
            mean_field_dwave_model += hermitian_conjugated(hopping_term)
            # Add spin-down hopping term
            operators = ((down_index(site), 1), (down_index(bottom_neighbor),
                                                 0))
            hopping_term = FermionOperator(operators, -tunneling)
            mean_field_dwave_model += hopping_term
            mean_field_dwave_model += hermitian_conjugated(hopping_term)

            # Add pairing term
            operators = ((up_index(site), 1), (down_index(bottom_neighbor), 1))
            pairing_term = FermionOperator(operators, -sc_gap / 2.)
            operators = ((down_index(site), 1), (up_index(bottom_neighbor), 1))
            pairing_term += FermionOperator(operators, sc_gap / 2.)
            mean_field_dwave_model -= pairing_term
            mean_field_dwave_model -= hermitian_conjugated(pairing_term)
    # Return.
    return mean_field_dwave_model
from openfermion.transforms import jordan_wigner
from openfermion.ops import FermionOperator
from openfermion.utils import hermitian_conjugated
from forestopenfermion import qubitop_to_pyquilpauli, pyquilpauli_to_qubitop

from pyquil.quil import Program
from pyquil.gates import X
from pyquil.paulis import exponentiate
from pyquil.api import QVMConnection

hubbard_hamiltonian = FermionOperator()
spatial_orbitals = 4
for i in range(spatial_orbitals):
    electron_hop_alpha = FermionOperator(((2*i, 1), (2*((i+1) % spatial_orbitals), 0)))
    electron_hop_beta = FermionOperator(((2*i+1, 1), ((2 * ((i+1) % spatial_orbitals) + 1), 0)))
    hubbard_hamiltonian += -1 * (electron_hop_alpha + hermitian_conjugated(electron_hop_alpha))
    hubbard_hamiltonian += -1 * (electron_hop_beta + hermitian_conjugated(electron_hop_beta))
    hubbard_hamiltonian += FermionOperator(((2*i, 1), (2*i, 0), (2*i+1, 1), (2*i+1, 0)), 4.0)
hubbard_term_generator = jordan_wigner(hubbard_hamiltonian)
pyquil_hubbard_generator = qubitop_to_pyquilpauli(hubbard_term_generator)


localized_electrons_program = Program()
localized_electrons_program.inst([X(0), X(1)])
pyquil_program = Program()
for term in pyquil_hubbard_generator.terms:
    pyquil_program += exponentiate(0.1*term)
print (localized_electrons_program + pyquil_program)
qvm = QVMConnection()
print(qvm.run(pyquil_program, [0], 10))
wf = qvm.wavefunction(pyquil_program)
Пример #26
0
    def test_ucc_h2_singlet(self):
        geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))]
        basis = 'sto-3g'
        multiplicity = 1
        filename = os.path.join(THIS_DIRECTORY, 'data',
                                'H2_sto-3g_singlet_0.7414')
        self.molecule = MolecularData(geometry,
                                      basis,
                                      multiplicity,
                                      filename=filename)
        self.molecule.load()

        # Get molecular Hamiltonian.
        self.molecular_hamiltonian = self.molecule.get_molecular_hamiltonian()

        # Get FCI RDM.
        self.fci_rdm = self.molecule.get_molecular_rdm(use_fci=1)

        # Get explicit coefficients.
        self.nuclear_repulsion = self.molecular_hamiltonian.constant
        self.one_body = self.molecular_hamiltonian.one_body_tensor
        self.two_body = self.molecular_hamiltonian.two_body_tensor

        # Get fermion Hamiltonian.
        self.fermion_hamiltonian = normal_ordered(
            get_fermion_operator(self.molecular_hamiltonian))

        # Get qubit Hamiltonian.
        self.qubit_hamiltonian = jordan_wigner(self.fermion_hamiltonian)

        # Get the sparse matrix.
        self.hamiltonian_matrix = get_sparse_operator(
            self.molecular_hamiltonian)
        # Test UCCSD for accuracy against FCI using loaded t amplitudes.
        ucc_operator = uccsd_generator(self.molecule.ccsd_single_amps,
                                       self.molecule.ccsd_double_amps)

        hf_state = jw_hartree_fock_state(self.molecule.n_electrons,
                                         count_qubits(self.qubit_hamiltonian))
        uccsd_sparse = jordan_wigner_sparse(ucc_operator)
        uccsd_state = scipy.sparse.linalg.expm_multiply(uccsd_sparse, hf_state)
        expected_uccsd_energy = expectation(self.hamiltonian_matrix,
                                            uccsd_state)
        self.assertAlmostEqual(expected_uccsd_energy,
                               self.molecule.fci_energy,
                               places=4)
        print("UCCSD ENERGY: {}".format(expected_uccsd_energy))

        # Test CCSD singlet for precise match against FCI using loaded t
        # amplitudes
        packed_amplitudes = uccsd_singlet_get_packed_amplitudes(
            self.molecule.ccsd_single_amps, self.molecule.ccsd_double_amps,
            self.molecule.n_qubits, self.molecule.n_electrons)
        ccsd_operator = uccsd_singlet_generator(packed_amplitudes,
                                                self.molecule.n_qubits,
                                                self.molecule.n_electrons,
                                                anti_hermitian=False)

        ccsd_sparse_r = jordan_wigner_sparse(ccsd_operator)
        ccsd_sparse_l = jordan_wigner_sparse(
            -hermitian_conjugated(ccsd_operator))

        ccsd_state_r = scipy.sparse.linalg.expm_multiply(
            ccsd_sparse_r, hf_state)
        ccsd_state_l = scipy.sparse.linalg.expm_multiply(
            ccsd_sparse_l, hf_state)
        expected_ccsd_energy = ccsd_state_l.conjugate().dot(
            self.hamiltonian_matrix.dot(ccsd_state_r))
        self.assertAlmostEqual(expected_ccsd_energy, self.molecule.fci_energy)