Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing basis interface and abstract type changes in #40 #42

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# News

## v0.4.0 - 2024-12-10

This version implements the RFC in #40 without deprecating anything. Future versions will first add deprecation warnings before removing any existing interfaces.

- Eliminate all type parameters from `StateVector`, `AbstractKet`, `AbstractBra`, `AbstractOperator`, and `AbstractSuperOperator`.
- Implement new basis checking interface consisting of `multiplicable`, `addible`, `check_multiplicable`, `check_addible`, and `@compatiblebases`.
- Add `basis_l` and `basis_r` to get left and right bases of operators.
- Implement `size` for all bases and implement `getindex` for `CompositeBasis`.
- Add method interface to existing subtypes of `Bases`: `spinnumber`, `cutoff`, `offset`.
- Add `KetBraBasis`, `ChoiRefSysBasis`, `ChoiOutSysBasis`, and `_PauliBasis`. Note that eventually `_PauliBasis` will be renamed to `PauliBasis`.

## v0.3.7 - 2024-12-05

- Rename `PauliBasis` to `NQubitBasis` with warning, and add deprecation to `equal_bases`.

## v0.3.6 - 2024-09-08

- Add `coherentstate`, `thermalstate`, `displace`, `squeeze`, `wigner`, previously from QuantumOptics.
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "QuantumInterface"
uuid = "5717a53b-5d69-4fa3-b976-0bf2f97ca1e5"
authors = ["QuantumInterface.jl contributors"]
version = "0.3.6"
version = "0.4.0"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand Down
102 changes: 97 additions & 5 deletions src/QuantumInterface.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,104 @@
module QuantumInterface

import Base: ==, +, -, *, /, ^, length, one, exp, conj, conj!, transpose, copy
import LinearAlgebra: tr, ishermitian, norm, normalize, normalize!
import Base: show, summary
import SparseArrays: sparse, spzeros, AbstractSparseMatrix # TODO move to an extension
##
# Basis specific
##

"""
basis(a)

Return the basis of a quantum object.

If it's ambiguous, e.g. if an operator has a different
left and right basis, an [`IncompatibleBases`](@ref) error is thrown.

See [`StateVector`](@ref) and [`AbstractOperator`](@ref)
"""
function basis end

"""
basis_l(a)

Return the left basis of an operator.
"""
function basis_l end

"""
basis_r(a)

Return the right basis of an operator.
"""
function basis_r end

"""
Exception that should be raised for an illegal algebraic operation.
"""
mutable struct IncompatibleBases <: Exception end

#function bases end

function spinnumber end

function cutoff end

function offset end

##
# Standard methods
##

"""
multiplicable(a, b)

Check if any two subtypes of `StateVector` or `AbstractOperator`,
can be multiplied in the given order.
"""
function multiplicable end

"""
check_multiplicable(a, b)

Throw an [`IncompatibleBases`](@ref) error if the objects are
not multiplicable as determined by `multiplicable(a, b)`.

If the macro `@compatiblebases` is used anywhere up the call stack,
this check is disabled.
"""
function check_multiplicable end

"""
addible(a, b)

Check if any two subtypes of `StateVector` or `AbstractOperator`
can be added together.

Spcefically this checks whether the left basis of a is equal
to the left basis of b and whether the right basis of a is equal
to the right basis of b.
"""
function addible end

"""
check_addible(a, b)

Throw an [`IncompatibleBases`](@ref) error if the objects are
not addible as determined by `addible(a, b)`.

If the macro `@compatiblebases` is used anywhere up the call stack,
this check is disabled.
"""
function check_addible end

function apply! end

function dagger end

"""
directsum(x, y, z...)

Direct sum of the given objects. Alternatively, the unicode
symbol ⊕ (\\oplus) can be used.
"""
function directsum end
const ⊕ = directsum
directsum() = GenericBasis(0)
Expand Down Expand Up @@ -86,8 +176,9 @@ function squeeze end
function wigner end


