Example #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)
Example #2
0
    def __init__(self, orbprop, orb_qubit_map=None, symm_eigval_map=None):
        ham_fop = construct_exact_ham(orbprop)
        ham_qop = openfermion.jordan_wigner(ham_fop)
        n_site = openfermion.count_qubits(ham_qop)

        if symm_eigval_map is not None:
            symm_paulistr = symm.symmetry_pauli_string(
                orbprop, operation_list=list(symm_eigval_map))
            for symmop, qop in symm_paulistr.items():
                print('[ham_qop, {:5s}] = [ham_qop, {}] = {}'.format(
                    symmop, str(qop), openfermion.commutator(ham_qop, qop)))

            self.remover = symm.SymmRemover(n_site,
                                            list(symm_paulistr.values()))
            self.remover.set_eigvals(
                [symm_eigval_map[symm] for symm in symm_paulistr])
            ham_qop_tapered = self.remover.remove_symm_qubits(ham_qop)
            print(self.remover)
            print('len(ham         ) = ', len(ham_qop.terms))
            print('len(ham[tapered]) = ', len(ham_qop_tapered.terms))

            ham_qop = ham_qop_tapered

        self.ham_fop = ham_fop
        self.ham_qop = ham_qop
        self.ham_tensor = openfermion.get_sparse_operator(ham_qop)
        self.n_site = n_site
        self.n_qubit = openfermion.count_qubits(ham_qop)

        nterm = [0] * (
            n_site + 1
        )  # number of paulistrs which length is n (n=0,1,..,n_site).
        for k in ham_qop.terms:
            nterm[len(k)] += 1
        self.nterm = nterm
Example #3
0
    def test_get_ground_state_rdm_from_qubit_op(self):
        # Given
        n_sites = 2
        U = 5.0
        fhm = fermi_hubbard(
            x_dimension=n_sites,
            y_dimension=1,
            tunneling=1.0,
            coulomb=U,
            chemical_potential=U / 2,
            magnetic_field=0,
            periodic=False,
            spinless=False,
            particle_hole_symmetry=False,
        )
        fhm_qubit = jordan_wigner(fhm)
        fhm_int = get_interaction_operator(fhm)
        e, wf = jw_get_ground_state_at_particle_number(
            get_sparse_operator(fhm), n_sites
        )

        # When
        rdm = get_ground_state_rdm_from_qubit_op(
            qubit_operator=fhm_qubit, n_particles=n_sites
        )

        # Then
        self.assertAlmostEqual(e, rdm.expectation(fhm_int))
Example #4
0
    def __init__(self,
                 hamiltonian: Union[openfermion.DiagonalCoulombHamiltonian,
                                    openfermion.FermionOperator,
                                    openfermion.InteractionOperator,
                                    openfermion.QubitOperator],
                 use_linear_op: bool = False) -> None:
        """
        Args:
            hamiltonian: The Hamiltonian.
            use_linear_op: Whether to use a LinearOperator instead of a sparse
                matrix to compute expectation values. Using a LinearOperator
                is more memory-efficient but results in much slower expectation
                value computation.
        """
        self.hamiltonian = hamiltonian

        if isinstance(hamiltonian, openfermion.QubitOperator):
            hamiltonian_qubit_op = hamiltonian
        else:
            hamiltonian_qubit_op = openfermion.jordan_wigner(hamiltonian)

        self.variance_bound = hamiltonian_qubit_op.induced_norm(order=1)**2

        if use_linear_op:
            self._hamiltonian_linear_op = openfermion.LinearQubitOperator(
                hamiltonian_qubit_op)
        else:
            self._hamiltonian_linear_op = openfermion.get_sparse_operator(
                hamiltonian_qubit_op)
Example #5
0
    def test_run_psi4(self):

        geometry = {
            "sites": [{
                'species': 'H',
                'x': 0,
                'y': 0,
                'z': 0
            }, {
                'species': 'H',
                'x': 0,
                'y': 0,
                'z': 1.7
            }]
        }

        results, hamiltonian = run_psi4(geometry, save_hamiltonian=True)
        self.assertAlmostEqual(results['energy'], -0.8544322638069642)
        self.assertEqual(results['n_alpha'], 1)
        self.assertEqual(results['n_beta'], 1)
        self.assertEqual(results['n_mo'], 2)
        self.assertEqual(results['n_frozen_core'], 0)
        self.assertEqual(results['n_frozen_valence'], 0)

        self.assertEqual(hamiltonian.n_qubits, 4)
        qubit_operator = qubit_operator_sparse(jordan_wigner(hamiltonian))
        energy, state = jw_get_ground_state_at_particle_number(
            qubit_operator, 2)

        results_cisd, hamiltonian = run_psi4(geometry, method='ccsd')

        # For this system, the CCSD energy should be exact.
        self.assertAlmostEqual(energy, results_cisd['energy'])
