0
# Circuit Analysis
1
2
Symbolic circuit analysis tools for custom superconducting circuits, enabling automated quantization and Hamiltonian generation from circuit descriptions. Supports YAML-based circuit specification and flexible node/branch analysis.
3
4
## Capabilities
5
6
### Circuit Construction
7
8
Main class for building and analyzing custom superconducting circuits from symbolic descriptions.
9
10
```python { .api }
11
class Circuit:
12
def __init__(self, input_string: str, from_file: bool = False, ext_basis: str = None,
13
initiate_sym_calc: bool = True, truncated_dim: int = None):
14
"""
15
Custom circuit analysis from symbolic description.
16
17
Parameters:
18
- input_string (str): YAML circuit description or file path
19
- from_file (bool): Whether input_string is a file path
20
- ext_basis (str): External basis choice for quantization
21
- initiate_sym_calc (bool): Whether to immediately perform symbolic calculation
22
- truncated_dim (int): Truncated Hilbert space dimension
23
"""
24
25
def hamiltonian(self) -> np.ndarray:
26
"""Generate circuit Hamiltonian matrix."""
27
28
def eigenvals(self, evals_count: int = 6) -> np.ndarray:
29
"""Calculate circuit eigenvalues."""
30
31
def eigensys(self, evals_count: int = 6) -> tuple:
32
"""Calculate circuit eigenvalues and eigenvectors."""
33
34
def plot_evals_vs_paramvals(self, param_name: str, param_vals: np.ndarray,
35
evals_count: int = 6, **kwargs):
36
"""Plot energy levels vs circuit parameter."""
37
38
def wavefunction(self, esys: tuple = None, which: int = 0,
39
mode: str = 'abs_sqr') -> WaveFunction:
40
"""Return circuit wavefunction for specified eigenstate."""
41
42
def set_discretization(self, var_name: str, grid: Grid1d) -> None:
43
"""Set discretization grid for continuous circuit variable."""
44
45
def configure(self, **kwargs) -> None:
46
"""Configure circuit parameters."""
47
48
class SymbolicCircuit:
49
def __init__(self, nodes_dict: dict, branches_dict: dict, initiate: bool = True):
50
"""
51
Symbolic circuit representation from nodes and branches.
52
53
Parameters:
54
- nodes_dict (dict): Dictionary defining circuit nodes
55
- branches_dict (dict): Dictionary defining circuit branches
56
- initiate (bool): Whether to immediately build symbolic representation
57
"""
58
59
def configure(self, transformation: str = None, closure_branches: list = None) -> None:
60
"""Configure symbolic circuit transformation and closure."""
61
62
def generate_hamiltonian_symbolic(self) -> sympy.Expr:
63
"""Generate symbolic Hamiltonian expression."""
64
```
65
66
### Circuit Utilities
67
68
Helper functions for circuit construction, parameter management, and example generation.
69
70
```python { .api }
71
def truncation_template(system_hierarchy: list, individual_trunc_dim: int = 6, combined_trunc_dim: int = 30) -> list:
72
"""
73
Generate template for defining truncated dimensions for subsystems in hierarchical diagonalization.
74
75
Parameters:
76
- system_hierarchy (list): Hierarchy of system components
77
- individual_trunc_dim (int): Truncation dimension for individual subsystems
78
- combined_trunc_dim (int): Truncation dimension for combined systems
79
80
Returns:
81
- list: Truncation template structure
82
"""
83
84
def assemble_circuit(circuit_list: List[str], couplers: str, rename_parameters: bool = False) -> Tuple[str, List[Dict[int, int]]]:
85
"""
86
Assemble a large circuit from smaller sub-circuits and coupling elements.
87
88
Parameters:
89
- circuit_list (List[str]): List of sub-circuit YAML strings
90
- couplers (str): YAML string characterizing coupler branches
91
- rename_parameters (bool): Whether to rename conflicting parameters
92
93
Returns:
94
- Tuple[str, List[Dict[int, int]]]: Assembled circuit YAML and node mapping
95
"""
96
97
def assemble_transformation_matrix(transformation_name: str, **kwargs) -> np.ndarray:
98
"""
99
Create coordinate transformation matrix.
100
101
Parameters:
102
- transformation_name (str): Type of transformation
103
- **kwargs: Transformation parameters
104
105
Returns:
106
- np.ndarray: Transformation matrix
107
"""
108
109
def example_circuit(qubit_type: str) -> str:
110
"""
111
Get example circuit YAML description.
112
113
Parameters:
114
- qubit_type (str): Type of qubit circuit ('transmon', 'fluxonium', etc.)
115
116
Returns:
117
- str: YAML circuit description
118
"""
119
```
120
121
### Grid and Discretization
122
123
Classes for discretizing continuous circuit variables and managing computational grids.
124
125
```python { .api }
126
class Grid1d:
127
def __init__(self, min_val: float, max_val: float, pt_count: int):
128
"""
129
One-dimensional discretization grid.
130
131
Parameters:
132
- min_val (float): Minimum grid value
133
- max_val (float): Maximum grid value
134
- pt_count (int): Number of grid points
135
"""
136
137
@property
138
def grid_spacing(self) -> float:
139
"""Grid spacing between adjacent points."""
140
141
@property
142
def grid_points(self) -> np.ndarray:
143
"""Array of all grid points."""
144
145
def closest_index(self, value: float) -> int:
146
"""Find grid index closest to given value."""
147
```
148
149
## Usage Examples
150
151
### Basic Circuit Analysis
152
153
```python
154
import scqubits as scq
155
156
# Get example transmon circuit description
157
transmon_yaml = scq.core.circuit_utils.example_circuit('transmon')
158
print("Transmon circuit YAML:")
159
print(transmon_yaml)
160
161
# Create circuit from description
162
circuit = scq.Circuit(transmon_yaml, from_file=False)
163
164
# Calculate spectrum
165
energies = circuit.eigenvals(evals_count=6)
166
print("Circuit energy levels:", energies)
167
168
# Compare to built-in Transmon class
169
transmon_builtin = scq.Transmon(EJ=25.0, EC=0.2, ng=0.0, ncut=30)
170
builtin_energies = transmon_builtin.eigenvals(evals_count=6)
171
print("Built-in Transmon energies:", builtin_energies)
172
```
173
174
### Custom Circuit Design
175
176
```python
177
# Define custom circuit YAML
178
custom_circuit_yaml = """
179
branches:
180
- ["J", "JJ", 1, 2, EJ=25.0, EC=0.2]
181
- ["C", "C", 1, 0, C=1.0]
182
- ["L", "L", 2, 0, L=0.1]
183
184
nodes:
185
1: [0, 1]
186
2: [1, 0]
187
188
# Parameters for quantization
189
vars:
190
phi1: [0, 2*pi]
191
phi2: [0, 2*pi]
192
193
# Truncation settings
194
truncated_dim: 20
195
"""
196
197
# Create circuit
198
custom_circuit = scq.Circuit(custom_circuit_yaml, from_file=False)
199
200
# Set up discretization grids
201
phi_grid = scq.Grid1d(min_val=0, max_val=2*np.pi, pt_count=100)
202
custom_circuit.set_discretization('phi1', phi_grid)
203
custom_circuit.set_discretization('phi2', phi_grid)
204
205
# Calculate spectrum
206
spectrum = custom_circuit.eigenvals(evals_count=8)
207
print("Custom circuit spectrum:", spectrum)
208
```
209
210
### Parameter Sweeps with Circuits
211
212
```python
213
# Create fluxonium circuit
214
fluxonium_yaml = scq.core.circuit_utils.example_circuit('fluxonium')
215
fluxonium_circuit = scq.Circuit(fluxonium_yaml, from_file=False)
216
217
# Parameter sweep over external flux
218
flux_vals = np.linspace(0, 1, 51)
219
hilbert_space = scq.HilbertSpace([fluxonium_circuit])
220
221
def update_flux(system, flux_val):
222
"""Update circuit flux parameter."""
223
system.subsystem_list[0].configure(flux=flux_val)
224
225
sweep = scq.ParameterSweep(
226
hilbert_space=hilbert_space,
227
paramvals_by_name={'flux': flux_vals},
228
update_hilbert_space=update_flux,
229
evals_count=6
230
)
231
232
sweep.run()
233
sweep.plot_evals_vs_paramvals()
234
```
235
236
### Symbolic Circuit Construction
237
238
```python
239
# Define circuit using nodes and branches dictionaries
240
nodes_dict = {
241
1: [1, 0], # Node 1 at coordinates (1, 0)
242
2: [0, 1], # Node 2 at coordinates (0, 1)
243
3: [0, 0] # Ground node
244
}
245
246
branches_dict = {
247
'JJ1': {
248
'type': 'JJ',
249
'nodes': [1, 3],
250
'parameters': {'EJ': 20.0, 'EC': 0.15}
251
},
252
'JJ2': {
253
'type': 'JJ',
254
'nodes': [2, 3],
255
'parameters': {'EJ': 18.0, 'EC': 0.12}
256
},
257
'C12': {
258
'type': 'C',
259
'nodes': [1, 2],
260
'parameters': {'C': 5.0}
261
}
262
}
263
264
# Create symbolic circuit
265
symbolic_circuit = scq.SymbolicCircuit(
266
nodes_dict=nodes_dict,
267
branches_dict=branches_dict
268
)
269
270
# Generate symbolic Hamiltonian
271
H_symbolic = symbolic_circuit.generate_hamiltonian_symbolic()
272
print("Symbolic Hamiltonian:")
273
print(H_symbolic)
274
```
275
276
### Advanced Circuit Configuration
277
278
```python
279
# Create circuit with custom truncation
280
circuit_yaml = """
281
branches:
282
- ["JJ1", "JJ", 1, 0, EJ=25.0, EC=0.2]
283
- ["JJ2", "JJ", 2, 0, EJ=20.0, EC=0.18]
284
- ["C", "C", 1, 2, C=2.0]
285
286
nodes:
287
1: [0, 1]
288
2: [1, 0]
289
290
vars:
291
phi1: [-pi, pi]
292
phi2: [-pi, pi]
293
"""
294
295
# Create truncation template
296
truncation = scq.core.circuit_utils.truncation_template()
297
truncation.update({
298
'phi1_truncation': 15,
299
'phi2_truncation': 15,
300
'interaction_truncation': 10
301
})
302
303
# Create circuit with custom settings
304
circuit = scq.Circuit(circuit_yaml, from_file=False)
305
circuit.configure(
306
truncated_dim=50,
307
ext_basis='harmonic'
308
)
309
310
# Set up grid discretization
311
phi_grid_fine = scq.Grid1d(min_val=-np.pi, max_val=np.pi, pt_count=150)
312
circuit.set_discretization('phi1', phi_grid_fine)
313
circuit.set_discretization('phi2', phi_grid_fine)
314
315
# Calculate detailed spectrum
316
detailed_spectrum = circuit.eigenvals(evals_count=12)
317
print("Detailed circuit spectrum:", detailed_spectrum)
318
```
319
320
### Circuit Visualization and Analysis
321
322
```python
323
# Create circuit and calculate wavefunctions
324
circuit = scq.Circuit(transmon_yaml, from_file=False)
325
evals, evecs = circuit.eigensys(evals_count=4)
326
327
# Analyze ground state wavefunction
328
ground_state_wf = circuit.wavefunction(esys=(evals, evecs), which=0)
329
ground_state_wf.plot(mode='abs_sqr')
330
331
# Analyze first excited state
332
excited_state_wf = circuit.wavefunction(esys=(evals, evecs), which=1)
333
excited_state_wf.plot(mode='abs_sqr')
334
335
# Calculate matrix elements for circuit operators
336
# Note: Circuit operators need to be defined based on circuit variables
337
print("Energy level differences:")
338
for i in range(1, len(evals)):
339
transition = evals[i] - evals[0]
340
print(f"0->{i} transition: {transition:.4f} GHz")
341
```
342
343
### Multi-Junction Circuits
344
345
```python
346
# Three-junction flux qubit circuit
347
flux_qubit_yaml = """
348
branches:
349
- ["JJ1", "JJ", 1, 0, EJ=10.0, EC=0.1]
350
- ["JJ2", "JJ", 2, 0, EJ=10.0, EC=0.1]
351
- ["JJ3", "JJ", 1, 2, EJ=8.0, EC=0.08]
352
- ["L", "L", 1, 2, L=0.5]
353
354
nodes:
355
1: [0, 1]
356
2: [1, 0]
357
358
# External flux threading the loop
359
external_flux: 0.5
360
361
vars:
362
phi1: [-2*pi, 2*pi]
363
phi2: [-2*pi, 2*pi]
364
365
truncated_dim: 25
366
"""
367
368
# Create and analyze flux qubit circuit
369
flux_circuit = scq.Circuit(flux_qubit_yaml, from_file=False)
370
371
# Sweep external flux
372
flux_values = np.linspace(0, 1, 101)
373
374
def update_circuit_flux(system, flux_val):
375
system.subsystem_list[0].configure(external_flux=flux_val)
376
377
flux_sweep = scq.ParameterSweep(
378
hilbert_space=scq.HilbertSpace([flux_circuit]),
379
paramvals_by_name={'external_flux': flux_values},
380
update_hilbert_space=update_circuit_flux,
381
evals_count=8
382
)
383
384
flux_sweep.run()
385
flux_sweep.plot_evals_vs_paramvals()
386
```