-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Project on a subsystem and drop it? i.e. how do I perform (⟨a|⊗Id)*(|b⟩⊗|c⟩) → (⟨a|b⟩)|c⟩
#322
Comments
⟨a|⊗Id)*(|b⟩⊗|c⟩ → (⟨a|b⟩)⊗|c⟩
(⟨a|⊗Id)*(|b⟩⊗|c⟩) → (⟨a|b⟩)⊗|c⟩
(⟨a|⊗Id)*(|b⟩⊗|c⟩) → (⟨a|b⟩)⊗|c⟩
(⟨a|⊗Id)*(|b⟩⊗|c⟩) → (⟨a|b⟩)|c⟩
Here is an attempt at a rather ugly and inefficient solution function drop_singular_bases(ket)
b = tensor([b for b in basis(ket).bases if length(b)>1]...)
return Ket(b, ket.data)
end
function project_and_drop(state, project_on, basis_index)
singularbasis = GenericBasis(1)
singularket = basisstate(singularbasis,1)
proj = projector(singularket, project_on')
basis_r = collect(Any,basis(state).bases)
basis_l = copy(basis_r)
basis_l[basis_index] = singularbasis
emproj = embed(tensor(basis_l...),tensor(basis_r...),basis_index,proj)
result = emproj*state
return drop_singular_bases(result)
end Tested here:
|
Is it important for you to get the state In principle you could also obtain the state |
Sorry, it is also quite easy to get the state from the density matrix.
Note that you get some inaccuracies due to the numerics. |
@ChristophHotter , using a density matrix for an otherwise vector-like operation is slow, especially given that you are adding matrix diagonalization to it. 500x slower and 100x more allocated memory in the following example.
|
Yes, you are completely right. Using the density matrix doesn't make much sense. However, I think there is an easy solution for your problem. Normalizing basically just divides out the common factor ( I wrote a function
Is this what you need? |
This is similar to what I am trying to do, thanks! However, I want to remove only one of the subsystem, not split all the subsystems. Moreover, the assumption that the state is factorizable is not something I can afford. It becomes factorizable only after the projection on I think you are doing I want to do Even worse, I would need to perform this for explicitly non factorizable It would be awesome if I can specify This type of subsystem projections is pretty common in (memory-efficient) Monte Carlo simulations of small quantum computing devices. E.g. we have 5 transmons, all of them entangled in a non-factorizable state, and we want to measure only one of them. Postselecting on the measurement result would give us 4-qubit kets. For qubits, that is a 2x memory savings, but even if we did not care about the memory savings, the speadup compared to creating (even sparse) projector matrices would be significant. At this point, I should also ask whether you would accept a PR providing a function called |
Just wanted to explain this in one more way: If a partial trace is |
I think a good solution would be to implement tensor products of kets with operators, and also bras with operators, such that you can create @Krastanov Would this solve your issue? |
@ChristophHotter I'm not sure if that actually solves the problem. Also, I think this is basically the same as creating a 1D basis as @Krastanov did in his initial example. The @Krastanov If you use Here's a slightly optimized version of your code: function project_and_drop(state, project_on, basis_index)
singularbasis = GenericBasis(1)
singularket = basisstate(singularbasis,1)
proj = Operator(singularbasis, project_on.basis, project_on.data')
bases = state.basis.bases
basis_l = tensor((i==basis_index ? singularbasis : bases[i] for i=1:length(bases))...)
emproj = LazyTensor(basis_l, state.basis, basis_index, proj, 1.0)
result = emproj*state
return drop_singular_bases(result)
end |
@david-pl , thanks, this will be very useful (and I should probably look at the LazyTensor source code). @ChristophHotter , the general tensor object you suggest might be too much for QuantumOptics, but it would be certainly interesting if such helper functions exist for mixing QuantumOptics and the various tensor network libraries that are popping up. |
It would be nice to include a function like this in QO.jl. Perhaps call it |
I have some very simple code to handle tensor products of bras and kets with operators, for example:
This allows us to do things like |
The SVD of the coefficient matrix (Schmidt decomposition), obtained by reshaping the state vector, will directly give us both the ket vectors corresponding to the singular value 1. This would not generate a density matrix. As we have only one nonzero singular value, there may be a more efficient way of doing this. |
State-operator tensor products now supported in QuantumOpticsBase: qojulia/QuantumOpticsBase.jl#61 |
This is great! I would suggest keeping this issue still open though as the state-operator tensor product is not trivially supported by |
Imagine I have a vector
|b⟩⊗|c⟩
that I know for a fact is factorizable like this. This can arise in a situation in which I have just projected by|b⟩⟨b|⊗Id
. How do I now extract|c⟩
? How do I drop the dimension corresponding to|b⟩
.One way to do that would be to have a
SingularBasis
of dimension 1 so I can doproject(b, basisstate(SingularBasis(),0))
and then somedropsingular
function to remove subsystems of size 1.Or maybe there is something in
embed
that already does this.Any suggestions how to do it or whether it is already implemented?
The text was updated successfully, but these errors were encountered: