Skip to content

Commit 1b2a005

Browse files
committed
Merge branch 'closed_system_example'
2 parents 14a733f + 4b35b6e commit 1b2a005

File tree

7 files changed

+82
-62
lines changed

7 files changed

+82
-62
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ docs/site/
2222
# committed for packages, but should be committed for applications that require a static
2323
# environment.
2424
Manifest.toml
25+
.vscode

html/introduction/01-closed_system.html

+25-21
Large diffs are not rendered by default.

markdown/introduction/01-closed_system.md

+22-16
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ title: "An Intro to HOQST - closed-system simulation"
44
---
55

66

7-
## Close System Examples
8-
This notebook will get you started with HOQST by introducing you to the functionality for solving colsed-system equations.
7+
## Closed-system Examples
8+
This notebook will get you started with HOQST by introducing you to the functionality for solving closed-system equations.
99

10-
### Define the Hamiltonin
11-
The first step is to define an Hamiltonian. In this tutorial we focus on a 2-level system with the following Hamiltonian
10+
### Define the Hamiltonian
11+
The first step is to define a Hamiltonian. In this tutorial, we focus on a 2-level system with the following Hamiltonian:
1212

1313
$$H(s) = - \sigma_z$$
1414

15-
where $s= t/t_f$ is the dimensionless time and $t_f$ is the total evolution time. We use a constant Hamiltonian so the simulation results can be trivially confirmed. The syntax is the same for time dependent Hamiltonians. Let's first define the Hamiltonian by:
15+
where $s= t/t_f$ is the dimensionless time and $t_f$ is the total evolution time. We use the constant Hamiltonian so that the simulation results can be trivially confirmed. The syntax is the same for time-dependent Hamiltonians. Let's first define the Hamiltonian by:
1616

1717
```julia
1818
using QuantumAnnealingTools, OrdinaryDiffEq, Plots
@@ -29,7 +29,7 @@ with size: (2, 2)
2929

3030

3131

32-
In this example, we use the `DenseHamiltonian` object. The syntax is the same for other type of Hamiltonians.
32+
In this example, we use the `DenseHamiltonian` [type](https://docs.julialang.org/en/v1/manual/types/#man-types). It means the underlying data structure of this Hamiltonian type is [Julia array](https://docs.julialang.org/en/v1/manual/arrays/). There exists a different Hamiltonian type named `SparseHamiltonian` that relies on [sparse array](https://docs.julialang.org/en/v1/stdlib/SparseArrays/) as its internal data structure. Sparsity can only provide performance improvement when the system size is large. So, as a rule of thumb, users should only consider using `SparseHamiltonian` when the system size is larger than 10 qubits.
3333

3434
The closed-system evolution is completely specified by the Hamiltonian and the initial state. We can combine them into a single `Annealing` object by:
3535

@@ -65,25 +65,25 @@ We start with the Schrodinger equation
6565
\lvert \dot{\phi} \rangle = -i t_f H(s) \lvert \phi \rangle \ .
6666
\end{equation}
6767

68-
To solve the this differential equation, we need to choose a proper algortihm. HOQST relies on `OrdinaryDiffEq.jl` as the low level solver, which support a large collection of [algorithms](https://docs.sciml.ai/latest/solvers/ode_solve/). We do not guarantee compatibilities to every solver in this list. Users can try specific algorithms if they are interested. We provide a list of algorithms we tested and recommended here:
68+
To solve this differential equation, we need to choose a proper algorithm. HOQST relies on `OrdinaryDiffEq.jl` as the low-level solver, which supports a large collection of [algorithms](https://docs.sciml.ai/latest/solvers/ode_solve/). We do not guarantee compatibilities to every solver in this list. Users can try specific algorithms if they are interested. We provide a list of algorithms we tested and recommended here:
6969

7070
1. The default Tsitouras 5/4 Runge-Kutta method(Tsit5()).
7171

7272
This is the default method in `OrdinaryDiffEq` and works well in most cases.
7373

74-
2. A second order A-B-L-S-stable one-step ESDIRK method(TRBDF2()).
74+
2. A second-order A-B-L-S-stable one-step ESDIRK method(TRBDF2()).
7575

76-
This is the method widely used in large scale classical circuit simulations. Because this method has order of 2, it is recommended to use smaller error tolerance comparing with other higher order methods.
76+
This is the method widely used in large scale classical circuit simulations. Because this is a second-order method, it is recommended to use smaller error tolerance comparing with other higher-order methods.
7777

7878
3. A simple linear exponential method(LinearExponential()).
7979

80-
This method simply discretize the Hamiltonian and do matrix exponential for each interval.
80+
This method discretizes the Hamiltonian and does the matrix exponential for each interval.
8181

8282
4. Adaptive exponential Rosenbrock methods(Exprb32()/Exprb43()).
8383

8484
This method belongs to the adaptive exponential Runge-Kutta method family.
8585

86-
It is important to notice that, method 3 and 4 are exponential methods which would preserve the norm of the state vectors. To solve our the Schrodinger equation we use the function `solve_schrodinger`.
86+
It is important to notice that methods 3 and 4 are exponential methods that are supposed to preserve the state vectors' norm. To solve the Schrodinger equation, we use the function `solve_schrodinger`:
8787

8888
```julia
8989
sol_tsit = solve_schrodinger(annealing, tf, alg=Tsit5(), abstol=1e-6, reltol=1e-6);
@@ -97,14 +97,20 @@ sol_exprb32 = solve_schrodinger(annealing, tf, alg=Exprb32(), tstops=range(0,tf,
9797

9898

9999

100+
101+
In the above code block, the keyword arguments `abstol` and `reltol` are the absolute and relative error tolerances for [step size control](https://diffeq.sciml.ai/stable/basics/common_solver_opts/) in adaptive stepsize ODE algorithms. They are usually chosen by trial-and-error in real applications.
102+
100103
We plot the observable $\langle X \rangle$ during the evolution.
101104
```julia
105+
# this code block shows how to plot the expectation value of X
102106
t_list = range(0,tf,length=100)
103107
tsit = []
104108
trbdf = []
105109
linexp = []
106110
exprb32 = []
107111
for s in t_list
112+
# sol_tsit(s)'*σx*sol_tsit(s) calculates the
113+
# expectation value <ψ(s)|X|ψ(s)>
108114
push!(tsit, real(sol_tsit(s)'*σx*sol_tsit(s)))
109115
push!(trbdf, real(sol_trbdf(s)'*σx*sol_trbdf(s)))
110116
push!(linexp, real(sol_linexp(s)'*σx*sol_linexp(s)))
@@ -126,11 +132,11 @@ title!("Free Evolution")
126132
### Other close system equations
127133
The package also contains several other closed-system solvers.
128134
#### Von Neumann equation
129-
Von Neumann equation is the "Schrodinger" equation for density matrices
135+
The Von Neumann equation is the "Schrodinger" equation for density matrices:
130136

131137
$$\dot{\rho} = -it_f[H(s), \rho] \ .$$
132138

133-
Even though Von Neumann equation is equivalent to the Schrodinger equation, it is sometimes numerically more stable than the Schrodinger equation. Users is encouraged to try to solve it using different algorithms.
139+
Even though the Von Neumann equation is equivalent to the Schrodinger equation, it is sometimes numerically more stable than the Schrodinger equation. Users are encouraged to try to solve it using different algorithms.
134140

135141
```julia
136142
annealing = Annealing(H, u0)
@@ -207,7 +213,7 @@ u: 78-element Array{Array{Complex{Float64},2},1}:
207213

208214

209215

210-
As shown below, the solution given by the solver is the density matrix instead of state vector:
216+
As shown below, the solution given by the solver is the density matrix instead of the state vector:
211217

212218
```julia
213219
sol_tsit(0.5)
@@ -272,7 +278,7 @@ hare\julia\stdlib\v1.5\LinearAlgebra\src\triangular.jl:34
272278

273279

274280

275-
We can again plot the $\langle X \rangle$ for different methods
281+
We can again plot the $\langle X \rangle$ for different methods:
276282

277283
```julia
278284
sol_tsit = solve_von_neumann(annealing, tf, alg=Tsit5(), reltol=1e-6);
@@ -315,7 +321,7 @@ using `solve_unitary`. The ODE form of the problem is
315321

316322
$$\dot{U} = -i t_f H(s) U \ .$$
317323

318-
Again, although this is in principle equivalent to Schrondinger/Von Neumann equation, the unitary becomes handy in certain cases, e.g. when solving the Redfeild equation.
324+
Although this is in principle equivalent to Schrodinger/Von Neumann equation, the unitary becomes handy in certain cases, e.g., when solving the Redfield equation.
319325

320326
```julia
321327
annealing = Annealing(H, u0)

notebook/introduction/01-closed_system.ipynb

+9-9
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
{
44
"cell_type": "markdown",
55
"source": [
6-
"## Close System Examples\nThis notebook will get you started with HOQST by introducing you to the functionality for solving colsed-system equations.\n\n### Define the Hamiltonin\nThe first step is to define an Hamiltonian. In this tutorial we focus on a 2-level system with the following Hamiltonian\n\n$$H(s) = - \\sigma_z$$\n\nwhere $s= t/t_f$ is the dimensionless time and $t_f$ is the total evolution time. We use a constant Hamiltonian so the simulation results can be trivially confirmed. The syntax is the same for time dependent Hamiltonians. Let's first define the Hamiltonian by:"
6+
"## Closed-system Examples\nThis notebook will get you started with HOQST by introducing you to the functionality for solving closed-system equations.\n\n### Define the Hamiltonian\nThe first step is to define a Hamiltonian. In this tutorial, we focus on a 2-level system with the following Hamiltonian:\n\n$$H(s) = - \\sigma_z$$\n\nwhere $s= t/t_f$ is the dimensionless time and $t_f$ is the total evolution time. We use the constant Hamiltonian so that the simulation results can be trivially confirmed. The syntax is the same for time-dependent Hamiltonians. Let's first define the Hamiltonian by:"
77
],
88
"metadata": {}
99
},
@@ -19,7 +19,7 @@
1919
{
2020
"cell_type": "markdown",
2121
"source": [
22-
"In this example, we use the `DenseHamiltonian` object. The syntax is the same for other type of Hamiltonians.\n\nThe closed-system evolution is completely specified by the Hamiltonian and the initial state. We can combine them into a single `Annealing` object by:"
22+
"In this example, we use the `DenseHamiltonian` [type](https://docs.julialang.org/en/v1/manual/types/#man-types). It means the underlying data structure of this Hamiltonian type is [Julia array](https://docs.julialang.org/en/v1/manual/arrays/). There exists a different Hamiltonian type named `SparseHamiltonian` that relies on [sparse array](https://docs.julialang.org/en/v1/stdlib/SparseArrays/) as its internal data structure. Sparsity can only provide performance improvement when the system size is large. So, as a rule of thumb, users should only consider using `SparseHamiltonian` when the system size is larger than 10 qubits. \n\nThe closed-system evolution is completely specified by the Hamiltonian and the initial state. We can combine them into a single `Annealing` object by:"
2323
],
2424
"metadata": {}
2525
},
@@ -35,7 +35,7 @@
3535
{
3636
"cell_type": "markdown",
3737
"source": [
38-
"The initial state in above code block is\n$$\\lvert \\phi(0) \\rangle = \\lvert + \\rangle \\ .$$\n\nWe will consider three variants of the closed-system equations in this tutorial.\n\n### Schrodinger equation\nWe start with the Schrodinger equation\n\\begin{equation}\n \\lvert \\dot{\\phi} \\rangle = -i t_f H(s) \\lvert \\phi \\rangle \\ .\n\\end{equation}\n\nTo solve the this differential equation, we need to choose a proper algortihm. HOQST relies on `OrdinaryDiffEq.jl` as the low level solver, which support a large collection of [algorithms](https://docs.sciml.ai/latest/solvers/ode_solve/). We do not guarantee compatibilities to every solver in this list. Users can try specific algorithms if they are interested. We provide a list of algorithms we tested and recommended here:\n\n1. The default Tsitouras 5/4 Runge-Kutta method(Tsit5()).\n\n This is the default method in `OrdinaryDiffEq` and works well in most cases.\n\n2. A second order A-B-L-S-stable one-step ESDIRK method(TRBDF2()).\n\n This is the method widely used in large scale classical circuit simulations. Because this method has order of 2, it is recommended to use smaller error tolerance comparing with other higher order methods.\n \n3. A simple linear exponential method(LinearExponential()).\n\n This method simply discretize the Hamiltonian and do matrix exponential for each interval.\n \n4. Adaptive exponential Rosenbrock methods(Exprb32()/Exprb43()).\n\n This method belongs to the adaptive exponential Runge-Kutta method family.\n \nIt is important to notice that, method 3 and 4 are exponential methods which would preserve the norm of the state vectors. To solve our the Schrodinger equation we use the function `solve_schrodinger`."
38+
"The initial state in above code block is\n$$\\lvert \\phi(0) \\rangle = \\lvert + \\rangle \\ .$$\n\nWe will consider three variants of the closed-system equations in this tutorial.\n\n### Schrodinger equation\nWe start with the Schrodinger equation\n\\begin{equation}\n \\lvert \\dot{\\phi} \\rangle = -i t_f H(s) \\lvert \\phi \\rangle \\ .\n\\end{equation}\n\nTo solve this differential equation, we need to choose a proper algorithm. HOQST relies on `OrdinaryDiffEq.jl` as the low-level solver, which supports a large collection of [algorithms](https://docs.sciml.ai/latest/solvers/ode_solve/). We do not guarantee compatibilities to every solver in this list. Users can try specific algorithms if they are interested. We provide a list of algorithms we tested and recommended here:\n\n1. The default Tsitouras 5/4 Runge-Kutta method(Tsit5()).\n\n This is the default method in `OrdinaryDiffEq` and works well in most cases.\n\n2. A second-order A-B-L-S-stable one-step ESDIRK method(TRBDF2()).\n\n This is the method widely used in large scale classical circuit simulations. Because this is a second-order method, it is recommended to use smaller error tolerance comparing with other higher-order methods.\n \n3. A simple linear exponential method(LinearExponential()).\n\n This method discretizes the Hamiltonian and does the matrix exponential for each interval.\n \n4. Adaptive exponential Rosenbrock methods(Exprb32()/Exprb43()).\n\n This method belongs to the adaptive exponential Runge-Kutta method family.\n \nIt is important to notice that methods 3 and 4 are exponential methods that are supposed to preserve the state vectors' norm. To solve the Schrodinger equation, we use the function `solve_schrodinger`:"
3939
],
4040
"metadata": {}
4141
},
@@ -51,23 +51,23 @@
5151
{
5252
"cell_type": "markdown",
5353
"source": [
54-
"We plot the observable $\\langle X \\rangle$ during the evolution."
54+
"In the above code block, the keyword arguments `abstol` and `reltol` are the absolute and relative error tolerances for [step size control](https://diffeq.sciml.ai/stable/basics/common_solver_opts/) in adaptive stepsize ODE algorithms. They are usually chosen by trial-and-error in real applications. \n\nWe plot the observable $\\langle X \\rangle$ during the evolution."
5555
],
5656
"metadata": {}
5757
},
5858
{
5959
"outputs": [],
6060
"cell_type": "code",
6161
"source": [
62-
"t_list = range(0,tf,length=100)\ntsit = []\ntrbdf = []\nlinexp = []\nexprb32 = []\nfor s in t_list\n push!(tsit, real(sol_tsit(s)'*σx*sol_tsit(s)))\n push!(trbdf, real(sol_trbdf(s)'*σx*sol_trbdf(s)))\n push!(linexp, real(sol_linexp(s)'*σx*sol_linexp(s)))\n push!(exprb32, real(sol_exprb32(s)'*σx*sol_exprb32(s)))\nend\nscatter(t_list[1:3:end], tsit[1:3:end], label=\"Tsit\", marker=:+, markersize=8)\nscatter!(t_list[2:3:end], trbdf[2:3:end], label=\"TRBDF\")\nscatter!(t_list[3:3:end], linexp[3:3:end], label=\"LinExp\", marker=:d)\nplot!(t_list, exprb32, label=\"Exprb\", linestyle=:dash)\nxlabel!(\"t (ns)\")\nylabel!(\"<X>\")\ntitle!(\"Free Evolution\")"
62+
"# this code block shows how to plot the expectation value of X\nt_list = range(0,tf,length=100)\ntsit = []\ntrbdf = []\nlinexp = []\nexprb32 = []\nfor s in t_list\n # sol_tsit(s)'*σx*sol_tsit(s) calculates the \n # expectation value <ψ(s)|X|ψ(s)>\n push!(tsit, real(sol_tsit(s)'*σx*sol_tsit(s)))\n push!(trbdf, real(sol_trbdf(s)'*σx*sol_trbdf(s)))\n push!(linexp, real(sol_linexp(s)'*σx*sol_linexp(s)))\n push!(exprb32, real(sol_exprb32(s)'*σx*sol_exprb32(s)))\nend\nscatter(t_list[1:3:end], tsit[1:3:end], label=\"Tsit\", marker=:+, markersize=8)\nscatter!(t_list[2:3:end], trbdf[2:3:end], label=\"TRBDF\")\nscatter!(t_list[3:3:end], linexp[3:3:end], label=\"LinExp\", marker=:d)\nplot!(t_list, exprb32, label=\"Exprb\", linestyle=:dash)\nxlabel!(\"t (ns)\")\nylabel!(\"<X>\")\ntitle!(\"Free Evolution\")"
6363
],
6464
"metadata": {},
6565
"execution_count": null
6666
},
6767
{
6868
"cell_type": "markdown",
6969
"source": [
70-
"### Other close system equations\nThe package also contains several other closed-system solvers.\n#### Von Neumann equation\nVon Neumann equation is the \"Schrodinger\" equation for density matrices\n\n$$\\dot{\\rho} = -it_f[H(s), \\rho] \\ .$$\n\nEven though Von Neumann equation is equivalent to the Schrodinger equation, it is sometimes numerically more stable than the Schrodinger equation. Users is encouraged to try to solve it using different algorithms."
70+
"### Other close system equations\nThe package also contains several other closed-system solvers.\n#### Von Neumann equation\nThe Von Neumann equation is the \"Schrodinger\" equation for density matrices:\n\n$$\\dot{\\rho} = -it_f[H(s), \\rho] \\ .$$\n\nEven though the Von Neumann equation is equivalent to the Schrodinger equation, it is sometimes numerically more stable than the Schrodinger equation. Users are encouraged to try to solve it using different algorithms."
7171
],
7272
"metadata": {}
7373
},
@@ -83,7 +83,7 @@
8383
{
8484
"cell_type": "markdown",
8585
"source": [
86-
"As shown below, the solution given by the solver is the density matrix instead of state vector:"
86+
"As shown below, the solution given by the solver is the density matrix instead of the state vector:"
8787
],
8888
"metadata": {}
8989
},
@@ -131,7 +131,7 @@
131131
{
132132
"cell_type": "markdown",
133133
"source": [
134-
"We can again plot the $\\langle X \\rangle$ for different methods"
134+
"We can again plot the $\\langle X \\rangle$ for different methods:"
135135
],
136136
"metadata": {}
137137
},
@@ -147,7 +147,7 @@
147147
{
148148
"cell_type": "markdown",
149149
"source": [
150-
"#### Unitary\nLastly, we can also solve the unitary\n\n$$U(s) = T_+ \\exp\\bigg\\{ -i t_f \\int_0^s H(s') \\mathrm{d}s' \\bigg\\}$$\n\nusing `solve_unitary`. The ODE form of the problem is\n\n$$\\dot{U} = -i t_f H(s) U \\ .$$\n\nAgain, although this is in principle equivalent to Schrondinger/Von Neumann equation, the unitary becomes handy in certain cases, e.g. when solving the Redfeild equation."
150+
"#### Unitary\nLastly, we can also solve the unitary\n\n$$U(s) = T_+ \\exp\\bigg\\{ -i t_f \\int_0^s H(s') \\mathrm{d}s' \\bigg\\}$$\n\nusing `solve_unitary`. The ODE form of the problem is\n\n$$\\dot{U} = -i t_f H(s) U \\ .$$\n\nAlthough this is in principle equivalent to Schrodinger/Von Neumann equation, the unitary becomes handy in certain cases, e.g., when solving the Redfield equation."
151151
],
152152
"metadata": {}
153153
},

pdf/introduction/01-closed_system.pdf

2.47 KB
Binary file not shown.

script/introduction/01-closed_system.jl

+3
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@ sol_linexp = solve_schrodinger(annealing, tf, alg=LinearExponential(), abstol=1e
2323
sol_exprb32 = solve_schrodinger(annealing, tf, alg=Exprb32(), tstops=range(0,tf,length=100));
2424

2525

26+
# this code block shows how to plot the expectation value of X
2627
t_list = range(0,tf,length=100)
2728
tsit = []
2829
trbdf = []
2930
linexp = []
3031
exprb32 = []
3132
for s in t_list
33+
# sol_tsit(s)'*σx*sol_tsit(s) calculates the
34+
# expectation value <ψ(s)|X|ψ(s)>
3235
push!(tsit, real(sol_tsit(s)'*σx*sol_tsit(s)))
3336
push!(trbdf, real(sol_trbdf(s)'*σx*sol_trbdf(s)))
3437
push!(linexp, real(sol_linexp(s)'*σx*sol_linexp(s)))

0 commit comments

Comments
 (0)