Giter VIP home page Giter VIP logo

prototype-zne's Introduction

Platform Python Qiskit
Tests Coverage Release DOI License


Logo

Zero Noise Extrapolation (ZNE)


Table of contents

  1. About This Project
  2. About Prototypes
  3. Deprecation Policy
  4. Using Quantum Services
  5. Acknowledgements
  6. References
  7. License

For users

  1. Installation
  2. Tutorials
  3. Reference Guide
  4. How-tos
  5. Explanations
  6. How to Give Feedback

For developers

  1. Contribution Guidelines

About This Project

This module builds on top of the Estimator primitive official specification, providing a highly customizable zero noise extrapolation (ZNE) workflow for error mitigation on expectation value calculations. This is achieved by injecting orchestrated ZNE capabilities into an Estimator class of choice in two phases:

  1. Amplifying the noise introduced by the gates of input circuits.
  2. Extrapolating the returned expectation values to the zero noise limit.

In principle, this prototype is compatible with any Estimator class as long as it implements the qiskit.primitives.BaseEstimator interface (e.g. qiskit.primitives.Estimator, qiskit.primitives.BackendEstimator, qiskit_ibm_runtime.Estimator). Notice, however, that error mitigation techniques only make sense in the context of noisy computations; therefore using ZNE on noisless platforms (e.g. simulators), although technically possible, will not produce better results.

Furthermore, the software architecture has been devised specifically to allow users to create their custom noise amplification and extrapolation techniques, and to plug them into the overall ZNE workflow seamlessly. Libraries of pre-implemented strategies for both of these tasks are provided in the module, and external packages can easily be made to work with this tool by providing implementations of well defined interfaces for these tasks.

Before using the module for new work, users should read through the reference guide, specifically the current limitations of the module. Demo tutorials are also available as jupyter notebooks.


About Prototypes

Prototypes is a collaboration between developers and researchers that will give users early access to solutions from cutting-edge research in areas like error mitigation, quantum simulation, and machine learning. These software packages are built on top of, and may eventually be integrated into the Qiskit SDK. They are a contribution as part of the Qiskit community.

Check out our landing page and blog post for more information!


Deprecation Policy

Prototypes are meant to evolve rapidly and, as such, do not follow Qiskit's deprecation policy. We may occasionally make breaking changes in order to improve the user experience. When possible, we will keep old interfaces and mark them as deprecated, as long as they can co-exist with the new ones. Each substantial improvement, breaking change, or deprecation will be documented in CHANGELOG.md.


Using Quantum Services

If you are interested in using quantum services (i.e. using a real quantum computer, not a simulator) you can look at the Qiskit Partners program for partner organizations that have provider packages available for their offerings.

Importantly, Qiskit IBM Runtime is a quantum computing service and programming model that allows users to optimize workloads and efficiently execute them on quantum systems at scale; extending the existing interface in Qiskit with a set of new primitive programs.


Acknowledgements

  • Mario Motta: for scientific insight and guidance.
  • Julien Gacon: for providing a util function that maps gate names to the corresponding gate classes and for general discussions.
  • Derek Wang: for suggesting new features and stress-testing the tool.

References

[1] Kandala, Abhinav, et al. "Extending the computational reach of a noisy superconducting quantum processor." arXiv:1805.04492(2018).

[2] Stamatopoulos, Nikitas, et al. "Option pricing using quantum computers." Quantum4 (2020): 291.

[3] LaRose, Ryan, et al. "Mitiq: A software package for error mitigation on noisy quantum computers." arXiv:2009.04417(2020).

[4] Kim, Youngseok, et al. "Scalable error mitigation for noisy quantum circuits produces competitive expectation values." arXiv:2108.09197(2021).

[5] T. Giurgica-Tiron, Y. Hindy, R. LaRose, A. Mari and W. J. Zeng, "Digital zero noise extrapolation for quantum error mitigation," 2020 IEEE International Conference on Quantum Computing and Engineering (QCE), Denver, CO, USA, 2020, pp. 306-316, doi: 10.1109/QCE49297.2020.00045.


