chemistrygen.py 4.0 KB
Newer Older
Q
Quleaf 已提交
1 2
# !/usr/bin/env python3
# Copyright (c) 2020 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.
Q
Quleaf 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Q
Quleaf 已提交
16
r"""
Q
Quleaf 已提交
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
chemistry
"""

from numpy import array, kron, trace
import openfermion
import openfermionpyscf
import scipy
import scipy.linalg

__all__ = [
    "calc_H_rho_from_qubit_operator",
    "read_calc_H",
]


Q
Quleaf 已提交
32 33 34 35 36 37 38 39 40
def _Hamiltonian_str_convert(qubit_op):
    r"""Convert provided Hamiltonian information to Pauli string

    Args:
        qubit_op: instance of ``QubitOperator`` class defined in ``openfermion``

    Returns:
        H_info for Hamiltonian
    """
Q
Quleaf 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
    info_dic = qubit_op.terms

    def process_tuple(tup):
        if len(tup) == 0:
            return 'i0'
        else:
            res = ''
            for ele in tup:
                res += ele[1].lower()
                res += str(ele[0])
                res += ','
            return res[:-1]

    H_info = []

    for key, value in qubit_op.terms.items():
        H_info.append([value.real, process_tuple(key)])

    return H_info


Q
Quleaf 已提交
62
def calc_H_rho_from_qubit_operator(qubit_op, n_qubits):
Q
Quleaf 已提交
63 64 65 66 67 68 69 70 71 72 73 74 75
    r"""Generate a Hamiltonian from QubitOperator

    Args:
        qubit_op: instance of ``QubitOperator`` class defined in ``openfermion``
        n_qubits: number of qubits

    Raises:
        Exception: unrecognized basis

    Returns:
        Tuple:
        -  H: (2**n, 2**n) complex128 array, as the Hamiltonian (n == n_qubits)
        -  rho: (2**n, 2**n) complex128 array, as the density matrix (n == n_qubits)
Q
Quleaf 已提交
76
    """
Q
Quleaf 已提交
77
    
Q
Quleaf 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

    # const
    beta = 1

    sigma_table = {
        'I': array([[1, 0], [0, 1]]),
        'Z': array([[1, 0], [0, -1]]),
        'X': array([[0, 1], [1, 0]]),
        'Y': array([[0, -1j], [1j, 0]])
    }

    # calc Hamiltonian
    H = 0
    for terms, h in qubit_op.terms.items():
        basis_list = ['I'] * n_qubits
        for index, action in terms:
            basis_list[index] = action

        for sigma_symbol in basis_list:
            b = sigma_table.get(sigma_symbol, None)
            if b is None:
                raise Exception('unrecognized basis')
            h = kron(h, b)

        H = H + h

    # calc rho
    rho = scipy.linalg.expm(-1 * beta *
                            H) / trace(scipy.linalg.expm(-1 * beta * H))

Q
Quleaf 已提交
108 109
    return H.astype('complex128'), rho.astype(
        'complex128')  # the returned dic will have 2 ** n value
Q
Quleaf 已提交
110 111 112


def read_calc_H(geo_fn, multiplicity=1, charge=0):
Q
Quleaf 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125 126
    r"""Read and calc the H and rho

    Args:
        geo_fn (str): geometry filename
        multiplicity (int, optional): used in openfermionpyscf, Defaults to 1.
        charge (int, optional): used in openfermionpyscf, Defaults to 0.

    Raises:
        Exception: filename should be a string

    Returns:
        Tuple:
        -  H: the Hamiltonian
        -  nqubit: qubit 的个数
Q
Quleaf 已提交
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
    """

    if not isinstance(geo_fn, str):  # geo_fn = 'h2.xyz'
        raise Exception('filename is a string')

    geo = []

    with open(geo_fn) as f:
        f.readline()
        f.readline()

        for line in f:
            species, x, y, z = line.split()
            geo.append([species, (float(x), float(y), float(z))])

    # meanfield data
Q
Quleaf 已提交
143 144
    molecular_hamiltonian = openfermionpyscf.generate_molecular_hamiltonian(geo, 'sto-3g', multiplicity, charge)
    qubit_op = openfermion.transforms.jordan_wigner(molecular_hamiltonian)
Q
Quleaf 已提交
145

Q
Quleaf 已提交
146
    # calc H
Q
Quleaf 已提交
147
    Hamiltonian = _Hamiltonian_str_convert(qubit_op)
Q
Quleaf 已提交
148
    return Hamiltonian, molecular_hamiltonian.n_qubits
Q
Quleaf 已提交
149 150


Q
Quleaf 已提交
151
if __name__ == '__main__':
Q
Quleaf 已提交
152
    filename = 'h2.xyz'
Q
Quleaf 已提交
153
    H, N = read_calc_H(geo_fn=filename)
Q
Quleaf 已提交
154
    print('H', H)