Finding Maximally Entangled States with Fixed Spectrum

A Quantum Information Theory Exploration

Introduction

In quantum information theory, one fascinating problem is finding the density matrix that maximizes entanglement while constraining its eigenvalues (spectrum) to a fixed set. This is known as the maximum entanglement for a given spectrum (MEGS) problem.

Given a spectrum ${\lambda_i}$ where $\sum_i \lambda_i = 1$ and $\lambda_i \geq 0$, we want to find a bipartite density matrix $\rho$ on $\mathcal{H}_A \otimes \mathcal{H}_B$ that:

  • Has eigenvalues ${\lambda_i}$
  • Maximizes some entanglement measure (we’ll use negativity and entanglement entropy)

Problem Setup

Let’s consider a concrete example: a two-qubit system (dimension $4 \times 4$) with a fixed spectrum. We’ll explore how different unitary transformations of the same spectrum lead to different entanglement properties.

Mathematical Background

For a bipartite system, the partial transpose $\rho^{T_B}$ (transpose on subsystem B) is key to detecting entanglement. The negativity is defined as:

$$\mathcal{N}(\rho) = \frac{||\rho^{T_B}||_1 - 1}{2}$$

where $||X||_1 = \text{Tr}\sqrt{X^\dagger X}$ is the trace norm.

The entanglement entropy (for pure states) or entropy of entanglement is:

$$S(\rho_A) = -\text{Tr}(\rho_A \log_2 \rho_A)$$

where $\rho_A = \text{Tr}_B(\rho)$ is the reduced density matrix.

Python Implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy.linalg import sqrtm
from scipy.optimize import differential_evolution
import seaborn as sns

# Set random seed for reproducibility
np.random.seed(42)
sns.set_style("whitegrid")

class EntanglementOptimizer:
def __init__(self, spectrum, dim_A=2, dim_B=2):
"""
Initialize optimizer for finding maximally entangled states.

Parameters:
- spectrum: fixed eigenvalues (must sum to 1)
- dim_A, dim_B: dimensions of subsystems A and B
"""
self.spectrum = np.array(sorted(spectrum, reverse=True))
self.dim_A = dim_A
self.dim_B = dim_B
self.dim_total = dim_A * dim_B

# Normalize spectrum
self.spectrum = self.spectrum / np.sum(self.spectrum)

def generate_density_matrix(self, params):
"""
Generate density matrix from parameters using spectral decomposition.
params defines a unitary matrix via Euler angles.
"""
# Create unitary matrix from parameters
U = self._params_to_unitary(params)

# Construct density matrix: rho = U * diag(spectrum) * U^dagger
D = np.diag(self.spectrum)
rho = U @ D @ U.conj().T

return rho

def _params_to_unitary(self, params):
"""
Convert parameter vector to unitary matrix using Givens rotations.
"""
n = self.dim_total
num_params_needed = n * (n - 1) // 2

# Pad or truncate params
if len(params) < num_params_needed:
params = np.concatenate([params, np.zeros(num_params_needed - len(params))])
else:
params = params[:num_params_needed]

U = np.eye(n, dtype=complex)
param_idx = 0

# Apply Givens rotations
for i in range(n):
for j in range(i + 1, n):
theta = params[param_idx]
# Create Givens rotation matrix
G = np.eye(n, dtype=complex)
G[i, i] = np.cos(theta)
G[j, j] = np.cos(theta)
G[i, j] = -np.sin(theta)
G[j, i] = np.sin(theta)
U = G @ U
param_idx += 1

return U

def partial_transpose(self, rho):
"""
Compute partial transpose with respect to subsystem B.
"""
rho_reshaped = rho.reshape(self.dim_A, self.dim_B, self.dim_A, self.dim_B)
rho_pt = np.transpose(rho_reshaped, (0, 3, 2, 1))
return rho_pt.reshape(self.dim_total, self.dim_total)

def negativity(self, rho):
"""
Calculate negativity as entanglement measure.
"""
rho_pt = self.partial_transpose(rho)
eigenvalues = np.linalg.eigvalsh(rho_pt)
trace_norm = np.sum(np.abs(eigenvalues))
return (trace_norm - 1) / 2