License

Apache License 2.0

prototype-zne's People

Contributors

1ucian0 avatar garrison avatar github-actions[bot] avatar pedrorrivero avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

prototype-zne's Issues

Add a plotting utility for results

What is the expected behavior?

Often times we want to display the noise amplification and extrapolation processes, to check supervise the process. This could be automated from a mitigated EstimatorResult (i.e. with the appropriate ZNE metadata).


Originally by: Areeq Hasan

Add `RichardsonExtrapolator`

What is the expected behavior?

Add a new adaptive PolynomialExtrapolator class for performing Richardson extrapolation.

Isolate indexing logic for noisy experiments

What is the expected enhancement?

Sub-experiments have to be indexed in a consistent way so that we can package them for computation (i.e. for different noise factors), and recover them in the right order for post-processing (i.e. extrapolation).

For $N$ noise factors and $M$ experiments, ZNE works by building sub-experiments for each combination of experiment and noise factor, and later analyzing the noisy results from all sub-experiments related to the same experiment to produce $M$ error mitigated results (i.e. via extrapolation). This process can be described mathematically as a mapping from $M$ experiments to $M \cdot N$ sub-experiments: $(exp_m, n) → sub_m^n$. Where $m \in [0, M[$ refers to the experiment, and $n \in [0, N[$ refers to the applied noise factor.

The question comes when we flatten this latter structure (i.e. doubly-indexed) into a single-index data type to comply with the specification for the underlying Estimator class. We call this process indexing, and it can be done in several ways with the only condition being that the process has to be reversible (i.e. multiplexing and demultiplexing) in order to group noisy results from related sub-experiments back together.

As of the current implementation, the following indexing is assumed everywhere: $(m, n) → N*m + n$. This is okay and works, nonetheless two concerns arise:

  1. We would not like our solution to rely on implicit assumptions, cause it makes it hard to understand, maintain and update.
  2. If at any point in time we decide to modify the indexing, we would need to do this in several places (i.e. delocalized) with a potential to introduce inconsistencies and therefore bugs.

This enhancement will consist on isolating the indexing logic within an Indexer class that will take care of the multiplexing and demultiplexing processes, effectively decoupling this logic from the rest of the code and opening up the potential for seamlessly introducing new indexing strategies in the future.

Update docstrings dynamically

What is the expected enhancement?

Currently, the meta module takes care of adding the required functionality to implement the different stages of ZNE, but it does not update the docstrings of the relevant methods and classes to account for it. The reason for this —and main challenge— is that they need to be updated dynamically (i.e. for any given class and its associated methods).

This will require an upgrade to the current docstrings util.

Allow bypassing ZNE functionality from `run()`

What is the expected enhancement?

With the current implementation, a default zne_strategy can be configured on __init__(), or by accessing the object's attribute by the same name. If that is the case, when zne_strategy=None is provided in run() the default will apply.

If said default is equivalent to applying no ZNE this is a way of bypassing the functionality, but, if it is not, then we would need to provide a no-op zne_strategy to achieve this behavior; which can be cumbersome.

This enhancement consists on bypassing the ZNE functionality in a simpler way. Additionally, we suggest adding a noop() class method to ZNEStrategy in order to quickly build a no-op zne_strategy object.

Caching in `ZNEStrategy` incompatible with being mutable

What is the current behavior?

In the current implementation num_noise_factors is a cached property, however, noise_factors can be updated. In a similar fashion amplify_circuit_noise() relies on the noise_amplifier to not change. This applies to other attributes as well.

What is the expected behavior?

If we are to allow caching, ZNEStrategy needs to be immutable at least in certain aspects (e.g. noise_amplifier). Alternatively, one could clear all cached info when relevant attributes are updated.

Additional context

Related to #4.

Suggestions

Cache clearing seems to be the optimal solution.

Using ZNE with Aer primitives

What is the current behavior?

Thanks a lot for all your work on this prototype ! I waned to use it with the Aer Estimator primitive. However since qiskit.primitives.Estimator and qiskit_aer.primitives.Estimator have different call signature I don't think that works at the moment.

The issue is that the zne init function passes the options kwarg explicitly. That matches the call of qiskit.primitives.Estimator and qiskit.primitves.BackendEstimator but not the call of the qiskit_aer.primitives.Estimator

As a result, the following code:

from qiskit.providers.fake_provider import FakeNairobi, FakeGuadalupeV2, FakeGuadalupe
from zne import zne, ZNEStrategy
from zne.noise_amplification import LocalFoldingAmplifier
from zne.extrapolation import PolynomialExtrapolator
from qiskit.circuit.random import random_circuit
from qiskit.quantum_info import SparsePauliOp
from qiskit_aer.primitives import Estimator as AerEstimator
from qiskit_aer.noise import NoiseModel

## Build our input circuit and observable
circuit = random_circuit(2, 4, seed=1).decompose(reps=1)
observable = SparsePauliOp("ZZ")

# create noise model
seed = 170
device = FakeGuadalupe()
coupling_map = device.configuration().coupling_map
noise_model = NoiseModel.from_backend(device)

# Build ZNEEstimator
ZNEEstimator = zne(AerEstimator)
estimator = ZNEEstimator(backend_options={
        "method": "density_matrix",
        "coupling_map": coupling_map,
        "noise_model": noise_model,
    },
    run_options={"seed": seed, "shots": 10000},
    transpile_options={"seed_transpiler": seed},)

returns the following error:

TypeError: __init__() got an unexpected keyword argument 'options'

What is the expected enhancement?

It would be great to be able to use the prototype with the AER estimators !

Context

No response

Suggestions

I think the only change needed is to not pass the options keyword argument as part of the zne init function.
I've forked the repo and made that simple change here

With that change, the prototype works well with the Aer estimator, but I'm not 100% sure if it's breaking something else.

Code of Conduct

  • I agree to follow this project's Code of Conduct

Add method for computing a list of realizable noise factors for folding amplifiers

What is the expected behavior?

Users might want to know in advance which float noise factors are possible to realize with a given circuit using the digital folding amplifiers. Hence, we need a small class method get_noise_factors(circuit, min, max) (e.g. living in FoldingAmplifier) that outputs all noise factors for a given circuit in a provided (min, max) interval.


Originally by: Friederike Metz

Incorrect expectation values for the identity observable

Device

MacBook Pro

OS

macOS Sonoma 14.0

Python version

3.11.7

Release version or branch/commit

1.2.2

What is the current behavior?

The expectation values returned by the ZNEEstimator are not correct for this particular example. I'm including the results of the "reference implementation" of the Estimator in qiskit.primitives and the exp values differ greatly.

What is the expected behavior?

Expectation values return by the ZNEEstimator are similar to the reference implementation.

Steps to reproduce the problem

from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import BackendEstimator, Estimator as RefEstimator
from qiskit.providers.fake_provider import FakeBogota
from zne import zne, ZNEStrategy
from zne.noise_amplification import TwoQubitAmplifier

ZNEEstimator = zne(BackendEstimator)
fake_nairobi = FakeBogota()

circuit = RealAmplitudes(num_qubits=5, reps=2, entanglement="full")
num_parameters = circuit.num_parameters
observable = SparsePauliOp("IIIII")
parameter_values = [[0] * num_parameters]

# Reference estimator
ref_job = RefEstimator().run(circuit, observable, parameter_values)
ref_result = ref_job.result()
print("ref result:", ref_result.values)

# ZNE estimator
zne_strategy = ZNEStrategy(noise_factors=[1, 3, 5], noise_amplifier=TwoQubitAmplifier())
zne_estimator = ZNEEstimator(backend=fake_nairobi)
zne_job = zne_estimator.run(circuit, observable, parameter_values, zne_strategy=zne_strategy)
zne_result = zne_job.result()
print("zne result", zne_result.values)

Context

Tested this example with different versions of the library and the 1.0.0 was the last version that produced correct results.

Suggestions

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Add `TwoQubitAmplifier` facade

What is the expected behavior?

Facade for LocalFoldingAmplifier that deals exclusively with two-qubit gates —similar to CxAmplifier.

Refactor `ZNEStrategy`

What is the expected enhancement?

With the new interface in Qiskit Terra 0.22, ZNEStrategy no longer needs to be a frozen class. On top of that, all the internal functionality that it holds (now) makes it not very well suited to be a dataclass altogether; instead, something more tailored would be preferred.

how to set seed when using ZNEStrategy

Device

OS

Python version

Release version or branch/commit

What is the current behavior?

May i know when using zne(..) and ZNEStrategy(..), aside from noise_amplifier has input for seed. Any other part that i need to input seed? I use ZNEStrategy and each time get different result for ground state value

What is the expected behavior?

Steps to reproduce the problem

Context

Suggestions

Code of Conduct

  • I agree to follow this project's Code of Conduct

Upgrade `ImmutableStrategy`

What is the expected enhancement?

Currently, ImmutableStrategy updates __new__() and configures __repr__() to dynamically include the args passed to __init__().

There are cases, nonetheless, where we do not want some of those args to be included in repr, so exceptions have to be hardcoded into the class, forcing updates to ImmutableStrategy to create a child class. Ideally we would like to avoid this, letting the user specify which args to include and which not to.

Also, there are better ways to enforce immutability based on meta-programming concepts (e.g. __slots__, descriptors).

Missing barriers in `GlobalFoldingAmplifier`

What is the current behavior?

When using the random sub-folding-option it might happen that the selected sequence of gates simplifies during transpilation.

What is the expected behavior?

Therefore, we should add barriers after each instruction.

Suggestions

Adding extra barriers only in the sub-folding part of the global folding may lead to issues where simplification is avoided on the sub-folding but not on the full foldings.


Originally by: Friederike Metz

Add caching functionality

What is the expected enhancement?

After refactoring ZNEStrtegy and making it mutable, caching had to be removed. This is a proposal to reinstantiate caching with a more elaborate approach that deals with mutability issues, to regain the efficiency that was lost.

See #14 and #29 fore more details.

Pass effective noise factors to extrapolator

What is the current behavior?

The ZNE runs give the following warning:

(From https://github.com/qiskit-community/prototype-zne/blob/main/zne/noise_amplification/folding_amplifier/folding_amplifier.py in line 147)

UserWarning: Rounding of noise factor: Foldings are performed with noise factor 1.11 instead of specified noise factor 1.10 which amounts to a relative error of 1.01%.

and similar for other noise factors. The intended noise factor is 1.10, and I believe also curvefit takes 1.10

What is the expected enhancement?

The curvefit should take the "correct" value of 1.11 actually sent to the IBM device. This value should also be propagated (e.g., in the meta data)

Context

No response

Suggestions

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Allow number of noise factors instead of listing them

What is the expected behavior?

Instead of passing predetermined noise_factors to ZNEStrategy, users might just want to pass an option saying that ZNE should be performed with e.g. "the 10 lowest realizable noise factors".

The implementation could use #10.


Originally by: Friederike Metz

Strategy: add pickle handling

What is the expected enhancement?

As pickle is a default Python serialization mechanism it would be for strategy classes to be pickable.

Example:

import pickle
from ... import strategy

@strategy
class Awesomeness:
    def __init__(self, arg1, arg2, _something=None):
        pass

a = Awesomeness("chat-gpt", "dall-e")
pickle.dumps(a)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.