예제 #1
0
def test_reorder_fermionic_modes():
    ref_op = get_interaction_operator(
        FermionOperator(
            """
    0.0 [] +
    1.0 [0^ 0] +
    1.0 [1^ 1] +
    1.0 [0^ 1^ 2 3] +
    1.0 [1^ 1^ 2 2]
    """
        )
    )
    reordered_op = get_interaction_operator(
        FermionOperator(
            """
    0.0 [] +
    1.0 [0^ 0] +
    1.0 [2^ 2] +
    1.0 [0^ 2^ 1 3] +
    1.0 [2^ 2^ 1 1]
    """
        )
    )
    spin_block_op = reorder_fermionic_modes(ref_op, [0, 2, 1, 3])
    assert reordered_op == spin_block_op
    spin_block_qubit_op = jordan_wigner(spin_block_op)
    interleaved_qubit_op = jordan_wigner(ref_op)
    spin_block_spectrum = eigenspectrum(spin_block_qubit_op)
    interleaved_spectrum = eigenspectrum(interleaved_qubit_op)
    assert np.allclose(spin_block_spectrum, interleaved_spectrum)
예제 #2
0
    def test_apply_generated_unitary(self):
        """APply the generated unitary transformation from the fqe namespace
        """
        norb = 4
        nele = 3
        time = 0.001
        ops = FermionOperator('1^ 3^ 5 0', 2.0 - 2.j) + FermionOperator(
            '0^ 5^ 3 1', 2.0 + 2.j)

        wfn = fqe.get_number_conserving_wavefunction(nele, norb)
        wfn.set_wfn(strategy='random')
        wfn.normalize()

        reference = fqe.apply_generated_unitary(wfn, time, 'taylor', ops)

        h1e = numpy.zeros((2 * norb, 2 * norb), dtype=numpy.complex128)
        h2e = hamiltonian_utils.nbody_matrix(ops, norb)
        h2e = hamiltonian_utils.antisymm_two_body(h2e)
        hamil = general_hamiltonian.General(tuple([h1e, h2e]))
        compute = wfn.apply_generated_unitary(time, 'taylor', hamil)

        for key in wfn.sectors():
            with self.subTest(key=key):
                diff = reference._civec[key].coeff - compute._civec[key].coeff
                err = linalg.norm(diff)
                self.assertTrue(err < 1.e-8)
예제 #3
0
 def op1e(const, Tmat):
     fop = FermionOperator('', const)
     for p in range(n_orb):
         for q in range(n_orb):
             fop += FermionOperator( ((2*p  , 1),(2*q  , 0)), Tmat[p,q] )
             fop += FermionOperator( ((2*p+1, 1),(2*q+1, 0)), Tmat[p,q] )
     return fop
예제 #4
0
    def __init__(self, qubit_pair_1, qubit_pair_2, system_n_qubits=None):
        self.spin_complement = True
        assert len(qubit_pair_1) == 2
        assert len(qubit_pair_2) == 2
        self.qubits = [qubit_pair_1, qubit_pair_2]
        self.complement_qubits = [
            self.spin_complement_orbitals(qubit_pair_1),
            self.spin_complement_orbitals(qubit_pair_2)
        ]

        fermi_operator_1 = FermionOperator(
            '[{2}^ {3}^ {0} {1}] - [{0}^ {1}^ {2} {3}]'.format(
                *self.qubits[0], *self.qubits[1]))
        excitations_generators = [jordan_wigner(fermi_operator_1)]

        if [set(self.qubits[0]), set(self.qubits[1])] != [set(self.complement_qubits[0]), set(self.complement_qubits[1])] and \
           [set(self.qubits[0]), set(self.qubits[1])] != [set(self.complement_qubits[1]), set(self.complement_qubits[0])]:

            fermi_operator_2 = FermionOperator(
                '[{2}^ {3}^ {0} {1}] - [{0}^ {1}^ {2} {3}]'.format(
                    *self.complement_qubits[0], *self.complement_qubits[1]))
            excitations_generators.append(jordan_wigner(fermi_operator_2))

        super(SpinCompEffDFExc, self).\
            __init__(element='spin_d_f_exc_{}_{}'.format(qubit_pair_1, qubit_pair_2), order=2, n_var_parameters=1,
                     system_n_qubits=system_n_qubits, excitations_generators=excitations_generators)
