QuTiP BRME DSL Example#
This example (example_qutip_brme_dsl.py) demonstrates a more specialized workflow (BRME-style notation) and shows how the DSL maps physics-style LaTeX into operator references consumed by the QuTiP backend.
What you’ll learn#
How to express BRME-style interaction terms in LaTeX.
How the DSL canonicalizes and maps those operators to QuTiP objects.
Source#
1# flake8: noqa
2r"""
3Reimplementation of the QuTiP ``brmesolve`` tutorial using the LaTeX DSL.
4
5Original notebook steps (``qutip_example.ipynb``):
61) Constant Hamiltonian H = a^\dagger a for a truncated oscillator.
72) Add a time-dependent drive H(t) = H + sin(t)(a + a^\dagger).
83) Add simple dissipation with a decaying envelope.
94) Add a composite, explicitly time-dependent collapse operator.
10
11This example shows how each Hamiltonian/collapse operator can be expressed
12in LaTeX, compiled with the parser, and then passed directly to QuTiP
13``brmesolve`` while keeping the rest of the workflow unchanged.
14"""
15
16from __future__ import annotations
17
18import sys
19from pathlib import Path
20
21import numpy as np
22import matplotlib.pyplot as plt
23
24from latex_parser.latex_api import compile_model, make_config
25from qutip import about, basis, mesolve, plot_expectation_values
26
27
28def _number_op(cutoff: int):
29 """Use the DSL to build the bosonic number operator."""
30 cfg = make_config(bosons=[cutoff])
31 model = compile_model(
32 H_latex=r"n_{1}", params={}, config=cfg, c_ops_latex=None, backend="qutip"
33 )
34 return model.H
35
36
37def compile_constant_oscillator(cutoff: int):
38 cfg = make_config(bosons=[cutoff])
39 H_latex = r"a_{1}^{\dagger} a_{1}"
40 model = compile_model(
41 H_latex=H_latex, params={}, config=cfg, c_ops_latex=None, backend="qutip"
42 )
43 return model.H
44
45
46def compile_driven_oscillator(cutoff: int):
47 cfg = make_config(bosons=[cutoff])
48 H_latex = r"a_{1}^{\dagger} a_{1} + \sin(t) \left(a_{1} + a_{1}^{\dagger}\right)"
49 model = compile_model(
50 H_latex=H_latex, params={}, config=cfg, c_ops_latex=None, backend="qutip"
51 )
52 return model.H
53
54
55def compile_decay_collapse_ops(cutoff: int, kappa: float):
56 cfg = make_config(bosons=[cutoff])
57 model = compile_model(
58 H_latex=r"a_{1}^{\dagger} a_{1}",
59 params={"kappa": kappa},
60 config=cfg,
61 c_ops_latex=[
62 r"\sqrt{\kappa} \exp(-t/2) \, a_{1}",
63 r"\sqrt{\kappa} \exp(-t/2) \, a_{1}^{\dagger}",
64 ],
65 backend="qutip",
66 )
67 return model.H, model.c_ops, model.args
68
69
70def compile_composite_collapse_ops(cutoff: int, kappa: float):
71 cfg = make_config(bosons=[cutoff])
72 model = compile_model(
73 H_latex=r"a_{1}^{\dagger} a_{1}",
74 params={"kappa": kappa},
75 config=cfg,
76 c_ops_latex=[
77 r"\sqrt{\kappa} \, a_{1} \exp(I t)",
78 r"\sqrt{\kappa} \, a_{1}^{\dagger} \exp(-I t)",
79 ],
80 backend="qutip",
81 )
82 return model.H, model.c_ops, model.args
83
84
85def main() -> None:
86 N = 2
87 psi0 = basis(N, N - 1)
88 times = np.linspace(0, 10, 100)
89 n_op = _number_op(N)
90
91 # 1) Constant Hamiltonian
92 H_const = compile_constant_oscillator(N)
93 result_const = mesolve(H_const, psi0, times, e_ops=[n_op])
94 plot_expectation_values(result_const, ylabels=["<n>"])
95
96 # 2) Driven Hamiltonian with sin(t)
97 H_drive = compile_driven_oscillator(N)
98 result_drive = mesolve(H_drive, psi0, times, e_ops=[n_op])
99 plot_expectation_values(result_drive, ylabels=["<n>"])
100
101 # 3) Dissipation with decaying envelope (Bloch-Redfield a_ops form)
102 kappa = 0.2
103 H_decay, c_ops_decay, args_decay = compile_decay_collapse_ops(N, kappa)
104 result_decay = mesolve(
105 H_decay, psi0, times, c_ops=c_ops_decay, e_ops=[n_op], args=args_decay
106 )
107 plot_expectation_values(result_decay, ylabels=["<n>"])
108
109 # 4) Composite time-dependent collapse operator
110 H_comp, c_ops_comp, args_comp = compile_composite_collapse_ops(N, kappa)
111 result_comp = mesolve(
112 H_comp, psi0, times, c_ops=c_ops_comp, e_ops=[n_op], args=args_comp
113 )
114 plot_expectation_values(result_comp, ylabels=["<n>"])
115
116 # Parity checks mirroring the notebook assertions
117 assert np.allclose(result_const.expect[0], 1.0)
118 assert np.all(np.diff(result_comp.expect[0]) <= 0.0)
119 about()
120 plt.show()
121
122
123if __name__ == "__main__":
124 main()
Run#
python examples/example_qutip_brme_dsl.py
Notes#
This example is targeted at users integrating domain-specific LaTeX conventions (BRME) with the parser. Inspect IR output to verify mappings.