@@ -9,8 +9,7 @@ Abstract type for operators with a data field.
99This is an abstract type for operators that have a direct matrix representation
1010stored in their `.data` field.
1111"""
12- abstract type BLROperator{BL,BR} <: AbstractOperator end
13- abstract type DataOperator{BL,BR} <: BLROperator{BL,BR} end
12+ abstract type DataOperator{BL,BR} <: AbstractOperator end
1413
1514
1615# Common error messages
@@ -24,14 +23,14 @@ Embed operator acting on a joint Hilbert space where missing indices are filled
2423"""
2524function embed (basis_l:: CompositeBasis , basis_r:: CompositeBasis ,
2625 indices, op:: T ) where T<: DataOperator
27- N = length (basis_l. bases )
28- @assert length (basis_r. bases ) == N
26+ N = nsubsystems (basis_l)
27+ @assert nsubsystems (basis_r) == N
2928
30- reduce (tensor, basis_l. bases [indices]) == op. basis_l || throw (IncompatibleBases ())
31- reduce (tensor, basis_r. bases [indices]) == op. basis_r || throw (IncompatibleBases ())
29+ reduce (tensor, basis_l[indices]) == op. basis_l || throw (IncompatibleBases ())
30+ reduce (tensor, basis_r[indices]) == op. basis_r || throw (IncompatibleBases ())
3231
33- index_order = [idx for idx in 1 : length (basis_l . bases) if idx ∉ indices]
34- all_operators = AbstractOperator[identityoperator (T, eltype (op), basis_l. bases [i], basis_r. bases [i]) for i in index_order]
32+ index_order = [idx for idx in 1 : N if idx ∉ indices]
33+ all_operators = AbstractOperator[identityoperator (T, eltype (op), basis_l[i], basis_r[i]) for i in index_order]
3534
3635 for idx in indices
3736 pushfirst! (index_order, idx)
@@ -45,8 +44,8 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
4544
4645 # Reorient the matrix to act in the correctly ordered basis.
4746 # Get the dimensions necessary for index permuting.
48- dims_l = [b . shape[ 1 ] for b in basis_l. bases]
49- dims_r = [b . shape[ 1 ] for b in basis_r. bases]
47+ dims_l = size ( basis_l)
48+ dims_r = size ( basis_r)
5049
5150 # Get the order of indices to use in the first reshape. Julia indices go in
5251 # reverse order.
7473function embed (basis_l:: CompositeBasis , basis_r:: CompositeBasis ,
7574 index:: Integer , op:: T ) where T<: DataOperator
7675
77- N = length (basis_l. bases )
76+ N = nsubsystems (basis_l)
7877
7978 # Check stuff
80- @assert N == length (basis_r. bases)
81- basis_l. bases [index] == op. basis_l || throw (IncompatibleBases ())
82- basis_r. bases [index] == op. basis_r || throw (IncompatibleBases ())
79+ @assert nsubsystems (basis_r) == N
80+ basis_l[index] == op. basis_l || throw (IncompatibleBases ())
81+ basis_r[index] == op. basis_r || throw (IncompatibleBases ())
8382 check_indices (N, index)
8483
8584 # Build data
@@ -92,8 +91,8 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
9291 data = kron (data, op. data)
9392 i -= length (index)
9493 else
95- bl = basis_l. bases [i]
96- br = basis_r. bases [i]
94+ bl = basis_l[i]
95+ br = basis_r[i]
9796 id = SparseMatrixCSC {Tnum} (I, length (bl), length (br))
9897 data = kron (data, id)
9998 i -= 1
@@ -110,18 +109,21 @@ Expectation value of the given operator `op` for the specified `state`.
110109
111110`state` can either be a (density) operator or a ket.
112111"""
113- expect (op:: BLROperator{B,B} , state:: Ket{B} ) where B = dot (state. data, (op * state). data)
112+ function expect (op:: AbstractOperator , state:: Ket )
113+ check_multiplicable (op,op); check_multiplicable (op,state)
114+ dot (state. data, (op * state). data)
115+ end
114116
115117# TODO upstream this one
116118# expect(op::AbstractOperator{B,B}, state::AbstractKet{B}) where B = norm(op * state) ^ 2
117119
118- function expect (indices, op:: BLROperator{B,B} , state:: Ket{B2 } ) where {B,B2 <: CompositeBasis }
119- N = length (state . basis. shape )
120+ function expect (indices, op:: AbstractOperator , state:: Ket{B } ) where {B<: CompositeBasis }
121+ N = nsubsystems ( basis (state) )
120122 indices_ = complement (N, indices)
121123 expect (op, ptrace (state, indices_))
122124end
123125
124- expect (index:: Integer , op:: BLROperator{B,B} , state:: Ket{B2 } ) where {B,B2 <: CompositeBasis } = expect ([index], op, state)
126+ expect (index:: Integer , op:: AbstractOperator , state:: Ket{B } ) where {B<: CompositeBasis } = expect ([index], op, state)
125127
126128"""
127129 variance(op, state)
@@ -130,44 +132,42 @@ Variance of the given operator `op` for the specified `state`.
130132
131133`state` can either be a (density) operator or a ket.
132134"""
133- function variance (op:: BLROperator{B,B} , state:: Ket{B} ) where B
135+ function variance (op:: AbstractOperator , state:: Ket )
136+ check_multiplicable (op,op); check_multiplicable (op,state)
134137 x = op* state
135138 state. data' * (op* x). data - (state. data' * x. data)^ 2
136139end
137140
138- function variance (indices, op:: BLROperator{B,B} , state:: Ket{BC } ) where {B,BC <: CompositeBasis }
139- N = length (state . basis. shape )
141+ function variance (indices, op:: AbstractOperator , state:: Ket{B } ) where {B<: CompositeBasis }
142+ N = nsubsystems ( basis (state) )
140143 indices_ = complement (N, indices)
141144 variance (op, ptrace (state, indices_))
142145end
143146
144- variance (index:: Integer , op:: BLROperator{B,B} , state:: Ket{BC } ) where {B,BC <: CompositeBasis } = variance ([index], op, state)
147+ variance (index:: Integer , op:: AbstractOperator , state:: Ket{B } ) where {B<: CompositeBasis } = variance ([index], op, state)
145148
146149# Helper functions to check validity of arguments
147150function check_ptrace_arguments (a:: AbstractOperator , indices)
148151 if ! isa (a. basis_l, CompositeBasis) || ! isa (a. basis_r, CompositeBasis)
149152 throw (ArgumentError (" Partial trace can only be applied onto operators with composite bases." ))
150153 end
151- rank = length (a . basis_l. shape )
152- if rank != length (a . basis_r. shape )
154+ rank = nsubsystems ( basis_l (a) )
155+ if rank != nsubsystems ( basis_r (a) )
153156 throw (ArgumentError (" Partial trace can only be applied onto operators wich have the same number of subsystems in the left basis and right basis." ))
154157 end
155158 if rank == length (indices)
156159 throw (ArgumentError (" Partial trace can't be used to trace out all subsystems - use tr() instead." ))
157160 end
158- check_indices (length (a . basis_l. shape ), indices)
161+ check_indices (nsubsystems ( basis_l (a) ), indices)
159162 for i= indices
160- if a . basis_l. shape [i] != a . basis_r. shape [i]
163+ if size ( basis_l (a)) [i] != size ( basis_r (a)) [i]
161164 throw (ArgumentError (" Partial trace can only be applied onto subsystems that have the same left and right dimension." ))
162165 end
163166 end
164167end
165168function check_ptrace_arguments (a:: StateVector , indices)
166- if length (basis (a). shape ) == length (indices)
169+ if nsubsystems (basis (a)) == length (indices)
167170 throw (ArgumentError (" Partial trace can't be used to trace out all subsystems - use tr() instead." ))
168171 end
169- check_indices (length (basis (a). shape ), indices)
172+ check_indices (nsubsystems (basis (a)), indices)
170173end
171-
172- multiplicable (a:: AbstractOperator , b:: Ket ) = multiplicable (a. basis_r, b. basis)
173- multiplicable (a:: Bra , b:: AbstractOperator ) = multiplicable (a. basis, b. basis_l)
0 commit comments