feat: add numeric and symbolic scripts
This commit is contained in:
parent
6ea7900b55
commit
e80b7c3582
38 changed files with 3314 additions and 0 deletions
103
scripts/dps_hierarchy/02_werner_qutrit_symbolic.py
Normal file
103
scripts/dps_hierarchy/02_werner_qutrit_symbolic.py
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
"""
|
||||
02_werner_qutrit_symbolic.py
|
||||
|
||||
Same check as 01_werner_qubit_symbolic.py, generalized to d=3 (qutrits),
|
||||
using the sqrt(3/2)-scaled Gell-Mann convention fixed in the paper's own
|
||||
Tiles example (tr(sigma_i sigma_j) = d delta_ij = 3 delta_ij).
|
||||
|
||||
State family: rho(p) = p * P_anti/dim(P_anti) + (1-p) * I/9
|
||||
(the natural qutrit "Werner state" built from the antisymmetric subspace
|
||||
of C^3 x C^3, dimension 3), invariant under U(x)U for all U in U(3).
|
||||
|
||||
Result (the interesting part): the order-1 shadow-map/correlation-matrix
|
||||
criterion gives p_c = 1/2, but the TRUE separability threshold (Werner
|
||||
1989, p_sep = 1/(d+1)) is p_c = 1/4. Unlike the qubit case, the criterion
|
||||
is here only a valid but NOT tight sufficient condition -- symmetry forces
|
||||
"concentration" of the signal (single isotype => correlation matrix
|
||||
proportional to identity) but not "sharpening" of the threshold itself.
|
||||
|
||||
Requires: sympy. Runtime: under a minute.
|
||||
"""
|
||||
import sympy as sp
|
||||
from sympy import sqrt, I, simplify, Matrix, eye, zeros, re, symbols, Rational
|
||||
|
||||
d = 3
|
||||
|
||||
lam = [None] * 8
|
||||
lam[0] = Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 0]])
|
||||
lam[1] = Matrix([[0, -I, 0], [I, 0, 0], [0, 0, 0]])
|
||||
lam[2] = Matrix([[1, 0, 0], [0, -1, 0], [0, 0, 0]])
|
||||
lam[3] = Matrix([[0, 0, 1], [0, 0, 0], [1, 0, 0]])
|
||||
lam[4] = Matrix([[0, 0, -I], [0, 0, 0], [I, 0, 0]])
|
||||
lam[5] = Matrix([[0, 0, 0], [0, 0, 1], [0, 1, 0]])
|
||||
lam[6] = Matrix([[0, 0, 0], [0, 0, -I], [0, I, 0]])
|
||||
lam[7] = (1 / sqrt(3)) * Matrix([[1, 0, 0], [0, 1, 0], [0, 0, -2]])
|
||||
|
||||
c = sqrt(Rational(3, 2))
|
||||
sigma = [simplify(c * L) for L in lam]
|
||||
for i in range(8):
|
||||
for j in range(8):
|
||||
val = simplify((sigma[i] * sigma[j]).trace())
|
||||
assert val == (3 if i == j else 0), (i, j, val)
|
||||
|
||||
I3 = eye(3)
|
||||
|
||||
|
||||
def op_A(P):
|
||||
return sp.Matrix(sp.kronecker_product(P, I3))
|
||||
|
||||
|
||||
def op_B(P):
|
||||
return sp.Matrix(sp.kronecker_product(I3, P))
|
||||
|
||||
|
||||
V = zeros(9, 9)
|
||||
for a in range(3):
|
||||
for b in range(3):
|
||||
V[b * 3 + a, a * 3 + b] = 1
|
||||
|
||||
I9 = eye(9)
|
||||
P_anti = simplify((I9 - V) / 2)
|
||||
dim_anti = simplify(P_anti.trace()) # = 3
|
||||
|
||||
p = symbols('p', real=True)
|
||||
rho_p = simplify(p * P_anti / dim_anti + (1 - p) * I9 / 9)
|
||||
|
||||
|
||||
def entry(rho, ops):
|
||||
M = None
|
||||
for op in ops:
|
||||
M = op if M is None else M * op
|
||||
return simplify(re(simplify((rho * M).trace())))
|
||||
|
||||
|
||||
T = Matrix(8, 8, lambda i, j: entry(rho_p, [op_A(sigma[i]), op_B(sigma[j])]))
|
||||
print("Correlation matrix T(p) (should be proportional to I_8):")
|
||||
sp.pprint(T)
|
||||
|
||||
norm_const = 1 / sqrt(4) # (d_a-1)(d_bar_a-1) = 2*2 = 4
|
||||
Mn = simplify(norm_const * T)
|
||||
nuclear_norm = simplify(8 * sp.Abs(Mn[0, 0]))
|
||||
print("\nShadow-map nuclear norm:", nuclear_norm)
|
||||
print("Shadow-map threshold:", sp.solve(sp.Eq(nuclear_norm, 1), p))
|
||||
|
||||
|
||||
def partial_transpose_B_d(M, dim):
|
||||
Mpt = zeros(dim * dim, dim * dim)
|
||||
for a in range(dim):
|
||||
for b in range(dim):
|
||||
for cc in range(dim):
|
||||
for dd in range(dim):
|
||||
i, j = a * dim + b, cc * dim + dd
|
||||
i2, j2 = a * dim + dd, cc * dim + b
|
||||
Mpt[i2, j2] = M[i, j]
|
||||
return Mpt
|
||||
|
||||
|
||||
rho_pt = partial_transpose_B_d(rho_p, 3)
|
||||
print("\nPartial-transpose eigenvalues (PPT / true-separability threshold):")
|
||||
for ev in rho_pt.eigenvals().keys():
|
||||
print(" ", simplify(ev), " = 0 at p =", sp.solve(sp.Eq(ev, 0), p))
|
||||
|
||||
print("\nExpected: shadow-map threshold p=1/2 (NOT tight);"
|
||||
" true threshold (Werner 1989, p_sep=1/(d+1)) p=1/4.")
|
||||
Loading…
Add table
Add a link
Reference in a new issue