@@ -6,8 +6,10 @@ export AbstractOperator, DataOperator, length, basis, dagger, ishermitian, tenso
66
77import Base: == , + , - , * , / , ^ , length, one, exp, conj, conj!, transpose
88import LinearAlgebra: tr, ishermitian
9+ import SparseArrays: sparse
910import .. bases: basis, tensor, ptrace, permutesystems,
1011 samebases, check_samebases, multiplicable
12+ # import ..operators_sparse: SparseOperator
1113import .. states: dagger, normalize, normalize!
1214
1315using .. sortedindices, .. bases, .. states
@@ -131,11 +133,72 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
131133
132134 return tensor (out... )
133135end
136+
137+
138+ """
139+ embed(basis1[, basis2], indices::Vector, operators::Vector)
140+
141+ Embed operator acting on a joint Hilbert space where missing indices are filled up with identity operators.
142+ """
143+ function embed (basis_l:: CompositeBasis , basis_r:: CompositeBasis ,
144+ indices:: Vector{Int} , op:: T ) where T<: AbstractOperator
145+ N = length (basis_l. bases)
146+ @assert length (basis_r. bases) == N
147+
148+ @assert reduce (tensor, basis_l. bases[indices]) == op. basis_l
149+ @assert reduce (tensor, basis_r. bases[indices]) == op. basis_r
150+
151+ index_order = [idx for idx in 1 : length (basis_l. bases) if idx ∉ indices]
152+ all_operators = AbstractOperator[identityoperator (T, basis_l. bases[i], basis_r. bases[i]) for i in index_order]
153+
154+ for idx in indices[end : - 1 : 1 ]
155+ pushfirst! (index_order, idx)
156+ end
157+ pushfirst! (all_operators, op)
158+
159+ sortedindices. check_indices (N, indices)
160+
161+ # Create the operator.
162+ permuted_op = tensor (all_operators... )
163+
164+ # Create a copy to fill with correctly-ordered objects (basis and data).
165+ unpermuted_op = copy (permuted_op)
166+
167+ # Create the correctly ordered basis.
168+ unpermuted_op. basis_l = permutesystems (permuted_op. basis_l, index_order)
169+ unpermuted_op. basis_r = permutesystems (permuted_op. basis_r, index_order)
170+
171+ # Reorient the matrix to act in the correctly ordered basis.
172+ # Get the dimensions necessary for index permuting.
173+ dims_l = [b. shape[1 ] for b in basis_l. bases]
174+ dims_r = [b. shape[1 ] for b in basis_r. bases]
175+
176+ # Get the order of indices to use in the first reshape. Julia indices go in
177+ # reverse order.
178+ expand_order = index_order[end : - 1 : 1 ]
179+ # Get the dimensions associated with those indices.
180+ expand_dims_l = dims_l[expand_order]
181+ expand_dims_r = dims_r[expand_order]
182+
183+ # Prepare the permutation to the correctly ordered basis.
184+ perm_order_l = [indexin (idx, length (dims_l): - 1 : 1 )[1 ] for idx in expand_order]
185+ perm_order_r = [indexin (idx, length (dims_r): - 1 : 1 )[1 ] for idx in expand_order]
186+
187+ # Perform the index expansion, the permutation, and the index collapse.
188+ M = (reshape (permuted_op. data, tuple ([expand_dims_l; expand_dims_r]. .. )) |>
189+ x -> permutedims (x, [perm_order_l; perm_order_r .+ length (dims_l)]) |>
190+ x -> sparse (reshape (x, (prod (dims_l), prod (dims_r)))))
191+
192+ unpermuted_op. data = M
193+
194+ return unpermuted_op
195+ end
134196embed (basis_l:: CompositeBasis , basis_r:: CompositeBasis , index:: Int , op:: AbstractOperator ) = embed (basis_l, basis_r, Int[index], [op])
135197embed (basis_l:: CompositeBasis , basis_r:: CompositeBasis , index:: Vector{Int} , op:: AbstractOperator ) = embed (basis_l, basis_r, index, [op])
136198embed (basis:: CompositeBasis , index:: Int , op:: AbstractOperator ) = embed (basis, basis, Int[index], [op])
137199embed (basis:: CompositeBasis , indices:: Vector{Int} , operators:: Vector{T} ) where {T<: AbstractOperator } = embed (basis, basis, indices, operators)
138200embed (basis:: CompositeBasis , index:: Vector{Int} , op:: AbstractOperator ) = embed (basis, basis, index, [op])
201+ embed (basis:: CompositeBasis , indices:: Vector{Int} , op:: AbstractOperator ) = embed (basis, basis, indices, op)
139202
140203"""
141204 embed(basis1[, basis2], operators::Dict)
@@ -202,7 +265,31 @@ normalize!(op::AbstractOperator) = throw(ArgumentError("normalize! is not define
202265
203266"""
204267 expect(op, state)
268+ index_order = [idx for idx in 1:length(dims) if idx ∉ indices]
269+
270+ eyedim = prod(dims[index_order])
271+
272+ for idx in indices[end:-1:1]
273+ pushfirst!(index_order, idx)
274+ end
275+
276+ alldim = prod(dims[index_order])
277+
278+ index_order
279+
280+ expand_order = [dims[idx] for idx in index_order][end:-1:1]
281+
282+ perm_order = [indexin(idx, expand_order)[1] for idx in dims[end:-1:1]]
283+
284+ println(index_order)
285+ println(expand_order)
286+ println(perm_order)
287+
288+ my_matrix = kron(m, eye(eltype(m), eyedim))
205289
290+ M = (reshape(my_matrix, tuple([expand_order; expand_order]...)) |>
291+ x -> permutedims(x, [perm_order; perm_order .+ length(dims)]) |>
292+ x -> sparse(reshape(x, (prod(dims), prod(dims)))))
206293Expectation value of the given operator `op` for the specified `state`.
207294
208295`state` can either be a (density) operator or a ket.
0 commit comments