Example #6
0
    def __init__(self,
                 name,
                 geometry,
                 multiplicity,
                 charge,
                 n_orbitals,
                 n_electrons,
                 basis='sto-3g',
                 frozen_els=None):
        self.name = name
        self.multiplicity = multiplicity
        self.charge = charge
        self.basis = basis
        self.geometry = geometry

        self.molecule_data = MolecularData(geometry=self.geometry,
                                           basis=basis,
                                           multiplicity=self.multiplicity,
                                           charge=self.charge)

        self.molecule_psi4 = run_psi4(
            self.molecule_data, run_fci=True)  # old version of openfermion

        # Hamiltonian transforms
        self.molecule_ham = self.molecule_psi4.get_molecular_hamiltonian()
        self.hf_energy = self.molecule_psi4.hf_energy.item(
        )  # old version of openfermion
        self.fci_energy = self.molecule_psi4.fci_energy.item(
        )  # old version of openfermion

        # TODO: the code below corresponds to the most recent version in the opefermion documentation.
        #  However it has problems with ray???
        # calculate_molecule_psi4 = run_pyscf(self.molecule_data, run_scf=True, run_cisd=True, run_fci=True)
        # self.molecule_ham = calculate_molecule_psi4.get_molecular_hamiltonian()
        # self.hf_energy = calculate_molecule_psi4.hf_energy
        # self.fci_energy = float(calculate_molecule_psi4.fci_energy)
        # del calculate_molecule_psi4

        self.energy_eigenvalues = None  # use this only if calculating excited states

        if frozen_els is None:
            self.n_electrons = n_electrons
            self.n_orbitals = n_orbitals
            self.n_qubits = n_orbitals
            self.fermion_ham = get_fermion_operator(self.molecule_ham)
        else:
            self.n_electrons = n_electrons - len(frozen_els['occupied'])
            self.n_orbitals = n_orbitals - len(frozen_els['occupied']) - len(
                frozen_els['unoccupied'])
            self.n_qubits = self.n_orbitals
            self.fermion_ham = freeze_orbitals(
                get_fermion_operator(self.molecule_ham),
                occupied=frozen_els['occupied'],
                unoccupied=frozen_els['unoccupied'],
                prune=True)
        self.jw_qubit_ham = jordan_wigner(self.fermion_ham)

        # this is used only for calculating excited states. list of [term_index, term_state]
        self.H_lower_state_terms = None
Example #7
0
    def operations(self, qubits: Sequence[cirq.Qid]) -> cirq.OP_TREE:
        """Returns qubit operators based on STO-3G and UCCSD ansatz"""
        _symbols = list(self.params())
        _ucc_operator = self._fermionic_operators  # self._get_fermionic_operators()

        for i, fo in enumerate(_ucc_operator[::2]):
            # Jordan-Wigner transform each fermionic operator + its Hermitian conjugate
            qo_list = list(of.jordan_wigner(fo - of.hermitian_conjugated(fo)))
            yield IGeneralizedUCCSD.qubit_to_gate_operators(
                qubit_operators=qo_list, qubits=qubits, par=_symbols[i])
Example #8
0
 def test_get_diagonal_component_polynomial_tensor(self):
     fermion_op = FermionOperator("0^ 1^ 2^ 0 1 2", 1.0)
     fermion_op += FermionOperator("0^ 1^ 2^ 0 1 3", 2.0)
     fermion_op += FermionOperator((), 3.0)
     polynomial_tensor = get_polynomial_tensor(fermion_op)
     diagonal_op, remainder_op = get_diagonal_component(polynomial_tensor)
     self.assertTrue((diagonal_op + remainder_op) == polynomial_tensor)
     diagonal_qubit_op = jordan_wigner(get_fermion_operator(diagonal_op))
     remainder_qubit_op = jordan_wigner(get_fermion_operator(remainder_op))
     for term in diagonal_qubit_op.terms:
         for pauli in term:
             self.assertTrue(pauli[1] == "Z")
     for term in remainder_qubit_op.terms:
         is_diagonal = True
         for pauli in term:
             if pauli[1] != "Z":
                 is_diagonal = False
                 break
         self.assertFalse(is_diagonal)
Example #9
0
 def test_get_diagonal_component_interaction_op(self):
     fermion_op = FermionOperator("1^ 1", 0.5)
     fermion_op += FermionOperator("2^ 2", 0.5)
     fermion_op += FermionOperator("1^ 2^ 0 3", 0.5)
     diagonal_op, remainder_op = get_diagonal_component(
         get_interaction_operator(fermion_op))
     self.assertTrue((diagonal_op +
                      remainder_op) == get_interaction_operator(fermion_op))
     diagonal_qubit_op = jordan_wigner(diagonal_op)
     remainder_qubit_op = jordan_wigner(remainder_op)
     for term in diagonal_qubit_op.terms:
         for pauli in term:
             self.assertTrue(pauli[1] == "Z")
     is_diagonal = True
     for term in remainder_qubit_op.terms:
         for pauli in term:
             if pauli[1] != "Z":
                 is_diagonal = False
                 break
     self.assertFalse(is_diagonal)
