Closed cburdine closed 1 month ago
@cburdine Thank you so much for the PR and the detailed description ! @elloyd-1qbit and I will take a look at it.
In the meantime, it seems our linter (pycodetest
) picked up some stuff and will make your tests fail. If you ask for details, and open the menus you'll see the code files and lines that were brought up.
It seems at first glance all unit tests pass though, which is rad :)
@ValentinS4t1qbit and @elloyd-1qbit, there's one additional point that I would like your feedback on.
Currently rotoselect
requires a function of the form
def exp_rotoselect(var_params, var_rot_axes, ansatz, qubit_hamiltonian):
ansatz.update_var_params(var_params)
for i, axis in enumerate(var_rot_axes):
ansatz.circuit._variational_gates[i].name = axis
energy = sim.get_expectation_value(qubit_hamiltonian, ansatz.circuit)
return energy
to be passed in, which requires the user to manually modify the protected member ansatz.circuit._variational_gates
.
I'm thinking we could add a ansatz.update_var_gates()
function or perhaps add a gates
argument to ansatz.update_var_params()
to make this more seamless. Any thoughts?
Well done! I agree adding a ansatz.update_var_gates()
function would be really handy.
@cburdine To clarify: do we intend to add ansatz.update_var_gates()
in this PR ? Does it feel straightforward enough to implement ?
Or would the recommendation be opening a "feature suggestion" issue ? I know you're working on the hackathon, I want to be mindful of your time.
@ValentinS4t1qbit It looks like adding an update_var_gates()
function will require a change to the interface in the abstract class Ansatz
. Functions will then need to be implemented for each ansatz class individually. Test cases will also need to be added to each of the ansatzes, which may take some time. (If you can think of a better way of doing this, let me know! :bulb:)
I'm currently working on getting the first draft of a PR for issue 384 submitted, which is similar in that it requires extending the functionality of each ansatz class individually. Once I get that submitted I will circle back to this PR and add this feature.
This is a PR to address Issue 386: Augment the Rotosolve optimizer to support Rotoselect
:sparkles: New Features:
rotoselect()
function that implements Algorithm 2 from https://arxiv.org/pdf/1905.09692. This implementation requires 7 function evaluations (per parameter per iteration).extrapolate_exp()
function to extrapolate sinusoidal expectation values using the methods from Appendix A in the above paper.rotoselect()
algorithm (Heisenberg model and a trivial single-qubit Hamiltonian).:construction: Changes to Existing Features:
rotosolve_step()
to return both the optimized parameter set and the extrapolated estimate of the expectation value at that optimal parameter set. This modification is necessary for code reuse, and to allow for further optimization of the existing implementation ofrotoselect()
.extrapolate
option to therotoselect()
algorithm to allow for the use of extrapolated expectation values from the last call torotosolve_step()
in place of an actual function evaluation. This optimization setting reduces the number of function evaluations from three (per parameter per iteration) to two (per parameter per iteration). Theextrapolate
argument is currently set to False by default. More details about this optimization below:memo: Footnote on optimizing
rotosolve()
:The existing
rotosolve_step()
function used $\phi = 0$ by default, which is reasonable because it allows for the removal of the gate at compile time. However, if $\phi = \theta{d-1}^\ast$ is used, then the extrapolated expectation value of $\langle M \rangle{\theta_{d-1}^\ast}$ returned from the previous call torotosolve_step()
can be used in place of a direct evaluation of it.rotosolve_step()
has been modified so that the gate angle $\phi$ and a previously extrapolated expectation value $\langle M \rangle{\theta{d-1}^\ast}$ can be passed intorotosolve_step()
via the optional argumentsphi
andm_phi
respectively. By selecting $\phi = \theta{d-1}^\ast$ and using the extrapolated $\langle M \rangle{\phi} = \langle M \rangle{\theta{d-1}^\ast}$ from the previous optimized parameter, we only need to evaluate $\langle M \rangle{\phi + \pi/2}$ and $\langle M \rangle{\phi + \pi/2}$ to optimize the current parameter. In total, this requires 2/3 the number of evaluations, as long as the extrapolated value is accurate.On an ideal quantum computer with no sampling error, this optimized
rotosolve()
(i.e. withextrapolate=True
) should behave identically to the previous unoptimized version. However, I anticipate that it may perform slightly worse than the unoptimizedrotosolve()
on noisy devices for the same number of iterations. While the unoptimized version (i.e. withextrapolate=False
) is more stable, it requires 50% more evaluations than the optimized version. In terms of the total number of evaluations (which is probably the best basis of comparison), I am not sure which will perform better under noise. If in the future you find that the optimized version is too unstable for noisy devices, then you may consider removing theextrapolate
argument.