예제 #5
0
    def screen_out_operator_terms_below_threshold(
        threshold: float, fermion_generator: FermionOperator, ignore_singles=False
    ) -> Tuple[np.ndarray, FermionOperator]:
        """Screen single and double excitation operators based on a guess
            for the amplitudes
        Args:
            threshold (float): threshold to select excitations. Only those with
                absolute amplitudes above the threshold are kept.
            fermion_generator (openfermion.FermionOperator): Fermion Operator
                containing the generators for the UCC ansatz
        Returns:
            amplitudes (np.array): screened amplitudes
            new_fermion_generator (openfermion.FermionOperator): screened
                Fermion Operator
        """

        new_fermion_generator = FermionOperator()
        amplitudes = []
        for op in fermion_generator.terms:
            if abs(fermion_generator.terms[op]) > threshold or (
                len(op) == 2 and ignore_singles == True
            ):
                new_fermion_generator += FermionOperator(
                    op, fermion_generator.terms[op]
                )
                amplitudes.append(fermion_generator.terms[op])
        amplitudes = np.array(amplitudes)
        return amplitudes, new_fermion_generator
예제 #6
0
def fci_fermion_operator_representation(norb: int, nele: int,
                                        m_s: int) -> 'FermionOperator':
    """Generate the Full Configuration interaction wavefunction in the
    openfermion FermionOperator representation with coefficients of 1.0.

    Args:
        norb (int) - number of spatial orbitals

        nele (int) - number of electrons

        m_s (int) - s_z spin quantum number

    Returns:
        FermionOperator
    """
    nalpha, nbeta = alpha_beta_electrons(nele, m_s)
    gsstr = init_bitstring_groundstate(nalpha)
    alphadets = lexicographic_bitstring_generator(gsstr, norb)
    gsstr = init_bitstring_groundstate(nbeta)
    betadets = lexicographic_bitstring_generator(gsstr, norb)
    ops = FermionOperator('', 1.0)
    for bstr in betadets:
        for astr in alphadets:
            ops += determinant_to_ops(astr, bstr)
    return ops - FermionOperator('', 1.0)
 def test_basic_split(self):
     """Test spliting the fermion operators for a simple case.
     """
     test_ops = FermionOperator('1 1^', 1.0)
     test_ops = normal_ordered(test_ops)
     terms, _ = split_openfermion_tensor(test_ops)
     self.assertEqual(FermionOperator('1^ 1', -1.0), terms[2])
예제 #8
0
    def __init__(self, qubit_1, qubit_2, system_n_qubits=None, encoding='jw'):
        self.spin_complement = True

        self.qubits = [[qubit_1], [qubit_2]]
        self.complement_qubits = [
            self.spin_complement_orbitals([qubit_1]),
            self.spin_complement_orbitals([qubit_2])
        ]

        fermi_operator_1 = FermionOperator('[{1}^ {0}] - [{0}^ {1}]'.format(
            qubit_2, qubit_1))

        if encoding == 'jw':
            excitations_generators = [jordan_wigner(fermi_operator_1)]
        else:
            assert encoding == 'bk'
            excitations_generators = [bravyi_kitaev(fermi_operator_1)]

        if {*self.qubits[0], *self.qubits[1]} != {*self.complement_qubits[0], *self.complement_qubits[1]} and \
           {*self.qubits[0], *self.qubits[1]} != {*self.complement_qubits[1], *self.complement_qubits[0]}:

            fermi_operator_2 = FermionOperator(
                '[{1}^ {0}] - [{0}^ {1}]'.format(self.complement_qubits[1][0],
                                                 self.complement_qubits[0][0]))
            if encoding == 'jw':
                excitations_generators = [jordan_wigner(fermi_operator_2)]
            else:
                assert encoding == 'bk'
                excitations_generators = [bravyi_kitaev(fermi_operator_2)]

        super(SpinCompSFExc, self).\
            __init__(element='spin_s_f_exc_{}_{}'.format(qubit_2, qubit_1), order=1, n_var_parameters=1,
                     excitations_generators=excitations_generators, system_n_qubits=system_n_qubits)
