VMC
Variational Monte Carlo(VMC) algorithm in second quantization.
Theory of VMC in quantum chemistry
Local energy & Gradient
Theory
The formula of local energy & gradient calculation.
Classical VMC
For NQS \(\ket{\varPsi}\), one can sample ON vector \(|n\rangle \sim |\varPsi(n)|^2/\langle\varPsi|\varPsi\rangle\) , which can be sampled by using of MCMC sampling or Autoregressive sampling. So the expectation of energy functional \(E = \langle \hat{H}\rangle\) can be calculated by
When we use Autoregressive Sampling , \(\langle\varPsi|\varPsi\rangle=1\), then \(\langle E\rangle = \langle E_{\rm loc}\rangle_{n\sim |\varPsi(n)|^2}\).
In general “Local-energy” \(E_{\rm loc}\) can be calculated by
Where \(H_{nm} = \langle n|\hat{H}|m\rangle\). Because \(H_{nm}\equiv 0, \forall m\notin SD\), so
hat{U}sing Slater–Condon Rule (see: ./libs/C_extension/get_comb_tensor, ./libs/C_extension/get_hij_torch).
Gradient of energy \(\langle E\rangle\) is
which conductor \(\partial_\theta := \dfrac{\partial}{\partial\theta}\), the derivative of the parameter \(\theta\).
Multi-Psi
In this case, we choose an autoregressive wavefunction ansatz, called sampling part \(\varPhi(n) := \langle n | \varPhi \rangle, \sum_n |\varPhi(n)|^2 = 1\), and a extra correction factor, called extra part \(f_n\). Then total wavefunction \(\varPsi(n) = \langle n|\varPsi\rangle\) can be represent as
In general
The expectation of energy \(E\) is
The denominator is actually a constant, so remark it as \(B = \big\langle |\varPhi(n)|^2\big\rangle_{n\sim |\varPhi(n)|^2}, \widetilde{f}_n := f_n/\sqrt B\). Define local energy as
Formally, the correction factor provides a (nonlinear) transformation of the Hamiltonian.
The gradient can be calculated as
With some symmetry
We consider state \(\ket{N,S,M}\) which is eigenvector of operators \(\{N,S,S_z\}\) , Let Spin Flip operator \(\hat{U}_{\rm SF}:=\mathrm{e}^{\mathrm{i}\mathrm{\pi}(S_x-N/2)}\), can flip spins, such as
For states with \(M=0\), then \(N_\alpha = N_\beta = N/2\), it leads to
For example, with the basis set \(\{ \ket{n_\alpha m_\beta} := \ket{n}\otimes \ket{m}:\ket{n},\ket{m}\in\{\ket{0},\ket{1}\},\ket{0} = \begin{bmatrix}1\\0\end{bmatrix},\ket{1} = \begin{bmatrix}0\\1\end{bmatrix} \}\), the matrix elements like
then \(\hat{U}_{\rm SF} \ket{1_\alpha 1_\beta} = -\ket{1_\alpha 1_\beta}\) can be verified. In conclusion
Where \(|n_{\rm SF}\rangle\) is the state whose spins be flipped in state \(\ket{n}\). If target state \(\ket{\varPsi}\) with \(N\) electrons has determinate eigenvalue \(\eta\) of operator \(\hat{U}_{\rm SF}\) (\(\eta\) is defined by yourself. such as H-chain(\(n=50\)), \(N_\alpha\) is 25, if the target state is siglet, then \(\eta = (-1)^{25-0}=-1\))
Define projector \(\hat{P}_\eta = \dfrac{1}{2}(\hat{I}+\eta \hat{U}_{\rm SF})\), which \(I\) is unit operator, it is easy to show that \(\hat{P}_{\eta}^2 = \hat{I}, [\hat{P}_{\eta} , \hat{H}]=0\), for our symmetry-projected NQS
the expectation of energy is
Define \(B = 2\bigg\langle \dfrac{f_n^*\langle n|\hat{P}_\eta|\varPsi\rangle}{\langle n|\varPhi\rangle} \bigg\rangle_n, \ \widetilde{f}_{n} = f_n/\sqrt{B}\), Then
local-energy is
Method
The methods of local energy & gradient calculating.
Reduce \(n^{\prime}\)
(See J. Chem. Theory Comput. 2025, 21, 20, 10252–10262 for detail)
Method 1:
select \(m\) which \(|\langle n|H|m\rangle| \geq \epsilon\), sampling from \(P(m^{\prime}),\ P(m^{\prime}) \propto |H_{nm^{\prime}}|, |H_{nm^{\prime}}| \lt \epsilon\),
\(N\) is the total samples, then:
e.g. we can set \(N = 100, \epsilon = 0.01\) when calculating H-chain(n=50) using aoa bias, reducing the \(m\) to 0.05% with an error of less than 0.2mHa.
see: vmc/energy/eloc/_reduce_psi
Method 2:
Use LookUp-Table(LUT) coming from sampling to reduce \(\varPsi(n^{\prime})\), \(\varPsi(n^{\prime})\) is non-zero if \(n^{\prime}\) is the key of the LUT.
Note: This methods could be is ineffective when When \(p(n)\) presents basically the same (H50, STO-6G, aoa-basis).
see: vmc/energy/eloc/_only_sample_space
NEQS(N Excited QS)
NEQS ref:
Pfau et al., Science 385, eadn0137 (2024). DOI: 10.1126/science.adn0137
arXiv:2506.08594v1
The ansatz of NEQS is \(\varPsi(\mathcal{S})=\det \boldsymbol{\varPsi}(\mathcal{S})\), here \(\mathcal{S}\) is a sample of NEQS, we refer to this as the total sample, is the tuple of \(K\) single samples, which is the configuration in classical NQS, i.e. \(\mathcal{S} = (S_1,S_2,\cdots,S_K)\). And the total ansatz \(\boldsymbol{\varPsi}(\mathcal{S})\) consists of \(K\) single ansätze \(\psi_1,\psi_2,\cdots,\psi_K\):
Then the energy becomes
这里的两个local energy定义为矩阵形式 \(\boldsymbol{E}_{\rm loc}\) 和标量形式 \(E_{\rm loc}(\mathcal{S})\):
and
后者可作为一般的local energy以用于(min)SR的梯度计算与更新。前者对角化之后可以得到所计算的 \(K\) 个态的能量。 以上公式中出现的 \((\boldsymbol{\hat{\mathcal{H}}\varPsi})(\mathcal{S})\) 为
这里 \(\hat{\mathcal{H}}=\sum_{k=1}^K\hat{H}_k\), 每一个 \(\hat{H}_k\) 作用在对应的子空间的configuration \(\ket{S_k}\) 上。
NEQS的local energy的计算方法可以仍然使用NQS的计算方法 (include SIMPLE, REDUCE, …),依照以上矩阵元循环计算(see pynqs/energy/eloc.py 的函数 excited_eloc)。
在计算结束之后,传入标量形式的local energy \(E_{\rm loc}(\mathcal{S})\) 以计算并更新梯度。
激发态能量可以通过对角化矩阵形式的local energy \(\boldsymbol{E}_{\rm loc}\) 得到(see pynqs/energy/etot.py 的函数 calculate_energy)。
对于NEQS的采样,这里是对total sample
从每一个total sample \(\mathcal{S}_n\) 中挑选出第 \(K\) 个single sample \(S_k\) 进行单双激发(此处的propose方式也和NQS的一样,可选单激发、双激发,以及其混合)。
数据会逐single sample进行存储。也就是sample的形状还是 (K*nsample,...), 这部分的实现见 pynqs/sample/metropolis.py 的函数 _neqs_metropolis_step 函数。
这部分功能用起来比较简单,需要传入一个ansatz的list,比如可以使用以下代码进行生成
1 K = 2
2 for k in range(0,K):
3 hfps = HFPS(
4 nqubits=sorb,
5 nele=nele,
6 n_det=1,
7 n_layer=1,
8 hidden_shape=16,
9 hidden_activation='SiLU',
10 device=device,
11 param_dtype=torch.float64,
12 # J='NNMPS',
13 # J_shape=[1,16,4],
14 HFDS=1, # 这里HFDS=1, method=0是NNBF,
15 method=0,
16 n_hidden=0,
17 use_hole=False,
18 use_SAAM=0,
19 spin=0,
20 iscale=1e-2,
21 # normalization=3.203e+00,
22 )
23 NNBF_list.append(hfps)
获得列表 NNBF_list 之后,可以直接传入
1 from pynqs.ansatz import Excitedwavefunctions
2 from pynqs.config import samples_topk_config
3 samples_topk_config.apply(debug=False)
4
5 ansatz = Excitedwavefunctions(
6 single_ansatz = NNBF_list,
7 K = K,
8 nqubits=sorb,
9 nele=nele,
10 dtype=torch.float64,
11 device=device,
12 )
注意,在 PyNQS 程序中,打印Topk的configuration的部分是使用WFLUT进行实现的,WFLUT在目前的NEQS中并没有实现。
所以若进行NEQS计算,需要先设置 samples_topk_config.apply(debug=False)。
之后优化器会自动识别NEQS的类型,然后进行网络的训练。
在训练之后,若需得到第 \(k\) 个态的波函数,可以根据对角化local energy得到的本征矢 \(V_k\) 进行变换, 即定义
在实际计算中,可以用以下程序进行实现:
1 from pynqs.ansatz import Targetwavefunctions
2
3 ansatz = Targetwavefunctions(
4 c = c,
5 single_ansatz = NNBF_list,
6 dtype=torch.float64,
7 device=device,
8 )
here c is \(\boldsymbol{E}_{\rm loc}\) 的第 \(k\) 个本征矢。