Skip to content
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

g_a_integrals: possible missing a coefficient of lambda/S ? #96

Closed
daviehh opened this issue Nov 6, 2021 · 6 comments · Fixed by #97
Closed

g_a_integrals: possible missing a coefficient of lambda/S ? #96

daviehh opened this issue Nov 6, 2021 · 6 comments · Fixed by #97
Assignees
Labels
bug Something isn't working

Comments

@daviehh
Copy link

daviehh commented Nov 6, 2021

First, thanks for open sourcing this implementation! I was writing my own implementation in julia from scratch following your paper SciPostPhys.7.6.080, but noticed a discrepancy in the J values: basically, e.g. with this example the infidelity J_T agrees but the integral of g_a differs. Glancing over the code, look like the integral of g_a

g_a_integrals[i_pulse] += abs(Δϵ) ** 2 * dt # dt may vary!

does not agree with the second line of Eq. 7 in the paper: the integrand missed the \lambda_{a,l}/S_l(t) term and is just (\delta \epsilon)^2, and when I also drop that \lambda_{a,l}/S_l(t) term my julia code does agree with your python code. If I understand it correctly, this does not affect the shape of the controls (may change a bit due to iterating process stopping at a different iteration) but may just be that the actual J values would be different from the definition in the reference paper? What would be the correct term for the running cost int g_a part of J?

Again, thanks a lot!

@goerz
Copy link
Member

goerz commented Nov 6, 2021

I was writing my own implementation in julia from scratch following your paper SciPostPhys.7.6.080

I got you covered there! Have a look at https://github.com/JuliaQuantumControl/Krotov.jl

It's not as polished yet as the Python version and still in "alpha" mode (no stable API), but it has some extra features such as parametrized pulses from the start, and of course huge gains in parallel performance.

Feel free to get in touch about the Julia implementation...

About the discrepancy, at first glance, I'd say you're right, but let me double-check. In any case, this only affects the printed output at each iteration, but does not change the optimization in any way. Let me check also what it means for ΔJ (what exactly Krotov guarantees to be smaller than zero for "monotonic convergence"). If you're right, we gotta be a bit careful about not dividing by zero (since S(t) is usually zero at the edges)

@daviehh
Copy link
Author

daviehh commented Nov 6, 2021

@goerz Thanks for the quick reply! I was writing the julia code as part of a learining process. Just to add the λ/S term is also present in other refs, e.g. Eq. 4 in https://arxiv.org/pdf/1008.5126.pdf

I understand that this is should not change the pulse shapes and is more-or-less a printing output thing, but it may change the final shape a bit if the resulting J value is used as part of the logic in when to stop the iterations (haven't checked yet)?

Thank you for double-checking! Concerning the divide-by-zero if this is indeed an issue: it should indeed be dealt with carefully in the code, but not a mathematical issue since Δε is given by S/λ*Im[...], inserting it into g_a = λ/S*Δε^2 as follows would not give divide-by-zero when the code is written as the last line

ga_int

@goerz
Copy link
Member

goerz commented Nov 7, 2021

Yes, that's all correct :-)

Do you want to have a look at #97 and compare with the numbers you're getting with your version?

goerz added a commit to JuliaQuantumControl/Krotov.jl that referenced this issue Nov 7, 2021
@daviehh
Copy link
Author

daviehh commented Nov 7, 2021

Thanks for the confirmation and fix! Now I get the same numbers for the J, J_T and ∫gₐ(t)dt with #97

One other thing I noticed is with the printout for the iterations is that the ΔJ column does not mean how much ΔJ changes between iterations for iteration after the first one, the code

Σgₐdt = np.sum(kwargs['g_a_integrals'])
J = J_T_val + Σgₐdt
if iteration > 0:
J_T_prev_val = J_T_prev(**kwargs)
ΔJ_T = J_T_val - J_T_prev_val
ΔJ = ΔJ_T + Σgₐdt

suggests that the ΔJ column is ΔJ_T plus ∫gₐ(t)dt and not difference of the J value between the iterations. Is this as intended (see below for example with 01_example_simple_state_to_state.ipynb)?

Thank you!

Screen Shot 2021-11-07 at 3 21 34 PM

@goerz
Copy link
Member

goerz commented Nov 8, 2021

That's right, and very much intended: The point is that gₐ more generally includes a "reference field", which just "happens to be" the guess field for that iteration. However, to calculate a ΔJ, you have to use the same reference field in both the terms, so the Δϵ vanishes in one of them.

I could have sworn that was explained somewhere in the documentation, but I can't find it at the moment...

Anyway, thanks for checking! I'll merge this, then.

@daviehh
Copy link
Author

daviehh commented Nov 8, 2021

Got it, thanks for explaining!

@goerz goerz self-assigned this Nov 8, 2021
@goerz goerz added the bug Something isn't working label Nov 8, 2021
@goerz goerz closed this as completed in #97 Nov 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants