@@ -90,48 +90,58 @@ tensor(op::AbstractOperator) = op
9090tensor (operators:: AbstractOperator... ) = reduce (tensor, operators)
9191
9292
93+
94+ """
95+ docstring
96+ """
97+ function check_indices (indices:: Array )
98+ status = true
99+ # Check that no sub-list contains duplicates.
100+ for i in filter (x -> typeof (x) <: Array , indices)
101+ status &= (length (Set (i)) == length (i))
102+ end
103+ # Check that there are no duplicates across `indices`
104+ for (idx, i) in enumerate (indices[1 : end - 1 ])
105+ for j in indices[idx+ 1 : end ]
106+ status &= (length (intersect (i, j)) == 0 )
107+ end
108+ end
109+ return status
110+ end
111+
112+
93113"""
94114 embed(basis1[, basis2], indices::Vector, operators::Vector)
95115
96116Tensor product of operators where missing indices are filled up with identity operators.
97117"""
98118function embed (basis_l:: CompositeBasis , basis_r:: CompositeBasis ,
99- indices:: Vector{Int} , operators:: Vector{T} ) where T<: AbstractOperator
119+ indices:: Vector , operators:: Vector{T} ) where T<: AbstractOperator
120+
121+ @assert check_indices (indices)
122+
100123 N = length (basis_l. bases)
101124 @assert length (basis_r. bases) == N
102- @assert length (indices) >= length (operators)
103- op_b_len = Int[isa (op. basis_l, CompositeBasis) ? length (op. basis_l. bases) : 1 for op= operators]
104-
105- # Neglect indices covered by composite operators
106- k = 1
107- new_idx = Int[]
108- for i= 1 : length (operators)
109- push! (new_idx, indices[k])
110- ptr_index = filter (p-> ! (p ∈ indices[k: k+ op_b_len[i]- 1 ]), 1 : N)
111- operators[i]. basis_l == ptrace (basis_l, ptr_index) || throw (bases. IncompatibleBases ())
112- operators[i]. basis_r == ptrace (basis_r, ptr_index) || throw (bases. IncompatibleBases ())
113- k += op_b_len[i]
114- end
115- # Recursively lower index to fit length
116- for i= 1 : length (operators)- 1
117- new_idx[i+ 1 : end ] .- = (op_b_len[i] - 1 )
118- end
125+ @assert length (indices) == length (operators)
119126
120- n = N- sum (op_b_len) + length (operators)
121- # Assign operators according to their position
122- out = Array {AbstractOperator,1} (undef, n)
123- for i= 1 : length (operators)
124- out[new_idx[i]] = operators[i]
127+ idxop_sb = [x for x in zip (indices, operators) if typeof (x[1 ]) <: Int64 ]
128+ indices_sb = [x[1 ] for x in idxop_sb]
129+ ops_sb = [x[2 ] for x in idxop_sb]
130+
131+ for (idxsb, opsb) in zip (indices_sb, ops_sb)
132+ @assert (opsb. basis_l == basis_l. bases[idxsb]) || throw (bases. IncompatibleBases ())
133+ @assert (opsb. basis_r == basis_r. bases[idxsb]) || throw (bases. IncompatibleBases ())
125134 end
126- # Find positions and assign identities
127- id_idx = filter (p-> ! (p ∈ indices), 1 : N)
128- new_id_idx = filter (p-> ! (p ∈ new_idx), 1 : n)
129- @assert length (id_idx) == length (new_id_idx)
130- for i= 1 : length (id_idx)
131- out[new_id_idx[i]] = identityoperator (T, basis_l. bases[id_idx[i]], basis_r. bases[id_idx[i]])
135+
136+ embed_op = tensor ([i ∈ indices_sb ? ops_sb[indexin (i, indices_sb)[1 ]] : identityoperator (T, basis_l. bases[i], basis_r. bases[i]) for i= 1 : N]. .. )
137+
138+ idxop_comp = [x for x in zip (indices, operators) if typeof (x[1 ]) <: Array ]
139+
140+ for (idxs, op) in idxop_comp
141+ embed_op *= embed (basis_l, basis_r, idxs, op)
132142 end
133143
134- return tensor (out ... )
144+ return embed_op
135145end
136146
137147
@@ -145,16 +155,16 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
145155 N = length (basis_l. bases)
146156 @assert length (basis_r. bases) == N
147157
148- @assert reduce (tensor, basis_l. bases[indices]) == op. basis_l
149- @assert reduce (tensor, basis_r. bases[indices]) == op. basis_r
158+ @assert reduce (tensor, basis_l. bases[indices]) == op. basis_l || throw (bases . IncompatibleBases ())
159+ @assert reduce (tensor, basis_r. bases[indices]) == op. basis_r || throw (bases . IncompatibleBases ())
150160
151161 index_order = [idx for idx in 1 : length (basis_l. bases) if idx ∉ indices]
152162 all_operators = AbstractOperator[identityoperator (T, basis_l. bases[i], basis_r. bases[i]) for i in index_order]
153163
154- for idx in indices[ end : - 1 : 1 ]
164+ for idx in indices
155165 pushfirst! (index_order, idx)
156166 end
157- pushfirst ! (all_operators, op)
167+ push ! (all_operators, op)
158168
159169 sortedindices. check_indices (N, indices)
160170
@@ -165,8 +175,8 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
165175 unpermuted_op = copy (permuted_op)
166176
167177 # 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)
178+ unpermuted_op. basis_l = basis_l
179+ unpermuted_op. basis_r = basis_r
170180
171181 # Reorient the matrix to act in the correctly ordered basis.
172182 # Get the dimensions necessary for index permuting.
@@ -181,8 +191,8 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
181191 expand_dims_r = dims_r[expand_order]
182192
183193 # 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 ]
194+ perm_order_l = [indexin (idx, expand_order) [1 ] for idx in 1 : length (dims_l) ]
195+ perm_order_r = [indexin (idx, expand_order) [1 ] for idx in 1 : length (dims_r) ]
186196
187197 # Perform the index expansion, the permutation, and the index collapse.
188198 M = (reshape (permuted_op. data, tuple ([expand_dims_l; expand_dims_r]. .. )) |>
@@ -195,7 +205,7 @@ function embed(basis_l::CompositeBasis, basis_r::CompositeBasis,
195205end
196206embed (basis_l:: CompositeBasis , basis_r:: CompositeBasis , index:: Int , op:: AbstractOperator ) = embed (basis_l, basis_r, Int[index], [op])
197207embed (basis:: CompositeBasis , index:: Int , op:: AbstractOperator ) = embed (basis, basis, Int[index], [op])
198- embed (basis:: CompositeBasis , indices:: Vector{Int} , operators:: Vector{T} ) where {T<: AbstractOperator } = embed (basis, basis, indices, operators)
208+ embed (basis:: CompositeBasis , indices:: Vector , operators:: Vector{T} ) where {T<: AbstractOperator } = embed (basis, basis, indices, operators)
199209embed (basis:: CompositeBasis , indices:: Vector{Int} , op:: AbstractOperator ) = embed (basis, basis, indices, op)
200210
201211"""
0 commit comments