Skip to content

Clarifying the express interface #56

@akirakyle

Description

@akirakyle

I've been thinking a lot about interfaces as I keep working on #40 where among many other things, I've been trying to figure out the best interface for conversion among superoperators. I realized the design issues there are similar to the design issues for express, which is also in some sense, an interface for conversions between types. The julia docs also document conversion patterns which either use a type's constructor T(x) or Base.convert. I think the main issue in conversion is how to specify "additional" information necessary for conversion. For example the fock cutoff, or in the superoperator case, the precision with which the spectrum of a superoperator is obtained to convert to the kraus representation.

So I wanted to ask a few questions about how the express interface is or isn't supposed to handle the following hypothetical scenarios:

  • Say I have a ket = QuantumSymbolics.CoherentState(α) where α is a symbolic number. Then I want a symbolic matrix representation of ket in the fock basis with a cutoff, so I want Ket(FockBasis(cutoff), exp(-{|α|^2/2}) * [1,α, α^2/sqrt(2),..., α^cutoff/sqrt(cutoff!)]. Would this be some hypothetical express(ket, SymbolicMatrixRepr(cutoff))? What if I explicitly want dense versus sparse representations?
  • What if I want this ket expressed in PositionBasis or MomentumBasis? It seems like just adding the xmin, xmax, N or pmin, pmax, N fields to QuantumOpticsRepr won't specify which of FockBasis, PositionBasis, or MomentumBasis one would want?

Perhaps I'm totally misunderstanding the intended interface for express, but as it is, I'm not sure how it will capture all the types of conversions and the parameters they might need. In order to do this, it seems like combinations of AbstractRepresentation and AbstractUse will end up just being stand ins for a T(x) type constructor and it might be better just to use that pattern? For example Ket(FockBasis(cutoff), ket) where ket is as defined as above.

On the other hand, the type T(x) constructor method wouldn't seem to be able to handle the other use of express which converts expressions containing multiple terms. This is mainly relevant for QuantumSymbolics expressions and for Lazy* that can actually represent multiple terms. For example conversion of the symbolic ket⊗ket to LazyKet(FockBasis(cutoff)⊗FockBasis(cutoff), [ket,ket]). However, I think a more flexible design might be to have AbstractRepresentation be essentially just a set of conversion rules for how to call T(x) type constructors. Sensible sets can be provided but it should be easily to define one's own rules depending on what exactly on wants. For example, something schematically like

QuantumOpticsRepr(cutoff) = Dict(
CoherentState => ket -> Ket(FockBasis(cutoff), ket),
STensor => LazyTensor
)

Hopefully this would make it easier for a user to modify existing sets if they largely cover what one wants but want slight differences like only using LazyProduct or something. I'm imagining that, somewhat like SymbolicUtils.toexpr which build_function uses, we could traverse the expression tree starting from leaves and calling the appropriate T(x) conversion to build up the converted expression.

Something I'm also worried about is that express has preferred defaults, for example the current fock cutoff of 2 is way to low for any coherent state and won't give normalized states (which seems like another option express ought to have).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions