Source code for deepquantum.photonic.torontonian_
"""Functions for Torontonian"""
import torch
from .qmath import get_powerset
[docs]
def get_submat_tor(a: torch.Tensor, z: torch.Tensor) -> torch.Tensor:
"""Get the sub-matrix for torontonian calculation."""
idx1 = z
idx2 = idx1 + a.shape[-1] // 2
idx = torch.cat([idx1, idx2])
idx = torch.sort(idx)[0]
if a.dim() == 1:
return a[idx]
if a.dim() == 2:
return a[idx][:, idx]
def _tor_helper(submat: torch.Tensor, sub_gamma: torch.Tensor) -> torch.Tensor:
size = submat.shape[-1]
cov_q_inv = torch.eye(size, dtype=submat.dtype, device=submat.device) - submat
exp_term = sub_gamma @ torch.linalg.solve(cov_q_inv, sub_gamma.conj()) / 2
return torch.exp(exp_term) / torch.sqrt(torch.linalg.det(cov_q_inv))
[docs]
def torontonian(o_mat: torch.Tensor, gamma: torch.Tensor | None = None) -> torch.Tensor:
"""Calculate the torontonian function for the given matrix.
See https://research-information.bris.ac.uk/ws/portalfiles/portal/329011096/thesis.pdf Eq.(3.54)
"""
size = o_mat.shape[-1]
if gamma is None:
gamma = torch.zeros(size, dtype=o_mat.dtype, device=o_mat.device)
m = size // 2
powerset = get_powerset(m)
tor = (-1) ** m
for i in range(1, len(powerset)):
y_sets = torch.tensor(powerset[i], device=o_mat.device)
num_y = len(y_sets[0])
sub_mats = torch.vmap(get_submat_tor, in_dims=(None, 0))(o_mat, y_sets)
sub_gammas = torch.vmap(get_submat_tor, in_dims=(None, 0))(gamma, y_sets)
coeff = torch.vmap(_tor_helper)(sub_mats, sub_gammas)
coeff_sum = (-1) ** (m - num_y) * coeff.sum()
tor += coeff_sum
return tor
[docs]
def torontonian_batch(o_mat: torch.Tensor, gamma: torch.Tensor | None = None) -> torch.Tensor:
"""Calculate the batch torontonian."""
assert o_mat.dim() == 3, 'Input tensor should be in batched size'
assert o_mat.shape[-2] == o_mat.shape[-1]
assert o_mat.shape[-1] % 2 == 0, 'Input matrix dimension should be even'
if gamma is None: # torontonian case
tors = torch.vmap(torontonian, in_dims=(0, None))(o_mat, gamma)
else: # loop torontonian case
tors = torch.vmap(torontonian, in_dims=(0, 0))(o_mat, gamma)
return tors