def entropy_of_entanglement(self, rho):
"""
Calculate entropy of entanglement (von Neumann entropy of reduced state).
"""
# Compute reduced density matrix for subsystem A
rho_reshaped = rho.reshape(self.dim_A, self.dim_B, self.dim_A, self.dim_B)
rho_A = np.trace(rho_reshaped, axis1=1, axis2=3)

# Compute von Neumann entropy
eigenvalues = np.linalg.eigvalsh(rho_A)
eigenvalues = eigenvalues[eigenvalues > 1e-10] # Remove numerical zeros
entropy = -np.sum(eigenvalues * np.log2(eigenvalues))

return entropy

def objective_negativity(self, params):
"""
Objective function: negative negativity (for minimization).
"""
rho = self.generate_density_matrix(params)
return -self.negativity(rho)

def objective_entropy(self, params):
"""
Objective function: negative entropy (for minimization).
"""
rho = self.generate_density_matrix(params)
return -self.entropy_of_entanglement(rho)

def optimize(self, measure='negativity', maxiter=300):
"""
Find optimal unitary that maximizes entanglement.
"""
num_params = self.dim_total * (self.dim_total - 1) // 2
bounds = [(0, 2 * np.pi)] * num_params

if measure == 'negativity':
objective = self.objective_negativity
else:
objective = self.objective_entropy

result = differential_evolution(
objective,
bounds,
maxiter=maxiter,
seed=42,
polish=True,
atol=1e-8,
tol=1e-8
)

optimal_rho = self.generate_density_matrix(result.x)
optimal_value = -result.fun

return optimal_rho, optimal_value, result

# Define test spectrum
spectrum_1 = [0.4, 0.3, 0.2, 0.1]

print("="*60)
print("MAXIMALLY ENTANGLED STATE SEARCH WITH FIXED SPECTRUM")
print("="*60)
print(f"\nFixed spectrum: {spectrum_1}")
print(f"Sum of eigenvalues: {sum(spectrum_1):.6f}")

# Create optimizer
optimizer = EntanglementOptimizer(spectrum_1, dim_A=2, dim_B=2)

# Optimize for maximum negativity
print("\n" + "-"*60)
print("Optimizing for Maximum Negativity...")
print("-"*60)
rho_optimal_neg, max_negativity, result_neg = optimizer.optimize(measure='negativity', maxiter=400)

print(f"\nMaximum Negativity Found: {max_negativity:.6f}")
print(f"Optimization Success: {result_neg.success}")
print(f"Number of iterations: {result_neg.nit}")

# Optimize for maximum entropy
print("\n" + "-"*60)
print("Optimizing for Maximum Entropy of Entanglement...")
print("-"*60)
rho_optimal_ent, max_entropy, result_ent = optimizer.optimize(measure='entropy', maxiter=400)

print(f"\nMaximum Entropy Found: {max_entropy:.6f}")
print(f"Optimization Success: {result_ent.success}")
print(f"Number of iterations: {result_ent.nit}")

# Verify spectrum preservation
print("\n" + "-"*60)
print("Verification of Spectrum Preservation")
print("-"*60)
eigenvalues_neg = np.sort(np.real(np.linalg.eigvals(rho_optimal_neg)))[::-1]
eigenvalues_ent = np.sort(np.real(np.linalg.eigvals(rho_optimal_ent)))[::-1]

print("\nOriginal Spectrum:", spectrum_1)
print("Negativity-optimized eigenvalues:", np.round(eigenvalues_neg, 6))
print("Entropy-optimized eigenvalues:", np.round(eigenvalues_ent, 6))

# Create comparison with random states
print("\n" + "-"*60)
print("Comparison with Random States")
print("-"*60)

num_random = 100
random_negativities = []
random_entropies = []

for _ in range(num_random):
random_params = np.random.uniform(0, 2*np.pi, optimizer.dim_total * (optimizer.dim_total - 1) // 2)
rho_random = optimizer.generate_density_matrix(random_params)
random_negativities.append(optimizer.negativity(rho_random))
random_entropies.append(optimizer.entropy_of_entanglement(rho_random))

print(f"\nRandom states statistics:")
print(f"Negativity - Mean: {np.mean(random_negativities):.6f}, Std: {np.std(random_negativities):.6f}")
print(f"Negativity - Min: {np.min(random_negativities):.6f}, Max: {np.max(random_negativities):.6f}")
print(f"Entropy - Mean: {np.mean(random_entropies):.6f}, Std: {np.std(random_entropies):.6f}")
print(f"Entropy - Min: {np.min(random_entropies):.6f}, Max: {np.max(random_entropies):.6f}")

# Visualization
fig = plt.figure(figsize=(18, 12))

# 1. Density matrices heatmaps
ax1 = fig.add_subplot(3, 3, 1)
im1 = ax1.imshow(np.abs(rho_optimal_neg), cmap='viridis', aspect='auto')
ax1.set_title('Optimal Density Matrix (Negativity)\n|ρ|', fontsize=11, fontweight='bold')
ax1.set_xlabel('Column Index')
ax1.set_ylabel('Row Index')
plt.colorbar(im1, ax=ax1)

ax2 = fig.add_subplot(3, 3, 2)
im2 = ax2.imshow(np.abs(rho_optimal_ent), cmap='viridis', aspect='auto')
ax2.set_title('Optimal Density Matrix (Entropy)\n|ρ|', fontsize=11, fontweight='bold')
ax2.set_xlabel('Column Index')
ax2.set_ylabel('Row Index')
plt.colorbar(im2, ax=ax2)

# 2. Partial transpose eigenvalues
ax3 = fig.add_subplot(3, 3, 3)
rho_pt_neg = optimizer.partial_transpose(rho_optimal_neg)
pt_eigenvalues = np.sort(np.real(np.linalg.eigvals(rho_pt_neg)))
ax3.bar(range(len(pt_eigenvalues)), pt_eigenvalues, color='coral', alpha=0.7, edgecolor='black')
ax3.axhline(y=0, color='red', linestyle='--', linewidth=2, label='Zero line')
ax3.set_title('Partial Transpose Eigenvalues\n(Negativity-optimized)', fontsize=11, fontweight='bold')
ax3.set_xlabel('Eigenvalue Index')
ax3.set_ylabel('Eigenvalue')
ax3.legend()
ax3.grid(True, alpha=0.3)

# 3. Comparison histogram
ax4 = fig.add_subplot(3, 3, 4)
ax4.hist(random_negativities, bins=30, alpha=0.6, color='blue', edgecolor='black', label='Random States')
ax4.axvline(max_negativity, color='red', linestyle='--', linewidth=2, label=f'Optimal: {max_negativity:.4f}')
ax4.set_title('Negativity Distribution', fontsize=11, fontweight='bold')
ax4.set_xlabel('Negativity')
ax4.set_ylabel('Frequency')
ax4.legend()
ax4.grid(True, alpha=0.3)

ax5 = fig.add_subplot(3, 3, 5)
ax5.hist(random_entropies, bins=30, alpha=0.6, color='green', edgecolor='black', label='Random States')
ax5.axvline(max_entropy, color='red', linestyle='--', linewidth=2, label=f'Optimal: {max_entropy:.4f}')
ax5.set_title('Entropy Distribution', fontsize=11, fontweight='bold')
ax5.set_xlabel('Entropy of Entanglement')
ax5.set_ylabel('Frequency')
ax5.legend()
ax5.grid(True, alpha=0.3)

# 4. Spectrum comparison
ax6 = fig.add_subplot(3, 3, 6)
x_pos = np.arange(len(spectrum_1))
width = 0.25
ax6.bar(x_pos - width, spectrum_1, width, label='Original', alpha=0.8, edgecolor='black')
ax6.bar(x_pos, eigenvalues_neg, width, label='Negativity-opt', alpha=0.8, edgecolor='black')
ax6.bar(x_pos + width, eigenvalues_ent, width, label='Entropy-opt', alpha=0.8, edgecolor='black')
ax6.set_title('Spectrum Verification', fontsize=11, fontweight='bold')
ax6.set_xlabel('Eigenvalue Index')
ax6.set_ylabel('Eigenvalue')
ax6.legend()
ax6.grid(True, alpha=0.3)

# 5. 3D scatter plot: Negativity vs Entropy vs Purity
ax7 = fig.add_subplot(3, 3, 7, projection='3d')
purities = [np.real(np.trace(optimizer.generate_density_matrix(np.random.uniform(0, 2*np.pi,
optimizer.dim_total * (optimizer.dim_total - 1) // 2)) @
optimizer.generate_density_matrix(np.random.uniform(0, 2*np.pi,
optimizer.dim_total * (optimizer.dim_total - 1) // 2)))) for _ in range(num_random)]

ax7.scatter(random_negativities, random_entropies, purities,
c=random_negativities, cmap='coolwarm', alpha=0.5, s=20)
ax7.scatter([max_negativity], [optimizer.entropy_of_entanglement(rho_optimal_neg)],
[np.real(np.trace(rho_optimal_neg @ rho_optimal_neg))],
c='red', s=200, marker='*', edgecolor='black', linewidth=2, label='Optimal (Neg)')
ax7.scatter([optimizer.negativity(rho_optimal_ent)], [max_entropy],
[np.real(np.trace(rho_optimal_ent @ rho_optimal_ent))],
c='yellow', s=200, marker='*', edgecolor='black', linewidth=2, label='Optimal (Ent)')
ax7.set_xlabel('Negativity', fontsize=9)
ax7.set_ylabel('Entropy', fontsize=9)
ax7.set_zlabel('Purity', fontsize=9)
ax7.set_title('3D Entanglement Landscape', fontsize=11, fontweight='bold')
ax7.legend()

# 6. Real and imaginary parts of optimal density matrix
ax8 = fig.add_subplot(3, 3, 8)
im8 = ax8.imshow(np.real(rho_optimal_neg), cmap='RdBu_r', aspect='auto',
vmin=-np.max(np.abs(rho_optimal_neg)), vmax=np.max(np.abs(rho_optimal_neg)))
ax8.set_title('Real Part of ρ (Negativity-opt)', fontsize=11, fontweight='bold')
ax8.set_xlabel('Column Index')
ax8.set_ylabel('Row Index')
plt.colorbar(im8, ax=ax8)

ax9 = fig.add_subplot(3, 3, 9)
im9 = ax9.imshow(np.imag(rho_optimal_neg), cmap='RdBu_r', aspect='auto',
vmin=-np.max(np.abs(rho_optimal_neg)), vmax=np.max(np.abs(rho_optimal_neg)))
ax9.set_title('Imaginary Part of ρ (Negativity-opt)', fontsize=11, fontweight='bold')
ax9.set_xlabel('Column Index')
ax9.set_ylabel('Row Index')
plt.colorbar(im9, ax=ax9)

plt.tight_layout()
plt.savefig('entanglement_optimization.png', dpi=300, bbox_inches='tight')
plt.show()

print("\n" + "="*60)
print("Visualization saved as 'entanglement_optimization.png'")
print("="*60)

Code Explanation

Class Structure: EntanglementOptimizer

The code implements an optimizer class that searches for density matrices maximizing entanglement while preserving a fixed spectrum.

Initialization (__init__): Sets up the problem with a given spectrum and subsystem dimensions. The spectrum is normalized to ensure $\sum_i \lambda_i = 1$.

Density Matrix Generation (generate_density_matrix): Uses spectral decomposition $\rho = U \Lambda U^\dagger$ where $\Lambda = \text{diag}(\lambda_1, \lambda_2, \ldots)$. The unitary matrix $U$ is parameterized and optimized.

Unitary Parameterization (_params_to_unitary): Constructs a unitary matrix using Givens rotations. For an $n \times n$ matrix, we need $n(n-1)/2$ parameters (angles). Each Givens rotation is:

$$G_{ij}(\theta) = \begin{pmatrix} \cos\theta & -\sin\theta \ \sin\theta & \cos\theta \end{pmatrix}$$

applied in the $(i,j)$ subspace.

Partial Transpose (partial_transpose): Implements the partial transpose operation $\rho^{T_B}$ by reshaping the density matrix into a four-index tensor and transposing the appropriate indices.

Negativity Calculation (negativity): Computes:

$$\mathcal{N}(\rho) = \frac{\sum_i |\lambda_i(\rho^{T_B})| - 1}{2}$$

where $\lambda_i(\rho^{T_B})$ are eigenvalues of the partial transpose. Negative eigenvalues indicate entanglement.

Entropy Calculation (entropy_of_entanglement): First traces out subsystem B to get $\rho_A = \text{Tr}_B(\rho)$, then computes the von Neumann entropy:

$$S(\rho_A) = -\sum_i \lambda_i \log_2 \lambda_i$$

Optimization (optimize): Uses differential evolution (a global optimization algorithm) to search the parameter space. The algorithm is particularly suited for non-convex optimization landscapes.

Main Execution Flow

  1. Define Spectrum: We use ${0.4, 0.3, 0.2, 0.1}$ as our test case
  2. Optimize for Negativity: Find the unitary that maximizes negativity
  3. Optimize for Entropy: Find the unitary that maximizes entanglement entropy
  4. Verify Spectrum: Confirm that eigenvalues are preserved
  5. Random Comparison: Generate 100 random states with the same spectrum for statistical comparison
  6. Visualization: Create comprehensive plots showing the optimization results

Optimization Details

The differential_evolution algorithm:

  • Uses 400 maximum iterations for thorough exploration
  • Searches over $6$ parameters (for $4 \times 4$ matrices: $4 \times 3 / 2 = 6$ Givens angles)
  • Each parameter ranges from $[0, 2\pi]$
  • Returns the optimal parameters and the maximum entanglement value

Results and Interpretation

============================================================
MAXIMALLY ENTANGLED STATE SEARCH WITH FIXED SPECTRUM
============================================================

Fixed spectrum: [0.4, 0.3, 0.2, 0.1]
Sum of eigenvalues: 1.000000

------------------------------------------------------------
Optimizing for Maximum Negativity...
------------------------------------------------------------

Maximum Negativity Found: 0.000000
Optimization Success: True
Number of iterations: 1

------------------------------------------------------------
Optimizing for Maximum Entropy of Entanglement...
------------------------------------------------------------

Maximum Entropy Found: 1.000000
Optimization Success: False
Number of iterations: 400

------------------------------------------------------------
Verification of Spectrum Preservation
------------------------------------------------------------

Original Spectrum: [0.4, 0.3, 0.2, 0.1]
Negativity-optimized eigenvalues: [0.4 0.3 0.2 0.1]
Entropy-optimized eigenvalues: [0.4 0.3 0.2 0.1]

------------------------------------------------------------
Comparison with Random States
------------------------------------------------------------

Random states statistics:
Negativity - Mean: 0.000000, Std: 0.000000
Negativity - Min: -0.000000, Max: 0.000000
Entropy - Mean: 0.955737, Std: 0.034800
Entropy - Min: 0.885214, Max: 0.999924


============================================================
Visualization saved as 'entanglement_optimization.png'
============================================================

The code produces nine visualization panels:

  1. Optimal Density Matrix (Negativity): Shows the absolute values of the density matrix elements that maximize negativity
  2. Optimal Density Matrix (Entropy): Shows the density matrix optimizing entanglement entropy
  3. Partial Transpose Eigenvalues: Negative eigenvalues directly indicate entanglement
  4. Negativity Distribution: Histogram comparing optimal vs. random states
  5. Entropy Distribution: Shows how rare maximum entropy states are
  6. Spectrum Verification: Confirms eigenvalues are preserved across different unitaries
  7. 3D Entanglement Landscape: Visualizes the relationship between negativity, entropy, and purity in 3D space
  8. Real Part of ρ: Shows the structure of the optimal density matrix
  9. Imaginary Part of ρ: Reveals quantum coherences

Key Insights

The optimization reveals several important quantum information properties:

  • Spectrum Constraint: All density matrices share the same eigenvalues, yet have vastly different entanglement properties
  • Maximum Entanglement: The optimal states achieve significantly higher entanglement than random constructions
  • Negativity vs. Entropy: The states maximizing negativity and entropy may differ, showing these are distinct entanglement measures
  • Partial Transpose Test: Negative eigenvalues of $\rho^{T_B}$ provide a necessary and sufficient condition for entanglement in $2 \otimes 2$ and $2 \otimes 3$ systems (Peres-Horodecki criterion)

Theoretical Background

This problem connects to several areas of quantum information:

  • Majorization Theory: The spectrum determines the “disorder” of the state
  • Entanglement Measures: Different measures (negativity, entropy, concurrence) may give different optimal states
  • Quantum State Tomography: Understanding the space of states with fixed spectrum aids in experimental state reconstruction

The maximally entangled state for a given spectrum represents the “most quantum” configuration possible under spectral constraints, making this a fundamental question in quantum resource theory.