Closed mtfishman closed 2 years ago
An additional generalization would be to allow a Matrix
in the SimpleOp
struct instead of a string for the opname, like is proposed here: https://github.com/ITensor/ITensors.jl/issues/722
That could be done by extending SimpleOp
to:
struct SimpleOp{N,T<:Union{String,Matrix}}
name::T
sites::NTuple{N,Int}
params::NamedTuple
end
(and maybe rename the field name
to something more general like op
).
Another thing to consider is that we could expose the Op
and Circuit
types externally to allow operations like:
exp(Op("X", 1)) -> Op(exp, "X", 1)
2 * Op("X", 1) -> Op(2, "X", 1)
Op("X", 1) * Op("Y", 2)
Op("X", 1) * Op("Y", 2) + Op("Y", 1) * Op("X", 2)
but that is more of an interface enhancement that would iterate on the plan above.
Internally, we should unify the
state
andgate
interface inPastaQ
with thestate
,op
, andOpSum
interface in ITensors.Part of this would be to have a hierarchy of types representing gates or operators which would be used internally by both ITensors and PastaQ, to simplify parsing gate lists and to have a common format for making gate lists, Trotter circuits, and MPOs.
The starting point would be something like this:
This is essentially just the
SiteOp
type used byOpSum
: https://github.com/ITensor/ITensors.jl/blob/v0.2.9/src/physics/autompo.jl#L10-L14 with a new name (sinceSiteOp
doesn't make much sense, since it can by multi-site). So this is just a "simple" gate representation like:Then, these would get put together into a product (or sum of products) to make an operator
Op
, like this:This is similar to the
MPOTerm
type used byOpSum
(https://github.com/ITensor/ITensors.jl/blob/v0.2.9/src/physics/autompo.jl#L90-L93). This would be the internal representation for more sophisticated (sums of) products of operators as well as function applications, like:The reason it is a
Vector{Vector{SimpleOp}}
is that the innerVector
stores a product ofSimpleOp
and the outerVector
stores a sum of those products, so(exp, 0.1im, "a† * a + a * a†", 1, 2)
would get parsed into a structure like:In principle the field
opsum
could be a general lazy representation for adding and multiplying gates, but I think adding sums of gates is sufficient. Finally, I think we can restrict all of the terms in the sum to have support on the same sites, so maybe something like this:where
sites
is the same as the sites of all of theVector{SimpleOp{N}}
terms. The internal constructor could check that the sites of all of theVector{SimpleOp{N}}
are all the same and then store them in thesites
field.A question would be how to represent products of on-site terms as well. One proposal would be:
in which case it would fit into the same data structure as above. To me this makes sense since you can interpret the above as
exp(0.1im (X₁ Y₁ + Y₁ X₁))
. There would be a question about how to do mixtures of on-site and multi-site products. In that case you could do:If you don't have a product somewhere, you could use an identity:
I think we could make
"I"
interpreted as a universal identityI
(Julia already has that defined) so it would be a no-op. In principle we could get pretty fancy and have a syntax like this:where the sites in the parentheses get extracted when parsing.
Then, the ITensors.jl
OpSum
could be defined as:so simply a sum of
Op
s.Additionally, the
PastaQ
/ITensor
operator or gate lists for gate evolution can be converted to aVector{Op}
internally. We could even consider defining something like:or maybe
OpList
,GateList
,OpProd
,GateProd
, etc. as an internal representation for a circuit. In that way, we can define functions likeinv
,dag
, etc. of a circuit. We could have fieldsinv
anddag
inOp
orSimpleOp
to store the fact that an inverse or dagger needs to be performed (and maybe other standard fields, likeisunitary
,isorthogonal
,grad
, etc.).This would help with unifying
gate
andop
, since there could be a single functionality for converting anOp
into aMatrix
orITensor
(i.e. parsing the opname strings to get sums of products of gates that get turned into anOp
which then gets turned into the correctMatrix
/ITensor
). So basically all of the complexity for converting anOp
to aMatrix
/ITensor
would be in functions likeop(::Op, ::SiteType)
.Ultimately I think
gate
could just be an alias forop
(or a wrapper), since their functionality is very similar. The actual definitions of the gates for theQubit
/Qudit
site types could be in eitherPastaQ
orITensors
(core standard ones inITensors
and more complicated quantum-computing specific ones inPastaQ
).Finally, a small piece is unifying the
state
implementation. I think we can basically just importstate
from ITensors and remove thePastaQ
implementation.