Skip to content

Commit c740385

Browse files
committed
WIP on QPE example for THC
1 parent ee158fb commit c740385

2 files changed

Lines changed: 867 additions & 15 deletions

File tree

qualtran/bloqs/chemistry/thc/walk_operator.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
"""Function for building a walk operator for the THC hamiltonian."""
15+
import attrs
16+
import numpy as np
1517
from numpy.typing import NDArray
18+
from openfermion.resource_estimates.utils import QI
1619

1720
from qualtran.bloqs.block_encoding.lcu_block_encoding import SelectBlockEncoding
1821
from qualtran.bloqs.chemistry.thc import PrepareTHC, SelectTHC
@@ -51,3 +54,59 @@ def get_walk_operator_for_thc_ham(
5154
block_encoding = SelectBlockEncoding(select=sel, prepare=prep)
5255
walk_op = QubitizationWalkOperator(block_encoding=block_encoding)
5356
return walk_op
57+
58+
59+
def get_reiher_thc_walk_operator(
60+
num_bits_theta: int = 16, num_bits_state_prep: int = 10
61+
) -> QubitizationWalkOperator:
62+
"""Build the THC walk operator for the Reiher hamiltoninan
63+
64+
Note currently we spoof the Hamiltonian by over writing prepare's 1-norm
65+
value with the correct value and use random THC factors for expediency.
66+
67+
Parameters are taken from openfermion compute_cost_thc_test.py.
68+
69+
Args:
70+
num_bits_theta: the number of bits of precision for the givens rotations
71+
num_bits_state_prep: The number of bits of precision for the preparation
72+
of the LCU coefficients using alias sampling.
73+
74+
Returns:
75+
walk_op: A constructed Reiher Hamiltonian walk operator.
76+
"""
77+
# Let's just generate some random coefficients for the moment with parameters
78+
# corresponding to the FeMoCo model complex.
79+
num_spin_orb = 108
80+
num_mu = 350
81+
num_bits_theta = 16
82+
num_bits_state_prep = 10
83+
tpq = np.random.normal(0, 1, size=(num_spin_orb // 2, num_spin_orb // 2))
84+
zeta = np.random.normal(0, 1, size=(num_mu, num_mu))
85+
zeta = 0.5 * (zeta + zeta.T)
86+
eta = np.random.normal(0, 1, size=(num_mu, num_spin_orb // 2))
87+
eri_thc = np.einsum("Pp,Pr,Qq,Qs,PQ->prqs", eta, eta, eta, eta, zeta, optimize=True)
88+
# In practice one typically uses the exact ERI tensor instead of that from
89+
# THC, but that's a minor detail.
90+
tpq_prime = (
91+
tpq
92+
- 0.5 * np.einsum("illj->ij", eri_thc, optimize=True)
93+
+ np.einsum("llij->ij", eri_thc, optimize=True)
94+
)
95+
t_l = np.linalg.eigvalsh(tpq_prime)
96+
qroam_blocking_factor = QI(num_mu + num_spin_orb // 2)[0]
97+
walk_op = get_walk_operator_for_thc_ham(
98+
t_l,
99+
eta,
100+
zeta,
101+
num_bits_state_prep=num_bits_state_prep,
102+
num_bits_theta=num_bits_theta,
103+
kr1=qroam_blocking_factor,
104+
kr2=qroam_blocking_factor,
105+
)
106+
# GIANT HACK: overwrite the lambda value directly
107+
# TODO: maybe parse THC hamiltonian files from openfermion directly
108+
block_encoding = attrs.evolve(
109+
walk_op.block_encoding, prepare=attrs.evolve(walk_op.prepare, sum_of_l1_coeffs=306.3)
110+
)
111+
walk_op = attrs.evolve(walk_op, block_encoding=block_encoding)
112+
return walk_op

0 commit comments

Comments
 (0)