include("bases.jl")
include("abstract_types.jl")
include("bases.jl")
include("show.jl")

include("linalg.jl")
include("tensor.jl")
Expand All @@ -100,5 +191,6 @@ include("julia_linalg.jl")
include("sparse.jl")

include("sortedindices.jl")
include("deprecated.jl")

end # module
77 changes: 33 additions & 44 deletions src/abstract_types.jl
Original file line number Diff line number Diff line change
@@ -1,57 +1,46 @@
"""
Abstract base class for `Bra` and `Ket` states.
Abstract type for all specialized bases of a Hilbert space.

The `Basis` type specifies an orthonormal basis for the Hilbert
space of the studied system. All subtypes must implement `Base.:(==)`,
and `Base.size`. `size` should return a tuple representing the total dimension
of the Hilbert space with any tensor product structure the basis has such that
`length(b::Basis) = prod(size(b))` gives the total Hilbert dimension

Composite systems can be defined with help of [`CompositeBasis`](@ref).

All relevant properties of subtypes of `Basis` defined in `QuantumInterface`
should be accessed using their documented functions and should not
assume anything about the internal representation of instances of these
types (i.e. don't access the struct's fields directly).
"""
abstract type Basis end

The state vector class stores the coefficients of an abstract state
in respect to a certain basis. These coefficients are stored in the
`data` field and the basis is defined in the `basis`
field.
"""
abstract type StateVector{B,T} end
abstract type AbstractKet{B,T} <: StateVector{B,T} end
abstract type AbstractBra{B,T} <: StateVector{B,T} end
Abstract type for `Bra` and `Ket` states.

The state vector class stores an abstract state with respect
to a certain basis. All subtypes must implement the `basis`
method which should this basis as a subtype of `Basis`.
"""
Abstract base class for all operators.
abstract type StateVector end
abstract type AbstractKet <: StateVector end
abstract type AbstractBra <: StateVector end

All deriving operator classes have to define the fields
`basis_l` and `basis_r` defining the left and right side bases.
"""
Abstract type for all operators and super operators.

All subtypes must implement the methods `basis_l` and
`basis_r` which return subtypes of `Basis` and
represent the left and right bases that the operator
maps between and thus is compatible with a `Bra` defined
in the left basis and a `Ket` defined in the right basis.

For fast time evolution also at least the function
`mul!(result::Ket,op::AbstractOperator,x::Ket,alpha,beta)` should be
implemented. Many other generic multiplication functions can be defined in
terms of this function and are provided automatically.
"""
abstract type AbstractOperator{BL,BR} end
abstract type AbstractOperator end

"""
Base class for all super operator classes.

Super operators are bijective mappings from operators given in one specific
basis to operators, possibly given in respect to another, different basis.
To embed super operators in an algebraic framework they are defined with a
left hand basis `basis_l` and a right hand basis `basis_r` where each of
them again consists of a left and right hand basis.
```math
A_{bl_1,bl_2} = S_{(bl_1,bl_2) ↔ (br_1,br_2)} B_{br_1,br_2}
\\\\
A_{br_1,br_2} = B_{bl_1,bl_2} S_{(bl_1,bl_2) ↔ (br_1,br_2)}
```
"""
abstract type AbstractSuperOperator{B1,B2} end

function summary(stream::IO, x::AbstractOperator)
print(stream, "$(typeof(x).name.name)(dim=$(length(x.basis_l))x$(length(x.basis_r)))\n")
if samebases(x)
print(stream, " basis: ")
show(stream, basis(x))
else
print(stream, " basis left: ")
show(stream, x.basis_l)
print(stream, "\n basis right: ")
show(stream, x.basis_r)
end
end

show(stream::IO, x::AbstractOperator) = summary(stream, x)

traceout!(s::StateVector, i) = ptrace(s,i)
const AbstractQObjType = Union{<:StateVector,<:AbstractOperator}
Loading
Loading