# [Computing propagators](@id doc-TE:Computing-propagators)

```@setup propagator
using QuantumToolbox
```

## Using a solver to compute a propagator

Many solvers accept an identity matrix as the initial state. When such [`QuantumObject`](@ref) is passed as the initial state, the propagator is computed. This can be used to compute a propagator for [`sesolve`](@ref), [`mesolve`](@ref), [`brmesolve`](@ref), etc. For example, 

```@example propagator
ϵ0 = 1.0 * 2π
Ω = 0.8 * 2π
Δt = π/5
H = (ϵ0/2) * sigmaz() + (Ω/2) * sigmax()
```

The propagator ``\hat{U}`` for the [Schrodinger equation](@ref doc-TE:Schrödinger-Equation-Solver) with a small time step ``\Delta t`` can be used as

```math
|\psi(t + \Delta t)\rangle = \hat{U}(\Delta t) |\psi(t)\rangle
```

For a Hamiltonian `H`, the corresponding propagator ``\hat{U}(\Delta t)`` can be generated by using [`sesolve`](@ref) with the initial state given as `qeye_like(H)`, which is an identity [`Operator`](@ref) (same as `H.type`), namely

```@example propagator
U_se = sesolve(H, qeye_like(H), [0, Δt]; progress_bar = Val(false)).states[end]
```

Thus, the state at time ``t = n \Delta t`` can be computed by applying the propagator ``\hat{U}(\Delta t)`` repeatedly ``n`` times on the initial state ``|\psi(0)\rangle``:

```@example propagator
n = 10
ψ0 = basis(2, 0)

ψt = U_se^n * ψ0
```

Similarly, the propagator ``\mathcal{U}`` for [Lindblad master equation](@ref doc-TE:Lindblad-Master-Equation-Solver) with a small time step ``\Delta t`` can be used as

```math
|\hat{\rho}(t + \Delta t)\rangle\!\rangle = \mathcal{U}(\Delta t) |\hat{\rho}(t)\rangle\!\rangle,
```

where ``|\hat{\rho}(t)\rangle\!\rangle`` is the [vectorized density operator](@ref doc:Superoperators-and-Vectorized-Operators).

For a Liouvillian superoperator `L`, the corresponding propagator ``\mathcal{U}(\Delta t)`` can be generated by using [`mesolve`](@ref) with the initial state given as `qeye_like(L)`, which is an identity [`SuperOperator`](@ref) (same as `L.type`), namely

```@example propagator
L = liouvillian(H)
U_me = mesolve(L, qeye_like(L), [0, Δt]; progress_bar = Val(false)).states[end]
```

Thus, the state at time ``t = n \Delta t`` can be computed by applying the propagator ``\mathcal{U}(\Delta t)`` repeatedly ``n`` times on the initial [vectorized density operator](@ref doc:Superoperators-and-Vectorized-Operators) ``|\hat{\rho}(0)\rangle\!\rangle``:

```@example propagator
n = 10
ρ0_vec = mat2vec(ket2dm(basis(2, 0))) # type=OperatorKet()

ρt_vec = U_me^n * ρ0_vec
```
