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

Make sure LRE executors work with observables #2513

Open
Tracked by #2223
purva-thakre opened this issue Sep 25, 2024 · 7 comments · May be fixed by #2681
Open
Tracked by #2223

Make sure LRE executors work with observables #2513

purva-thakre opened this issue Sep 25, 2024 · 7 comments · May be fixed by #2681
Assignees
Labels
good first issue Good for newcomers lre Layerwise Richardson Extrapolation
Milestone

Comments

@purva-thakre
Copy link
Collaborator

purva-thakre commented Sep 25, 2024

All the top-level functions in LRE should work with observable. This issue is to make sure of this as well as add unit tests for the same.

@purva-thakre purva-thakre added the lre Layerwise Richardson Extrapolation label Sep 25, 2024
@natestemen natestemen added this to the 0.41.0 milestone Oct 10, 2024
@purva-thakre purva-thakre self-assigned this Oct 11, 2024
@natestemen natestemen modified the milestones: 0.41.0, 0.42.0 Oct 25, 2024
@purva-thakre purva-thakre self-assigned this Nov 8, 2024
@purva-thakre purva-thakre modified the milestones: 0.42.0, 0.43.0 Dec 20, 2024
@purva-thakre purva-thakre modified the milestones: 0.43.0, 0.44.0 Feb 11, 2025
@purva-thakre purva-thakre removed their assignment Feb 19, 2025
@purva-thakre purva-thakre added the good first issue Good for newcomers label Feb 19, 2025
@Shivansh20128
Copy link
Contributor

Hi! I can work on this issue if it is available. I am listing all the top-level functions I could find in the code (after comparing them to functions in ZNE).

  1. execute_with_lre
  2. mitigate_executor
  3. lre_decorator

I hope these are the only functions when you say that all top-level functions in LRE should work with observable. Let me know if I missed any function.

@natestemen
Copy link
Member

Yup those are correct! The main code changes will be in execute_with_lre, and then they should be easily propagated to mitigate_executor and lre_decorator through the addition of a new observable argument.

@Shivansh20128
Copy link
Contributor

Great! You can assign this to me then.
Thanks

@Shivansh20128
Copy link
Contributor

To work with observable, I think I need to change the executor as well (here).

So in the line:

    for scaled_circuit in noise_scaled_circuits:
        circ_exp_val = executor(scaled_circuit)
        lre_exp_values.append(circ_exp_val)

Since I need to pass the observables here, I need call the function executor.evaluate().

    for scaled_circuit in noise_scaled_circuits:
        circ_exp_val = executor.evaluate(scaled_circuit, observables)
        lre_exp_values.append(circ_exp_val)

And for that to work, I also need to change the executor from the definition:

def execute_with_lre(
    input_circuit: QPROGRAM,
    executor: Callable[[QPROGRAM], float],
    ...

to:

def execute_with_lre(
    input_circuit: QPROGRAM,
    executor: Union[Executor, Callable[[QPROGRAM], float]],
    ...

This is further leading to more changes in the program and tests in the test file. Am I heading in the right direction?
Thanks

@natestemen
Copy link
Member

Good find, that's exactly right! Sorry for not pointing this out earlier, but the first step is exactly what @bdg221 is working on in #2676. I'll give that PR a review today, and hopefully it will be merged soon. If you want to start this issue in the meantime you can start working on top of that branch.

@Shivansh20128
Copy link
Contributor

Shivansh20128 commented Feb 28, 2025

Oh alright. This helps. But there is another problem. I am getting the below error when I tried running the execute_with_lre along with the parameter observable. Note: this error is coming after I specified the return type of the executor as float.

ValueError: When using an executor that returns a float-like result, measurements should be added before the circuit is executed instead of with an observable.

I tried running the below test:

@pytest.mark.parametrize(
    "degree, fold_multiplier, observable",
    [(2, 2, Observable(PauliString(spec="Z"))), (2, 3, Observable(PauliString(spec="Z"))), (3, 4, Observable(PauliString(spec="Z")))],
)
def test_lre_executor_with_observables(degree, fold_multiplier, observable):
    """Verify LRE executor with observable works as expected."""
    test_executor = Executor(execute)
    lre_exp_val = execute_with_lre(
        test_cirq,
        test_executor,
        degree=degree,
        fold_multiplier=fold_multiplier,
        observable=observable,
    )
    assert isinstance(lre_exp_val, float)

    assert test_executor.calls_to_executor == len(
        multivariate_layer_scaling(test_cirq, degree, fold_multiplier)
    )

I think the solution to this requires changing the return type of executor from float. Or we need to add measurements before the circuit is executed (as the error suggests), but I am unsure what that means and how to do that. @bdg221, I think you might have thought about this while working on the previous issue. Please suggest.

@natestemen
Copy link
Member

In order to make this work, you'll need an executor function which returns either bitstrings or a density matrix. Some documentation can be found here and an example of how this is done in ZNE here:

@pytest.mark.parametrize(
"executor", (sample_bitstrings, compute_density_matrix)
)
def test_with_observable_batched_factory(executor):

@Shivansh20128 Shivansh20128 linked a pull request Mar 1, 2025 that will close this issue
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers lre Layerwise Richardson Extrapolation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants