Skip to content

Conversation

@Gavin-Rockwood
Copy link

@Gavin-Rockwood Gavin-Rockwood commented Dec 1, 2025

Checklist

Thank you for contributing to QuantumToolbox.jl! Please make sure you have finished the following tasks before opening the PR.

  • Please read Contributing to Quantum Toolbox in Julia.
  • Any code changes were done in a way that does not break public API.
  • Appropriate tests were added and tested locally by running: make test.
  • Any code changes should be julia formatted by running: make format.
  • All documents (in docs/ folder) related to code changes were updated and able to build locally by running: make docs.
  • (If necessary) the CHANGELOG.md should be updated (regarding to the code changes) and built by running: make changelog.

Request for a review after you have completed all the tasks. If you have not finished them all, you can also open a Draft Pull Request to let the others know this on-going work.

Description

Updated TimeEvolutionProblem be parametrically typed using the type of the starting state as well as expanded sesolve, mesolve and mcsolve to allow them to take in operators, superoperators and operators respectively (along with other changes to facilitate this). ssesolve and smesolve are still in progress.

Related issues or PRs

Working on #521

Comment on lines 109 to 127
T = Base.promote_eltype(L_evo, ψ0)
ρ0 = if isoperket(ψ0) # Convert it to dense vector with complex element type
to_dense(_complex_float_type(T), copy(ψ0.data))
else
to_dense(_complex_float_type(T), mat2vec(ket2dm(ψ0).data))
# ρ0 = if isoperket(ψ0) # Convert it to dense vector with complex element type
# to_dense(_complex_float_type(T), copy(ψ0.data))
# else
# to_dense(_complex_float_type(T), mat2vec(ket2dm(ψ0).data))
# end
if isoper(ψ0)
ρ0 = to_dense(_complex_float_type(T), mat2vec(ψ0.data))
state_type = Operator()
elseif isoperket(ψ0)
ρ0 = to_dense(_complex_float_type(T), copy(ψ0.data))
state_type = OperatorKet()
elseif isket(ψ0)
ρ0 = to_dense(_complex_float_type(T), mat2vec(ket2dm(ψ0).data))
state_type = Operator()
elseif issuper(ψ0)
ρ0 = to_dense(_complex_float_type(T), copy(ψ0.data))
state_type = SuperOperator()
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
T = Base.promote_eltype(L_evo, ψ0)
ρ0 = if isoperket(ψ0) # Convert it to dense vector with complex element type
to_dense(_complex_float_type(T), copy(ψ0.data))
else
to_dense(_complex_float_type(T), mat2vec(ket2dm(ψ0).data))
# ρ0 = if isoperket(ψ0) # Convert it to dense vector with complex element type
# to_dense(_complex_float_type(T), copy(ψ0.data))
# else
# to_dense(_complex_float_type(T), mat2vec(ket2dm(ψ0).data))
# end
if isoper(ψ0)
ρ0 = to_dense(_complex_float_type(T), mat2vec(ψ0.data))
state_type = Operator()
elseif isoperket(ψ0)
ρ0 = to_dense(_complex_float_type(T), copy(ψ0.data))
state_type = OperatorKet()
elseif isket(ψ0)
ρ0 = to_dense(_complex_float_type(T), mat2vec(ket2dm(ψ0).data))
state_type = Operator()
elseif issuper(ψ0)
ρ0 = to_dense(_complex_float_type(T), copy(ψ0.data))
state_type = SuperOperator()
end
# Convert to dense vector with complex element type
T = _complex_float_type(Base.promote_eltype(L_evo, ψ0))
if isoperket(ψ0) || issuper(ψ0)
ρ0 = to_dense(T, copy(ψ0.data))
states_type = ψ0.type
else
ρ0 = to_dense(T, mat2vec(ket2dm(ψ0).data))
states_type = Operator()
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ket2dm will do nothing if the input is density matrix (Operator), so it doesn't hurt performance, and we can also do ket2dm for Operator input.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, maybe also use states_type instead of state_type to avoid confusion, since we call it states_type in TimeEvolutionProblem

Comment on lines +332 to 340
if isoper(state)
to_dense(_complex_float_type(T), mat2vec(state.data))
elseif isoperket(state)
to_dense(_complex_float_type(T), copy(state.data))
elseif isket(state)
to_dense(_complex_float_type(T), mat2vec(ket2dm(state).data))
elseif issuper(state)
to_dense(_complex_float_type(T), copy(state.data))
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Suggested change
if isoper(state)
to_dense(_complex_float_type(T), mat2vec(state.data))
elseif isoperket(state)
to_dense(_complex_float_type(T), copy(state.data))
elseif isket(state)
to_dense(_complex_float_type(T), mat2vec(ket2dm(state).data))
elseif issuper(state)
to_dense(_complex_float_type(T), copy(state.data))
end
if isoperket(state) || issuper(state)
to_dense(T, copy(state.data))
else
to_dense(T, mat2vec(ket2dm(state).data))
end

if getVal(isoperket)
ρt = map-> QuantumObject(ϕ, type = OperatorKet(), dims = dimensions), sol.u)
function _gen_mesolve_solution(sol, prob::TimeEvolutionProblem{ST}) where {ST<:Union{Operator,OperatorKet,SuperOperator}}
if prob.states_type == Operator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here should be

Suggested change
if prob.states_type == Operator
if prob.states_type isa Operator

cause prob.states_type should be Operator() ?

Comment on lines +3 to +11
#_smesolve_generate_state(u, dims, isoperket::Val{false}) = QuantumObject(vec2mat(u), type = Operator(), dims = dims)
#_smesolve_generate_state(u, dims, isoperket::Val{true}) = QuantumObject(u, type = OperatorKet(), dims = dims)
function _smesolve_generate_state(u, dims, type)
if type == OperatorKet
return QuantumObject(u, type = type, dims = dims)
else
return QuantumObject(vec2mat(u), type = Operator(), dims = dims)
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#_smesolve_generate_state(u, dims, isoperket::Val{false}) = QuantumObject(vec2mat(u), type = Operator(), dims = dims)
#_smesolve_generate_state(u, dims, isoperket::Val{true}) = QuantumObject(u, type = OperatorKet(), dims = dims)
function _smesolve_generate_state(u, dims, type)
if type == OperatorKet
return QuantumObject(u, type = type, dims = dims)
else
return QuantumObject(vec2mat(u), type = Operator(), dims = dims)
end
end
_smesolve_generate_state(u, dims, type::Operator) = QuantumObject(vec2mat(u), type = type, dims = dims)
_smesolve_generate_state(u, dims, type::OperatorKet) = QuantumObject(u, type = type, dims = dims)

prob = ODEProblem{getVal(inplace),FullSpecialize}(L, ρ0, tspan, params; kwargs4...)

return TimeEvolutionProblem(prob, tlist, L_evo.dimensions, (isoperket = Val(isoperket(ψ0)),))
return TimeEvolutionProblem(prob, tlist, state_type, L_evo.dimensions)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return TimeEvolutionProblem(prob, tlist, state_type, L_evo.dimensions)
return TimeEvolutionProblem(prob, tlist, states_type, L_evo.dimensions)

Comment on lines +239 to 241
ψ0 = map(to_dense, ψ0) # Convert all initial states to dense vectors

ψ0_iter = map(get_data, ψ0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes the input ψ0 provided by users, better do it in same way as mesolve:

Suggested change
ψ0 = map(to_dense, ψ0) # Convert all initial states to dense vectors
ψ0_iter = map(get_data, ψ0)
ψ0_iter = map(state -> to_dense(_complex_float_type(eltype(state)), copy(state.data)), ψ0) # Convert all initial states to dense vectors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants