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

Stark Ramsey XY Amp Scan experiment #1009

Merged

Conversation

nkanazawa1989
Copy link
Collaborator

@nkanazawa1989 nkanazawa1989 commented Jan 12, 2023

Summary

This PR adds StarkRamseyXYAmpScan experiment and a dedicated fitter. This experiment characterizes the Stark shift vs tone amplitude curve to calibrate a required amplitude to cause a target shift. One can also do the same experiment with StarkRamseyXY, but this experiment avoids two dimensional sweep of tone length and amplitude.

This experiment returns several quantities that may be used to run following spectroscopy experiments. Since Stark shift is asymmetric with respect to f_S = 0 because of the higher levels anti-crossings on f_S < 0 side, parameters are defined for each shift direction:

  • stark_pos_coef_o1
  • stark_pos_coef_o2
  • stark_pos_coef_o3
  • stark_neg_coef_o1
  • stark_neg_coef_o2
  • stark_neg_coef_o3
  • stark_ferr

Details and comments

In c2b3d85 I decided to add linear terms (stark_pos_coef_o1, stark_neg_coef_o1) to the fit model. Although coefficients of these terms are small, these are the most effective terms to account for the asymmetry at around x=0; quadratic term doesn't add asymmetry, and cubit term is too small in this regime.

image

In above experiment result, Ramsey Y curves show asymmetry which is fit well by the linear terms. The chisq is not great and we need some discussion for implementation of the systematic validation logic.

The test experiment result is available in a017cfc2-93ba-4157-82d2-63dc05fc5764. This experiment result was obtained with the following experiment code:

from qiskit_ibm_provider import IBMProvider
from qiskit_experiments.library import StarkRamseyFast

provider = IBMProvider()
backend = provider.get_backend("ibm_auckland")

qind = 0
exp = StarkRamseyFast(physical_qubits=(qind,), backend=backend)
exp.analysis.plotter.set_figure_options(figure_title=f"Q{qind:02d}")

exp_data = exp.run().block_for_results()
exp_data.save()

@nkanazawa1989 nkanazawa1989 added the on hold On hold until something else is done. label Jan 12, 2023
@nkanazawa1989 nkanazawa1989 changed the title [WIP] Stark Ramsey Fast experiment Stark Ramsey Fast experiment Jun 2, 2023
@nkanazawa1989 nkanazawa1989 added Changelog: New Feature Include in the "Added" section of the changelog and removed on hold On hold until something else is done. labels Jun 2, 2023
@nkanazawa1989 nkanazawa1989 marked this pull request as ready for review June 2, 2023 02:06
Copy link
Collaborator

@wshanks wshanks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good! I have some suggestions and questions but I didn't see any blocking issues with this PR.

@@ -381,7 +390,7 @@ def set_experiment_options(self, **fields):

super().set_experiment_options(**fields)

def delays(self) -> np.ndarray:
def parameters(self) -> np.ndarray:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has not been released yet, so it is okay to change the API, but we should try to get this change in before the next release.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree. These Stark experiments are the target of 0.6.

qiskit_experiments/library/characterization/ramsey_xy.py Outdated Show resolved Hide resolved
qiskit_experiments/library/characterization/ramsey_xy.py Outdated Show resolved Hide resolved
qiskit_experiments/library/characterization/ramsey_xy.py Outdated Show resolved Hide resolved
qiskit_experiments/library/characterization/ramsey_xy.py Outdated Show resolved Hide resolved
Comment on lines 115 to 148
defpar c_1^+:
desc: The linear term coefficient of the positive Stark shift.
init_guess: See the fit model description.
bounds: None

defpar c_2^+:
desc: The quadratic term coefficient of the positive Stark shift.
init_guess: See the fit model description.
bounds: None

defpar c_3^+:
desc: The cubic term coefficient of the positive Stark shift.
init_guess: See the fit model description.
bounds: None

defpar c_1^-:
desc: The linear term coefficient of the negative Stark shift.
init_guess: See the fit model description.
bounds: None

defpar c_2^-:
desc: The quadratic term coefficient of the negative Stark shift.
init_guess: See the fit model description.
bounds: None

defpar c_3^-:
desc: The cubic term coefficient of the negative Stark shift.
init_guess: See the fit model description.
bounds: None

defpar f_\epsilon:
desc: Constant phase accumulation which is independent of the Stark tone amplitude.
init_guess: 0
bounds: None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these match the model? I am wondering about c_3^- vs c3_neg and f_\epsilon vs f_err.

Copy link
Collaborator Author

@nkanazawa1989 nkanazawa1989 Jun 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think c_3^- and c3_neg are sort of comparable names. c_{3, {\text neg}} is little hard to read without rendering and ^+- may cause unexpected issue in database or regex search. I only replaced f_\epsilon with f_{\rm err} in the math display in 2a9dc3e

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, hmm, I see how in the docstring a TeX format works better, but what I wonder about is if the entries here are documenting the parameters in the docstring discussion or the parameters that are used in the lmfit model. Perhaps the TeX names are best, but the descriptions should mention the lmfit names as well for reference?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Done in 76f1fb5

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! One very minor question -- should we reference LMFIT directly or just fit parameters? I was mainly interested in the documentation matching up with the fit parameters since they are user facing if the user uses return_fit_parameters and gets the CurveFitResult. I don't know if LMFIT matters for that or is an implementation detail?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced with model parameter name in e751212

Copy link
Collaborator Author