예제 #9
0
def transform_to_spin_broken(ops: 'FermionOperator') -> 'FermionOperator':
    """Convert a Fermion Operator string from number broken to spin broken
    operators.

    Args:
        ops (FermionOperator) - input FermionOperator

    Returns:
        (FermionOperator) - transformed FermionOperator to spin broken indexing
    """
    newstr = FermionOperator()
    for term in ops.terms:
        opstr = ''
        for element in term:
            if element[0] % 2:
                if element[1]:
                    opstr += str(element[0]) + ' '
                else:
                    opstr += str(element[0]) + '^ '
            else:
                if element[1]:
                    opstr += str(element[0]) + '^ '
                else:
                    opstr += str(element[0]) + ' '
        newstr += FermionOperator(opstr, ops.terms[term])
    return newstr
    def test_mutate_config_vacuum(self):
        """Adding a single electron to the vavuum should return a parity of one
        and the set bit.
        """
        ref0 = [1, 0, 1]
        ref0a = [1, 0, 0]
        ops0 = FermionOperator('0^', 1.0)
        ref1 = [0, 8, 1]
        ref1a = [0, 8, 0]
        ops1 = FermionOperator('7^', 1.0)

        ops2 = FermionOperator('0', 1.0)
        ops3 = FermionOperator('7', 1.0)
        ref23 = [0, 0, 0]
        for term in ops0.terms:
            self.assertListEqual(
                ref0, list(openfermion_utils.mutate_config(0, 0, term)))
            self.assertListEqual(
                ref0a, list(openfermion_utils.mutate_config(1, 0, term)))
        for term in ops1.terms:
            self.assertListEqual(
                ref1, list(openfermion_utils.mutate_config(0, 0, term)))
            self.assertListEqual(
                ref1a, list(openfermion_utils.mutate_config(0, 8, term)))
        for term in ops2.terms:
            self.assertListEqual(
                ref23, list(openfermion_utils.mutate_config(0, 0, term)))
        for term in ops3.terms:
            self.assertListEqual(
                ref23, list(openfermion_utils.mutate_config(0, 0, term)))
    def test_apply_spinful_fermionop(self):
        """
        Make sure the spin-orbital reordering is working by comparing
        apply operation
        """
        wfn = Wavefunction([[2, 0, 2]])
        wfn.set_wfn(strategy='random')
        wfn.normalize()
        cirq_wf = to_cirq(wfn).reshape((-1, 1))

        op_to_apply = FermionOperator()
        test_state = copy.deepcopy(wfn)
        test_state.set_wfn('zero')
        for p, q, r, s in product(range(2), repeat=4):
            op = FermionOperator(
                ((2 * p, 1), (2 * q + 1, 1), (2 * r + 1, 0), (2 * s, 0)),
                coefficient=numpy.random.randn())
            op_to_apply += op + hermitian_conjugated(op)
            test_state += wfn.apply(op + hermitian_conjugated(op))

        opmat = get_sparse_operator(op_to_apply, n_qubits=4).toarray()
        new_state_cirq = opmat @ cirq_wf

        # this part is because we need to pass a normalized wavefunction
        norm_constant = new_state_cirq.conj().T @ new_state_cirq
        new_state_cirq /= numpy.sqrt(norm_constant)
        new_state_wfn = from_cirq(new_state_cirq.flatten(), thresh=1.0E-12)
        new_state_wfn.scale(numpy.sqrt(norm_constant))

        self.assertTrue(
            numpy.allclose(test_state.get_coeff((2, 0)),
                           new_state_wfn.get_coeff((2, 0))))
    def test_evolve_spinful_fermionop(self):
        """
        Make sure the spin-orbital reordering is working by comparing
        time evolution
        """
        wfn = Wavefunction([[2, 0, 2]])
        wfn.set_wfn(strategy='random')
        wfn.normalize()
        cirq_wf = to_cirq(wfn).reshape((-1, 1))

        op_to_apply = FermionOperator()
        for p, q, r, s in product(range(2), repeat=4):
            op = FermionOperator(
                ((2 * p, 1), (2 * q + 1, 1), (2 * r + 1, 0), (2 * s, 0)),
                coefficient=numpy.random.randn())
            op_to_apply += op + hermitian_conjugated(op)

        opmat = get_sparse_operator(op_to_apply, n_qubits=4).toarray()
        dt = 0.765
        new_state_cirq = scipy.linalg.expm(-1j * dt * opmat) @ cirq_wf
        new_state_wfn = from_cirq(new_state_cirq.flatten(), thresh=1.0E-12)
        test_state = wfn.time_evolve(dt, op_to_apply)
        self.assertTrue(
            numpy.allclose(test_state.get_coeff((2, 0)),
                           new_state_wfn.get_coeff((2, 0))))
    def test_fqe_to_fermion_operator(self):
        """Convert the fqe representation to openfermion operators.

        Note: Due to the unique OpenFermion data structure and the conversion
        of the data internally, test requires an iterative stucture rather than
        assertDictEqual
        """
        def _calc_coeff(val):
            return round(val / numpy.sqrt(30.0), 7) + .0j

        coeff = [
            _calc_coeff(1.0),
            _calc_coeff(2.0),
            _calc_coeff(3.0),
            _calc_coeff(4.0)
        ]

        data = numpy.array([[coeff[0]], [coeff[1]], [coeff[2]], [coeff[3]]],
                           dtype=numpy.complex128)

        test = FermionOperator('0^ 1^', coeff[0])
        test += FermionOperator('0^ 3^', coeff[1])
        test += FermionOperator('2^ 1^', coeff[2])
        test += FermionOperator('2^ 3^', coeff[3])
        wfn = wavefunction.Wavefunction([[2, 0, 2]])
        data = numpy.reshape(data, (2, 2))
        passed_data = {(2, 0): data}
        wfn.set_wfn(strategy='from_data', raw_data=passed_data)
        ops = openfermion_utils.fqe_to_fermion_operator(wfn)
        self.assertListEqual(list(ops.terms.keys()), list(test.terms.keys()))
        for term in ops.terms:
            self.assertAlmostEqual(ops.terms[term], test.terms[term])
    def test_integration_jellium_hamiltonian_with_negation(self):
        hamiltonian = normal_ordered(
            jellium_model(Grid(2, 3, 1.), plane_wave=False))

        part_a = FermionOperator.zero()
        part_b = FermionOperator.zero()

        add_to_a_or_b = 0  # add to a if 0; add to b if 1
        for term, coeff in hamiltonian.terms.items():
            # Partition terms in the Hamiltonian into part_a or part_b
            if add_to_a_or_b:
                part_a += FermionOperator(term, coeff)
            else:
                part_b += FermionOperator(term, coeff)
            add_to_a_or_b ^= 1

        reference = normal_ordered(commutator(part_a, part_b))
        result = commutator_ordered_diagonal_coulomb_with_two_body_operator(
            part_a, part_b)

        self.assertTrue(result.isclose(reference))

        negative = commutator_ordered_diagonal_coulomb_with_two_body_operator(
            part_b, part_a)
        result += negative

        self.assertTrue(result.isclose(FermionOperator.zero()))
