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

2274 Benchmark User Guide #2566

Open
wants to merge 33 commits into
base: main
Choose a base branch
from

Conversation

Shivansh20128
Copy link

Description

This PR adds a user guide section for benchmarks.
Closes issue #2274


License

  • I license this contribution under the terms of the GNU GPL, version 3 and grant Unitary Fund the right to provide additional permissions as described in section 7 of the GNU GPL, version 3.

Before opening the PR, please ensure you have completed the following where appropriate.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Hello @Shivansh20128, thank you for submitting a PR to Mitiq! We will respond as soon as possible, and if you have any questions in the meantime, you can ask us on the Unitary Fund Discord.

@Shivansh20128
Copy link
Author

Hi! Can someone review this draft PR and reply if this is the kind of documentation the project needs? I will then add the rest of it accordingly.
Thank You

Copy link

codecov bot commented Nov 12, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.72%. Comparing base (3315184) to head (0ca08d1).
Report is 9 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2566   +/-   ##
=======================================
  Coverage   98.72%   98.72%           
=======================================
  Files          92       92           
  Lines        4168     4169    +1     
=======================================
+ Hits         4115     4116    +1     
  Misses         53       53           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@natestemen natestemen linked an issue Nov 12, 2024 that may be closed by this pull request
@natestemen
Copy link
Member

@Shivansh20128 this is exactly the kind of thing we're looking for!

@Shivansh20128
Copy link
Author

Shivansh20128 commented Nov 12, 2024

@purva-thakre Can you tell me why this error is coming in the checks performed? This is a different one from the previous check error, which I have linked to an open issue. I don't think its related to the changes I have made, so maybe I am just unlucky to encounter two tests failing non-deterministically🥲 for the two pushes I have made.

@cosenal
Copy link
Contributor

cosenal commented Nov 12, 2024

@Shivansh20128 https://github.com/unitaryfund/mitiq/actions/runs/11801809295/job/32876002160?pr=2566 is definitely unrelated to your changes, but it's not even a test that fails non-deterministically, or has anything to do with Mitiq. It looks like Python panicked when calling some core routine written in Rust 😱 Interesting, but definitely not in the scope of this PR 😄

@Shivansh20128
Copy link
Author

It looks like Python panicked when calling some core routine written in Rust 😱 Interesting, but definitely not in the scope of this PR 😄

Aahh. Okay. Thank you

@Shivansh20128
Copy link
Author

I think the error in the docs-build will be resolved once #2570 is merged.

@Shivansh20128
Copy link
Author

Shivansh20128 commented Nov 14, 2024

Upon reading the document shared by @cosenal and based on the discussion on the discord channel, this is the example for Mirror Circuits that I could come up with. Its a bit lengthy example, and does not follow the workflow we design in the beginning of the benchmarks section.

from typing import List, Tuple
import numpy as np
import cirq
import networkx as nx
from mitiq import zne
from mitiq import benchmarks

topology = nx.complete_graph(7)

def get_circuit(depth: int) -> Tuple[cirq.Circuit, List[int]]:
    circuit, correct_bitstring = benchmarks.generate_mirror_circuit(
        nlayers=depth,
        two_qubit_gate_prob=1.0,
        connectivity_graph=topology,
        return_type="cirq",
    )
    return circuit, correct_bitstring

circuit, correct_bitstring = get_circuit(depth=7)

def execute(
    circuit: cirq.Circuit,
    correct_bitstring: List[int],
    noise_level=0.005,
) -> float:
    """Executes the input circuit(s) and returns ⟨A⟩, where
    A = |correct_bitstring⟩⟨correct_bitstring| for each circuit.
    """
    noisy_circuit = circuit.with_noise(cirq.depolarize(p=noise_level))

    noisy_circuit += cirq.measure(*sorted(circuit.all_qubits()), key="m")
    backend = cirq.DensityMatrixSimulator()

    backend = cirq.DensityMatrixSimulator()

    result = backend.run(noisy_circuit)
    expval = result.measurements["m"].tolist().count(correct_bitstring)
    return expval

def execute_with_fixed_bitstring(circuit, noise_level=0.005):
    return execute(circuit, correct_bitstring, noise_level)

true_value = execute(circuit, correct_bitstring,noise_level=0.0)
noisy_value = execute(circuit, correct_bitstring)

zne_value = zne.execute_with_zne(circuit, execute_with_fixed_bitstring)  # Noisy quantum computer + Mitiq

print(f"Error w/o  Mitiq: {abs((true_value - noisy_value) / true_value):.3f}")
print(f"Error w Mitiq:    {abs((true_value - zne_value) / true_value):.3f}")

Can someone review this example, if this looks okay. Also, I am not sure for what circuit size the mitiq application will show improvements, but I noticed better performance for bigger circuits. If that is the case, then I think we should go with depth>7 or 8. Please check the example and let me know what changes it needs.


## Randomized Benchmarking Circuits

The {func}`.generate_rb_circuits` are sequences of random gates (generally Clifford gates), to estimate an average error rate. They’re standard in benchmarking for evaluating how well mitiq’s error mitigation reduces this error rate across different levels of noise.
Copy link
Collaborator

@purva-thakre purva-thakre Nov 14, 2024

Choose a reason for hiding this comment

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

Can you add some details about what the state of each circuit is supposed to be? For example, the ideal output of a randomized benchmarking circuit is an identity.

GHZ and W circuits define a state. So, you could use some latex equations to show what the states are supposed to be etc.

We don't want to describe what the addition of noise will do to a circuit. the focus is on the details of the benchmarking circuit. All docstrings link a reference used to define a particular benchmarking circuit. You could use details from these refs if you don't know a lot about these circuits.

Copy link
Collaborator

Choose a reason for hiding this comment

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

You can also use .final_state_vector() to show the ideal circuit state, which is what we expect it to be.

from mitiq.benchmarks import generate_ghz_circuit
circuit = generate_ghz_circuit(n_qubits=3)
circuit.final_state_vector()

this will spit out the 1-D vector form of a 3 qubit GHZ state.

image

Copy link
Author

@Shivansh20128 Shivansh20128 Nov 15, 2024

Choose a reason for hiding this comment

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

You can also use .final_state_vector() to show the ideal circuit state, which is what we expect it to be.

Yes, I can add this function to the example workflow at the top of the file instead of adding it explicitly inside every circuit, so every circuit's ideal circuit state can be seen.

Copy link
Author

Choose a reason for hiding this comment

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

We don't want to describe what the addition of noise will do to a circuit. the focus is on the details of the benchmarking circuit. All docstrings link a reference used to define a particular benchmarking circuit. You could use details from these refs if you don't know a lot about these circuits.

Since the section is about benchmarking, I believe we should show improvements with mitiq when compared to a noisy circuit without mitiq. But if you think otherwise, I can remove that part from the examples.

Also, since I have now added .final_state_vector(), shall I still go ahead and add the latex equations to show what the states are supposed to be?

Copy link
Collaborator

Choose a reason for hiding this comment

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

The focus is on benchmarking circuits. Not benchmarking the performance of a QEM technique using mitiq.

@Shivansh20128 Shivansh20128 marked this pull request as ready for review November 15, 2024 17:02
Copy link
Contributor

@cosenal cosenal left a comment

Choose a reason for hiding this comment

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

Overall this is what we had in mind.
I agree with @purva-thakre that a snippet on how to use each circuit type would make the user guide too heavy, so let's leave only the small demo at the top.
I left some comments throughout the PR, looking forward to the next iteration.

docs/source/guide/benchmarks.md Outdated Show resolved Hide resolved
docs/source/guide/benchmarks.md Outdated Show resolved Hide resolved
docs/source/guide/benchmarks.md Outdated Show resolved Hide resolved
docs/source/guide/benchmarks.md Outdated Show resolved Hide resolved
docs/source/guide/benchmarks.md Outdated Show resolved Hide resolved
docs/source/guide/benchmarks.md Outdated Show resolved Hide resolved
docs/source/guide/benchmarks.md Outdated Show resolved Hide resolved
Shivansh20128 and others added 2 commits November 19, 2024 21:07
Co-authored-by: Alessandro Cosentino <[email protected]>
Co-authored-by: Alessandro Cosentino <[email protected]>
@Shivansh20128
Copy link
Author

Overall this is what we had in mind. I agree with @purva-thakre that a snippet on how to use each circuit type would make the user guide too heavy, so let's leave only the small demo at the top.

@cosenal Just to make sure, you want to remove the all the code snippets from the circuits and leave just the one at the top?

from mitiq.benchmarks import generate_ghz_circuit

circuit = generate_ghz_circuit(n_qubits=7)

So shall I remove all the blocks like these?

@cosenal
Copy link
Contributor

cosenal commented Nov 22, 2024

Overall this is what we had in mind. I agree with @purva-thakre that a snippet on how to use each circuit type would make the user guide too heavy, so let's leave only the small demo at the top.

@cosenal Just to make sure, you want to remove the all the code snippets from the circuits and leave just the one at the top?

from mitiq.benchmarks import generate_ghz_circuit

circuit = generate_ghz_circuit(n_qubits=7)

So shall I remove all the blocks like these?

No, those small snippets on how to generate the circuits are good. What I meant is that we shouldn't have snippets running error mitigation for each class of circuits.

@purva-thakre
Copy link
Collaborator

purva-thakre commented Nov 22, 2024

What I had in mind for how each section describing a benchmarking circuit might look like is shown below. Right now, the details pertaining to each circuit are lacking.

image

We can discuss this during the community call.

w_state_outline.txt

Edit: Note that we don't use $G(p)$ exactly as defined in the paper. There should be a line or two discussing these changes as well.

for i, j in zip(range(0, n_qubits), range(1, n_qubits)):
N = n_qubits - i
angle = 2 * np.arccos(np.sqrt(1 / N))
circuit.append(
cirq.Ry(rads=angle).controlled().on(qubits[i], qubits[j])
)
circuit.append(cirq.CNOT(qubits[j], qubits[i]))

Copy link
Collaborator

@purva-thakre purva-thakre left a comment

Choose a reason for hiding this comment

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

I suggested some changes. @Shivansh20128 let me know if you have the time to work on these.

If not, I can take over.

docs/source/guide/benchmarking-circuits.md Outdated Show resolved Hide resolved

## Mirror Circuits

The {func}`.generate_mirror_circuit` involves running a quantum circuit forward and then “mirroring” it (applying the reverse operations). Ideally, this results in returning the system to the initial state, so they’re great for testing if the noise mitigation is effective in preserving information through complex sequences.
Copy link
Collaborator

Choose a reason for hiding this comment

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

It might be better to show an example code block.

Copy link
Collaborator

@purva-thakre purva-thakre Nov 26, 2024

Choose a reason for hiding this comment

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

Most of the benchmarking circuit docstrings have a link to some reference that was used to define the function. Could you please mention these in the circuit descriptions?

https://mitiq.readthedocs.io/en/stable/apidoc.html#module-mitiq.benchmarks.mirror_circuits

The W-state outline txt file contains an example of how to use {cite} for the references listed in docs/source/refs.bib

@Shivansh20128
Copy link
Author

I suggested some changes. @Shivansh20128 let me know if you have the time to work on these.

Okay. I will make the changes.

@Shivansh20128
Copy link
Author

Hi @purva-thakre , I have added an example code block for the generate_mirror_circuit.

I have also added references for the benchmarking circuits wherever I could find them in the API-doc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add benchmarks to user guide
4 participants