Example #10
0
    def __init__(self, fermion_ham, n_orbitals, n_electrons):
        self.name = '{}_e_{}_orb'.format(n_electrons, n_orbitals)
        self.n_electrons = n_electrons

        self.n_orbitals = n_orbitals
        self.n_qubits = self.n_orbitals
        self.fermion_ham = fermion_ham
        self.qubit_ham = jordan_wigner(self.fermion_ham)

        self.hf_energy = 0  # wild guess

        self.H_lower_state_terms = None
Example #11
0
def get_mb_wavefunction_circuit(packed_amplitudes: ndarray, n_spin_orb, n_electron, n_gadgets):

   fermion_generator = uccsd_singlet_generator(packed_amplitudes, n_spin_orb,
                                               n_electron)

   qubit_generator = jordan_wigner(fermion_generator)
   qubit_generator.compress()

   mb_wavefunction_circuit = generate_hf_wavefunction_circuit(n_spin_orb, n_electron//2, n_electron//2)

   for pauli, coeff in list(qubit_generator.terms.items())[:n_gadgets]:
       pauli_evolution(pauli, coeff, mb_wavefunction_circuit)

   return mb_wavefunction_circuit
Example #12
0
        def single_test(i):
            N = 8

            #k = np.random.rand(N,N)
            #k -= (k+k.T)/2  # random real antisymmetric matrix
            k = get_random_antihermite_mat(N)
            umat = scipy.linalg.expm(k)
            #print(umat)

            c1 = freqerica.circuit.rotorb.OrbitalRotation(umat)

            from openfermion import FermionOperator, jordan_wigner, get_sparse_operator
            fop = FermionOperator()
            for p in range(N):
                for q in range(N):
                    fop += FermionOperator(((p, 1), (q, 0)), k[p, q])
            qop = jordan_wigner(fop)
            #print(qop)

            #from freqerica.circuit.trotter import TrotterStep
            from freqerica.util.qulacsnize import convert_state_vector
            import qulacs
            #M = 100
            #c2 = TrotterStep(N, qop/M)

            s1 = qulacs.QuantumState(N)
            s1.set_Haar_random_state()
            #s2 = s1.copy()
            s3 = convert_state_vector(N, s1.get_vector())

            c1._circuit.update_quantum_state(s1)
            #for i in range(M): c2._circuit.update_quantum_state(s2)

            s3 = scipy.sparse.linalg.expm_multiply(get_sparse_operator(qop),
                                                   s3)

            #ip12 = qulacs.state.inner_product(s1, s2)
            ip13 = np.conjugate(convert_state_vector(N,
                                                     s1.get_vector())).dot(s3)
            #ip23 = np.conjugate(convert_state_vector(N, s2.get_vector())).dot(s3)
            #print('dot(s1,s2)', abs(ip12), ip12)
            #print('dot(s1,s3)', abs(ip13), ip13)
            #print('dot(s2,s3)', abs(ip23), ip23)

            print('[trial{:02d}] fidelity-1 : {:+.1e}   dot=({:+.5f})'.format(
                i,
                abs(ip13) - 1, ip13))
Example #13
0
 def __init__(self,
              name: str,
              ansatz: VariationalAnsatz,
              hamiltonian: Union[openfermion.DiagonalCoulombHamiltonian,
                                 openfermion.FermionOperator,
                                 openfermion.InteractionOperator,
                                 openfermion.QubitOperator],
              preparation_circuit: Optional[cirq.Circuit] = None,
              datadir: Optional[str] = None) -> None:
     self.hamiltonian = hamiltonian
     if isinstance(hamiltonian, openfermion.QubitOperator):
         hamiltonian_qubit_op = hamiltonian
     else:
         hamiltonian_qubit_op = openfermion.jordan_wigner(hamiltonian)
     self._variance_bound = hamiltonian_qubit_op.induced_norm(order=1)**2
     self._hamiltonian_linear_op = openfermion.LinearQubitOperator(
         hamiltonian_qubit_op)
     super().__init__(name, ansatz, preparation_circuit, datadir)
Example #14
0
def one_particle_ucc(h, reference=1, trotter_order=1, trotter_steps=1):
    """
    UCC-style ansatz preserving particle number.

    @author: Joel, Carl

    :param np.ndarray h: The hamiltonian matrix.
    :param int reference: the binary number corresponding to the reference
        state (which must be a Fock-state).
    :param int trotter_order: trotter order in suzuki_trotter
    :param int trotter_steps: trotter steps in suzuki_trotter
    :return: function(theta) which returns the ansatz Program
    """
    dim = h.shape[0]

    terms = []
    for occupied in range(dim):
        if reference & (1 << occupied):
            for unoccupied in range(dim):
                if not reference & (1 << unoccupied):
                    term = FermionOperator(((unoccupied, 1), (occupied, 0))) \
                           - FermionOperator(((occupied, 1), (unoccupied, 0)))
                    terms.append(qubitop_to_pyquilpauli(jordan_wigner(term)))

    exp_maps = trotterize(terms, trotter_order, trotter_steps)

    def wrap(theta):
        """
        Returns the ansatz Program.

        :param np.ndarray theta: parameters
        :return: the Program
        :rtype: pyquil.Program
        """
        prog = Program()
        for qubit in range(int.bit_length(reference)):
            if reference & (1 << qubit):
                prog += X(qubit)
        for idx, exp_map in enumerate(exp_maps):
            for exp in exp_map:
                prog += exp(theta[idx])
        return prog

    return wrap
Example #15
0
def test_rotorb_circuit():
    import scipy.linalg
    np.set_printoptions(linewidth=300)

    N = 8

    #k = np.random.rand(N,N)
    #k -= (k+k.T)/2  # random real antisymmetric matrix
    k = get_random_antihermite_mat(N)
    umat = scipy.linalg.expm(k)
    print(umat)

    c1 = OrbitalRotation(umat)

    from openfermion import FermionOperator, jordan_wigner, get_sparse_operator
    fop = FermionOperator()
    for p in range(N):
        for q in range(N):
            fop += FermionOperator(((p, 1), (q, 0)), k[p, q])
    qop = jordan_wigner(fop)
    #print(qop)

    from trotter_qulacs import TrotterStep
    from util_qulacs import convert_state_vector
    M = 100
    c2 = TrotterStep(N, qop / M)

    s1 = qulacs.QuantumState(N)
    s1.set_Haar_random_state()
    s2 = s1.copy()
    s3 = convert_state_vector(N, s1.get_vector())

    c1._circuit.update_quantum_state(s1)
    for i in range(M):
        c2._circuit.update_quantum_state(s2)

    s3 = scipy.sparse.linalg.expm_multiply(get_sparse_operator(qop), s3)

    ip12 = qulacs.state.inner_product(s1, s2)
    ip13 = np.conjugate(convert_state_vector(N, s1.get_vector())).dot(s3)
    ip23 = np.conjugate(convert_state_vector(N, s2.get_vector())).dot(s3)
    print('dot(s1,s2)', abs(ip12), ip12)
    print('dot(s1,s3)', abs(ip13), ip13)
    print('dot(s2,s3)', abs(ip23), ip23)
def benchmark_molecular_operator_jordan_wigner(n_qubits):
    """Test speed with which molecular operators transform to qubit operators.

    Args:
        n_qubits: The size of the molecular operator instance. Ideally, we
            would be able to transform to a qubit operator for 50 qubit
            instances in less than a minute. We are way too slow right now.

    Returns:
        runtime: The number of seconds required to make the conversion.
    """
    # Get an instance of InteractionOperator.
    molecular_operator = random_interaction_operator(n_qubits)

    # Convert to a qubit operator.
    start = time.time()
    _ = jordan_wigner(molecular_operator)
    end = time.time()

    # Return runtime.
    runtime = end - start
    return runtime
 def get_hamiltonian_evaluation_operator(w: IWaveFunction) -> QubitOperator:
     molecule = w.molecule
     molecule.load()
     return jordan_wigner(molecule.get_molecular_hamiltonian())
Example #18
0
def test_hubbard_model(abscissa: int, ordinate: int, tunneling: float, coulomb: float, magnetic_field: float, chemical_potential: float, periodic: bool, spinless: bool, symmetry: bool):
    hubbard_operator = fermi_hubbard(
        x_dimension=abscissa,
        y_dimension=ordinate,
        tunneling=tunneling,
        coulomb=coulomb,
        chemical_potential=chemical_potential,
        magnetic_field=magnetic_field,
        periodic=periodic,
        spinless=spinless,
        particle_hole_symmetry=symmetry
    )
    # print(hubbard_operator)
    jw_hamiltonian = jordan_wigner(hubbard_operator)
    print('Jordan-Wigner hamiltonian without compression: ')
    print(jw_hamiltonian)
    print()
    jw_hamiltonian.compress()
    print('Jordan-Wigner hamiltonian with compression: ')
    print(jw_hamiltonian)
    print()
    sparse_operator = get_sparse_operator(hubbard_operator)
    print('Sparse operator')
    print(sparse_operator)
    print()
    print(f'Energy of the model is {get_ground_state(sparse_operator)[0]} in units of T and J')

    # xs = range(1, 9)
    # energy_levels = [
    #     get_ground_state(
    #         get_sparse_operator(
    #             fermi_hubbard(
    #                 x_dimension=x,
    #                 y_dimension=ordinate,
    #                 tunneling=tunneling,
    #                 coulomb=coulomb,
    #                 chemical_potential=chemical_potential,
    #                 magnetic_field=magnetic_field,
    #                 periodic=periodic,
    #                 spinless=spinless,
    #                 particle_hole_symmetry=symmetry
    #             )
    #         )
    #     )[0]
    #     for x in xs
    # ]
    #
    # os.makedirs('assets/hubbard', exist_ok=True)
    #
    # draw_plot(
    #     xs, energy_levels,
    #     x_label='X coordinate',
    #     y_label='Ground state energy in units of T and J',
    #     title='Ground state energy of the Hubbard model',
    #     path='assets/hubbard/x.jpeg'
    # )
    #
    # energy_levels = [
    #     get_ground_state(
    #         get_sparse_operator(
    #             fermi_hubbard(
    #                 x_dimension=abscissa,
    #                 y_dimension=x,
    #                 tunneling=tunneling,
    #                 coulomb=coulomb,
    #                 chemical_potential=chemical_potential,
    #                 magnetic_field=magnetic_field,
    #                 periodic=periodic,
    #                 spinless=spinless,
    #                 particle_hole_symmetry=symmetry
    #             )
    #         )
    #     )[0]
    #     for x in xs
    # ]
    # draw_plot(
    #     xs, energy_levels,
    #     x_label='Y coordinate',
    #     y_label='Ground state energy in units of T and J',
    #     title='Ground state energy of the Hubbard model',
    #     path='assets/hubbard/y.jpeg'
    # )

    ts = np.arange(0, 4, 0.2)
    energy_levels = [
        get_ground_state(
            get_sparse_operator(
                fermi_hubbard(
                    x_dimension=abscissa,
                    y_dimension=ordinate,
                    tunneling=t,
                    coulomb=coulomb,
                    chemical_potential=chemical_potential,
                    magnetic_field=magnetic_field,
                    periodic=periodic,
                    spinless=spinless,
                    particle_hole_symmetry=symmetry
                )
            )
        )[0]
        for t in ts
    ]
    draw_plot(
        ts, energy_levels,
        x_label='Tunneling coefficient',
        y_label='Ground state energy in units of T and J',
        title='Ground state energy of the Hubbard model',
        path='assets/hubbard/t.jpeg'
    )
Example #19
0
def test_operators_initialization(coefficient: float):
    # 1. Let's create some basic operator

    operator = FermionOperator('2^ 1 3 7^', coefficient)
    alternative_operator = coefficient * FermionOperator(((2, 1), (1, 0), (3, 0), (6, 1)))

    sum_of_operators = operator + alternative_operator

    identity = FermionOperator('')
    zero = FermionOperator()

    # print(f'Fermion operator: {operator}; the terms are {list(operator.terms.keys())[0]}')
    print(f'Fermion operator: {operator}; the flattened terms are {operator.flattened_terms}')
    print(f'Alternative fermion operator: {alternative_operator}')
    print(f'Sum fermion operator: {sum_of_operators}; the terms are {sum_of_operators.terms}')
    # print(operator == alternative_operator)
    print(f'Identity operator: {identity}')
    print(f'Zero operator: {zero}')

    # 2. Checking operator combinations

    lhs_operator = FermionOperator('17^')
    rhs_operator = FermionOperator('19^')

    print(describe_result(lhs_operator, rhs_operator, lambda lhs, rhs: lhs * rhs, '*'))
    print(describe_result(lhs_operator, lhs_operator, lambda lhs, rhs: lhs * rhs, '*'))

    print(describe_result(lhs_operator, rhs_operator, lambda lhs, rhs: lhs + rhs, '+'))
    print(describe_result(lhs_operator, 5, lambda lhs, rhs: lhs ** rhs, '^'))

    # print(describe_result(lhs_operator * rhs_operator, lhs_operator, lambda lhs, rhs: lhs / rhs, '/')) # Throws an exception

    # 3. Use some auxiliary functions

    print(f'Operator {lhs_operator ** 5} occupies {count_qubits(lhs_operator)} qubits')
    print(f'Operator {rhs_operator ** 2} occupies {count_qubits(rhs_operator)} qubits')
    print(f'Operator {operator} occupies {count_qubits(operator)} qubits')

    print(f'Operator {operator} is {"not " if not operator.is_normal_ordered() else ""}normal ordered')
    print(f'Operator {(lhs_operator + rhs_operator)} is {"not " if not (lhs_operator + rhs_operator).is_normal_ordered() else ""}normal ordered')
    print(f'Operator {(lhs_operator * rhs_operator)} is {"not " if not (lhs_operator * rhs_operator).is_normal_ordered() else ""}normal ordered')
    print(f'Operator {(rhs_operator * lhs_operator)} is {"not " if not (rhs_operator * lhs_operator).is_normal_ordered() else ""}normal ordered')

    print(f'Commutator of {lhs_operator} and {rhs_operator} is {commutator(lhs_operator, rhs_operator)}')

    # 4. See qubit operators

    operator = QubitOperator('X1 Z3', coefficient) + QubitOperator('X20', coefficient - 1)
    print(f'Operator {operator} occupies {count_qubits(operator)} qubits')

    # 4. Perform transformations from fermion to qubit operators

    fermion_operator = FermionOperator_('5^', 0.1 + 0.2j)
    fermion_operator += hermitian_conjugated(fermion_operator)
    jw_operator = jordan_wigner(fermion_operator)
    bk_operator = bravyi_kitaev(fermion_operator)

    print()
    print('Source fermion operator:')
    print(fermion_operator)
    print()
    print('Source fermion operator with conjugate:')
    print(fermion_operator)
    print()
    print('Source fermion operator with conjugate passed through Jordan-Wigner transformation:')
    print(jw_operator)
    print()
    print('Eigenspectrum of the obtained operator:')
    print(eigenspectrum(jw_operator))
    print()
    print('Reversed:')
    print(reverse_jordan_wigner(jw_operator))
    print()
    print('Source fermion operator with conjugate passed through Bravyi-Kitaev transformation:')
    print(bk_operator)
    print()
    print('Eigenspectrum of the obtained operator:')
    print(eigenspectrum(bk_operator))
    print()
Example #20
0
 def do_transform(self, fermion_operator: openfermion.FermionOperator,
                  *args, **kwargs) -> openfermion.QubitOperator:
     return openfermion.jordan_wigner(fermion_operator, *args, **kwargs)
Example #21
0
    # dummy geometry
    geometry = [["Li", [0, 0, 0], ["H", [0, 0, 1.4]]]]
    charge = 0
    multiplicity = 1
    molecule = of.MolecularData(
        geometry=geometry,
        basis="sto-3g",
        charge=charge,
        multiplicity=multiplicity,
    )
    molecule.one_body_integrals = h1e
    molecule.two_body_integrals = np.einsum("ijlk", -2 * h2e)
    molecular_hamiltonian = molecule.get_molecular_hamiltonian()
    molecular_hamiltonian.constant = 0
    ham_fop = of.get_fermion_operator(molecular_hamiltonian)
    ham_mat = of.get_sparse_operator(of.jordan_wigner(ham_fop)).toarray()

    cirq_ci = fqe.to_cirq(wfn)
    cirq_ci = cirq_ci.reshape((2**12, 1))
    assert np.isclose(cirq_ci.conj().T @ ham_mat @ cirq_ci, ecalc)

    hf_idx = int("111100000000", 2)
    hf_idx2 = int("111001000000", 2)
    hf_vec = np.zeros((2**12, 1))
    hf_vec2 = np.zeros((2**12, 1))
    hf_vec[hf_idx, 0] = 1.0
    hf_vec2[hf_idx2, 0] = 1.0

    # scale diagonal so vacuum has non-zero energy
    ww, vv = davidsonliu(ham_mat + np.eye(ham_mat.shape[0]),
                         1,
Example #22
0
    def test_trotterstep_circuit(self):
        from freqerica.op.symbol import WrappedExpr as Symbol
        from openfermion import FermionOperator, jordan_wigner, get_sparse_operator
        from sympy import Array
        import numpy as np
        np.random.seed(100)
        import scipy
        import qulacs

        n_orb = 2

        const = Symbol('const')
        T1 = [[None for _ in range(n_orb)] for _ in range(n_orb)]
        for p in range(n_orb):
            for q in range(p, n_orb):
                t = Symbol('t{}{}'.format(p,q))
                T1[p][q] = T1[q][p] = t
        T1 = Array(T1)
        print(T1)

        const_value = np.random.rand()
        T1_value = np.random.rand(n_orb,n_orb)*0.01
        T1_value += T1_value.T
        print(const_value)
        print(T1_value)

        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

        fop_symbol = op1e(const, T1)
        qop_symbol = jordan_wigner(fop_symbol)
        print(fop_symbol)
        print(qop_symbol)

        n_qubit = n_orb*2

        # c1 : TrotterStep with symbolic qop
        c1 = freqerica.circuit.trotter.TrotterStep(n_qubit, (-1j)*qop_symbol)
        print(c1)
        symbol_number_pairs = [(const, const_value), (T1, T1_value)]
        c1.subs(symbol_number_pairs)
        print(c1)

        # c2 : TrotterStep with numerical qop
        fop_number = op1e(const_value, T1_value)
        qop_number = jordan_wigner(fop_number)
        c2 = freqerica.circuit.trotter.TrotterStep(n_qubit, (-1j)*qop_number)
        print(c2)

        # c3 : oldtype with numerical qop
        c3 = qulacs.QuantumCircuit(n_qubit)
        freqerica.circuit.trotter.trotter_step_2nd_order(c3, (-1j)*qop_number)



        s0 = qulacs.QuantumState(n_qubit)
        s0.set_Haar_random_state()
        s1 = s0.copy()
        s2 = s0.copy()
        s3 = s0.copy()
        from freqerica.util.qulacsnize import convert_state_vector
        sv = convert_state_vector( n_qubit, s0.get_vector() )

        corr1 = []
        corr2 = []
        corr3 = []
        corrv = []
        for t in range(100):
            corr1.append( qulacs.state.inner_product(s0, s1) )
            corr2.append( qulacs.state.inner_product(s0, s2) )
            corr3.append( qulacs.state.inner_product(s0, s3)*np.exp(-1j*qop_number.terms[()]*t) )
            corrv.append( np.dot(np.conjugate(convert_state_vector(n_qubit, s0.get_vector())), sv) )
            c1._circuit.update_quantum_state(s1)
            c2._circuit.update_quantum_state(s2)
            c3.update_quantum_state(s3)
            sv = scipy.sparse.linalg.expm_multiply(-1j * get_sparse_operator(qop_number), sv)
Example #23
0
    ansatz = ansatz_1()

    init_qasm = None

    global_cache = GlobalCache(e_system, excited_state=0)
    global_cache.calculate_exc_gen_sparse_matrices_dict(ansatz)

    backend = MatrixCacheBackend

    optimizer = 'BFGS'
    optimizer_options = {'gtol': 10e-8, 'maxiter': 10}
    vqe_runner = VQERunner(e_system, backend=backend, print_var_parameters=False, use_ansatz_gradient=True,
                           optimizer=optimizer, optimizer_options=optimizer_options)

    result = vqe_runner.vqe_run(ansatz=ansatz,  cache=global_cache, init_state_qasm=init_qasm)

    parameters = result.x
    statevector = global_cache.get_statevector(ansatz, parameters, init_state_qasm=init_qasm)
    statevector = statevector.todense()

    operator = 'elenaananana'   # TODO: TOVA trqbva da e klas openfermion.FermionicOperator
    operator = openfermion.jordan_wigner(operator)
    operator = openfermion.get_sparse_operator(operator, n_orbitals)

    expectation_value = statevector.dot(operator).dot(statevector.conj().transpose())

    print(expectation_value)

    print('yolo')

Example #24
0
    def test_run_psi4(
        self,
        psi4_config: Psi4Config,
        expected_tuple: ExpectedTuple,
        jw_particle_num: Optional[int],
    ):
        results_dict = run_psi4(
            geometry=psi4_config.geometry,
            n_active_extract=psi4_config.n_active_extract,
            n_occupied_extract=psi4_config.n_occupied_extract,
            freeze_core=psi4_config.freeze_core,
            freeze_core_extract=psi4_config.freeze_core_extract,
            method=psi4_config.method,
            options=psi4_config.options,
            save_hamiltonian=True,
            save_rdms=psi4_config.save_rdms,
        )

        results, hamiltonian, rdm = (
            results_dict["results"],
            results_dict["hamiltonian"],
            results_dict["rdms"],
        )

        if rdm:
            energy_from_rdm = rdm.expectation(hamiltonian)

        if psi4_config.save_rdms:
            assert math.isclose(results["energy"], energy_from_rdm)
        else:
            assert (math.isclose(results["energy"], expected_tuple.exp_energy)
                    if expected_tuple.exp_energy else True)

        assert (results["n_alpha"] == expected_tuple.exp_alpha
                if expected_tuple.exp_alpha else True)
        assert (results["n_beta"] == expected_tuple.exp_beta
                if expected_tuple.exp_beta else True)
        assert (results["n_mo"] == expected_tuple.exp_mo
                if expected_tuple.exp_mo else True)
        assert (results["n_frozen_core"] == expected_tuple.exp_frozen_core
                if expected_tuple.exp_frozen_core else True)
        assert (results["n_frozen_valence"]
                == expected_tuple.exp_frozen_valence
                if expected_tuple.exp_frozen_valence else True)
        assert (hamiltonian.n_qubits == expected_tuple.exp_n_qubits
                if expected_tuple.exp_n_qubits else True)

        if expected_tuple.exp_one_body_tensor_shape:
            assert (rdm.one_body_tensor.shape[0] ==
                    expected_tuple.exp_one_body_tensor_shape)

            assert math.isclose(einsum("ii->", rdm.one_body_tensor), 2)

        if jw_particle_num:
            qubit_operator = qubit_operator_sparse(jordan_wigner(hamiltonian))
            energy, _ = jw_get_ground_state_at_particle_number(
                qubit_operator, jw_particle_num)

            if expected_tuple.extra_energy_check:
                assert math.isclose(energy,
                                    expected_tuple.extra_energy_check,
                                    rel_tol=1e-7)
            else:
                assert math.isclose(energy, results["energy"], rel_tol=1e-7)
    def observable_measurement(self) -> Tuple[Callable[[cirq.Circuit, Callable[[List[cirq.Qid]], List[cirq.Operation]], int], float], int]:
        """
        Prepares an observable measurement function.
        Not yet general but specific for the H2 Hamiltonian objective.
        :return: Measurement function that: (Input) the circuit, ordered qubits and #measurement repetitions,
        (Output) expectation value. Also returns the circuit cost (number of circuits) required to calculate the expectation value.
        """
        # Hamiltonian observable in the form of qubit operators.
        q_op = jordan_wigner(self.molecule.get_molecular_hamiltonian())
        qubits = self.qubits  # ordered_qubits
        pauli_term_size_lookup = {}
        pauli_weight_lookup = {}
        for term_pauli, term_weight in q_op.terms.items():
            term_size = len(term_pauli)
            if term_size not in pauli_term_size_lookup:
                pauli_term_size_lookup[term_size] = []
            # Set dictionaries
            pauli_term_size_lookup[term_size].append(term_pauli)
            pauli_weight_lookup[term_pauli] = term_weight

        def probability_to_expectation(probability: float, out: int):
            """
            :param probability: Statistical probability [0, 1] corresponding to '0' output measurement.
            :param out: Whether to give information about the '0' or '1' output measurement.
            :return: Scaled measurement probability for either '0' or '1' output measurement in range [-1, 1].
            """
            if out == 0:
                return 2 * probability - 1
            else:
                return 1 - 2 * probability

        def measure_observable(base_circuit: cirq.Circuit, noise_wrapper: Callable[[List[cirq.Qid]], List[cirq.Operation]], meas_reps: int) -> float:  # , ordered_qubits: List[cirq.Qid]
            """
            Constructs multiple quantum circuits to measure the expectation value of a given observable.
            :param base_circuit: Base circuit to measure (can be noisy)
            :param noise_wrapper: Noise wrapper function that generates single or two qubit noise operations
            :param meas_reps: Number of measurement repetitions for each circuit (higher means more accurate) [1, +inf).
            :return: (Approximation of) Hamiltonian observable expectation value.
            """
            result = 0
            basis_map = IGeneralizedUCCSD.pauli_basis_map()  # Consistent qubit mapping
            labels = ['Z' + str(i) for i in range(len(qubits))]  # Computational measurement labels
            simulator = cirq.DensityMatrixSimulator()
            expectation_lookup = QubitOperator(' ', 1.0)  # Base term

            circuit_01 = base_circuit.copy()  # Single pauli term measurement circuit
            for operator in pauli_term_size_lookup[1]:
                circuit_01.append([(basis_map[new_basis](qubits[qubit_id], 1), noise_wrapper(qubits[qubit_id])) for qubit_id, new_basis in operator])
            circuit_01.append(cirq.measure(q, key=labels[i]) for i, q in enumerate(qubits))
            circuit_01_shots = simulator.run(circuit_01, repetitions=meas_reps)

            # Single pauli terms
            for lb in labels:
                probability = circuit_01_shots.multi_measurement_histogram(keys=[lb])[(0,)] / meas_reps
                expectation = probability_to_expectation(probability, out=0)
                expectation_lookup += QubitOperator(lb, expectation)

            # Two pauli terms
            for operator_labels in itertools.combinations(labels, 2):
                probability = (circuit_01_shots.multi_measurement_histogram(keys=operator_labels)[(0, 0)] +
                               circuit_01_shots.multi_measurement_histogram(keys=operator_labels)[(1, 1)]) / meas_reps
                expectation = probability_to_expectation(probability, out=0)
                expectation_lookup += QubitOperator(' '.join(operator_labels), expectation)

            # Four pauli terms
            for operator in pauli_term_size_lookup[4]:  # Four pauli term measurement circuit
                operator_labels = [new_basis + str(qubit_id) for qubit_id, new_basis in operator]
                # Build circuit with basis transformation and measurement operators
                circuit_02 = base_circuit.copy()
                circuit_02.append([(basis_map[new_basis](qubits[qubit_id], 1), noise_wrapper(qubits[qubit_id])) for qubit_id, new_basis in operator])
                circuit_02.append(cirq.measure(q, key=operator_labels[i]) for i, q in enumerate(qubits))
                # Run measurement
                circuit_02_shots = simulator.run(circuit_02, repetitions=meas_reps)
                # Only equal parities
                probability = (circuit_02_shots.multi_measurement_histogram(keys=operator_labels)[(0, 0, 1, 1)] +
                               circuit_02_shots.multi_measurement_histogram(keys=operator_labels)[(1, 1, 0, 0)] +
                               circuit_02_shots.multi_measurement_histogram(keys=operator_labels)[(0, 1, 1, 0)] +
                               circuit_02_shots.multi_measurement_histogram(keys=operator_labels)[(1, 0, 1, 0)] +
                               circuit_02_shots.multi_measurement_histogram(keys=operator_labels)[(1, 0, 0, 1)] +
                               circuit_02_shots.multi_measurement_histogram(keys=operator_labels)[(0, 1, 0, 1)] +
                               circuit_02_shots.multi_measurement_histogram(keys=operator_labels)[(0, 0, 0, 0)] +
                               circuit_02_shots.multi_measurement_histogram(keys=operator_labels)[(1, 1, 1, 1)]) / meas_reps
                expectation = probability_to_expectation(probability, out=0)
                expectation_lookup += QubitOperator(' '.join(operator_labels), expectation)

            # print(expectation_lookup)

            # Multiply hamiltonian term weights with circuit expectation values for each specific qubit operator set
            for operator in itertools.chain.from_iterable(pauli_term_size_lookup.values()):
                if operator in expectation_lookup.terms:
                    result += pauli_weight_lookup[operator] * expectation_lookup.terms[operator]
                    # print(f'Added {operator}(term): {pauli_weight_lookup[operator]}(weight) * {expectation_lookup.terms[operator]}(expectation) = {pauli_weight_lookup[operator] * expectation_lookup.terms[operator]}')
            return result

        return measure_observable, 5