예제 #15
0
    def test_identity_recognized_as_potential_term(self):
        potential_terms, kinetic_terms = (
            diagonal_coulomb_potential_and_kinetic_terms_as_arrays(
                FermionOperator.identity()))

        self.assertListEqual(list(potential_terms),
                             [FermionOperator.identity()])
        self.assertListEqual(list(kinetic_terms), [])
 def test_ladder_op(self):
     """Make sure that our qubit ladder operators are the same as the jw
     transformation
     """
     create = jordan_wigner(FermionOperator('10^', 1. + .0j))
     annihilate = jordan_wigner(FermionOperator('10', 1. + .0j))
     self.assertEqual(create, openfermion_utils.ladder_op(10, 1))
     self.assertEqual(annihilate, openfermion_utils.ladder_op(10, 0))
def test_sparse():
    """Test some of the functions in SparseHamiltonian."""
    oper = FermionOperator('0 0^')
    oper += FermionOperator('1 1^')
    test = sparse_hamiltonian.SparseHamiltonian(oper)
    assert test.rank() == 2
    test = sparse_hamiltonian.SparseHamiltonian(oper, False)
    assert not test.is_individual()
예제 #18
0
def construct_ham_1body(hint, orb_qubit_map=None):
    if orb_qubit_map is None: orb_qubit_map = list(range(hint.shape[0]))

    ham_1body = FermionOperator()
    for (p, p_qubit), (q, q_qubit) in product(enumerate(orb_qubit_map),
                                              repeat=2):
        ham_1body += FermionOperator(((p_qubit, 1), (q_qubit, 0)), hint[p, q])

    return ham_1body
