0
# Superoperators and Open Systems
1
2
Superoperator representations for open quantum system dynamics and Liouvillian formalism.
3
4
## Capabilities
5
6
### Liouvillian Construction
7
8
Build Liouvillian superoperators for open system evolution.
9
10
```python { .api }
11
def liouvillian(H: Qobj, c_ops: list = None) -> Qobj:
12
"""
13
Create Liouvillian superoperator for master equation evolution.
14
15
Parameters:
16
- H: System Hamiltonian
17
- c_ops: List of collapse operators
18
19
Returns:
20
- Qobj: Liouvillian superoperator L
21
"""
22
23
def lindblad_dissipator(a: Qobj, b: Qobj = None) -> Qobj:
24
"""
25
Create Lindblad dissipator superoperator.
26
27
Parameters:
28
- a: Collapse operator
29
- b: Second operator (defaults to a.dag())
30
31
Returns:
32
- Qobj: Lindblad dissipator D[a,b]ρ = aρb† - ½{a†b,ρ}
33
"""
34
```
35
36
### Superoperator Operations
37
38
Basic operations on superoperators including pre/post multiplication.
39
40
```python { .api }
41
def spre(A: Qobj) -> Qobj:
42
"""
43
Create superoperator for left multiplication A·ρ.
44
45
Parameters:
46
- A: Operator for left multiplication
47
48
Returns:
49
- Qobj: Superoperator representing A·ρ
50
"""
51
52
def spost(A: Qobj) -> Qobj:
53
"""
54
Create superoperator for right multiplication ρ·A.
55
56
Parameters:
57
- A: Operator for right multiplication
58
59
Returns:
60
- Qobj: Superoperator representing ρ·A
61
"""
62
63
def sprepost(A: Qobj, B: Qobj) -> Qobj:
64
"""
65
Create superoperator for A·ρ·B.
66
67
Parameters:
68
- A: Left multiplication operator
69
- B: Right multiplication operator
70
71
Returns:
72
- Qobj: Superoperator representing A·ρ·B
73
"""
74
```
75
76
### Vector/Operator Conversion
77
78
Convert between operator and vector representations.
79
80
```python { .api }
81
def operator_to_vector(op: Qobj) -> Qobj:
82
"""
83
Convert operator to vector representation (vectorization).
84
85
Parameters:
86
- op: Operator to vectorize
87
88
Returns:
89
- Qobj: Vector representation of operator
90
"""
91
92
def vector_to_operator(vec: Qobj) -> Qobj:
93
"""
94
Convert vector back to operator representation.
95
96
Parameters:
97
- vec: Vector representation
98
99
Returns:
100
- Qobj: Operator reconstructed from vector
101
"""
102
103
def stack_columns(op: Qobj) -> Qobj:
104
"""
105
Stack columns of operator matrix into vector.
106
107
Parameters:
108
- op: Operator to stack
109
110
Returns:
111
- Qobj: Column-stacked vector
112
"""
113
114
def unstack_columns(vec: Qobj, shape: tuple) -> Qobj:
115
"""
116
Unstack vector back into operator matrix.
117
118
Parameters:
119
- vec: Stacked vector
120
- shape: Target operator shape
121
122
Returns:
123
- Qobj: Reconstructed operator
124
"""
125
```
126
127
### Superoperator Manipulation
128
129
Advanced superoperator transformations and representations.
130
131
```python { .api }
132
def reshuffle(obj: Qobj) -> Qobj:
133
"""
134
Reshuffle superoperator indices (Choi to chi representation).
135
136
Parameters:
137
- obj: Superoperator to reshuffle
138
139
Returns:
140
- Qobj: Reshuffled superoperator
141
"""
142
143
def to_choi(kraus_ops: list) -> Qobj:
144
"""
145
Convert Kraus operators to Choi matrix representation.
146
147
Parameters:
148
- kraus_ops: List of Kraus operators
149
150
Returns:
151
- Qobj: Choi matrix representation
152
"""
153
154
def to_kraus(choi: Qobj) -> list:
155
"""
156
Convert Choi matrix to Kraus operator representation.
157
158
Parameters:
159
- choi: Choi matrix
160
161
Returns:
162
- list: List of Kraus operators
163
"""
164
165
def to_super(op: Qobj) -> Qobj:
166
"""
167
Convert operator to superoperator representation.
168
169
Parameters:
170
- op: Operator to convert
171
172
Returns:
173
- Qobj: Superoperator representation
174
"""
175
```
176
177
### Usage Examples
178
179
```python
180
import qutip as qt
181
import numpy as np
182
183
# Build Liouvillian for damped harmonic oscillator
184
N = 10
185
a = qt.destroy(N)
186
H = a.dag() * a # Hamiltonian
187
188
# Collapse operators
189
gamma = 0.1
190
c_ops = [np.sqrt(gamma) * a] # Damping
191
192
# Create Liouvillian
193
L = qt.liouvillian(H, c_ops)
194
print(f"Liouvillian shape: {L.shape}")
195
196
# Manual Liouvillian construction
197
L_manual = -1j * (qt.spre(H) - qt.spost(H)) # Hamiltonian part
198
for c in c_ops:
199
L_manual += qt.lindblad_dissipator(c) # Add dissipation
200
201
# Verify they're the same
202
diff = (L - L_manual).norm()
203
print(f"Manual vs automatic Liouvillian difference: {diff:.2e}")
204
205
# Superoperator operations
206
sigma_x = qt.sigmax()
207
sigma_z = qt.sigmaz()
208
209
# Left and right multiplication superoperators
210
S_left = qt.spre(sigma_x) # σₓ·ρ
211
S_right = qt.spost(sigma_z) # ρ·σᵤ
212
S_both = qt.sprepost(sigma_x, sigma_z) # σₓ·ρ·σᵤ
213
214
# Test on a density matrix
215
rho = qt.ket2dm(qt.basis(2, 0)) # |0⟩⟨0|
216
217
# Apply superoperators
218
rho_left = S_left * qt.operator_to_vector(rho)
219
rho_left = qt.vector_to_operator(rho_left)
220
print(f"σₓ|0⟩⟨0|: {rho_left}")
221
222
# Vector/operator conversion
223
rho_vec = qt.operator_to_vector(rho)
224
print(f"Vectorized density matrix shape: {rho_vec.shape}")
225
226
rho_reconstructed = qt.vector_to_operator(rho_vec)
227
print(f"Reconstruction fidelity: {qt.fidelity(rho, rho_reconstructed):.6f}")
228
229
# Column stacking (alternative vectorization)
230
rho_stacked = qt.stack_columns(rho)
231
rho_unstacked = qt.unstack_columns(rho_stacked, rho.shape)
232
print(f"Stack/unstack fidelity: {qt.fidelity(rho, rho_unstacked):.6f}")
233
234
# Example: Amplitude damping channel
235
def amplitude_damping_kraus(gamma):
236
"""Create Kraus operators for amplitude damping."""
237
K0 = qt.Qobj([[1, 0], [0, np.sqrt(1-gamma)]])
238
K1 = qt.Qobj([[0, np.sqrt(gamma)], [0, 0]])
239
return [K0, K1]
240
241
# Convert to different representations
242
gamma = 0.3
243
kraus_ops = amplitude_damping_kraus(gamma)
244
245
# Kraus to Choi matrix
246
choi = qt.to_choi(kraus_ops)
247
print(f"Choi matrix:\n{choi}")
248
249
# Choi back to Kraus
250
kraus_reconstructed = qt.to_kraus(choi)
251
print(f"Number of reconstructed Kraus ops: {len(kraus_reconstructed)}")
252
253
# Apply channel using different representations
254
psi = qt.basis(2, 1) # |1⟩ state
255
rho_in = psi * psi.dag()
256
257
# Using Kraus operators
258
rho_out_kraus = sum(K * rho_in * K.dag() for K in kraus_ops)
259
260
# Using Choi matrix (more complex, via vectorization)
261
rho_vec = qt.operator_to_vector(rho_in)
262
# For Choi representation: need to apply proper transformation
263
# This is a simplified example - full Choi application is more involved
264
265
print(f"Output state after amplitude damping: {rho_out_kraus}")
266
print(f"Excited state population: {qt.expect(qt.num(2), rho_out_kraus):.3f}")
267
268
# Superoperator for general channel
269
def depolarizing_channel(p):
270
"""Create depolarizing channel superoperator."""
271
I = qt.qeye(2)
272
X = qt.sigmax()
273
Y = qt.sigmay()
274
Z = qt.sigmaz()
275
276
# Kraus operators
277
K0 = np.sqrt(1 - 3*p/4) * I
278
K1 = np.sqrt(p/4) * X
279
K2 = np.sqrt(p/4) * Y
280
K3 = np.sqrt(p/4) * Z
281
282
# Build superoperator
283
S = (1 - 3*p/4) * qt.sprepost(I, I)
284
S += (p/4) * (qt.sprepost(X, X) + qt.sprepost(Y, Y) + qt.sprepost(Z, Z))
285
286
return S
287
288
# Test depolarizing channel
289
p = 0.1
290
S_depol = depolarizing_channel(p)
291
292
# Apply to pure state
293
psi_pure = (qt.basis(2,0) + qt.basis(2,1)).unit()
294
rho_pure = psi_pure * psi_pure.dag()
295
rho_vec = qt.operator_to_vector(rho_pure)
296
rho_depol_vec = S_depol * rho_vec
297
rho_depol = qt.vector_to_operator(rho_depol_vec)
298
299
print(f"Initial purity: {(rho_pure**2).tr():.3f}")
300
print(f"After depolarizing: {(rho_depol**2).tr():.3f}")
301
```
302
303
## Types
304
305
```python { .api }
306
# Superoperator functions return Qobj instances with type='super'
307
# representing linear transformations on the space of operators
308
```