Skip to content

Implement ZNE postprocess function#2953

Open
dekelmeirom wants to merge 21 commits into
Qiskit:mainfrom
dekelmeirom:zne_postprocess
Open

Implement ZNE postprocess function#2953
dekelmeirom wants to merge 21 commits into
Qiskit:mainfrom
dekelmeirom:zne_postprocess

Conversation

@dekelmeirom

@dekelmeirom dekelmeirom commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add a post-process function to calculate the extrapolated expectation values when using ZNE with gate folding EM method.

Details and comments

Fixes #2850

AI/LLM disclosure

  • I used the following tool to generate or modify code: bob

@dekelmeirom dekelmeirom self-assigned this Jun 24, 2026
@dekelmeirom dekelmeirom added the wrapper-estimator Related to WrapperEstimator label Jun 24, 2026
@dekelmeirom
dekelmeirom marked this pull request as ready for review July 2, 2026 08:05
@dekelmeirom

Copy link
Copy Markdown
Collaborator Author

Note - this PR changes the I/O of the extrapolation methods in the same way #2948 does (so after #2948 will be merged, this PR will have changes only to the zne related functions)

@TsafrirA TsafrirA left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Some initial comments, mainly on the integration into the main post processor function.

Comment thread qiskit_ibm_runtime/decoders/executor_estimator/post_processor_v0_1.py Outdated
Comment thread qiskit_ibm_runtime/decoders/executor_estimator/post_processor_v0_1.py Outdated
Comment thread qiskit_ibm_runtime/executor_estimator/zne/extrapolation.py Outdated
Comment thread qiskit_ibm_runtime/executor_estimator/zne/extrapolation.py Outdated
Comment thread qiskit_ibm_runtime/executor_estimator/zne/extrapolation.py Outdated
@dekelmeirom

dekelmeirom commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

The extrapolation I/O changes were moved to a separate PR which will need to be merged first - #3000 (the tests will fail until this PR will be merged, but they pass combined with this PR code)

dekelmeirom added a commit to dekelmeirom/qiskit-ibm-runtime that referenced this pull request Jul 14, 2026
…hods (Qiskit#3000)

### Summary

Change the extrapolation input and output to align with the flow of the
EM methods.

### Details and comments

Related to Qiskit#2948 and Qiskit#2953 

### AI/LLM disclosure

- [ ] I didn't use LLM tooling, or only used it privately.
- [ ] I used the following tool to help write this PR description:
- [X] I used the following tool to generate or modify code: bob

---------

Co-authored-by: TsafrirA <113579969+TsafrirA@users.noreply.github.com>

@TsafrirA TsafrirA left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Some nitpicks, and a couple of things that need a fix -

  • Length validation will fail.
  • 'auto' value will fail for extrapolated_noise_factors.

len(observables_lists),
len(param_basis_pairs_lists),
len(param_shapes_list),
} != {len(result)}:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This will fail for ZNE, as the number of items is not the same as the number of pubs.

Also highlights that we are missing a test for estimator_v2_post_processor_v0_1 with a ZNE result.

Returns:
An :class:`~qiskit_ibm_runtime.results.EstimatorPubResult` with an empty metadata dict.
"""
# The last returned value is the selected extrapolators, that should be saved in the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
# The last returned value is the selected extrapolators, that should be saved in the
# TODO: The last returned value is the selected extrapolators, that should be saved in the

extrapolator: list[ExtrapolatorType],
measure_noise_data: PauliLindbladMap | np.ndarray | None,
) -> tuple[npt.NDArray[float], npt.NDArray[float], npt.NDArray[float], list[list[str]]]:
"""Process expectation values for a single item result.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
"""Process expectation values for a single item result.
"""Process expectation values for a single pub.

raise ValueError("Dedicated creg ``'_meas'`` is missing from one of the results.")

if data.ndim != 4:
# Shape: (num_randomizations, num_noise_scales, num_configs, shots, num_bits)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
# Shape: (num_randomizations, num_noise_scales, num_configs, shots, num_bits)
# Shape: (num_randomizations, num_configs, shots, num_bits)


# Combine the data from each noise factor
noise_amplified_data = []
for i, item_result in enumerate(item_results):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
for i, item_result in enumerate(item_results):
for item_result in item_results:

):
# In case each pub is associated with several items - create a list in which each element
# is a list containing all relevant items for that pub
combined_results = []

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The calculation of combined_results only applies to the ZNE branch, so I think we should move it into that branch.

"""Calculate expectation values and errors with ZNE, and return pub result.

Args:
item_results: The item result.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
item_results: The item result.
item_results: The item results.

param_basis_pairs,
readout_noise_data,
noise_factors=zne_noise_factors,
extrapolated_noise_factors=extrapolated_noise_factors,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The options have an auto value for extrapolated_noise_factors. I don't see where it's resolved. It's passed as is during prepare, and I don't see it being resolved here.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it should be resolved in finalize_options.


# Apply measurement flips if present
if "measurement_flips._meas" in item_result:
data ^= item_result["measurement_flips._meas"]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We can pop the measurement flips here. Also makes sure you can't apply it twice somehow.

pec_gamma=pec_gammas[pub_idx],
)
elif mitigation == "zne":
pub_result = create_pub_result_zne(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Just like in the PEA PR, some of the values could be None, but are passed as here as actual values. Need to validate. (Again, I don't understand how this passes static checks).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wrapper-estimator Related to WrapperEstimator

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wire ZNE into the executor estimator postprocess flow

2 participants