def benchmark_fermion_math_and_normal_order(n_qubits, term_length, power):
    """Benchmark both arithmetic operators and normal ordering on fermions.

    The idea is we generate two random FermionTerms, A and B, each acting
    on n_qubits with term_length operators. We then compute
    (A + B) ** power. This is costly that is the first benchmark. The second
    benchmark is in normal ordering whatever comes out.

    Args:
        n_qubits: The number of qubits on which these terms act.
        term_length: The number of operators in each term.
        power: Int, the exponent to which to raise sum of the two terms.

    Returns:
        runtime_math: The time it takes to perform (A + B) ** power
        runtime_normal_order: The time it takes to perform
            FermionOperator.normal_order()
    """
    # Generate random operator strings.
    operators_a = [(numpy.random.randint(n_qubits), numpy.random.randint(2))]
    operators_b = [(numpy.random.randint(n_qubits), numpy.random.randint(2))]
    for _ in range(term_length):

        # Make sure the operator is not trivially zero.
        operator_a = (numpy.random.randint(n_qubits), numpy.random.randint(2))
        while operator_a == operators_a[-1]:
            operator_a = (numpy.random.randint(n_qubits),
                          numpy.random.randint(2))
        operators_a += [operator_a]

        # Do the same for the other operator.
        operator_b = (numpy.random.randint(n_qubits), numpy.random.randint(2))
        while operator_b == operators_b[-1]:
            operator_b = (numpy.random.randint(n_qubits),
                          numpy.random.randint(2))
        operators_b += [operator_b]

    # Initialize FermionTerms and then sum them together.
    fermion_term_a = FermionOperator(tuple(operators_a),
                                     float(numpy.random.randn()))
    fermion_term_b = FermionOperator(tuple(operators_b),
                                     float(numpy.random.randn()))
    fermion_operator = fermion_term_a + fermion_term_b

    # Exponentiate.
    start_time = time.time()
    fermion_operator **= power
    runtime_math = time.time() - start_time

    # Normal order.
    start_time = time.time()
    normal_ordered(fermion_operator)
    runtime_normal_order = time.time() - start_time

    # Return.
    return runtime_math, runtime_normal_order
 def test_odd_rank_error(self):
     """Check that odd rank operators are not processed
     """
     ops = []
     ops.append(FermionOperator('10^ 1 2', 1.0))
     ops.append(FermionOperator('5^ 3^ 7^ 8 7', 1.0))
     for rank in range(2):
         with self.subTest(rank=(2 * rank + 1)):
             self.assertRaises(ValueError, split_openfermion_tensor,
                               ops[rank])
 def test_ascending_index_order(self):
     """Transformations in openfermion return FermionOperators from highest
     index to the lowest index.  Occationally we would like to reverse this.
     """
     ops = FermionOperator('5^ 4^ 3^ 2^ 1^ 0^', 1.0)
     test = FermionOperator('0^ 2^ 4^ 1^ 3^ 5^', 1.0)
     for key in ops.terms:
         f_ops = openfermion_utils.ascending_index_order(
             key, ops.terms[key])
     self.assertEqual(f_ops, test)
예제 #22
0
    def test_mask_hermitian_terms_results_in_duplicated_row(self):
        mask = bit_mask_of_modes_acted_on_by_fermionic_terms(
            [FermionOperator('2^ 3'), FermionOperator('3^ 2')], n_qubits=5)

        expected_mask = numpy.array([[False, False],
                                     [False, False],
                                     [True, True],
                                     [True, True],
                                     [False, False]])

        self.assertTrue(numpy.array_equal(mask, expected_mask))
 def test_fermion_opstring_to_bitstring(self):
     """Interoperability between OpenFermion and the FQE necessitates that
     we can convert between the representations.
     """
     ops = FermionOperator('0^ 1^', 1. + .0j) + \
           FermionOperator('2^ 5^', 2. + .0j) + \
           FermionOperator('8^ 9^', 3. + .0j)
     test = [[1, 1, 1. + .0j], [2, 4, 2. + .0j], [16, 16, 3. + .0j]]
     result = openfermion_utils.fermion_opstring_to_bitstring(ops)
     for val in result:
         self.assertTrue(val in test)
    def test_update_operator_coeff(self):
        """Update the coefficients of an operator string
        """
        coeff = numpy.ones(6, dtype=numpy.complex64)
        test = FermionOperator('1^', 1. + .0j)
        ops = FermionOperator('1^', 1. + .0j)
        for i in range(2, 7):
            ops += FermionOperator(str(i) + '^', i * (1. + .0j))
            test += FermionOperator(str(i) + '^', 1. + .0j)

        openfermion_utils.update_operator_coeff(ops, coeff)
        self.assertEqual(ops, test)
 def test_fermoinops_tomatrix(self):
     norb = 4
     ops = FermionOperator('9^ 1')
     self.assertRaises(ValueError, fermionops_tomatrix, ops, norb)
     ops = FermionOperator('10^ 4')
     self.assertRaises(ValueError, fermionops_tomatrix, ops, norb)
     ops = FermionOperator('3^ 1 4')
     self.assertRaises(ValueError, fermionops_tomatrix, ops, norb)
     ops = FermionOperator('3 1')
     self.assertRaises(ValueError, fermionops_tomatrix, ops, norb)
     ops = FermionOperator('3^ 1^')
     self.assertRaises(ValueError, fermionops_tomatrix, ops, norb)
예제 #26
0
def construct_ham_2body(gint, orb_qubit_map=None):
    if orb_qubit_map is None: orb_qubit_map = list(range(gint.shape[0]))

    ham_2body = FermionOperator()
    for (p, p_qubit), (q, q_qubit), (r, r_qubit), (s, s_qubit) in product(
            enumerate(orb_qubit_map), repeat=4):
        if p != r and q != s:
            ham_2body += FermionOperator(
                ((p_qubit, 1), (r_qubit, 1), (s_qubit, 0),
                 (q_qubit, 0)), gint[p, q, r, s]) * 0.5

    return ham_2body
예제 #27
0
def get_ground_state_rdm_from_qubit_op(
    qubit_operator: QubitOperator, n_particles: int
) -> InteractionRDM:
    """Diagonalize operator and compute the ground state 1- and 2-RDM

    Args:
        qubit_operator (openfermion.QubitOperator): The openfermion operator to diagonalize
        n_particles (int): number of particles in the target ground state

    Returns:
        rdm (openfermion.InteractionRDM): interaction RDM of the ground state with the particle
            number n_particles
    """

    sparse_operator = get_sparse_operator(qubit_operator)
    e, ground_state_wf = jw_get_ground_state_at_particle_number(
        sparse_operator, n_particles
    )  # float/np.array pair
    n_qubits = count_qubits(qubit_operator)

    one_body_tensor = []
    for i in range(n_qubits):
        for j in range(n_qubits):
            idag_j = get_sparse_operator(
                FermionOperator(f"{i}^ {j}"), n_qubits=n_qubits
            )
            idag_j = idag_j.toarray()
            one_body_tensor.append(
                np.conjugate(ground_state_wf) @ idag_j @ ground_state_wf
            )

    one_body_tensor = np.array(one_body_tensor)
    one_body_tensor = one_body_tensor.reshape(n_qubits, n_qubits)

    two_body_tensor = np.zeros((n_qubits,) * 4, dtype=complex)
    for p in range(n_qubits):
        for q in range(0, p + 1):
            for r in range(n_qubits):
                for s in range(0, r + 1):
                    pdag_qdag_r_s = get_sparse_operator(
                        FermionOperator(f"{p}^ {q}^ {r} {s}"), n_qubits=n_qubits
                    )
                    pdag_qdag_r_s = pdag_qdag_r_s.toarray()
                    rdm_element = (
                        np.conjugate(ground_state_wf) @ pdag_qdag_r_s @ ground_state_wf
                    )
                    two_body_tensor[p, q, r, s] = rdm_element
                    two_body_tensor[q, p, r, s] = -rdm_element
                    two_body_tensor[q, p, s, r] = rdm_element
                    two_body_tensor[p, q, s, r] = -rdm_element

    return InteractionRDM(one_body_tensor, two_body_tensor)
 def test_split_rank2468(self):
     """Split up to rank four operators
     """
     ops = {}
     ops[2] = FermionOperator('10^ 1', 1.0)
     ops[4] = FermionOperator('3^ 7^ 8 7', 1.0)
     ops[6] = FermionOperator('7^ 6^ 2^ 2 1 9', 1.0)
     ops[8] = FermionOperator('0^ 3^ 2^ 11^ 12 3 9 4', 1.0)
     full_string = ops[2] + ops[4] + ops[6] + ops[8]
     terms, _ = split_openfermion_tensor(full_string)
     for rank in range(2, 9, 2):
         with self.subTest(rank=rank):
             self.assertEqual(ops[rank], terms[rank])
 def test_mutate_config_operator_order_with_beta(self):
     """Same test as before but now we create a beta electron inbetween to
     ensure that the parity of the alpha string is accounted for
     """
     ref0 = [29, 1, -1]
     ops0 = FermionOperator('8^ 1^ 2', 1.0)
     ref1 = [29, 1, 1]
     ops1 = FermionOperator('2 1^ 8^', 1.0)
     for term in ops0.terms:
         self.assertListEqual(
             ref0, list(openfermion_utils.mutate_config(15, 0, term)))
     for term in ops1.terms:
         self.assertListEqual(
             ref1, list(openfermion_utils.mutate_config(15, 0, term)))
 def test_mutate_config_alpha_beta_order(self):
     """Any beta operator must commute with all alpha operators before it
     can act on the reference state.  This changes the parity
     """
     ref0 = [1, 4, -1]
     ops0 = FermionOperator('5^', 1.0)
     ref1 = [9, 0, 1]
     ops1 = FermionOperator('7', 1.0)
     for term in ops0.terms:
         self.assertListEqual(
             ref0, list(openfermion_utils.mutate_config(1, 0, term)))
     for term in ops1.terms:
         self.assertListEqual(
             ref1, list(openfermion_utils.mutate_config(9, 8, term)))