@nkanazawa1989 nkanazawa1989 Jul 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I misunderstood your intention. The model name is further replaced with lengthy name in the fit result object because something like c3_neg isn't really meaningful without context of this experiment, and indeed we can search for the name in the result database. This is updated to the name in the database in 9415e1d

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I did mean the c3_neg model names, but documenting the longer names is good as well and probably even better, though we should think about whether we want a consistent way of documenting tying all three together -- documentation symbols, model parameter name, and analysis result name (when it is directly a model parameter).

The case I was thinking of was the user using the return_fit_parameters analysis option which returns an object with all of the model parameters. I was thinking it would be nice to document those since otherwise the user needs to read the code to check what those names correspond. It is also valuable to document the analysis result names.

@nkanazawa1989 nkanazawa1989 changed the title Stark Ramsey Fast experiment Stark Ramsey XY Amp Scan experiment Jun 29, 2023
Copy link
Collaborator

@wshanks wshanks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few minor things here and in my replies to previous messages, but this looks about ready to merge now!

- add guard for non identical x values.
- add bounds to c2_pos and c2_neg
- drop unphysical test
@nkanazawa1989
Copy link
Collaborator Author

nkanazawa1989 commented Jun 30, 2023

Thanks Will for review. I also tested dynamics simulation of this experiment. Here is my notebook.
https://gist.github.com/nkanazawa1989/66491776a30b6caf6a2fa2d4355014b5

The result is bit weird. I assigned DriveChannel(1) for Stark gates and DriveChannel(0) for the rest of schedule. This is because Stark gates start from SetFrequency but this frequency is not reverted as a real backend doesn't carry over the frame to next gate. I found that the simulated shift strongly depends on the carrier frequency of this channel, i.e. channel_carrier_freqs argument of dynamics Solver, even though this frequency is immediately updated by the set frequency instruction. Because the Stark shift is insensitive to the pulse phase in the lowest order of perturbative expansion, the initial phase accumulation doesn't matter in this experiment. I gave up scrutinizing this. @DanPuzzuoli

A good news is the simulation cost is still tolerate, so we can add some realistic integration test. But I don't want to use existing QE pulse backend, because of the potential non Markov error contribution from the discontinuous carrier signal.

Copy link
Collaborator

@wshanks wshanks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I have just two minor questions outstanding so I will go ahead and mark this as approved.

@nkanazawa1989 nkanazawa1989 added this pull request to the merge queue Jul 5, 2023
Merged via the queue into qiskit-community:main with commit e0467f1 Jul 5, 2023
@nkanazawa1989 nkanazawa1989 deleted the experiment/stark_ramsey_fast branch July 5, 2023 07:24
@nkanazawa1989
Copy link
Collaborator Author

nkanazawa1989 commented Jul 11, 2023

@wshanks I realized why my simulation showed weird carrier frequency dependence, thanks to the discussion with @DanPuzzuoli . Since shift/set frequency instruction is formulated as a digital sideband mixing in the solver, setting carrier frequency = 0 yields large frequency delta when I set the Stark tone frequency. Because this frequency delta is above the Nyquist limit of the solver sampling clock (dt = 1/4.5 GSpS), it cannot play the Stark tone at expected frequency.

For the simulation, we need to use smaller dt or move carrier frequency more close to the drive frequency.

github-merge-queue bot pushed a commit that referenced this pull request Jul 23, 2023
### Summary

This PR adds `StarkP1Spectroscopy` experiment and a dedicated analysis.
User can set amplitudes to scan to run this experiment, and the analysis
class can convert the amplitudes into frequencies if Stark coefficients
are provided. These coefficients can be calibrated with
`StarkRamseyXYAmpScan` experiment introduced in #1009 .

### Details and comments

The test experiment result is available in
[6799e7ae-414f-4816-b887-b4c3ba498624](https://quantum-computing.ibm.com/experiments/6799e7ae-414f-4816-b887-b4c3ba498624).
This experiment result was obtained with the following experiment code:

```python
from qiskit_experiments.library import StarkP1Spectroscopy

exp = StarkP1Spectroscopy((0, ), backend)
exp_data = exp.run().block_for_results()
```

The Stark coefficients can be directly set in the analysis options. By
the default setting, the analysis class searches for the coefficients in
the experiment service. If analysis results for all coefficients are
found (i.e. previously saved in the service), it automatically converts
the amplitudes into frequencies for visualization.

A public class method
`StarkP1SpectAnalysis.retrieve_coefficients_from_service` is also
offered so that a user can set a coefficients dictionary in advance.
This is convenient when the experiment instance is run repeatedly,
because retrieving analysis data from the service causes a communication
overhead. For example,

```python
from qiskit_experiments.library.characterization.analysis import StarkP1SpectAnalysis

# overhead happens only once
coeffs = StarkP1SpectAnalysis.retrieve_coefficients_from_service(
    service=service,
    qubit=0,
    backend=backend.name,
)
exp.analysis.set_options(stark_coefficients=coeffs)

for _ in range(10):
    exp_data = exp.run().block_for_result()
    exp_data.save()
```

User can make a subclass of this analysis class `StarkP1SpectAnalysis`
to perform custom analysis. This built-in class doesn't perform any
analysis except for visualization. Instead, this class provides a
convenient hook `._run_spect_analysis` that takes (x, y, y_err) data and
returns a list of `AnalysisResultData`.

---------

Co-authored-by: Yael Ben-Haim <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants